diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-14 15:35:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-13 22:40:28 -0400 |
commit | ccae7af2bf07dfef69cc2eb6ebc9e1ff15addfbd (patch) | |
tree | f33391cf2efe9038c13b88ca4049317728a7ebf0 /drivers/media/tuners/tda8290.c | |
parent | 3785bc170f79ef04129731582b468c28e1326d6d (diff) |
[media] common: move media/common/tuners to media/tuners
Move the tuners one level up, as the "common" directory will be used
by drivers that are shared between more than one driver.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/tuners/tda8290.c')
-rw-r--r-- | drivers/media/tuners/tda8290.c | 874 |
1 files changed, 874 insertions, 0 deletions
diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c new file mode 100644 index 000000000000..8c4852114eeb --- /dev/null +++ b/drivers/media/tuners/tda8290.c | |||
@@ -0,0 +1,874 @@ | |||
1 | /* | ||
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. | ||
19 | |||
20 | This "tda8290" module was split apart from the original "tuner" module. | ||
21 | */ | ||
22 | |||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/videodev2.h> | ||
27 | #include "tuner-i2c.h" | ||
28 | #include "tda8290.h" | ||
29 | #include "tda827x.h" | ||
30 | #include "tda18271.h" | ||
31 | |||
32 | static int debug; | ||
33 | module_param(debug, int, 0644); | ||
34 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
35 | |||
36 | static int deemphasis_50; | ||
37 | module_param(deemphasis_50, int, 0644); | ||
38 | MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis"); | ||
39 | |||
40 | /* ---------------------------------------------------------------------- */ | ||
41 | |||
42 | struct tda8290_priv { | ||
43 | struct tuner_i2c_props i2c_props; | ||
44 | |||
45 | unsigned char tda8290_easy_mode; | ||
46 | |||
47 | unsigned char tda827x_addr; | ||
48 | |||
49 | unsigned char ver; | ||
50 | #define TDA8290 1 | ||
51 | #define TDA8295 2 | ||
52 | #define TDA8275 4 | ||
53 | #define TDA8275A 8 | ||
54 | #define TDA18271 16 | ||
55 | |||
56 | struct tda827x_config cfg; | ||
57 | }; | ||
58 | |||
59 | /*---------------------------------------------------------------------*/ | ||
60 | |||
61 | static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close) | ||
62 | { | ||
63 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
64 | |||
65 | unsigned char enable[2] = { 0x21, 0xC0 }; | ||
66 | unsigned char disable[2] = { 0x21, 0x00 }; | ||
67 | unsigned char *msg; | ||
68 | |||
69 | if (close) { | ||
70 | msg = enable; | ||
71 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
72 | /* let the bridge stabilize */ | ||
73 | msleep(20); | ||
74 | } else { | ||
75 | msg = disable; | ||
76 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) | ||
83 | { | ||
84 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
85 | |||
86 | unsigned char enable[2] = { 0x45, 0xc1 }; | ||
87 | unsigned char disable[2] = { 0x46, 0x00 }; | ||
88 | unsigned char buf[3] = { 0x45, 0x01, 0x00 }; | ||
89 | unsigned char *msg; | ||
90 | |||
91 | if (close) { | ||
92 | msg = enable; | ||
93 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
94 | /* let the bridge stabilize */ | ||
95 | msleep(20); | ||
96 | } else { | ||
97 | msg = disable; | ||
98 | tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1); | ||
99 | |||
100 | buf[2] = msg[1]; | ||
101 | buf[2] &= ~0x04; | ||
102 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 3); | ||
103 | msleep(5); | ||
104 | |||
105 | msg[1] |= 0x04; | ||
106 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /*---------------------------------------------------------------------*/ | ||
113 | |||
114 | static void set_audio(struct dvb_frontend *fe, | ||
115 | struct analog_parameters *params) | ||
116 | { | ||
117 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
118 | char* mode; | ||
119 | |||
120 | if (params->std & V4L2_STD_MN) { | ||
121 | priv->tda8290_easy_mode = 0x01; | ||
122 | mode = "MN"; | ||
123 | } else if (params->std & V4L2_STD_B) { | ||
124 | priv->tda8290_easy_mode = 0x02; | ||
125 | mode = "B"; | ||
126 | } else if (params->std & V4L2_STD_GH) { | ||
127 | priv->tda8290_easy_mode = 0x04; | ||
128 | mode = "GH"; | ||
129 | } else if (params->std & V4L2_STD_PAL_I) { | ||
130 | priv->tda8290_easy_mode = 0x08; | ||
131 | mode = "I"; | ||
132 | } else if (params->std & V4L2_STD_DK) { | ||
133 | priv->tda8290_easy_mode = 0x10; | ||
134 | mode = "DK"; | ||
135 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
136 | priv->tda8290_easy_mode = 0x20; | ||
137 | mode = "L"; | ||
138 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
139 | priv->tda8290_easy_mode = 0x40; | ||
140 | mode = "LC"; | ||
141 | } else { | ||
142 | priv->tda8290_easy_mode = 0x10; | ||
143 | mode = "xx"; | ||
144 | } | ||
145 | |||
146 | if (params->mode == V4L2_TUNER_RADIO) { | ||
147 | /* Set TDA8295 to FM radio; Start TDA8290 with MN values */ | ||
148 | priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01; | ||
149 | tuner_dbg("setting to radio FM\n"); | ||
150 | } else { | ||
151 | tuner_dbg("setting tda829x to system %s\n", mode); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static struct { | ||
156 | unsigned char seq[2]; | ||
157 | } fm_mode[] = { | ||
158 | { { 0x01, 0x81} }, /* Put device into expert mode */ | ||
159 | { { 0x03, 0x48} }, /* Disable NOTCH and VIDEO filters */ | ||
160 | { { 0x04, 0x04} }, /* Disable color carrier filter (SSIF) */ | ||
161 | { { 0x05, 0x04} }, /* ADC headroom */ | ||
162 | { { 0x06, 0x10} }, /* group delay flat */ | ||
163 | |||
164 | { { 0x07, 0x00} }, /* use the same radio DTO values as a tda8295 */ | ||
165 | { { 0x08, 0x00} }, | ||
166 | { { 0x09, 0x80} }, | ||
167 | { { 0x0a, 0xda} }, | ||
168 | { { 0x0b, 0x4b} }, | ||
169 | { { 0x0c, 0x68} }, | ||
170 | |||
171 | { { 0x0d, 0x00} }, /* PLL off, no video carrier detect */ | ||
172 | { { 0x14, 0x00} }, /* disable auto mute if no video */ | ||
173 | }; | ||
174 | |||
175 | static void tda8290_set_params(struct dvb_frontend *fe, | ||
176 | struct analog_parameters *params) | ||
177 | { | ||
178 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
179 | |||
180 | unsigned char soft_reset[] = { 0x00, 0x00 }; | ||
181 | unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; | ||
182 | unsigned char expert_mode[] = { 0x01, 0x80 }; | ||
183 | unsigned char agc_out_on[] = { 0x02, 0x00 }; | ||
184 | unsigned char gainset_off[] = { 0x28, 0x14 }; | ||
185 | unsigned char if_agc_spd[] = { 0x0f, 0x88 }; | ||
186 | unsigned char adc_head_6[] = { 0x05, 0x04 }; | ||
187 | unsigned char adc_head_9[] = { 0x05, 0x02 }; | ||
188 | unsigned char adc_head_12[] = { 0x05, 0x01 }; | ||
189 | unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; | ||
190 | unsigned char pll_bw_low[] = { 0x0d, 0x27 }; | ||
191 | unsigned char gainset_2[] = { 0x28, 0x64 }; | ||
192 | unsigned char agc_rst_on[] = { 0x0e, 0x0b }; | ||
193 | unsigned char agc_rst_off[] = { 0x0e, 0x09 }; | ||
194 | unsigned char if_agc_set[] = { 0x0f, 0x81 }; | ||
195 | unsigned char addr_adc_sat = 0x1a; | ||
196 | unsigned char addr_agc_stat = 0x1d; | ||
197 | unsigned char addr_pll_stat = 0x1b; | ||
198 | unsigned char adc_sat, agc_stat, | ||
199 | pll_stat; | ||
200 | int i; | ||
201 | |||
202 | set_audio(fe, params); | ||
203 | |||
204 | if (priv->cfg.config) | ||
205 | tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config); | ||
206 | tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); | ||
207 | tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); | ||
208 | tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); | ||
209 | msleep(1); | ||
210 | |||
211 | if (params->mode == V4L2_TUNER_RADIO) { | ||
212 | unsigned char deemphasis[] = { 0x13, 1 }; | ||
213 | |||
214 | /* FIXME: allow using a different deemphasis */ | ||
215 | |||
216 | if (deemphasis_50) | ||
217 | deemphasis[1] = 2; | ||
218 | |||
219 | for (i = 0; i < ARRAY_SIZE(fm_mode); i++) | ||
220 | tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2); | ||
221 | |||
222 | tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2); | ||
223 | } else { | ||
224 | expert_mode[1] = priv->tda8290_easy_mode + 0x80; | ||
225 | tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); | ||
226 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); | ||
227 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); | ||
228 | if (priv->tda8290_easy_mode & 0x60) | ||
229 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); | ||
230 | else | ||
231 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); | ||
232 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); | ||
233 | } | ||
234 | |||
235 | |||
236 | tda8290_i2c_bridge(fe, 1); | ||
237 | |||
238 | if (fe->ops.tuner_ops.set_analog_params) | ||
239 | fe->ops.tuner_ops.set_analog_params(fe, params); | ||
240 | |||
241 | for (i = 0; i < 3; i++) { | ||
242 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
243 | &addr_pll_stat, 1, &pll_stat, 1); | ||
244 | if (pll_stat & 0x80) { | ||
245 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
246 | &addr_adc_sat, 1, | ||
247 | &adc_sat, 1); | ||
248 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
249 | &addr_agc_stat, 1, | ||
250 | &agc_stat, 1); | ||
251 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); | ||
252 | break; | ||
253 | } else { | ||
254 | tuner_dbg("tda8290 not locked, no signal?\n"); | ||
255 | msleep(100); | ||
256 | } | ||
257 | } | ||
258 | /* adjust headroom resp. gain */ | ||
259 | if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { | ||
260 | tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", | ||
261 | agc_stat, adc_sat, pll_stat & 0x80); | ||
262 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); | ||
263 | msleep(100); | ||
264 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
265 | &addr_agc_stat, 1, &agc_stat, 1); | ||
266 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
267 | &addr_pll_stat, 1, &pll_stat, 1); | ||
268 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { | ||
269 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", | ||
270 | agc_stat, pll_stat & 0x80); | ||
271 | if (priv->cfg.agcf) | ||
272 | priv->cfg.agcf(fe); | ||
273 | msleep(100); | ||
274 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
275 | &addr_agc_stat, 1, | ||
276 | &agc_stat, 1); | ||
277 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
278 | &addr_pll_stat, 1, | ||
279 | &pll_stat, 1); | ||
280 | if((agc_stat > 115) || !(pll_stat & 0x80)) { | ||
281 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); | ||
282 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); | ||
283 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2); | ||
284 | msleep(100); | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /* l/ l' deadlock? */ | ||
290 | if(priv->tda8290_easy_mode & 0x60) { | ||
291 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
292 | &addr_adc_sat, 1, | ||
293 | &adc_sat, 1); | ||
294 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
295 | &addr_pll_stat, 1, | ||
296 | &pll_stat, 1); | ||
297 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { | ||
298 | tuner_dbg("trying to resolve SECAM L deadlock\n"); | ||
299 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); | ||
300 | msleep(40); | ||
301 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | tda8290_i2c_bridge(fe, 0); | ||
306 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); | ||
307 | } | ||
308 | |||
309 | /*---------------------------------------------------------------------*/ | ||
310 | |||
311 | static void tda8295_power(struct dvb_frontend *fe, int enable) | ||
312 | { | ||
313 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
314 | unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ | ||
315 | |||
316 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); | ||
317 | |||
318 | if (enable) | ||
319 | buf[1] = 0x01; | ||
320 | else | ||
321 | buf[1] = 0x03; | ||
322 | |||
323 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
324 | } | ||
325 | |||
326 | static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) | ||
327 | { | ||
328 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
329 | unsigned char buf[] = { 0x01, 0x00 }; | ||
330 | |||
331 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); | ||
332 | |||
333 | if (enable) | ||
334 | buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ | ||
335 | else | ||
336 | buf[1] = 0x00; /* reset active bit */ | ||
337 | |||
338 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
339 | } | ||
340 | |||
341 | static void tda8295_set_video_std(struct dvb_frontend *fe) | ||
342 | { | ||
343 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
344 | unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; | ||
345 | |||
346 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
347 | |||
348 | tda8295_set_easy_mode(fe, 1); | ||
349 | msleep(20); | ||
350 | tda8295_set_easy_mode(fe, 0); | ||
351 | } | ||
352 | |||
353 | /*---------------------------------------------------------------------*/ | ||
354 | |||
355 | static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) | ||
356 | { | ||
357 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
358 | unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ | ||
359 | |||
360 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); | ||
361 | |||
362 | if (enable) | ||
363 | buf[1] &= ~0x40; | ||
364 | else | ||
365 | buf[1] |= 0x40; | ||
366 | |||
367 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
368 | } | ||
369 | |||
370 | static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) | ||
371 | { | ||
372 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
373 | unsigned char set_gpio_cf[] = { 0x44, 0x00 }; | ||
374 | unsigned char set_gpio_val[] = { 0x46, 0x00 }; | ||
375 | |||
376 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
377 | &set_gpio_cf[0], 1, &set_gpio_cf[1], 1); | ||
378 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
379 | &set_gpio_val[0], 1, &set_gpio_val[1], 1); | ||
380 | |||
381 | set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ | ||
382 | |||
383 | if (enable) { | ||
384 | set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */ | ||
385 | set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */ | ||
386 | } | ||
387 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2); | ||
388 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); | ||
389 | } | ||
390 | |||
391 | static int tda8295_has_signal(struct dvb_frontend *fe) | ||
392 | { | ||
393 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
394 | |||
395 | unsigned char hvpll_stat = 0x26; | ||
396 | unsigned char ret; | ||
397 | |||
398 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1); | ||
399 | return (ret & 0x01) ? 65535 : 0; | ||
400 | } | ||
401 | |||
402 | /*---------------------------------------------------------------------*/ | ||
403 | |||
404 | static void tda8295_set_params(struct dvb_frontend *fe, | ||
405 | struct analog_parameters *params) | ||
406 | { | ||
407 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
408 | |||
409 | unsigned char blanking_mode[] = { 0x1d, 0x00 }; | ||
410 | |||
411 | set_audio(fe, params); | ||
412 | |||
413 | tuner_dbg("%s: freq = %d\n", __func__, params->frequency); | ||
414 | |||
415 | tda8295_power(fe, 1); | ||
416 | tda8295_agc1_out(fe, 1); | ||
417 | |||
418 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
419 | &blanking_mode[0], 1, &blanking_mode[1], 1); | ||
420 | |||
421 | tda8295_set_video_std(fe); | ||
422 | |||
423 | blanking_mode[1] = 0x03; | ||
424 | tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); | ||
425 | msleep(20); | ||
426 | |||
427 | tda8295_i2c_bridge(fe, 1); | ||
428 | |||
429 | if (fe->ops.tuner_ops.set_analog_params) | ||
430 | fe->ops.tuner_ops.set_analog_params(fe, params); | ||
431 | |||
432 | if (priv->cfg.agcf) | ||
433 | priv->cfg.agcf(fe); | ||
434 | |||
435 | if (tda8295_has_signal(fe)) | ||
436 | tuner_dbg("tda8295 is locked\n"); | ||
437 | else | ||
438 | tuner_dbg("tda8295 not locked, no signal?\n"); | ||
439 | |||
440 | tda8295_i2c_bridge(fe, 0); | ||
441 | } | ||
442 | |||
443 | /*---------------------------------------------------------------------*/ | ||
444 | |||
445 | static int tda8290_has_signal(struct dvb_frontend *fe) | ||
446 | { | ||
447 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
448 | |||
449 | unsigned char i2c_get_afc[1] = { 0x1B }; | ||
450 | unsigned char afc = 0; | ||
451 | |||
452 | tuner_i2c_xfer_send_recv(&priv->i2c_props, | ||
453 | i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1); | ||
454 | return (afc & 0x80)? 65535:0; | ||
455 | } | ||
456 | |||
457 | /*---------------------------------------------------------------------*/ | ||
458 | |||
459 | static void tda8290_standby(struct dvb_frontend *fe) | ||
460 | { | ||
461 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
462 | |||
463 | unsigned char cb1[] = { 0x30, 0xD0 }; | ||
464 | unsigned char tda8290_standby[] = { 0x00, 0x02 }; | ||
465 | unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; | ||
466 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; | ||
467 | |||
468 | tda8290_i2c_bridge(fe, 1); | ||
469 | if (priv->ver & TDA8275A) | ||
470 | cb1[1] = 0x90; | ||
471 | i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
472 | tda8290_i2c_bridge(fe, 0); | ||
473 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); | ||
474 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); | ||
475 | } | ||
476 | |||
477 | static void tda8295_standby(struct dvb_frontend *fe) | ||
478 | { | ||
479 | tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */ | ||
480 | |||
481 | tda8295_power(fe, 0); | ||
482 | } | ||
483 | |||
484 | static void tda8290_init_if(struct dvb_frontend *fe) | ||
485 | { | ||
486 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
487 | |||
488 | unsigned char set_VS[] = { 0x30, 0x6F }; | ||
489 | unsigned char set_GP00_CF[] = { 0x20, 0x01 }; | ||
490 | unsigned char set_GP01_CF[] = { 0x20, 0x0B }; | ||
491 | |||
492 | if ((priv->cfg.config == 1) || (priv->cfg.config == 2)) | ||
493 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); | ||
494 | else | ||
495 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); | ||
496 | tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); | ||
497 | } | ||
498 | |||
499 | static void tda8295_init_if(struct dvb_frontend *fe) | ||
500 | { | ||
501 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
502 | |||
503 | static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; | ||
504 | static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; | ||
505 | static unsigned char set_pll_reg6[] = { 0x3e, 0x63 }; | ||
506 | static unsigned char set_pll_reg0[] = { 0x38, 0x23 }; | ||
507 | static unsigned char set_pll_reg7[] = { 0x3f, 0x01 }; | ||
508 | static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; | ||
509 | static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; | ||
510 | |||
511 | tda8295_power(fe, 1); | ||
512 | |||
513 | tda8295_set_easy_mode(fe, 0); | ||
514 | tda8295_set_video_std(fe); | ||
515 | |||
516 | tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); | ||
517 | tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); | ||
518 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2); | ||
519 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2); | ||
520 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2); | ||
521 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); | ||
522 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); | ||
523 | |||
524 | tda8295_agc1_out(fe, 0); | ||
525 | tda8295_agc2_out(fe, 0); | ||
526 | } | ||
527 | |||
528 | static void tda8290_init_tuner(struct dvb_frontend *fe) | ||
529 | { | ||
530 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
531 | unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, | ||
532 | 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; | ||
533 | unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, | ||
534 | 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; | ||
535 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, | ||
536 | .buf=tda8275_init, .len = 14}; | ||
537 | if (priv->ver & TDA8275A) | ||
538 | msg.buf = tda8275a_init; | ||
539 | |||
540 | tda8290_i2c_bridge(fe, 1); | ||
541 | i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
542 | tda8290_i2c_bridge(fe, 0); | ||
543 | } | ||
544 | |||
545 | /*---------------------------------------------------------------------*/ | ||
546 | |||
547 | static void tda829x_release(struct dvb_frontend *fe) | ||
548 | { | ||
549 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
550 | |||
551 | /* only try to release the tuner if we've | ||
552 | * attached it from within this module */ | ||
553 | if (priv->ver & (TDA18271 | TDA8275 | TDA8275A)) | ||
554 | if (fe->ops.tuner_ops.release) | ||
555 | fe->ops.tuner_ops.release(fe); | ||
556 | |||
557 | kfree(fe->analog_demod_priv); | ||
558 | fe->analog_demod_priv = NULL; | ||
559 | } | ||
560 | |||
561 | static struct tda18271_config tda829x_tda18271_config = { | ||
562 | .gate = TDA18271_GATE_ANALOG, | ||
563 | }; | ||
564 | |||
565 | static int tda829x_find_tuner(struct dvb_frontend *fe) | ||
566 | { | ||
567 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
568 | struct analog_demod_ops *analog_ops = &fe->ops.analog_ops; | ||
569 | int i, ret, tuners_found; | ||
570 | u32 tuner_addrs; | ||
571 | u8 data; | ||
572 | struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; | ||
573 | |||
574 | if (!analog_ops->i2c_gate_ctrl) { | ||
575 | printk(KERN_ERR "tda8290: no gate control were provided!\n"); | ||
576 | |||
577 | return -EINVAL; | ||
578 | } | ||
579 | |||
580 | analog_ops->i2c_gate_ctrl(fe, 1); | ||
581 | |||
582 | /* probe for tuner chip */ | ||
583 | tuners_found = 0; | ||
584 | tuner_addrs = 0; | ||
585 | for (i = 0x60; i <= 0x63; i++) { | ||
586 | msg.addr = i; | ||
587 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
588 | if (ret == 1) { | ||
589 | tuners_found++; | ||
590 | tuner_addrs = (tuner_addrs << 8) + i; | ||
591 | } | ||
592 | } | ||
593 | /* if there is more than one tuner, we expect the right one is | ||
594 | behind the bridge and we choose the highest address that doesn't | ||
595 | give a response now | ||
596 | */ | ||
597 | |||
598 | analog_ops->i2c_gate_ctrl(fe, 0); | ||
599 | |||
600 | if (tuners_found > 1) | ||
601 | for (i = 0; i < tuners_found; i++) { | ||
602 | msg.addr = tuner_addrs & 0xff; | ||
603 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
604 | if (ret == 1) | ||
605 | tuner_addrs = tuner_addrs >> 8; | ||
606 | else | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | if (tuner_addrs == 0) { | ||
611 | tuner_addrs = 0x60; | ||
612 | tuner_info("could not clearly identify tuner address, " | ||
613 | "defaulting to %x\n", tuner_addrs); | ||
614 | } else { | ||
615 | tuner_addrs = tuner_addrs & 0xff; | ||
616 | tuner_info("setting tuner address to %x\n", tuner_addrs); | ||
617 | } | ||
618 | priv->tda827x_addr = tuner_addrs; | ||
619 | msg.addr = tuner_addrs; | ||
620 | |||
621 | analog_ops->i2c_gate_ctrl(fe, 1); | ||
622 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
623 | |||
624 | if (ret != 1) { | ||
625 | tuner_warn("tuner access failed!\n"); | ||
626 | analog_ops->i2c_gate_ctrl(fe, 0); | ||
627 | return -EREMOTEIO; | ||
628 | } | ||
629 | |||
630 | if ((data == 0x83) || (data == 0x84)) { | ||
631 | priv->ver |= TDA18271; | ||
632 | tda829x_tda18271_config.config = priv->cfg.config; | ||
633 | dvb_attach(tda18271_attach, fe, priv->tda827x_addr, | ||
634 | priv->i2c_props.adap, &tda829x_tda18271_config); | ||
635 | } else { | ||
636 | if ((data & 0x3c) == 0) | ||
637 | priv->ver |= TDA8275; | ||
638 | else | ||
639 | priv->ver |= TDA8275A; | ||
640 | |||
641 | dvb_attach(tda827x_attach, fe, priv->tda827x_addr, | ||
642 | priv->i2c_props.adap, &priv->cfg); | ||
643 | priv->cfg.switch_addr = priv->i2c_props.addr; | ||
644 | } | ||
645 | if (fe->ops.tuner_ops.init) | ||
646 | fe->ops.tuner_ops.init(fe); | ||
647 | |||
648 | if (fe->ops.tuner_ops.sleep) | ||
649 | fe->ops.tuner_ops.sleep(fe); | ||
650 | |||
651 | analog_ops->i2c_gate_ctrl(fe, 0); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static int tda8290_probe(struct tuner_i2c_props *i2c_props) | ||
657 | { | ||
658 | #define TDA8290_ID 0x89 | ||
659 | u8 reg = 0x1f, id; | ||
660 | struct i2c_msg msg_read[] = { | ||
661 | { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, | ||
662 | { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, | ||
663 | }; | ||
664 | |||
665 | /* detect tda8290 */ | ||
666 | if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { | ||
667 | printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", | ||
668 | __func__, reg); | ||
669 | return -ENODEV; | ||
670 | } | ||
671 | |||
672 | if (id == TDA8290_ID) { | ||
673 | if (debug) | ||
674 | printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", | ||
675 | __func__, i2c_adapter_id(i2c_props->adap), | ||
676 | i2c_props->addr); | ||
677 | return 0; | ||
678 | } | ||
679 | return -ENODEV; | ||
680 | } | ||
681 | |||
682 | static int tda8295_probe(struct tuner_i2c_props *i2c_props) | ||
683 | { | ||
684 | #define TDA8295_ID 0x8a | ||
685 | #define TDA8295C2_ID 0x8b | ||
686 | u8 reg = 0x2f, id; | ||
687 | struct i2c_msg msg_read[] = { | ||
688 | { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, | ||
689 | { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, | ||
690 | }; | ||
691 | |||
692 | /* detect tda8295 */ | ||
693 | if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { | ||
694 | printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", | ||
695 | __func__, reg); | ||
696 | return -ENODEV; | ||
697 | } | ||
698 | |||
699 | if ((id & 0xfe) == TDA8295_ID) { | ||
700 | if (debug) | ||
701 | printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", | ||
702 | __func__, (id == TDA8295_ID) ? | ||
703 | "tda8295c1" : "tda8295c2", | ||
704 | i2c_adapter_id(i2c_props->adap), | ||
705 | i2c_props->addr); | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | return -ENODEV; | ||
710 | } | ||
711 | |||
712 | static struct analog_demod_ops tda8290_ops = { | ||
713 | .set_params = tda8290_set_params, | ||
714 | .has_signal = tda8290_has_signal, | ||
715 | .standby = tda8290_standby, | ||
716 | .release = tda829x_release, | ||
717 | .i2c_gate_ctrl = tda8290_i2c_bridge, | ||
718 | }; | ||
719 | |||
720 | static struct analog_demod_ops tda8295_ops = { | ||
721 | .set_params = tda8295_set_params, | ||
722 | .has_signal = tda8295_has_signal, | ||
723 | .standby = tda8295_standby, | ||
724 | .release = tda829x_release, | ||
725 | .i2c_gate_ctrl = tda8295_i2c_bridge, | ||
726 | }; | ||
727 | |||
728 | struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | ||
729 | struct i2c_adapter *i2c_adap, u8 i2c_addr, | ||
730 | struct tda829x_config *cfg) | ||
731 | { | ||
732 | struct tda8290_priv *priv = NULL; | ||
733 | char *name; | ||
734 | |||
735 | priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); | ||
736 | if (priv == NULL) | ||
737 | return NULL; | ||
738 | fe->analog_demod_priv = priv; | ||
739 | |||
740 | priv->i2c_props.addr = i2c_addr; | ||
741 | priv->i2c_props.adap = i2c_adap; | ||
742 | priv->i2c_props.name = "tda829x"; | ||
743 | if (cfg) | ||
744 | priv->cfg.config = cfg->lna_cfg; | ||
745 | |||
746 | if (tda8290_probe(&priv->i2c_props) == 0) { | ||
747 | priv->ver = TDA8290; | ||
748 | memcpy(&fe->ops.analog_ops, &tda8290_ops, | ||
749 | sizeof(struct analog_demod_ops)); | ||
750 | } | ||
751 | |||
752 | if (tda8295_probe(&priv->i2c_props) == 0) { | ||
753 | priv->ver = TDA8295; | ||
754 | memcpy(&fe->ops.analog_ops, &tda8295_ops, | ||
755 | sizeof(struct analog_demod_ops)); | ||
756 | } | ||
757 | |||
758 | if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) { | ||
759 | tda8295_power(fe, 1); | ||
760 | if (tda829x_find_tuner(fe) < 0) | ||
761 | goto fail; | ||
762 | } | ||
763 | |||
764 | switch (priv->ver) { | ||
765 | case TDA8290: | ||
766 | name = "tda8290"; | ||
767 | break; | ||
768 | case TDA8295: | ||
769 | name = "tda8295"; | ||
770 | break; | ||
771 | case TDA8290 | TDA8275: | ||
772 | name = "tda8290+75"; | ||
773 | break; | ||
774 | case TDA8295 | TDA8275: | ||
775 | name = "tda8295+75"; | ||
776 | break; | ||
777 | case TDA8290 | TDA8275A: | ||
778 | name = "tda8290+75a"; | ||
779 | break; | ||
780 | case TDA8295 | TDA8275A: | ||
781 | name = "tda8295+75a"; | ||
782 | break; | ||
783 | case TDA8290 | TDA18271: | ||
784 | name = "tda8290+18271"; | ||
785 | break; | ||
786 | case TDA8295 | TDA18271: | ||
787 | name = "tda8295+18271"; | ||
788 | break; | ||
789 | default: | ||
790 | goto fail; | ||
791 | } | ||
792 | tuner_info("type set to %s\n", name); | ||
793 | |||
794 | fe->ops.analog_ops.info.name = name; | ||
795 | |||
796 | if (priv->ver & TDA8290) { | ||
797 | if (priv->ver & (TDA8275 | TDA8275A)) | ||
798 | tda8290_init_tuner(fe); | ||
799 | tda8290_init_if(fe); | ||
800 | } else if (priv->ver & TDA8295) | ||
801 | tda8295_init_if(fe); | ||
802 | |||
803 | return fe; | ||
804 | |||
805 | fail: | ||
806 | memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops)); | ||
807 | |||
808 | tda829x_release(fe); | ||
809 | return NULL; | ||
810 | } | ||
811 | EXPORT_SYMBOL_GPL(tda829x_attach); | ||
812 | |||
813 | int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
814 | { | ||
815 | struct tuner_i2c_props i2c_props = { | ||
816 | .adap = i2c_adap, | ||
817 | .addr = i2c_addr, | ||
818 | }; | ||
819 | |||
820 | unsigned char soft_reset[] = { 0x00, 0x00 }; | ||
821 | unsigned char easy_mode_b[] = { 0x01, 0x02 }; | ||
822 | unsigned char easy_mode_g[] = { 0x01, 0x04 }; | ||
823 | unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; | ||
824 | unsigned char addr_dto_lsb = 0x07; | ||
825 | unsigned char data; | ||
826 | #define PROBE_BUFFER_SIZE 8 | ||
827 | unsigned char buf[PROBE_BUFFER_SIZE]; | ||
828 | int i; | ||
829 | |||
830 | /* rule out tda9887, which would return the same byte repeatedly */ | ||
831 | tuner_i2c_xfer_send_recv(&i2c_props, | ||
832 | soft_reset, 1, buf, PROBE_BUFFER_SIZE); | ||
833 | for (i = 1; i < PROBE_BUFFER_SIZE; i++) { | ||
834 | if (buf[i] != buf[0]) | ||
835 | break; | ||
836 | } | ||
837 | |||
838 | /* all bytes are equal, not a tda829x - probably a tda9887 */ | ||
839 | if (i == PROBE_BUFFER_SIZE) | ||
840 | return -ENODEV; | ||
841 | |||
842 | if ((tda8290_probe(&i2c_props) == 0) || | ||
843 | (tda8295_probe(&i2c_props) == 0)) | ||
844 | return 0; | ||
845 | |||
846 | /* fall back to old probing method */ | ||
847 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); | ||
848 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | ||
849 | tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1); | ||
850 | if (data == 0) { | ||
851 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); | ||
852 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | ||
853 | tuner_i2c_xfer_send_recv(&i2c_props, | ||
854 | &addr_dto_lsb, 1, &data, 1); | ||
855 | if (data == 0x7b) { | ||
856 | return 0; | ||
857 | } | ||
858 | } | ||
859 | tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); | ||
860 | return -ENODEV; | ||
861 | } | ||
862 | EXPORT_SYMBOL_GPL(tda829x_probe); | ||
863 | |||
864 | MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); | ||
865 | MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); | ||
866 | MODULE_LICENSE("GPL"); | ||
867 | |||
868 | /* | ||
869 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
870 | * --------------------------------------------------------------------------- | ||
871 | * Local variables: | ||
872 | * c-basic-offset: 8 | ||
873 | * End: | ||
874 | */ | ||