]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
de48eebc HH |
2 | |
3 | i2c tv tuner chip device driver | |
4 | controls the philips tda8290+75 tuner chip combo. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
910bb3e3 MK |
19 | |
20 | This "tda8290" module was split apart from the original "tuner" module. | |
de48eebc HH |
21 | */ |
22 | ||
1da177e4 | 23 | #include <linux/i2c.h> |
1da177e4 | 24 | #include <linux/delay.h> |
ffbb807c | 25 | #include <linux/videodev.h> |
910bb3e3 MK |
26 | #include "tuner-i2c.h" |
27 | #include "tda8290.h" | |
28 | ||
29 | static int debug = 0; | |
30 | module_param(debug, int, 0644); | |
31 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | |
32 | ||
33 | #define PREFIX "tda8290 " | |
1da177e4 LT |
34 | |
35 | /* ---------------------------------------------------------------------- */ | |
36 | ||
b2083199 | 37 | struct tda8290_priv { |
db8a6956 MK |
38 | struct tuner_i2c_props i2c_props; |
39 | ||
b2083199 MK |
40 | unsigned char tda8290_easy_mode; |
41 | unsigned char tda827x_lpsel; | |
42 | unsigned char tda827x_addr; | |
43 | unsigned char tda827x_ver; | |
44 | unsigned int sgIF; | |
910bb3e3 MK |
45 | |
46 | u32 frequency; | |
47 | ||
48 | unsigned int *lna_cfg; | |
49 | int (*tuner_callback) (void *dev, int command,int arg); | |
b2083199 MK |
50 | }; |
51 | ||
52 | /* ---------------------------------------------------------------------- */ | |
53 | ||
de48eebc HH |
54 | struct tda827x_data { |
55 | u32 lomax; | |
56 | u8 spd; | |
57 | u8 bs; | |
58 | u8 bp; | |
59 | u8 cp; | |
60 | u8 gc3; | |
61 | u8 div1p5; | |
1da177e4 LT |
62 | }; |
63 | ||
de48eebc HH |
64 | /* Note lomax entry is lo / 62500 */ |
65 | ||
66 | static struct tda827x_data tda827x_analog[] = { | |
67 | { .lomax = 992, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 62 MHz */ | |
68 | { .lomax = 1056, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 66 MHz */ | |
69 | { .lomax = 1216, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 76 MHz */ | |
70 | { .lomax = 1344, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 84 MHz */ | |
71 | { .lomax = 1488, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 93 MHz */ | |
72 | { .lomax = 1568, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 98 MHz */ | |
73 | { .lomax = 1744, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 109 MHz */ | |
74 | { .lomax = 1968, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 123 MHz */ | |
75 | { .lomax = 2128, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 133 MHz */ | |
76 | { .lomax = 2416, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 151 MHz */ | |
77 | { .lomax = 2464, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 154 MHz */ | |
78 | { .lomax = 2896, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 181 MHz */ | |
79 | { .lomax = 2960, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 185 MHz */ | |
80 | { .lomax = 3472, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 217 MHz */ | |
81 | { .lomax = 3904, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 244 MHz */ | |
82 | { .lomax = 4240, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 265 MHz */ | |
83 | { .lomax = 4832, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 302 MHz */ | |
84 | { .lomax = 5184, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 324 MHz */ | |
85 | { .lomax = 5920, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 370 MHz */ | |
86 | { .lomax = 7264, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 454 MHz */ | |
87 | { .lomax = 7888, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 493 MHz */ | |
88 | { .lomax = 8480, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 530 MHz */ | |
89 | { .lomax = 8864, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 554 MHz */ | |
90 | { .lomax = 9664, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 604 MHz */ | |
91 | { .lomax = 11088, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 696 MHz */ | |
92 | { .lomax = 11840, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 740 MHz */ | |
93 | { .lomax = 13120, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 820 MHz */ | |
94 | { .lomax = 13840, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 865 MHz */ | |
95 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ | |
1da177e4 LT |
96 | }; |
97 | ||
910bb3e3 MK |
98 | static void tda827x_set_analog_params(struct dvb_frontend *fe, |
99 | struct analog_parameters *params) | |
de48eebc HH |
100 | { |
101 | unsigned char tuner_reg[8]; | |
102 | unsigned char reg2[2]; | |
103 | u32 N; | |
104 | int i; | |
910bb3e3 | 105 | struct tda8290_priv *priv = fe->tuner_priv; |
b2083199 | 106 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; |
910bb3e3 | 107 | unsigned int freq = params->frequency; |
1da177e4 | 108 | |
910bb3e3 | 109 | if (params->mode == V4L2_TUNER_RADIO) |
de48eebc HH |
110 | freq = freq / 1000; |
111 | ||
910bb3e3 | 112 | N = freq + priv->sgIF; |
de48eebc HH |
113 | i = 0; |
114 | while (tda827x_analog[i].lomax < N) { | |
115 | if(tda827x_analog[i + 1].lomax == 0) | |
116 | break; | |
117 | i++; | |
118 | } | |
119 | ||
120 | N = N << tda827x_analog[i].spd; | |
121 | ||
122 | tuner_reg[0] = 0; | |
123 | tuner_reg[1] = (unsigned char)(N>>8); | |
124 | tuner_reg[2] = (unsigned char) N; | |
125 | tuner_reg[3] = 0x40; | |
b2083199 | 126 | tuner_reg[4] = 0x52 + (priv->tda827x_lpsel << 5); |
de48eebc | 127 | tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + |
9a741ec9 | 128 | (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; |
de48eebc HH |
129 | tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); |
130 | tuner_reg[7] = 0x8f; | |
131 | ||
132 | msg.buf = tuner_reg; | |
133 | msg.len = 8; | |
db8a6956 | 134 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
135 | |
136 | msg.buf= reg2; | |
137 | msg.len = 2; | |
138 | reg2[0] = 0x80; | |
139 | reg2[1] = 0; | |
db8a6956 | 140 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
141 | |
142 | reg2[0] = 0x60; | |
143 | reg2[1] = 0xbf; | |
db8a6956 | 144 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
145 | |
146 | reg2[0] = 0x30; | |
147 | reg2[1] = tuner_reg[4] + 0x80; | |
db8a6956 | 148 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
149 | |
150 | msleep(1); | |
151 | reg2[0] = 0x30; | |
152 | reg2[1] = tuner_reg[4] + 4; | |
db8a6956 | 153 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
154 | |
155 | msleep(1); | |
156 | reg2[0] = 0x30; | |
157 | reg2[1] = tuner_reg[4]; | |
db8a6956 | 158 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
159 | |
160 | msleep(550); | |
161 | reg2[0] = 0x30; | |
162 | reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; | |
db8a6956 | 163 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
1da177e4 | 164 | |
de48eebc | 165 | reg2[0] = 0x60; |
95736034 | 166 | reg2[1] = 0x3f; |
db8a6956 | 167 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
168 | |
169 | reg2[0] = 0x80; | |
170 | reg2[1] = 0x08; // Vsync en | |
db8a6956 | 171 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
172 | } |
173 | ||
910bb3e3 | 174 | static void tda827x_agcf(struct dvb_frontend *fe) |
1da177e4 | 175 | { |
910bb3e3 | 176 | struct tda8290_priv *priv = fe->tuner_priv; |
de48eebc | 177 | unsigned char data[] = {0x80, 0x0c}; |
b2083199 | 178 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, |
de48eebc | 179 | .flags = 0, .len = 2}; |
db8a6956 | 180 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
1da177e4 LT |
181 | } |
182 | ||
183 | /* ---------------------------------------------------------------------- */ | |
184 | ||
de48eebc HH |
185 | struct tda827xa_data { |
186 | u32 lomax; | |
187 | u8 svco; | |
188 | u8 spd; | |
189 | u8 scr; | |
190 | u8 sbs; | |
191 | u8 gc3; | |
1da177e4 LT |
192 | }; |
193 | ||
de48eebc HH |
194 | static struct tda827xa_data tda827xa_analog[] = { |
195 | { .lomax = 910, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, /* 56.875 MHz */ | |
196 | { .lomax = 1076, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 67.25 MHz */ | |
197 | { .lomax = 1300, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 81.25 MHz */ | |
198 | { .lomax = 1560, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 97.5 MHz */ | |
199 | { .lomax = 1820, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, /* 113.75 MHz */ | |
200 | { .lomax = 2152, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 134.5 MHz */ | |
201 | { .lomax = 2464, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 154 MHz */ | |
202 | { .lomax = 2600, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 162.5 MHz */ | |
203 | { .lomax = 2928, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 183 MHz */ | |
204 | { .lomax = 3120, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, /* 195 MHz */ | |
205 | { .lomax = 3640, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, /* 227.5 MHz */ | |
206 | { .lomax = 4304, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, /* 269 MHz */ | |
207 | { .lomax = 5200, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, /* 325 MHz */ | |
208 | { .lomax = 6240, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 390 MHz */ | |
209 | { .lomax = 7280, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 455 MHz */ | |
210 | { .lomax = 8320, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 520 MHz */ | |
211 | { .lomax = 8608, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, /* 538 MHz */ | |
212 | { .lomax = 8864, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 554 MHz */ | |
213 | { .lomax = 9920, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 620 MHz */ | |
214 | { .lomax = 10400, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 650 MHz */ | |
215 | { .lomax = 11200, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 700 MHz */ | |
216 | { .lomax = 12480, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 780 MHz */ | |
217 | { .lomax = 13120, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 820 MHz */ | |
218 | { .lomax = 13920, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 870 MHz */ | |
219 | { .lomax = 14576, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, /* 911 MHz */ | |
220 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ | |
1da177e4 LT |
221 | }; |
222 | ||
910bb3e3 MK |
223 | static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, |
224 | struct analog_parameters *params) | |
58ef4f92 | 225 | { |
910bb3e3 | 226 | struct tda8290_priv *priv = fe->tuner_priv; |
58ef4f92 HH |
227 | unsigned char buf[] = {0x22, 0x01}; |
228 | int arg; | |
db8a6956 | 229 | struct i2c_msg msg = {.addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = sizeof(buf)}; |
910bb3e3 MK |
230 | |
231 | if ((priv->lna_cfg == NULL) || (priv->tuner_callback == NULL)) | |
232 | return; | |
233 | ||
234 | if (*priv->lna_cfg) { | |
58ef4f92 HH |
235 | if (high) |
236 | tuner_dbg("setting LNA to high gain\n"); | |
237 | else | |
238 | tuner_dbg("setting LNA to low gain\n"); | |
239 | } | |
910bb3e3 | 240 | switch (*priv->lna_cfg) { |
58ef4f92 HH |
241 | case 0: /* no LNA */ |
242 | break; | |
243 | case 1: /* switch is GPIO 0 of tda8290 */ | |
244 | case 2: | |
245 | /* turn Vsync on */ | |
910bb3e3 | 246 | if (params->std & V4L2_STD_MN) |
cfeb8839 | 247 | arg = 1; |
58ef4f92 | 248 | else |
cfeb8839 | 249 | arg = 0; |
910bb3e3 MK |
250 | if (priv->tuner_callback) |
251 | priv->tuner_callback(priv->i2c_props.adap->algo_data, 1, arg); | |
58ef4f92 | 252 | buf[1] = high ? 0 : 1; |
910bb3e3 | 253 | if (*priv->lna_cfg == 2) |
58ef4f92 | 254 | buf[1] = high ? 1 : 0; |
db8a6956 | 255 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
58ef4f92 HH |
256 | break; |
257 | case 3: /* switch with GPIO of saa713x */ | |
910bb3e3 MK |
258 | if (priv->tuner_callback) |
259 | priv->tuner_callback(priv->i2c_props.adap->algo_data, 0, high); | |
58ef4f92 HH |
260 | break; |
261 | } | |
262 | } | |
263 | ||
910bb3e3 MK |
264 | static void tda827xa_set_analog_params(struct dvb_frontend *fe, |
265 | struct analog_parameters *params) | |
de48eebc | 266 | { |
58ef4f92 | 267 | unsigned char tuner_reg[11]; |
de48eebc HH |
268 | u32 N; |
269 | int i; | |
910bb3e3 | 270 | struct tda8290_priv *priv = fe->tuner_priv; |
b2083199 | 271 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; |
910bb3e3 | 272 | unsigned int freq = params->frequency; |
58ef4f92 | 273 | |
910bb3e3 | 274 | tda827xa_lna_gain(fe, 1, params); |
58ef4f92 | 275 | msleep(10); |
1da177e4 | 276 | |
910bb3e3 | 277 | if (params->mode == V4L2_TUNER_RADIO) |
de48eebc | 278 | freq = freq / 1000; |
1da177e4 | 279 | |
910bb3e3 | 280 | N = freq + priv->sgIF; |
de48eebc HH |
281 | i = 0; |
282 | while (tda827xa_analog[i].lomax < N) { | |
283 | if(tda827xa_analog[i + 1].lomax == 0) | |
284 | break; | |
285 | i++; | |
286 | } | |
287 | ||
288 | N = N << tda827xa_analog[i].spd; | |
289 | ||
290 | tuner_reg[0] = 0; | |
291 | tuner_reg[1] = (unsigned char)(N>>8); | |
292 | tuner_reg[2] = (unsigned char) N; | |
293 | tuner_reg[3] = 0; | |
294 | tuner_reg[4] = 0x16; | |
295 | tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + | |
9a741ec9 | 296 | tda827xa_analog[i].sbs; |
de48eebc | 297 | tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); |
58ef4f92 | 298 | tuner_reg[7] = 0x1c; |
de48eebc HH |
299 | tuner_reg[8] = 4; |
300 | tuner_reg[9] = 0x20; | |
58ef4f92 HH |
301 | tuner_reg[10] = 0x00; |
302 | msg.len = 11; | |
db8a6956 | 303 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 304 | |
58ef4f92 HH |
305 | tuner_reg[0] = 0x90; |
306 | tuner_reg[1] = 0xff; | |
307 | tuner_reg[2] = 0xe0; | |
308 | tuner_reg[3] = 0; | |
b2083199 | 309 | tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); |
58ef4f92 | 310 | msg.len = 5; |
db8a6956 | 311 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 312 | |
58ef4f92 HH |
313 | tuner_reg[0] = 0xa0; |
314 | tuner_reg[1] = 0xc0; | |
de48eebc | 315 | msg.len = 2; |
db8a6956 | 316 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 317 | |
58ef4f92 HH |
318 | tuner_reg[0] = 0x30; |
319 | tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; | |
db8a6956 | 320 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 321 | |
58ef4f92 | 322 | msg.flags = I2C_M_RD; |
db8a6956 | 323 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
58ef4f92 HH |
324 | msg.flags = 0; |
325 | tuner_reg[1] >>= 4; | |
326 | tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]); | |
327 | if (tuner_reg[1] < 1) | |
910bb3e3 | 328 | tda827xa_lna_gain(fe, 0, params); |
58ef4f92 HH |
329 | |
330 | msleep(100); | |
331 | tuner_reg[0] = 0x60; | |
332 | tuner_reg[1] = 0x3c; | |
db8a6956 | 333 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 334 | |
58ef4f92 HH |
335 | msleep(163); |
336 | tuner_reg[0] = 0x50; | |
337 | tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); | |
db8a6956 | 338 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 339 | |
58ef4f92 HH |
340 | tuner_reg[0] = 0x80; |
341 | tuner_reg[1] = 0x28; | |
db8a6956 | 342 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 343 | |
58ef4f92 HH |
344 | tuner_reg[0] = 0xb0; |
345 | tuner_reg[1] = 0x01; | |
db8a6956 | 346 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
793cf9e6 | 347 | |
58ef4f92 | 348 | tuner_reg[0] = 0xc0; |
b2083199 | 349 | tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); |
db8a6956 | 350 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
351 | } |
352 | ||
910bb3e3 | 353 | static void tda827xa_agcf(struct dvb_frontend *fe) |
1da177e4 | 354 | { |
910bb3e3 | 355 | struct tda8290_priv *priv = fe->tuner_priv; |
de48eebc | 356 | unsigned char data[] = {0x80, 0x2c}; |
b2083199 | 357 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, |
de48eebc | 358 | .flags = 0, .len = 2}; |
db8a6956 | 359 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 360 | } |
1da177e4 | 361 | |
de48eebc | 362 | /*---------------------------------------------------------------------*/ |
1da177e4 | 363 | |
910bb3e3 | 364 | static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) |
de48eebc | 365 | { |
910bb3e3 | 366 | struct tda8290_priv *priv = fe->tuner_priv; |
db8a6956 | 367 | |
de48eebc | 368 | unsigned char enable[2] = { 0x21, 0xC0 }; |
0157a9cc | 369 | unsigned char disable[2] = { 0x21, 0x00 }; |
de48eebc HH |
370 | unsigned char *msg; |
371 | if(close) { | |
372 | msg = enable; | |
db8a6956 | 373 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); |
de48eebc HH |
374 | /* let the bridge stabilize */ |
375 | msleep(20); | |
376 | } else { | |
377 | msg = disable; | |
db8a6956 | 378 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); |
de48eebc | 379 | } |
1da177e4 LT |
380 | } |
381 | ||
de48eebc HH |
382 | /*---------------------------------------------------------------------*/ |
383 | ||
910bb3e3 MK |
384 | static void set_audio(struct dvb_frontend *fe, |
385 | struct analog_parameters *params) | |
1da177e4 | 386 | { |
910bb3e3 MK |
387 | struct tda8290_priv *priv = fe->tuner_priv; |
388 | char* mode; | |
389 | ||
390 | priv->tda827x_lpsel = 0; | |
391 | if (params->std & V4L2_STD_MN) { | |
392 | priv->sgIF = 92; | |
393 | priv->tda8290_easy_mode = 0x01; | |
394 | priv->tda827x_lpsel = 1; | |
395 | mode = "MN"; | |
396 | } else if (params->std & V4L2_STD_B) { | |
397 | priv->sgIF = 108; | |
398 | priv->tda8290_easy_mode = 0x02; | |
399 | mode = "B"; | |
400 | } else if (params->std & V4L2_STD_GH) { | |
401 | priv->sgIF = 124; | |
402 | priv->tda8290_easy_mode = 0x04; | |
403 | mode = "GH"; | |
404 | } else if (params->std & V4L2_STD_PAL_I) { | |
405 | priv->sgIF = 124; | |
406 | priv->tda8290_easy_mode = 0x08; | |
407 | mode = "I"; | |
408 | } else if (params->std & V4L2_STD_DK) { | |
409 | priv->sgIF = 124; | |
410 | priv->tda8290_easy_mode = 0x10; | |
411 | mode = "DK"; | |
412 | } else if (params->std & V4L2_STD_SECAM_L) { | |
413 | priv->sgIF = 124; | |
414 | priv->tda8290_easy_mode = 0x20; | |
415 | mode = "L"; | |
416 | } else if (params->std & V4L2_STD_SECAM_LC) { | |
417 | priv->sgIF = 20; | |
418 | priv->tda8290_easy_mode = 0x40; | |
419 | mode = "LC"; | |
420 | } else { | |
421 | priv->sgIF = 124; | |
422 | priv->tda8290_easy_mode = 0x10; | |
423 | mode = "xx"; | |
424 | } | |
425 | ||
426 | if (params->mode == V4L2_TUNER_RADIO) | |
427 | priv->sgIF = 88; /* if frequency is 5.5 MHz */ | |
428 | ||
429 | tuner_dbg("setting tda8290 to system %s\n", mode); | |
430 | } | |
431 | ||
432 | static int tda8290_set_params(struct dvb_frontend *fe, | |
433 | struct analog_parameters *params) | |
434 | { | |
435 | struct tda8290_priv *priv = fe->tuner_priv; | |
de48eebc | 436 | unsigned char soft_reset[] = { 0x00, 0x00 }; |
b2083199 | 437 | unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; |
de48eebc | 438 | unsigned char expert_mode[] = { 0x01, 0x80 }; |
0157a9cc | 439 | unsigned char agc_out_on[] = { 0x02, 0x00 }; |
de48eebc HH |
440 | unsigned char gainset_off[] = { 0x28, 0x14 }; |
441 | unsigned char if_agc_spd[] = { 0x0f, 0x88 }; | |
442 | unsigned char adc_head_6[] = { 0x05, 0x04 }; | |
443 | unsigned char adc_head_9[] = { 0x05, 0x02 }; | |
444 | unsigned char adc_head_12[] = { 0x05, 0x01 }; | |
445 | unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; | |
446 | unsigned char pll_bw_low[] = { 0x0d, 0x27 }; | |
447 | unsigned char gainset_2[] = { 0x28, 0x64 }; | |
448 | unsigned char agc_rst_on[] = { 0x0e, 0x0b }; | |
449 | unsigned char agc_rst_off[] = { 0x0e, 0x09 }; | |
450 | unsigned char if_agc_set[] = { 0x0f, 0x81 }; | |
451 | unsigned char addr_adc_sat = 0x1a; | |
452 | unsigned char addr_agc_stat = 0x1d; | |
453 | unsigned char addr_pll_stat = 0x1b; | |
454 | unsigned char adc_sat, agc_stat, | |
9a741ec9 | 455 | pll_stat; |
58ef4f92 | 456 | int i; |
de48eebc | 457 | |
910bb3e3 MK |
458 | set_audio(fe, params); |
459 | ||
460 | if (priv->lna_cfg) | |
461 | tuner_dbg("tda827xa config is 0x%02x\n", *priv->lna_cfg); | |
db8a6956 MK |
462 | tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); |
463 | tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); | |
464 | tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); | |
de48eebc HH |
465 | msleep(1); |
466 | ||
b2083199 | 467 | expert_mode[1] = priv->tda8290_easy_mode + 0x80; |
db8a6956 MK |
468 | tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); |
469 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); | |
470 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); | |
b2083199 | 471 | if (priv->tda8290_easy_mode & 0x60) |
db8a6956 | 472 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); |
de48eebc | 473 | else |
db8a6956 MK |
474 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); |
475 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); | |
de48eebc | 476 | |
910bb3e3 | 477 | tda8290_i2c_bridge(fe, 1); |
b2083199 | 478 | if (priv->tda827x_ver != 0) |
910bb3e3 | 479 | tda827xa_set_analog_params(fe, params); |
de48eebc | 480 | else |
910bb3e3 | 481 | tda827x_set_analog_params(fe, params); |
58ef4f92 | 482 | for (i = 0; i < 3; i++) { |
db8a6956 MK |
483 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); |
484 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | |
58ef4f92 | 485 | if (pll_stat & 0x80) { |
db8a6956 MK |
486 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); |
487 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | |
488 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | |
489 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | |
58ef4f92 HH |
490 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); |
491 | break; | |
492 | } else { | |
493 | tuner_dbg("tda8290 not locked, no signal?\n"); | |
494 | msleep(100); | |
495 | } | |
496 | } | |
de48eebc | 497 | /* adjust headroom resp. gain */ |
4ac95af9 HH |
498 | if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { |
499 | tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", | |
500 | agc_stat, adc_sat, pll_stat & 0x80); | |
db8a6956 | 501 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); |
de48eebc | 502 | msleep(100); |
db8a6956 MK |
503 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); |
504 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | |
505 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | |
506 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | |
de48eebc | 507 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { |
4ac95af9 HH |
508 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", |
509 | agc_stat, pll_stat & 0x80); | |
b2083199 | 510 | if (priv->tda827x_ver != 0) |
910bb3e3 | 511 | tda827xa_agcf(fe); |
de48eebc | 512 | else |
910bb3e3 | 513 | tda827x_agcf(fe); |
de48eebc | 514 | msleep(100); |
db8a6956 MK |
515 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); |
516 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | |
517 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | |
518 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | |
de48eebc HH |
519 | if((agc_stat > 115) || !(pll_stat & 0x80)) { |
520 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); | |
db8a6956 MK |
521 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); |
522 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2); | |
de48eebc HH |
523 | msleep(100); |
524 | } | |
525 | } | |
526 | } | |
1da177e4 | 527 | |
de48eebc | 528 | /* l/ l' deadlock? */ |
b2083199 | 529 | if(priv->tda8290_easy_mode & 0x60) { |
db8a6956 MK |
530 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); |
531 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | |
532 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | |
533 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | |
de48eebc | 534 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { |
4ac95af9 | 535 | tuner_dbg("trying to resolve SECAM L deadlock\n"); |
db8a6956 | 536 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); |
de48eebc | 537 | msleep(40); |
db8a6956 | 538 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2); |
de48eebc HH |
539 | } |
540 | } | |
586b0cab | 541 | |
910bb3e3 | 542 | tda8290_i2c_bridge(fe, 0); |
db8a6956 | 543 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); |
910bb3e3 MK |
544 | |
545 | priv->frequency = (V4L2_TUNER_RADIO == params->mode) ? | |
546 | params->frequency * 125 / 2 : params->frequency * 62500; | |
547 | ||
de48eebc | 548 | return 0; |
1da177e4 LT |
549 | } |
550 | ||
de48eebc HH |
551 | /*---------------------------------------------------------------------*/ |
552 | ||
910bb3e3 | 553 | static int tda8290_has_signal(struct dvb_frontend *fe) |
1da177e4 | 554 | { |
910bb3e3 | 555 | struct tda8290_priv *priv = fe->tuner_priv; |
3782e050 | 556 | int ret; |
1da177e4 | 557 | |
910bb3e3 MK |
558 | unsigned char i2c_get_afc[1] = { 0x1B }; |
559 | unsigned char afc = 0; | |
1da177e4 | 560 | |
3782e050 | 561 | /* for now, report based on afc status */ |
910bb3e3 MK |
562 | tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); |
563 | tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); | |
3782e050 MK |
564 | |
565 | ret = (afc & 0x80) ? 65535 : 0; | |
566 | ||
567 | tuner_dbg("AFC status: %d\n", ret); | |
568 | ||
569 | return ret; | |
1da177e4 LT |
570 | } |
571 | ||
910bb3e3 | 572 | static int tda8290_get_status(struct dvb_frontend *fe, u32 *status) |
1da177e4 | 573 | { |
910bb3e3 | 574 | *status = 0; |
db8a6956 | 575 | |
3782e050 | 576 | if (tda8290_has_signal(fe)) |
910bb3e3 | 577 | *status = TUNER_STATUS_LOCKED; |
1da177e4 | 578 | |
3782e050 MK |
579 | return 0; |
580 | } | |
581 | ||
582 | static int tda8290_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | |
583 | { | |
584 | *strength = tda8290_has_signal(fe); | |
910bb3e3 MK |
585 | |
586 | return 0; | |
1da177e4 LT |
587 | } |
588 | ||
de48eebc HH |
589 | /*---------------------------------------------------------------------*/ |
590 | ||
910bb3e3 | 591 | static int tda8290_standby(struct dvb_frontend *fe) |
793cf9e6 | 592 | { |
910bb3e3 | 593 | struct tda8290_priv *priv = fe->tuner_priv; |
de48eebc HH |
594 | unsigned char cb1[] = { 0x30, 0xD0 }; |
595 | unsigned char tda8290_standby[] = { 0x00, 0x02 }; | |
0157a9cc | 596 | unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; |
b2083199 | 597 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; |
de48eebc | 598 | |
910bb3e3 | 599 | tda8290_i2c_bridge(fe, 1); |
b2083199 | 600 | if (priv->tda827x_ver != 0) |
de48eebc | 601 | cb1[1] = 0x90; |
db8a6956 | 602 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
910bb3e3 | 603 | tda8290_i2c_bridge(fe, 0); |
db8a6956 MK |
604 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); |
605 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); | |
910bb3e3 MK |
606 | |
607 | return 0; | |
793cf9e6 MCC |
608 | } |
609 | ||
de48eebc | 610 | |
910bb3e3 | 611 | static void tda8290_init_if(struct dvb_frontend *fe) |
de48eebc | 612 | { |
910bb3e3 | 613 | struct tda8290_priv *priv = fe->tuner_priv; |
db8a6956 | 614 | |
de48eebc | 615 | unsigned char set_VS[] = { 0x30, 0x6F }; |
58ef4f92 | 616 | unsigned char set_GP00_CF[] = { 0x20, 0x01 }; |
de48eebc HH |
617 | unsigned char set_GP01_CF[] = { 0x20, 0x0B }; |
618 | ||
910bb3e3 MK |
619 | if ((priv->lna_cfg) && |
620 | ((*priv->lna_cfg == 1) || (*priv->lna_cfg == 2))) | |
db8a6956 | 621 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); |
58ef4f92 | 622 | else |
db8a6956 MK |
623 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); |
624 | tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); | |
de48eebc HH |
625 | } |
626 | ||
910bb3e3 | 627 | static void tda8290_init_tuner(struct dvb_frontend *fe) |
1da177e4 | 628 | { |
910bb3e3 | 629 | struct tda8290_priv *priv = fe->tuner_priv; |
de48eebc | 630 | unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, |
9a741ec9 | 631 | 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; |
de48eebc | 632 | unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, |
9a741ec9 | 633 | 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; |
b2083199 | 634 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, |
c2f6f9d8 | 635 | .buf=tda8275_init, .len = 14}; |
b2083199 | 636 | if (priv->tda827x_ver != 0) |
de48eebc HH |
637 | msg.buf = tda8275a_init; |
638 | ||
910bb3e3 | 639 | tda8290_i2c_bridge(fe, 1); |
db8a6956 | 640 | i2c_transfer(priv->i2c_props.adap, &msg, 1); |
910bb3e3 | 641 | tda8290_i2c_bridge(fe, 0); |
de48eebc HH |
642 | } |
643 | ||
644 | /*---------------------------------------------------------------------*/ | |
1da177e4 | 645 | |
910bb3e3 | 646 | static int tda8290_release(struct dvb_frontend *fe) |
024cf530 | 647 | { |
910bb3e3 MK |
648 | kfree(fe->tuner_priv); |
649 | fe->tuner_priv = NULL; | |
650 | ||
651 | return 0; | |
024cf530 MK |
652 | } |
653 | ||
910bb3e3 MK |
654 | static int tda8290_get_frequency(struct dvb_frontend *fe, u32 *frequency) |
655 | { | |
656 | struct tda8290_priv *priv = fe->tuner_priv; | |
657 | *frequency = priv->frequency; | |
658 | return 0; | |
659 | } | |
660 | ||
661 | static struct dvb_tuner_ops tda8290_tuner_ops = { | |
662 | .sleep = tda8290_standby, | |
663 | .set_analog_params = tda8290_set_params, | |
664 | .release = tda8290_release, | |
665 | .get_frequency = tda8290_get_frequency, | |
666 | .get_status = tda8290_get_status, | |
3782e050 | 667 | .get_rf_strength = tda8290_get_rf_strength, |
7fd8b263 MK |
668 | }; |
669 | ||
910bb3e3 MK |
670 | struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, |
671 | struct i2c_adapter* i2c_adap, | |
672 | u8 i2c_addr, | |
673 | struct tda8290_config *cfg) | |
de48eebc | 674 | { |
b2083199 | 675 | struct tda8290_priv *priv = NULL; |
de48eebc HH |
676 | u8 data; |
677 | int i, ret, tuners_found; | |
678 | u32 tuner_addrs; | |
679 | struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; | |
680 | ||
b2083199 MK |
681 | priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); |
682 | if (priv == NULL) | |
910bb3e3 MK |
683 | return NULL; |
684 | fe->tuner_priv = priv; | |
685 | ||
686 | priv->i2c_props.addr = i2c_addr; | |
687 | priv->i2c_props.adap = i2c_adap; | |
688 | if (cfg) { | |
689 | priv->lna_cfg = cfg->lna_cfg; | |
690 | priv->tuner_callback = cfg->tuner_callback; | |
691 | } | |
db8a6956 | 692 | |
910bb3e3 | 693 | tda8290_i2c_bridge(fe, 1); |
de48eebc HH |
694 | /* probe for tuner chip */ |
695 | tuners_found = 0; | |
696 | tuner_addrs = 0; | |
697 | for (i=0x60; i<= 0x63; i++) { | |
698 | msg.addr = i; | |
db8a6956 | 699 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
700 | if (ret == 1) { |
701 | tuners_found++; | |
702 | tuner_addrs = (tuner_addrs << 8) + i; | |
703 | } | |
704 | } | |
705 | /* if there is more than one tuner, we expect the right one is | |
706 | behind the bridge and we choose the highest address that doesn't | |
707 | give a response now | |
708 | */ | |
910bb3e3 | 709 | tda8290_i2c_bridge(fe, 0); |
de48eebc HH |
710 | if(tuners_found > 1) |
711 | for (i = 0; i < tuners_found; i++) { | |
712 | msg.addr = tuner_addrs & 0xff; | |
db8a6956 | 713 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc HH |
714 | if(ret == 1) |
715 | tuner_addrs = tuner_addrs >> 8; | |
716 | else | |
717 | break; | |
718 | } | |
719 | if (tuner_addrs == 0) { | |
720 | tuner_addrs = 0x61; | |
910bb3e3 | 721 | tuner_info("could not clearly identify tuner address, defaulting to %x\n", |
01cb9633 | 722 | tuner_addrs); |
de48eebc HH |
723 | } else { |
724 | tuner_addrs = tuner_addrs & 0xff; | |
910bb3e3 | 725 | tuner_info("setting tuner address to %x\n", tuner_addrs); |
de48eebc | 726 | } |
b2083199 | 727 | priv->tda827x_addr = tuner_addrs; |
de48eebc HH |
728 | msg.addr = tuner_addrs; |
729 | ||
910bb3e3 | 730 | tda8290_i2c_bridge(fe, 1); |
db8a6956 | 731 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); |
de48eebc | 732 | if( ret != 1) |
910bb3e3 MK |
733 | tuner_warn("TDA827x access failed!\n"); |
734 | ||
735 | memcpy(&fe->ops.tuner_ops, &tda8290_tuner_ops, | |
736 | sizeof(struct dvb_tuner_ops)); | |
737 | ||
de48eebc | 738 | if ((data & 0x3c) == 0) { |
910bb3e3 MK |
739 | strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75", |
740 | sizeof(fe->ops.tuner_ops.info.name)); | |
741 | fe->ops.tuner_ops.info.frequency_min = 55000000; | |
742 | fe->ops.tuner_ops.info.frequency_max = 860000000; | |
743 | fe->ops.tuner_ops.info.frequency_step = 250000; | |
b2083199 | 744 | priv->tda827x_ver = 0; |
de48eebc | 745 | } else { |
910bb3e3 MK |
746 | strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75a", |
747 | sizeof(fe->ops.tuner_ops.info.name)); | |
748 | fe->ops.tuner_ops.info.frequency_min = 44000000; | |
749 | fe->ops.tuner_ops.info.frequency_max = 906000000; | |
750 | fe->ops.tuner_ops.info.frequency_step = 62500; | |
b2083199 | 751 | priv->tda827x_ver = 2; |
de48eebc | 752 | } |
7fd8b263 | 753 | |
b2083199 | 754 | priv->tda827x_lpsel = 0; |
1da177e4 | 755 | |
910bb3e3 MK |
756 | tda8290_init_tuner(fe); |
757 | tda8290_init_if(fe); | |
758 | return fe; | |
1da177e4 LT |
759 | } |
760 | ||
910bb3e3 | 761 | int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) |
95736034 | 762 | { |
910bb3e3 MK |
763 | struct tuner_i2c_props i2c_props = { |
764 | .adap = i2c_adap, | |
765 | .addr = i2c_addr | |
766 | }; | |
db8a6956 | 767 | |
44fd06fa HH |
768 | unsigned char soft_reset[] = { 0x00, 0x00 }; |
769 | unsigned char easy_mode_b[] = { 0x01, 0x02 }; | |
770 | unsigned char easy_mode_g[] = { 0x01, 0x04 }; | |
771 | unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; | |
95736034 HH |
772 | unsigned char addr_dto_lsb = 0x07; |
773 | unsigned char data; | |
774 | ||
910bb3e3 MK |
775 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); |
776 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | |
777 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | |
778 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | |
95736034 | 779 | if (data == 0) { |
910bb3e3 MK |
780 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); |
781 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | |
782 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | |
783 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | |
95736034 HH |
784 | if (data == 0x7b) { |
785 | return 0; | |
786 | } | |
787 | } | |
910bb3e3 | 788 | tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); |
95736034 HH |
789 | return -1; |
790 | } | |
791 | ||
910bb3e3 MK |
792 | EXPORT_SYMBOL_GPL(tda8290_probe); |
793 | EXPORT_SYMBOL_GPL(tda8290_attach); | |
794 | ||
795 | MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); | |
796 | MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann"); | |
797 | MODULE_LICENSE("GPL"); | |
798 | ||
1da177e4 LT |
799 | /* |
800 | * Overrides for Emacs so that we follow Linus's tabbing style. | |
801 | * --------------------------------------------------------------------------- | |
802 | * Local variables: | |
803 | * c-basic-offset: 8 | |
804 | * End: | |
805 | */ |