V4L/DVB (6786): tuner: add struct analog_demod_info to struct analog_tuner_ops
[linux-2.6-block.git] / drivers / media / video / tda9887.c
CommitLineData
1da177e4 1#include <linux/module.h>
1da177e4
LT
2#include <linux/kernel.h>
3#include <linux/i2c.h>
4#include <linux/types.h>
1da177e4
LT
5#include <linux/init.h>
6#include <linux/errno.h>
7#include <linux/slab.h>
8#include <linux/delay.h>
ffbb807c 9#include <linux/videodev.h>
5e453dc7 10#include <media/v4l2-common.h>
1da177e4 11#include <media/tuner.h>
ab166050 12#include "tuner-i2c.h"
31c9584c 13#include "tda9887.h"
1da177e4 14
674434c6 15
1da177e4
LT
16/* Chips:
17 TDA9885 (PAL, NTSC)
18 TDA9886 (PAL, SECAM, NTSC)
19 TDA9887 (PAL, SECAM, NTSC, FM Radio)
20
15396236 21 Used as part of several tuners
1da177e4
LT
22*/
23
31c9584c
MK
24static int tda9887_debug;
25module_param_named(debug, tda9887_debug, int, 0644);
26
15396236 27#define tda9887_info(fmt, arg...) do {\
1cba97d7
HV
28 printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \
29 i2c_adapter_id(priv->t->i2c->adapter), \
30 priv->t->i2c->addr, ##arg); } while (0)
15396236 31#define tda9887_dbg(fmt, arg...) do {\
31c9584c 32 if (tda9887_debug) \
1cba97d7
HV
33 printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \
34 i2c_adapter_id(priv->t->i2c->adapter), \
35 priv->t->i2c->addr, ##arg); } while (0)
1da177e4 36
b2083199 37struct tda9887_priv {
db8a6956
MK
38 struct tuner_i2c_props i2c_props;
39
b2083199 40 unsigned char data[4];
4e9154b8
MK
41
42 struct tuner *t;
b2083199 43};
1da177e4
LT
44
45/* ---------------------------------------------------------------------- */
46
47#define UNSET (-1U)
1da177e4
LT
48
49struct tvnorm {
50 v4l2_std_id std;
51 char *name;
52 unsigned char b;
53 unsigned char c;
54 unsigned char e;
55};
56
1da177e4
LT
57/* ---------------------------------------------------------------------- */
58
59//
60// TDA defines
61//
62
63//// first reg (b)
64#define cVideoTrapBypassOFF 0x00 // bit b0
65#define cVideoTrapBypassON 0x01 // bit b0
66
67#define cAutoMuteFmInactive 0x00 // bit b1
68#define cAutoMuteFmActive 0x02 // bit b1
69
70#define cIntercarrier 0x00 // bit b2
71#define cQSS 0x04 // bit b2
72
73#define cPositiveAmTV 0x00 // bit b3:4
74#define cFmRadio 0x08 // bit b3:4
75#define cNegativeFmTV 0x10 // bit b3:4
76
77
78#define cForcedMuteAudioON 0x20 // bit b5
79#define cForcedMuteAudioOFF 0x00 // bit b5
80
81#define cOutputPort1Active 0x00 // bit b6
82#define cOutputPort1Inactive 0x40 // bit b6
83
84#define cOutputPort2Active 0x00 // bit b7
85#define cOutputPort2Inactive 0x80 // bit b7
86
87
88//// second reg (c)
89#define cDeemphasisOFF 0x00 // bit c5
90#define cDeemphasisON 0x20 // bit c5
91
92#define cDeemphasis75 0x00 // bit c6
93#define cDeemphasis50 0x40 // bit c6
94
95#define cAudioGain0 0x00 // bit c7
96#define cAudioGain6 0x80 // bit c7
97
f98c55ea 98#define cTopMask 0x1f // bit c0:4
f5b0142a 99#define cTopDefault 0x10 // bit c0:4
1da177e4
LT
100
101//// third reg (e)
102#define cAudioIF_4_5 0x00 // bit e0:1
103#define cAudioIF_5_5 0x01 // bit e0:1
104#define cAudioIF_6_0 0x02 // bit e0:1
105#define cAudioIF_6_5 0x03 // bit e0:1
106
107
5e082f15
TP
108#define cVideoIFMask 0x1c // bit e2:4
109/* Video IF selection in TV Mode (bit B3=0) */
1da177e4
LT
110#define cVideoIF_58_75 0x00 // bit e2:4
111#define cVideoIF_45_75 0x04 // bit e2:4
112#define cVideoIF_38_90 0x08 // bit e2:4
113#define cVideoIF_38_00 0x0C // bit e2:4
114#define cVideoIF_33_90 0x10 // bit e2:4
115#define cVideoIF_33_40 0x14 // bit e2:4
116#define cRadioIF_45_75 0x18 // bit e2:4
117#define cRadioIF_38_90 0x1C // bit e2:4
118
5e082f15
TP
119/* IF1 selection in Radio Mode (bit B3=1) */
120#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
121#define cRadioIF_41_30 0x04 // bit e2,4
122
123/* Output of AFC pin in radio mode when bit E7=1 */
124#define cRadioAGC_SIF 0x00 // bit e3
125#define cRadioAGC_FM 0x08 // bit e3
1da177e4
LT
126
127#define cTunerGainNormal 0x00 // bit e5
128#define cTunerGainLow 0x20 // bit e5
129
130#define cGating_18 0x00 // bit e6
131#define cGating_36 0x40 // bit e6
132
133#define cAgcOutON 0x80 // bit e7
134#define cAgcOutOFF 0x00 // bit e7
135
136/* ---------------------------------------------------------------------- */
137
138static struct tvnorm tvnorms[] = {
139 {
f98c55ea
HV
140 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
141 .name = "PAL-BGHN",
1da177e4
LT
142 .b = ( cNegativeFmTV |
143 cQSS ),
144 .c = ( cDeemphasisON |
f98c55ea 145 cDeemphasis50 |
f5b0142a 146 cTopDefault),
f98c55ea
HV
147 .e = ( cGating_36 |
148 cAudioIF_5_5 |
1da177e4
LT
149 cVideoIF_38_90 ),
150 },{
151 .std = V4L2_STD_PAL_I,
152 .name = "PAL-I",
153 .b = ( cNegativeFmTV |
154 cQSS ),
155 .c = ( cDeemphasisON |
f98c55ea 156 cDeemphasis50 |
f5b0142a 157 cTopDefault),
f98c55ea
HV
158 .e = ( cGating_36 |
159 cAudioIF_6_0 |
1da177e4
LT
160 cVideoIF_38_90 ),
161 },{
162 .std = V4L2_STD_PAL_DK,
163 .name = "PAL-DK",
164 .b = ( cNegativeFmTV |
165 cQSS ),
166 .c = ( cDeemphasisON |
f98c55ea 167 cDeemphasis50 |
f5b0142a 168 cTopDefault),
f98c55ea
HV
169 .e = ( cGating_36 |
170 cAudioIF_6_5 |
171 cVideoIF_38_90 ),
1da177e4 172 },{
f98c55ea
HV
173 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
174 .name = "PAL-M/Nc",
1da177e4
LT
175 .b = ( cNegativeFmTV |
176 cQSS ),
177 .c = ( cDeemphasisON |
f98c55ea 178 cDeemphasis75 |
f5b0142a 179 cTopDefault),
f98c55ea
HV
180 .e = ( cGating_36 |
181 cAudioIF_4_5 |
1da177e4 182 cVideoIF_45_75 ),
f98c55ea
HV
183 },{
184 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
185 .name = "SECAM-BGH",
186 .b = ( cPositiveAmTV |
187 cQSS ),
f5b0142a 188 .c = ( cTopDefault),
f98c55ea
HV
189 .e = ( cGating_36 |
190 cAudioIF_5_5 |
191 cVideoIF_38_90 ),
1da177e4
LT
192 },{
193 .std = V4L2_STD_SECAM_L,
194 .name = "SECAM-L",
195 .b = ( cPositiveAmTV |
196 cQSS ),
f5b0142a 197 .c = ( cTopDefault),
3375c398 198 .e = ( cGating_36 |
5f7591c0 199 cAudioIF_6_5 |
1da177e4 200 cVideoIF_38_90 ),
f3c5987a
MCC
201 },{
202 .std = V4L2_STD_SECAM_LC,
203 .name = "SECAM-L'",
204 .b = ( cOutputPort2Inactive |
205 cPositiveAmTV |
206 cQSS ),
f5b0142a 207 .c = ( cTopDefault),
f3c5987a
MCC
208 .e = ( cGating_36 |
209 cAudioIF_6_5 |
210 cVideoIF_33_90 ),
1da177e4
LT
211 },{
212 .std = V4L2_STD_SECAM_DK,
213 .name = "SECAM-DK",
214 .b = ( cNegativeFmTV |
215 cQSS ),
216 .c = ( cDeemphasisON |
f98c55ea 217 cDeemphasis50 |
f5b0142a 218 cTopDefault),
f98c55ea
HV
219 .e = ( cGating_36 |
220 cAudioIF_6_5 |
221 cVideoIF_38_90 ),
1da177e4 222 },{
0dfd812d 223 .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
1da177e4
LT
224 .name = "NTSC-M",
225 .b = ( cNegativeFmTV |
226 cQSS ),
227 .c = ( cDeemphasisON |
f98c55ea 228 cDeemphasis75 |
f5b0142a 229 cTopDefault),
1da177e4
LT
230 .e = ( cGating_36 |
231 cAudioIF_4_5 |
232 cVideoIF_45_75 ),
233 },{
234 .std = V4L2_STD_NTSC_M_JP,
f98c55ea 235 .name = "NTSC-M-JP",
1da177e4
LT
236 .b = ( cNegativeFmTV |
237 cQSS ),
238 .c = ( cDeemphasisON |
f98c55ea 239 cDeemphasis50 |
f5b0142a 240 cTopDefault),
1da177e4
LT
241 .e = ( cGating_36 |
242 cAudioIF_4_5 |
243 cVideoIF_58_75 ),
244 }
245};
246
56fc08ca
MCC
247static struct tvnorm radio_stereo = {
248 .name = "Radio Stereo",
249 .b = ( cFmRadio |
250 cQSS ),
251 .c = ( cDeemphasisOFF |
f98c55ea 252 cAudioGain6 |
f5b0142a 253 cTopDefault),
f98c55ea
HV
254 .e = ( cTunerGainLow |
255 cAudioIF_5_5 |
56fc08ca
MCC
256 cRadioIF_38_90 ),
257};
258
259static struct tvnorm radio_mono = {
260 .name = "Radio Mono",
1da177e4
LT
261 .b = ( cFmRadio |
262 cQSS ),
263 .c = ( cDeemphasisON |
f98c55ea 264 cDeemphasis75 |
f5b0142a 265 cTopDefault),
f98c55ea
HV
266 .e = ( cTunerGainLow |
267 cAudioIF_5_5 |
1da177e4
LT
268 cRadioIF_38_90 ),
269};
270
271/* ---------------------------------------------------------------------- */
272
4e9154b8 273static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
1da177e4 274{
4e9154b8
MK
275 struct tda9887_priv *priv = fe->analog_demod_priv;
276
1da177e4
LT
277 static char *afc[16] = {
278 "- 12.5 kHz",
279 "- 37.5 kHz",
280 "- 62.5 kHz",
281 "- 87.5 kHz",
282 "-112.5 kHz",
283 "-137.5 kHz",
284 "-162.5 kHz",
285 "-187.5 kHz [min]",
286 "+187.5 kHz [max]",
287 "+162.5 kHz",
288 "+137.5 kHz",
289 "+112.5 kHz",
290 "+ 87.5 kHz",
291 "+ 62.5 kHz",
292 "+ 37.5 kHz",
293 "+ 12.5 kHz",
294 };
4eb0c144
HV
295 tda9887_info("read: 0x%2x\n", buf[0]);
296 tda9887_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
297 tda9887_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
298 tda9887_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
299 tda9887_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
300 tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
1da177e4
LT
301}
302
4e9154b8 303static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
1da177e4 304{
4e9154b8
MK
305 struct tda9887_priv *priv = fe->analog_demod_priv;
306
1da177e4
LT
307 static char *sound[4] = {
308 "AM/TV",
309 "FM/radio",
310 "FM/TV",
311 "FM/radio"
312 };
313 static char *adjust[32] = {
314 "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
315 "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
316 "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
317 "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
318 };
319 static char *deemph[4] = {
320 "no", "no", "75", "50"
321 };
322 static char *carrier[4] = {
323 "4.5 MHz",
324 "5.5 MHz",
325 "6.0 MHz",
326 "6.5 MHz / AM"
327 };
328 static char *vif[8] = {
329 "58.75 MHz",
330 "45.75 MHz",
331 "38.9 MHz",
332 "38.0 MHz",
333 "33.9 MHz",
334 "33.4 MHz",
335 "45.75 MHz + pin13",
336 "38.9 MHz + pin13",
337 };
338 static char *rif[4] = {
339 "44 MHz",
340 "52 MHz",
341 "52 MHz",
342 "44 MHz",
343 };
344
4eb0c144
HV
345 tda9887_info("write: byte B 0x%02x\n",buf[1]);
346 tda9887_info(" B0 video mode : %s\n",
1da177e4 347 (buf[1] & 0x01) ? "video trap" : "sound trap");
4eb0c144 348 tda9887_info(" B1 auto mute fm : %s\n",
1da177e4 349 (buf[1] & 0x02) ? "yes" : "no");
4eb0c144 350 tda9887_info(" B2 carrier mode : %s\n",
1da177e4 351 (buf[1] & 0x04) ? "QSS" : "Intercarrier");
4eb0c144 352 tda9887_info(" B3-4 tv sound/radio : %s\n",
1da177e4 353 sound[(buf[1] & 0x18) >> 3]);
4eb0c144 354 tda9887_info(" B5 force mute audio: %s\n",
1da177e4 355 (buf[1] & 0x20) ? "yes" : "no");
4eb0c144 356 tda9887_info(" B6 output port 1 : %s\n",
1da177e4 357 (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
4eb0c144 358 tda9887_info(" B7 output port 2 : %s\n",
1da177e4
LT
359 (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
360
4eb0c144
HV
361 tda9887_info("write: byte C 0x%02x\n",buf[2]);
362 tda9887_info(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]);
363 tda9887_info(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]);
364 tda9887_info(" C7 audio gain : %s\n",
1da177e4
LT
365 (buf[2] & 0x80) ? "-6" : "0");
366
4eb0c144
HV
367 tda9887_info("write: byte E 0x%02x\n",buf[3]);
368 tda9887_info(" E0-1 sound carrier : %s\n",
1da177e4 369 carrier[(buf[3] & 0x03)]);
4eb0c144 370 tda9887_info(" E6 l pll gating : %s\n",
1da177e4
LT
371 (buf[3] & 0x40) ? "36" : "13");
372
373 if (buf[1] & 0x08) {
374 /* radio */
4eb0c144 375 tda9887_info(" E2-4 video if : %s\n",
1da177e4 376 rif[(buf[3] & 0x0c) >> 2]);
4eb0c144 377 tda9887_info(" E7 vif agc output : %s\n",
1da177e4
LT
378 (buf[3] & 0x80)
379 ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio")
380 : "fm radio carrier afc");
381 } else {
382 /* video */
4eb0c144 383 tda9887_info(" E2-4 video if : %s\n",
1da177e4 384 vif[(buf[3] & 0x1c) >> 2]);
4eb0c144 385 tda9887_info(" E5 tuner gain : %s\n",
1da177e4
LT
386 (buf[3] & 0x80)
387 ? ((buf[3] & 0x20) ? "external" : "normal")
388 : ((buf[3] & 0x20) ? "minimum" : "normal"));
4eb0c144 389 tda9887_info(" E7 vif agc output : %s\n",
1da177e4
LT
390 (buf[3] & 0x80)
391 ? ((buf[3] & 0x20)
392 ? "pin3 port, pin22 vif agc out"
393 : "pin22 port, pin3 vif acg ext in")
394 : "pin3+pin22 port");
395 }
4eb0c144 396 tda9887_info("--\n");
1da177e4
LT
397}
398
399/* ---------------------------------------------------------------------- */
400
4e9154b8 401static int tda9887_set_tvnorm(struct dvb_frontend *fe)
1da177e4 402{
4e9154b8
MK
403 struct tda9887_priv *priv = fe->analog_demod_priv;
404 struct tuner *t = priv->t;
1da177e4 405 struct tvnorm *norm = NULL;
4e9154b8 406 char *buf = priv->data;
1da177e4
LT
407 int i;
408
15396236
MCC
409 if (t->mode == V4L2_TUNER_RADIO) {
410 if (t->audmode == V4L2_TUNER_MODE_MONO)
56fc08ca
MCC
411 norm = &radio_mono;
412 else
586b0cab 413 norm = &radio_stereo;
1da177e4
LT
414 } else {
415 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
416 if (tvnorms[i].std & t->std) {
417 norm = tvnorms+i;
418 break;
419 }
420 }
421 }
422 if (NULL == norm) {
4eb0c144 423 tda9887_dbg("Unsupported tvnorm entry - audio muted\n");
1da177e4
LT
424 return -1;
425 }
426
4eb0c144 427 tda9887_dbg("configure for: %s\n",norm->name);
1da177e4
LT
428 buf[1] = norm->b;
429 buf[2] = norm->c;
430 buf[3] = norm->e;
431 return 0;
432}
433
434static unsigned int port1 = UNSET;
435static unsigned int port2 = UNSET;
436static unsigned int qss = UNSET;
f98c55ea
HV
437static unsigned int adjust = UNSET;
438
1da177e4
LT
439module_param(port1, int, 0644);
440module_param(port2, int, 0644);
441module_param(qss, int, 0644);
442module_param(adjust, int, 0644);
443
4e9154b8 444static int tda9887_set_insmod(struct dvb_frontend *fe)
1da177e4 445{
4e9154b8
MK
446 struct tda9887_priv *priv = fe->analog_demod_priv;
447 char *buf = priv->data;
448
1da177e4
LT
449 if (UNSET != port1) {
450 if (port1)
451 buf[1] |= cOutputPort1Inactive;
452 else
453 buf[1] &= ~cOutputPort1Inactive;
454 }
455 if (UNSET != port2) {
456 if (port2)
457 buf[1] |= cOutputPort2Inactive;
458 else
459 buf[1] &= ~cOutputPort2Inactive;
460 }
461
462 if (UNSET != qss) {
463 if (qss)
464 buf[1] |= cQSS;
465 else
466 buf[1] &= ~cQSS;
467 }
468
f98c55ea
HV
469 if (adjust >= 0x00 && adjust < 0x20) {
470 buf[2] &= ~cTopMask;
1da177e4 471 buf[2] |= adjust;
f98c55ea 472 }
1da177e4
LT
473 return 0;
474}
475
4e9154b8 476static int tda9887_set_config(struct dvb_frontend *fe)
1da177e4 477{
4e9154b8
MK
478 struct tda9887_priv *priv = fe->analog_demod_priv;
479 struct tuner *t = priv->t;
480 char *buf = priv->data;
481
15396236 482 if (t->tda9887_config & TDA9887_PORT1_ACTIVE)
1da177e4 483 buf[1] &= ~cOutputPort1Inactive;
15396236 484 if (t->tda9887_config & TDA9887_PORT1_INACTIVE)
1da177e4 485 buf[1] |= cOutputPort1Inactive;
15396236 486 if (t->tda9887_config & TDA9887_PORT2_ACTIVE)
1da177e4 487 buf[1] &= ~cOutputPort2Inactive;
15396236 488 if (t->tda9887_config & TDA9887_PORT2_INACTIVE)
1da177e4
LT
489 buf[1] |= cOutputPort2Inactive;
490
15396236 491 if (t->tda9887_config & TDA9887_QSS)
1da177e4 492 buf[1] |= cQSS;
15396236 493 if (t->tda9887_config & TDA9887_INTERCARRIER)
1da177e4
LT
494 buf[1] &= ~cQSS;
495
15396236 496 if (t->tda9887_config & TDA9887_AUTOMUTE)
1da177e4 497 buf[1] |= cAutoMuteFmActive;
15396236 498 if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
1da177e4 499 buf[2] &= ~0x60;
15396236 500 switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
1da177e4
LT
501 case TDA9887_DEEMPHASIS_NONE:
502 buf[2] |= cDeemphasisOFF;
503 break;
504 case TDA9887_DEEMPHASIS_50:
505 buf[2] |= cDeemphasisON | cDeemphasis50;
506 break;
507 case TDA9887_DEEMPHASIS_75:
508 buf[2] |= cDeemphasisON | cDeemphasis75;
509 break;
510 }
511 }
15396236 512 if (t->tda9887_config & TDA9887_TOP_SET) {
f98c55ea 513 buf[2] &= ~cTopMask;
15396236 514 buf[2] |= (t->tda9887_config >> 8) & cTopMask;
f98c55ea 515 }
15396236 516 if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
3ae1adc6 517 buf[1] &= ~cQSS;
d7304dee
TP
518 if (t->tda9887_config & TDA9887_GATING_18)
519 buf[3] &= ~cGating_36;
cefccc80 520
5e082f15
TP
521 if (t->mode == V4L2_TUNER_RADIO) {
522 if (t->tda9887_config & TDA9887_RIF_41_3) {
523 buf[3] &= ~cVideoIFMask;
524 buf[3] |= cRadioIF_41_30;
525 }
526 if (t->tda9887_config & TDA9887_GAIN_NORMAL)
527 buf[3] &= ~cTunerGainLow;
cefccc80
MCC
528 }
529
1da177e4
LT
530 return 0;
531}
532
533/* ---------------------------------------------------------------------- */
534
4e9154b8 535static int tda9887_status(struct dvb_frontend *fe)
1da177e4 536{
4e9154b8 537 struct tda9887_priv *priv = fe->analog_demod_priv;
1da177e4
LT
538 unsigned char buf[1];
539 int rc;
540
541 memset(buf,0,sizeof(buf));
db8a6956 542 if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
4ac97914 543 tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc);
4e9154b8 544 dump_read_message(fe, buf);
1da177e4
LT
545 return 0;
546}
547
4e9154b8 548static void tda9887_configure(struct dvb_frontend *fe)
1da177e4 549{
4e9154b8
MK
550 struct tda9887_priv *priv = fe->analog_demod_priv;
551 struct tuner *t = priv->t;
1da177e4
LT
552 int rc;
553
b2083199 554 memset(priv->data,0,sizeof(priv->data));
4e9154b8 555 tda9887_set_tvnorm(fe);
56fc08ca 556
f98c55ea
HV
557 /* A note on the port settings:
558 These settings tend to depend on the specifics of the board.
559 By default they are set to inactive (bit value 1) by this driver,
560 overwriting any changes made by the tvnorm. This means that it
561 is the responsibility of the module using the tda9887 to set
562 these values in case of changes in the tvnorm.
563 In many cases port 2 should be made active (0) when selecting
564 SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
565
566 For the other standards the tda9887 application note says that
567 the ports should be set to active (0), but, again, that may
568 differ depending on the precise hardware configuration.
569 */
b2083199
MK
570 priv->data[1] |= cOutputPort1Inactive;
571 priv->data[1] |= cOutputPort2Inactive;
56fc08ca 572
4e9154b8
MK
573 tda9887_set_config(fe);
574 tda9887_set_insmod(fe);
1da177e4 575
793cf9e6 576 if (t->mode == T_STANDBY) {
b2083199 577 priv->data[1] |= cForcedMuteAudioON;
793cf9e6
MCC
578 }
579
4eb0c144 580 tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
b2083199 581 priv->data[1],priv->data[2],priv->data[3]);
31c9584c 582 if (tda9887_debug > 1)
4e9154b8 583 dump_write_message(fe, priv->data);
1da177e4 584
db8a6956 585 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
4ac97914 586 tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc);
1da177e4 587
31c9584c 588 if (tda9887_debug > 2) {
1da177e4 589 msleep_interruptible(1000);
4e9154b8 590 tda9887_status(fe);
1da177e4 591 }
1da177e4
LT
592}
593
594/* ---------------------------------------------------------------------- */
595
4e9154b8 596static void tda9887_tuner_status(struct dvb_frontend *fe)
1da177e4 597{
4e9154b8 598 struct tda9887_priv *priv = fe->analog_demod_priv;
31c9584c
MK
599 tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
600 priv->data[1], priv->data[2], priv->data[3]);
1da177e4
LT
601}
602
4e9154b8 603static int tda9887_get_afc(struct dvb_frontend *fe)
1da177e4 604{
4e9154b8 605 struct tda9887_priv *priv = fe->analog_demod_priv;
15396236
MCC
606 static int AFC_BITS_2_kHz[] = {
607 -12500, -37500, -62500, -97500,
608 -112500, -137500, -162500, -187500,
609 187500, 162500, 137500, 112500,
610 97500 , 62500, 37500 , 12500
611 };
612 int afc=0;
613 __u8 reg = 0;
1da177e4 614
db8a6956 615 if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
15396236 616 afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
1da177e4 617
15396236 618 return afc;
1da177e4
LT
619}
620
4e9154b8 621static void tda9887_standby(struct dvb_frontend *fe)
1da177e4 622{
4e9154b8 623 tda9887_configure(fe);
1da177e4
LT
624}
625
c7919d52
MK
626static void tda9887_set_params(struct dvb_frontend *fe,
627 struct analog_parameters *params)
1da177e4 628{
4e9154b8 629 tda9887_configure(fe);
1da177e4
LT
630}
631
4e9154b8 632static void tda9887_release(struct dvb_frontend *fe)
024cf530 633{
4e9154b8
MK
634 kfree(fe->analog_demod_priv);
635 fe->analog_demod_priv = NULL;
024cf530
MK
636}
637
1dde7a4f 638static struct analog_tuner_ops tda9887_tuner_ops = {
a55db8cd
MK
639 .info = {
640 .name = "TDA9887",
641 },
c7919d52 642 .set_params = tda9887_set_params,
9af596eb
MK
643 .standby = tda9887_standby,
644 .tuner_status = tda9887_tuner_status,
645 .get_afc = tda9887_get_afc,
646 .release = tda9887_release,
647};
648
31c9584c 649int tda9887_attach(struct tuner *t)
1da177e4 650{
b2083199 651 struct tda9887_priv *priv = NULL;
1da177e4 652
b2083199
MK
653 priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
654 if (priv == NULL)
655 return -ENOMEM;
16f29168 656 t->fe.analog_demod_priv = priv;
b2083199 657
1cba97d7
HV
658 priv->i2c_props.addr = t->i2c->addr;
659 priv->i2c_props.adap = t->i2c->adapter;
4e9154b8 660 priv->t = t;
db8a6956 661
1cba97d7 662 strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name));
1da177e4 663
1cba97d7
HV
664 tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c->addr,
665 t->i2c->driver->driver.name);
1da177e4 666
1dde7a4f 667 t->fe.ops.analog_demod_ops = &tda9887_tuner_ops;
1da177e4 668
15396236 669 return 0;
1da177e4 670}
31c9584c 671EXPORT_SYMBOL_GPL(tda9887_attach);
1da177e4 672
5ef4730d
MK
673MODULE_LICENSE("GPL");
674
1da177e4
LT
675/*
676 * Overrides for Emacs so that we follow Linus's tabbing style.
677 * ---------------------------------------------------------------------------
678 * Local variables:
679 * c-basic-offset: 8
680 * End:
681 */