V4L/DVB (5756): Tda9887: store tuning operations in tuner_operations structure
[linux-2.6/verdex.git] / drivers / media / video / tda9887.c
blobcaca1092790ec61a04f02206415f18c06eaff32d
1 #include <linux/module.h>
2 #include <linux/moduleparam.h>
3 #include <linux/kernel.h>
4 #include <linux/i2c.h>
5 #include <linux/types.h>
6 #include <linux/videodev.h>
7 #include <linux/init.h>
8 #include <linux/errno.h>
9 #include <linux/slab.h>
10 #include <linux/delay.h>
12 #include <media/v4l2-common.h>
13 #include <media/tuner.h>
16 /* Chips:
17 TDA9885 (PAL, NTSC)
18 TDA9886 (PAL, SECAM, NTSC)
19 TDA9887 (PAL, SECAM, NTSC, FM Radio)
21 Used as part of several tuners
24 #define tda9887_info(fmt, arg...) do {\
25 printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \
26 i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
27 #define tda9887_dbg(fmt, arg...) do {\
28 if (tuner_debug) \
29 printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \
30 i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
32 struct tda9887_priv {
33 unsigned char data[4];
36 /* ---------------------------------------------------------------------- */
38 #define UNSET (-1U)
40 struct tvnorm {
41 v4l2_std_id std;
42 char *name;
43 unsigned char b;
44 unsigned char c;
45 unsigned char e;
48 /* ---------------------------------------------------------------------- */
51 // TDA defines
54 //// first reg (b)
55 #define cVideoTrapBypassOFF 0x00 // bit b0
56 #define cVideoTrapBypassON 0x01 // bit b0
58 #define cAutoMuteFmInactive 0x00 // bit b1
59 #define cAutoMuteFmActive 0x02 // bit b1
61 #define cIntercarrier 0x00 // bit b2
62 #define cQSS 0x04 // bit b2
64 #define cPositiveAmTV 0x00 // bit b3:4
65 #define cFmRadio 0x08 // bit b3:4
66 #define cNegativeFmTV 0x10 // bit b3:4
69 #define cForcedMuteAudioON 0x20 // bit b5
70 #define cForcedMuteAudioOFF 0x00 // bit b5
72 #define cOutputPort1Active 0x00 // bit b6
73 #define cOutputPort1Inactive 0x40 // bit b6
75 #define cOutputPort2Active 0x00 // bit b7
76 #define cOutputPort2Inactive 0x80 // bit b7
79 //// second reg (c)
80 #define cDeemphasisOFF 0x00 // bit c5
81 #define cDeemphasisON 0x20 // bit c5
83 #define cDeemphasis75 0x00 // bit c6
84 #define cDeemphasis50 0x40 // bit c6
86 #define cAudioGain0 0x00 // bit c7
87 #define cAudioGain6 0x80 // bit c7
89 #define cTopMask 0x1f // bit c0:4
90 #define cTopDefault 0x10 // bit c0:4
92 //// third reg (e)
93 #define cAudioIF_4_5 0x00 // bit e0:1
94 #define cAudioIF_5_5 0x01 // bit e0:1
95 #define cAudioIF_6_0 0x02 // bit e0:1
96 #define cAudioIF_6_5 0x03 // bit e0:1
99 #define cVideoIF_58_75 0x00 // bit e2:4
100 #define cVideoIF_45_75 0x04 // bit e2:4
101 #define cVideoIF_38_90 0x08 // bit e2:4
102 #define cVideoIF_38_00 0x0C // bit e2:4
103 #define cVideoIF_33_90 0x10 // bit e2:4
104 #define cVideoIF_33_40 0x14 // bit e2:4
105 #define cRadioIF_45_75 0x18 // bit e2:4
106 #define cRadioIF_38_90 0x1C // bit e2:4
109 #define cTunerGainNormal 0x00 // bit e5
110 #define cTunerGainLow 0x20 // bit e5
112 #define cGating_18 0x00 // bit e6
113 #define cGating_36 0x40 // bit e6
115 #define cAgcOutON 0x80 // bit e7
116 #define cAgcOutOFF 0x00 // bit e7
118 /* ---------------------------------------------------------------------- */
120 static struct tvnorm tvnorms[] = {
122 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
123 .name = "PAL-BGHN",
124 .b = ( cNegativeFmTV |
125 cQSS ),
126 .c = ( cDeemphasisON |
127 cDeemphasis50 |
128 cTopDefault),
129 .e = ( cGating_36 |
130 cAudioIF_5_5 |
131 cVideoIF_38_90 ),
133 .std = V4L2_STD_PAL_I,
134 .name = "PAL-I",
135 .b = ( cNegativeFmTV |
136 cQSS ),
137 .c = ( cDeemphasisON |
138 cDeemphasis50 |
139 cTopDefault),
140 .e = ( cGating_36 |
141 cAudioIF_6_0 |
142 cVideoIF_38_90 ),
144 .std = V4L2_STD_PAL_DK,
145 .name = "PAL-DK",
146 .b = ( cNegativeFmTV |
147 cQSS ),
148 .c = ( cDeemphasisON |
149 cDeemphasis50 |
150 cTopDefault),
151 .e = ( cGating_36 |
152 cAudioIF_6_5 |
153 cVideoIF_38_90 ),
155 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
156 .name = "PAL-M/Nc",
157 .b = ( cNegativeFmTV |
158 cQSS ),
159 .c = ( cDeemphasisON |
160 cDeemphasis75 |
161 cTopDefault),
162 .e = ( cGating_36 |
163 cAudioIF_4_5 |
164 cVideoIF_45_75 ),
166 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
167 .name = "SECAM-BGH",
168 .b = ( cPositiveAmTV |
169 cQSS ),
170 .c = ( cTopDefault),
171 .e = ( cGating_36 |
172 cAudioIF_5_5 |
173 cVideoIF_38_90 ),
175 .std = V4L2_STD_SECAM_L,
176 .name = "SECAM-L",
177 .b = ( cPositiveAmTV |
178 cQSS ),
179 .c = ( cTopDefault),
180 .e = ( cGating_36 |
181 cAudioIF_6_5 |
182 cVideoIF_38_90 ),
184 .std = V4L2_STD_SECAM_LC,
185 .name = "SECAM-L'",
186 .b = ( cOutputPort2Inactive |
187 cPositiveAmTV |
188 cQSS ),
189 .c = ( cTopDefault),
190 .e = ( cGating_36 |
191 cAudioIF_6_5 |
192 cVideoIF_33_90 ),
194 .std = V4L2_STD_SECAM_DK,
195 .name = "SECAM-DK",
196 .b = ( cNegativeFmTV |
197 cQSS ),
198 .c = ( cDeemphasisON |
199 cDeemphasis50 |
200 cTopDefault),
201 .e = ( cGating_36 |
202 cAudioIF_6_5 |
203 cVideoIF_38_90 ),
205 .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
206 .name = "NTSC-M",
207 .b = ( cNegativeFmTV |
208 cQSS ),
209 .c = ( cDeemphasisON |
210 cDeemphasis75 |
211 cTopDefault),
212 .e = ( cGating_36 |
213 cAudioIF_4_5 |
214 cVideoIF_45_75 ),
216 .std = V4L2_STD_NTSC_M_JP,
217 .name = "NTSC-M-JP",
218 .b = ( cNegativeFmTV |
219 cQSS ),
220 .c = ( cDeemphasisON |
221 cDeemphasis50 |
222 cTopDefault),
223 .e = ( cGating_36 |
224 cAudioIF_4_5 |
225 cVideoIF_58_75 ),
229 static struct tvnorm radio_stereo = {
230 .name = "Radio Stereo",
231 .b = ( cFmRadio |
232 cQSS ),
233 .c = ( cDeemphasisOFF |
234 cAudioGain6 |
235 cTopDefault),
236 .e = ( cTunerGainLow |
237 cAudioIF_5_5 |
238 cRadioIF_38_90 ),
241 static struct tvnorm radio_mono = {
242 .name = "Radio Mono",
243 .b = ( cFmRadio |
244 cQSS ),
245 .c = ( cDeemphasisON |
246 cDeemphasis75 |
247 cTopDefault),
248 .e = ( cTunerGainLow |
249 cAudioIF_5_5 |
250 cRadioIF_38_90 ),
253 /* ---------------------------------------------------------------------- */
255 static void dump_read_message(struct tuner *t, unsigned char *buf)
257 static char *afc[16] = {
258 "- 12.5 kHz",
259 "- 37.5 kHz",
260 "- 62.5 kHz",
261 "- 87.5 kHz",
262 "-112.5 kHz",
263 "-137.5 kHz",
264 "-162.5 kHz",
265 "-187.5 kHz [min]",
266 "+187.5 kHz [max]",
267 "+162.5 kHz",
268 "+137.5 kHz",
269 "+112.5 kHz",
270 "+ 87.5 kHz",
271 "+ 62.5 kHz",
272 "+ 37.5 kHz",
273 "+ 12.5 kHz",
275 tda9887_info("read: 0x%2x\n", buf[0]);
276 tda9887_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
277 tda9887_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
278 tda9887_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
279 tda9887_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
280 tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
283 static void dump_write_message(struct tuner *t, unsigned char *buf)
285 static char *sound[4] = {
286 "AM/TV",
287 "FM/radio",
288 "FM/TV",
289 "FM/radio"
291 static char *adjust[32] = {
292 "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
293 "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
294 "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
295 "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
297 static char *deemph[4] = {
298 "no", "no", "75", "50"
300 static char *carrier[4] = {
301 "4.5 MHz",
302 "5.5 MHz",
303 "6.0 MHz",
304 "6.5 MHz / AM"
306 static char *vif[8] = {
307 "58.75 MHz",
308 "45.75 MHz",
309 "38.9 MHz",
310 "38.0 MHz",
311 "33.9 MHz",
312 "33.4 MHz",
313 "45.75 MHz + pin13",
314 "38.9 MHz + pin13",
316 static char *rif[4] = {
317 "44 MHz",
318 "52 MHz",
319 "52 MHz",
320 "44 MHz",
323 tda9887_info("write: byte B 0x%02x\n",buf[1]);
324 tda9887_info(" B0 video mode : %s\n",
325 (buf[1] & 0x01) ? "video trap" : "sound trap");
326 tda9887_info(" B1 auto mute fm : %s\n",
327 (buf[1] & 0x02) ? "yes" : "no");
328 tda9887_info(" B2 carrier mode : %s\n",
329 (buf[1] & 0x04) ? "QSS" : "Intercarrier");
330 tda9887_info(" B3-4 tv sound/radio : %s\n",
331 sound[(buf[1] & 0x18) >> 3]);
332 tda9887_info(" B5 force mute audio: %s\n",
333 (buf[1] & 0x20) ? "yes" : "no");
334 tda9887_info(" B6 output port 1 : %s\n",
335 (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
336 tda9887_info(" B7 output port 2 : %s\n",
337 (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
339 tda9887_info("write: byte C 0x%02x\n",buf[2]);
340 tda9887_info(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]);
341 tda9887_info(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]);
342 tda9887_info(" C7 audio gain : %s\n",
343 (buf[2] & 0x80) ? "-6" : "0");
345 tda9887_info("write: byte E 0x%02x\n",buf[3]);
346 tda9887_info(" E0-1 sound carrier : %s\n",
347 carrier[(buf[3] & 0x03)]);
348 tda9887_info(" E6 l pll gating : %s\n",
349 (buf[3] & 0x40) ? "36" : "13");
351 if (buf[1] & 0x08) {
352 /* radio */
353 tda9887_info(" E2-4 video if : %s\n",
354 rif[(buf[3] & 0x0c) >> 2]);
355 tda9887_info(" E7 vif agc output : %s\n",
356 (buf[3] & 0x80)
357 ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio")
358 : "fm radio carrier afc");
359 } else {
360 /* video */
361 tda9887_info(" E2-4 video if : %s\n",
362 vif[(buf[3] & 0x1c) >> 2]);
363 tda9887_info(" E5 tuner gain : %s\n",
364 (buf[3] & 0x80)
365 ? ((buf[3] & 0x20) ? "external" : "normal")
366 : ((buf[3] & 0x20) ? "minimum" : "normal"));
367 tda9887_info(" E7 vif agc output : %s\n",
368 (buf[3] & 0x80)
369 ? ((buf[3] & 0x20)
370 ? "pin3 port, pin22 vif agc out"
371 : "pin22 port, pin3 vif acg ext in")
372 : "pin3+pin22 port");
374 tda9887_info("--\n");
377 /* ---------------------------------------------------------------------- */
379 static int tda9887_set_tvnorm(struct tuner *t, char *buf)
381 struct tvnorm *norm = NULL;
382 int i;
384 if (t->mode == V4L2_TUNER_RADIO) {
385 if (t->audmode == V4L2_TUNER_MODE_MONO)
386 norm = &radio_mono;
387 else
388 norm = &radio_stereo;
389 } else {
390 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
391 if (tvnorms[i].std & t->std) {
392 norm = tvnorms+i;
393 break;
397 if (NULL == norm) {
398 tda9887_dbg("Unsupported tvnorm entry - audio muted\n");
399 return -1;
402 tda9887_dbg("configure for: %s\n",norm->name);
403 buf[1] = norm->b;
404 buf[2] = norm->c;
405 buf[3] = norm->e;
406 return 0;
409 static unsigned int port1 = UNSET;
410 static unsigned int port2 = UNSET;
411 static unsigned int qss = UNSET;
412 static unsigned int adjust = UNSET;
414 module_param(port1, int, 0644);
415 module_param(port2, int, 0644);
416 module_param(qss, int, 0644);
417 module_param(adjust, int, 0644);
419 static int tda9887_set_insmod(struct tuner *t, char *buf)
421 if (UNSET != port1) {
422 if (port1)
423 buf[1] |= cOutputPort1Inactive;
424 else
425 buf[1] &= ~cOutputPort1Inactive;
427 if (UNSET != port2) {
428 if (port2)
429 buf[1] |= cOutputPort2Inactive;
430 else
431 buf[1] &= ~cOutputPort2Inactive;
434 if (UNSET != qss) {
435 if (qss)
436 buf[1] |= cQSS;
437 else
438 buf[1] &= ~cQSS;
441 if (adjust >= 0x00 && adjust < 0x20) {
442 buf[2] &= ~cTopMask;
443 buf[2] |= adjust;
445 return 0;
448 static int tda9887_set_config(struct tuner *t, char *buf)
450 if (t->tda9887_config & TDA9887_PORT1_ACTIVE)
451 buf[1] &= ~cOutputPort1Inactive;
452 if (t->tda9887_config & TDA9887_PORT1_INACTIVE)
453 buf[1] |= cOutputPort1Inactive;
454 if (t->tda9887_config & TDA9887_PORT2_ACTIVE)
455 buf[1] &= ~cOutputPort2Inactive;
456 if (t->tda9887_config & TDA9887_PORT2_INACTIVE)
457 buf[1] |= cOutputPort2Inactive;
459 if (t->tda9887_config & TDA9887_QSS)
460 buf[1] |= cQSS;
461 if (t->tda9887_config & TDA9887_INTERCARRIER)
462 buf[1] &= ~cQSS;
464 if (t->tda9887_config & TDA9887_AUTOMUTE)
465 buf[1] |= cAutoMuteFmActive;
466 if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
467 buf[2] &= ~0x60;
468 switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
469 case TDA9887_DEEMPHASIS_NONE:
470 buf[2] |= cDeemphasisOFF;
471 break;
472 case TDA9887_DEEMPHASIS_50:
473 buf[2] |= cDeemphasisON | cDeemphasis50;
474 break;
475 case TDA9887_DEEMPHASIS_75:
476 buf[2] |= cDeemphasisON | cDeemphasis75;
477 break;
480 if (t->tda9887_config & TDA9887_TOP_SET) {
481 buf[2] &= ~cTopMask;
482 buf[2] |= (t->tda9887_config >> 8) & cTopMask;
484 if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
485 buf[1] &= ~cQSS;
486 if (t->tda9887_config & TDA9887_GATING_18)
487 buf[3] &= ~cGating_36;
489 if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
490 radio_stereo.e &= ~cTunerGainLow;
491 radio_mono.e &= ~cTunerGainLow;
494 return 0;
497 /* ---------------------------------------------------------------------- */
499 static int tda9887_status(struct tuner *t)
501 unsigned char buf[1];
502 int rc;
504 memset(buf,0,sizeof(buf));
505 if (1 != (rc = i2c_master_recv(&t->i2c,buf,1)))
506 tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc);
507 dump_read_message(t, buf);
508 return 0;
511 static void tda9887_configure(struct i2c_client *client)
513 struct tuner *t = i2c_get_clientdata(client);
514 struct tda9887_priv *priv = t->priv;
515 int rc;
517 memset(priv->data,0,sizeof(priv->data));
518 tda9887_set_tvnorm(t,priv->data);
520 /* A note on the port settings:
521 These settings tend to depend on the specifics of the board.
522 By default they are set to inactive (bit value 1) by this driver,
523 overwriting any changes made by the tvnorm. This means that it
524 is the responsibility of the module using the tda9887 to set
525 these values in case of changes in the tvnorm.
526 In many cases port 2 should be made active (0) when selecting
527 SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
529 For the other standards the tda9887 application note says that
530 the ports should be set to active (0), but, again, that may
531 differ depending on the precise hardware configuration.
533 priv->data[1] |= cOutputPort1Inactive;
534 priv->data[1] |= cOutputPort2Inactive;
536 tda9887_set_config(t,priv->data);
537 tda9887_set_insmod(t,priv->data);
539 if (t->mode == T_STANDBY) {
540 priv->data[1] |= cForcedMuteAudioON;
543 tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
544 priv->data[1],priv->data[2],priv->data[3]);
545 if (tuner_debug > 1)
546 dump_write_message(t, priv->data);
548 if (4 != (rc = i2c_master_send(&t->i2c,priv->data,4)))
549 tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc);
551 if (tuner_debug > 2) {
552 msleep_interruptible(1000);
553 tda9887_status(t);
557 /* ---------------------------------------------------------------------- */
559 static void tda9887_tuner_status(struct i2c_client *client)
561 struct tuner *t = i2c_get_clientdata(client);
562 struct tda9887_priv *priv = t->priv;
563 tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]);
566 static int tda9887_get_afc(struct i2c_client *client)
568 struct tuner *t = i2c_get_clientdata(client);
569 static int AFC_BITS_2_kHz[] = {
570 -12500, -37500, -62500, -97500,
571 -112500, -137500, -162500, -187500,
572 187500, 162500, 137500, 112500,
573 97500 , 62500, 37500 , 12500
575 int afc=0;
576 __u8 reg = 0;
578 if (1 == i2c_master_recv(&t->i2c,&reg,1))
579 afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
581 return afc;
584 static void tda9887_standby(struct i2c_client *client)
586 tda9887_configure(client);
589 static void tda9887_set_freq(struct i2c_client *client, unsigned int freq)
591 tda9887_configure(client);
594 static void tda9887_release(struct i2c_client *c)
596 struct tuner *t = i2c_get_clientdata(c);
598 kfree(t->priv);
599 t->priv = NULL;
602 static struct tuner_operations tda9887_tuner_ops = {
603 .set_tv_freq = tda9887_set_freq,
604 .set_radio_freq = tda9887_set_freq,
605 .standby = tda9887_standby,
606 .tuner_status = tda9887_tuner_status,
607 .get_afc = tda9887_get_afc,
608 .release = tda9887_release,
611 int tda9887_tuner_init(struct i2c_client *c)
613 struct tda9887_priv *priv = NULL;
614 struct tuner *t = i2c_get_clientdata(c);
616 priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
617 if (priv == NULL)
618 return -ENOMEM;
619 t->priv = priv;
621 strlcpy(c->name, "tda9887", sizeof(c->name));
623 tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr,
624 t->i2c.driver->driver.name);
626 memcpy(&t->ops, &tda9887_tuner_ops, sizeof(struct tuner_operations));
628 return 0;
632 * Overrides for Emacs so that we follow Linus's tabbing style.
633 * ---------------------------------------------------------------------------
634 * Local variables:
635 * c-basic-offset: 8
636 * End: