patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / media / video / tda9887.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/i2c.h>
4 #include <linux/types.h>
5 #include <linux/videodev.h>
6 #include <linux/init.h>
7 #include <linux/errno.h>
8 #include <linux/slab.h>
9
10 #include <media/audiochip.h>
11 #include <media/id.h>
12
13 /* Chips:
14    TDA9885 (PAL, NTSC)
15    TDA9886 (PAL, SECAM, NTSC)
16    TDA9887 (PAL, SECAM, NTSC, FM Radio)
17
18    found on:
19    - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv)
20       TDA9887 (world), TDA9885 (USA)
21       Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
22    - KNC One TV-Station RDS (saa7134)
23 */
24     
25
26 /* Addresses to scan */
27 static unsigned short normal_i2c[] = {
28         0x86 >>1,
29         0x96 >>1,
30         I2C_CLIENT_END,
31 };
32 static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
33 I2C_CLIENT_INSMOD;
34
35 /* insmod options */
36 static int debug =  0;
37 static char *pal =  "b";
38 static char *secam =  "l";
39 MODULE_PARM(debug,"i");
40 MODULE_PARM(pal,"s");
41 MODULE_PARM(secam,"s");
42 MODULE_LICENSE("GPL");
43
44 /* ---------------------------------------------------------------------- */
45
46 #define dprintk     if (debug) printk
47
48 struct tda9887 {
49         struct i2c_client client;
50         int radio,tvnorm;
51         int pinnacle_id;
52 };
53
54 static struct i2c_driver driver;
55 static struct i2c_client client_template;
56
57 /* ---------------------------------------------------------------------- */
58
59 //
60 // TDA defines
61 //
62
63 //// first reg
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
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
98
99 //// third reg
100 #define cAudioIF_4_5             0x00    // bit e0:1
101 #define cAudioIF_5_5             0x01    // bit e0:1
102 #define cAudioIF_6_0             0x02    // bit e0:1
103 #define cAudioIF_6_5             0x03    // bit e0:1
104
105
106 #define cVideoIF_58_75           0x00    // bit e2:4
107 #define cVideoIF_45_75           0x04    // bit e2:4
108 #define cVideoIF_38_90           0x08    // bit e2:4
109 #define cVideoIF_38_00           0x0C    // bit e2:4
110 #define cVideoIF_33_90           0x10    // bit e2:4
111 #define cVideoIF_33_40           0x14    // bit e2:4
112 #define cRadioIF_45_75           0x18    // bit e2:4
113 #define cRadioIF_38_90           0x1C    // bit e2:4
114
115
116 #define cTunerGainNormal         0x00    // bit e5
117 #define cTunerGainLow            0x20    // bit e5
118
119 #define cGating_18               0x00    // bit e6
120 #define cGating_36               0x40    // bit e6
121
122 #define cAgcOutON                0x80    // bit e7
123 #define cAgcOutOFF               0x00    // bit e7
124
125 static int tda9887_miro(struct tda9887 *t)
126 {
127         int rc;
128         u8   bData[4]     = { 0 };
129         u8   bVideoIF     = 0;
130         u8   bAudioIF     = 0;
131         u8   bDeEmphasis  = 0;
132         u8   bDeEmphVal   = 0;
133         u8   bModulation  = 0;
134         u8   bCarrierMode = 0;
135         u8   bOutPort1    = cOutputPort1Inactive;
136 #if 0
137         u8   bOutPort2    = cOutputPort2Inactive & mbTADState; // store i2c tuner state
138 #else
139         u8   bOutPort2    = cOutputPort2Inactive;
140 #endif
141         u8   bVideoTrap   = cVideoTrapBypassOFF;
142 #if 1
143         u8   bTopAdjust   = 0x0e /* -2dB */;
144 #else
145         u8   bTopAdjust   = 0;
146 #endif
147
148 #if 0
149         if (mParams.fVideoTrap)
150                 bVideoTrap   = cVideoTrapBypassON;
151 #endif
152
153         if (t->radio) {
154                 bVideoTrap   = cVideoTrapBypassOFF;
155                 bCarrierMode = cQSS;
156                 bModulation  = cFmRadio;
157                 bOutPort1    = cOutputPort1Inactive;
158                 bDeEmphasis  = cDeemphasisON;
159                 if (3 == t->pinnacle_id) {
160                         /* ntsc */
161                         bDeEmphVal   = cDeemphasis75;
162                         bAudioIF     = cAudioIF_4_5;
163                         bVideoIF     = cRadioIF_45_75;
164                 } else {
165                         /* pal */
166                         bAudioIF     = cAudioIF_5_5;
167                         bVideoIF     = cRadioIF_38_90;
168                         bDeEmphVal   = cDeemphasis50;
169                 }
170
171         } else if (t->tvnorm == VIDEO_MODE_PAL) {
172                 bDeEmphasis  = cDeemphasisON;
173                 bDeEmphVal   = cDeemphasis50;
174                 bModulation  = cNegativeFmTV;
175                 bOutPort1    = cOutputPort1Inactive;
176                 if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
177                         bCarrierMode = cIntercarrier;
178                 } else {
179                         // stereo boards
180                         bCarrierMode = cQSS;
181                 }
182                 switch (pal[0]) {
183                 case 'b':
184                 case 'g':
185                 case 'h':
186                         bVideoIF     = cVideoIF_38_90;
187                         bAudioIF     = cAudioIF_5_5;
188                         break;
189                 case 'd':
190                         bVideoIF     = cVideoIF_38_00;
191                         bAudioIF     = cAudioIF_6_5;
192                         break;
193                 case 'i':
194                         bVideoIF     = cVideoIF_38_90;
195                         bAudioIF     = cAudioIF_6_0;
196                         break;
197                 case 'm':
198                 case 'n':
199                         bVideoIF     = cVideoIF_45_75;
200                         bAudioIF     = cAudioIF_4_5;
201                         bDeEmphVal   = cDeemphasis75;
202                         if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
203                                 bCarrierMode = cIntercarrier;
204                         } else {
205                                 bCarrierMode = cQSS;
206                         }
207                         break;
208                 }
209
210         } else if (t->tvnorm == VIDEO_MODE_SECAM) {
211                 bAudioIF     = cAudioIF_6_5;
212                 bDeEmphasis  = cDeemphasisON;
213                 bDeEmphVal   = cDeemphasis50;
214                 bModulation  = cNegativeFmTV;
215                 bCarrierMode = cQSS;
216                 bOutPort1    = cOutputPort1Inactive;                
217                 switch (secam[0]) {
218                 case 'd':
219                         bVideoIF     = cVideoIF_38_00;
220                         break;
221                 case 'k':
222                         bVideoIF     = cVideoIF_38_90;
223                         break;
224                 case 'l':
225                         bVideoIF     = cVideoIF_38_90;
226                         bDeEmphasis  = cDeemphasisOFF;
227                         bDeEmphVal   = cDeemphasis75;
228                         bModulation  = cPositiveAmTV;
229                         break;
230                 case 'L' /* L1 */:
231                         bVideoIF     = cVideoIF_33_90;
232                         bDeEmphasis  = cDeemphasisOFF;
233                         bDeEmphVal   = cDeemphasis75;
234                         bModulation  = cPositiveAmTV;
235                         break;
236                 }
237
238         } else if (t->tvnorm == VIDEO_MODE_NTSC) {
239                 bVideoIF     = cVideoIF_45_75;
240                 bAudioIF     = cAudioIF_4_5;
241                 bDeEmphasis  = cDeemphasisON;
242                 bDeEmphVal   = cDeemphasis75;
243                 bModulation  = cNegativeFmTV;                
244                 bOutPort1    = cOutputPort1Inactive;
245                 if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
246                         bCarrierMode = cIntercarrier;
247                 } else {
248                         bCarrierMode = cQSS;
249                 }
250         }
251
252         bData[1] = bVideoTrap        |  // B0: video trap bypass
253                 cAutoMuteFmInactive  |  // B1: auto mute
254                 bCarrierMode         |  // B2: InterCarrier for PAL else QSS 
255                 bModulation          |  // B3 - B4: positive AM TV for SECAM only
256                 cForcedMuteAudioOFF  |  // B5: forced Audio Mute (off)
257                 bOutPort1            |  // B6: Out Port 1 
258                 bOutPort2;              // B7: Out Port 2 
259         bData[2] = bTopAdjust |   // C0 - C4: Top Adjust 0 == -16dB  31 == 15dB
260                 bDeEmphasis   |   // C5: De-emphasis on/off
261                 bDeEmphVal    |   // C6: De-emphasis 50/75 microsec
262                 cAudioGain0;      // C7: normal audio gain
263         bData[3] = bAudioIF      |  // E0 - E1: Sound IF
264                 bVideoIF         |  // E2 - E4: Video IF
265                 cTunerGainNormal |  // E5: Tuner gain (normal)
266                 cGating_18       |  // E6: Gating (18%)
267                 cAgcOutOFF;         // E7: VAGC  (off)
268         
269         dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x [pinnacle_id=%d]\n",
270                 bData[1],bData[2],bData[3],t->pinnacle_id);
271         if (4 != (rc = i2c_master_send(&t->client,bData,4)))
272                 printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
273         return 0;
274 }
275
276 /* ---------------------------------------------------------------------- */
277
278 #if 0
279 /* just for reference: old knc-one saa7134 stuff */
280 static unsigned char buf_pal_bg[]    = { 0x00, 0x16, 0x70, 0x49 };
281 static unsigned char buf_pal_i[]     = { 0x00, 0x16, 0x70, 0x4a };
282 static unsigned char buf_pal_dk[]    = { 0x00, 0x16, 0x70, 0x4b };
283 static unsigned char buf_pal_l[]     = { 0x00, 0x06, 0x50, 0x4b };
284 static unsigned char buf_fm_stereo[] = { 0x00, 0x0e, 0x0d, 0x77 };
285 #endif
286
287 static unsigned char buf_pal_bg[]    = { 0x00, 0x96, 0x70, 0x49 };
288 static unsigned char buf_pal_i[]     = { 0x00, 0x96, 0x70, 0x4a };
289 static unsigned char buf_pal_dk[]    = { 0x00, 0x96, 0x70, 0x4b };
290 static unsigned char buf_pal_l[]     = { 0x00, 0x86, 0x50, 0x4b };
291 static unsigned char buf_fm_stereo[] = { 0x00, 0x8e, 0x0d, 0x77 };
292 static unsigned char buf_ntsc[]      = { 0x00, 0x96, 0x70, 0x44 };
293 static unsigned char buf_ntsc_jp[]   = { 0x00, 0x96, 0x70, 0x40 };
294
295 static int tda9887_configure(struct tda9887 *t)
296 {
297         unsigned char *buf = NULL;
298         int rc;
299
300         if (t->radio) {
301                 dprintk("tda9885/6/7: FM Radio mode\n");
302                 buf = buf_fm_stereo;
303
304         } else if (t->tvnorm == VIDEO_MODE_PAL) {
305                 dprintk("tda9885/6/7: PAL-%c mode\n",pal[0]);
306                 switch (pal[0]) {
307                 case 'b':
308                 case 'g':
309                         buf = buf_pal_bg;
310                         break;
311                 case 'i':
312                         buf = buf_pal_i;
313                         break;
314                 case 'd':
315                 case 'k':
316                         buf = buf_pal_dk;
317                         break;
318                 case 'l':
319                         buf = buf_pal_l;
320                         break;
321                 }
322
323         } else if (t->tvnorm == VIDEO_MODE_NTSC) {
324                 dprintk("tda9885/6/7: NTSC mode\n");
325                 buf = buf_ntsc;
326
327         } else if (t->tvnorm == VIDEO_MODE_SECAM) {
328                 dprintk("tda9885/6/7: SECAM mode\n");
329                 buf = buf_pal_l;
330
331         } else if (t->tvnorm == 6 /* BTTV hack */) {
332                 dprintk("tda9885/6/7: NTSC-Japan mode\n");
333                 buf = buf_ntsc_jp;
334         }
335
336         if (NULL == buf) {
337                 printk("tda9885/6/7 unknown norm=%d\n",t->tvnorm);
338                 return 0;
339         }
340
341         dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x\n",
342                 buf[1],buf[2],buf[3]);
343         if (4 != (rc = i2c_master_send(&t->client,buf,4)))
344                 printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
345         return 0;
346 }
347
348 /* ---------------------------------------------------------------------- */
349
350 static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
351 {
352         struct tda9887 *t;
353
354         client_template.adapter = adap;
355         client_template.addr    = addr;
356
357         printk("tda9887: chip found @ 0x%x\n", addr<<1);
358
359         if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
360                 return -ENOMEM;
361         memset(t,0,sizeof(*t));
362         t->client = client_template;
363         t->pinnacle_id = -1;
364         t->tvnorm=VIDEO_MODE_PAL;
365         i2c_set_clientdata(&t->client, t);
366         i2c_attach_client(&t->client);
367         
368         return 0;
369 }
370
371 static int tda9887_probe(struct i2c_adapter *adap)
372 {
373 #ifdef I2C_CLASS_TV_ANALOG
374         if (adap->class & I2C_CLASS_TV_ANALOG)
375                 return i2c_probe(adap, &addr_data, tda9887_attach);
376 #else
377         switch (adap->id) {
378         case I2C_ALGO_BIT | I2C_HW_B_BT848:
379         case I2C_ALGO_BIT | I2C_HW_B_RIVA:
380         case I2C_ALGO_SAA7134:
381                 return i2c_probe(adap, &addr_data, tda9887_attach);
382                 break;
383         }
384 #endif
385         return 0;
386 }
387
388 static int tda9887_detach(struct i2c_client *client)
389 {
390         struct tda9887 *t = i2c_get_clientdata(client);
391
392         i2c_detach_client(client);
393         kfree(t);
394         return 0;
395 }
396
397 static int
398 tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
399 {
400         struct tda9887 *t = i2c_get_clientdata(client);
401
402         switch (cmd) {
403
404         /* --- configuration --- */
405         case AUDC_SET_RADIO:
406                 t->radio = 1;
407                 if (-1 != t->pinnacle_id)
408                         tda9887_miro(t);
409                 else
410                         tda9887_configure(t);
411                 break;
412                 
413         case AUDC_CONFIG_PINNACLE:
414         {
415                 int *i = arg;
416
417                 t->pinnacle_id = *i;
418                 tda9887_miro(t);
419                 break;
420         }
421         /* --- v4l ioctls --- */
422         /* take care: bttv does userspace copying, we'll get a
423            kernel pointer here... */
424         case VIDIOCSCHAN:
425         {
426                 struct video_channel *vc = arg;
427
428                 t->radio  = 0;
429                 t->tvnorm = vc->norm;
430                 if (-1 != t->pinnacle_id)
431                         tda9887_miro(t);
432                 else
433                         tda9887_configure(t);
434                 break;
435         }
436         default:
437                 /* nothing */
438                 break;
439         }
440         return 0;
441 }
442
443 /* ----------------------------------------------------------------------- */
444
445 static struct i2c_driver driver = {
446         .owner          = THIS_MODULE,
447         .name           = "i2c tda9887 driver",
448         .id             = -1, /* FIXME */
449         .flags          = I2C_DF_NOTIFY,
450         .attach_adapter = tda9887_probe,
451         .detach_client  = tda9887_detach,
452         .command        = tda9887_command,
453 };
454 static struct i2c_client client_template =
455 {
456         I2C_DEVNAME("tda9887"),
457         .flags     = I2C_CLIENT_ALLOW_USE,
458         .driver    = &driver,
459 };
460
461 static int tda9887_init_module(void)
462 {
463         i2c_add_driver(&driver);
464         return 0;
465 }
466
467 static void tda9887_cleanup_module(void)
468 {
469         i2c_del_driver(&driver);
470 }
471
472 module_init(tda9887_init_module);
473 module_exit(tda9887_cleanup_module);
474
475 /*
476  * Overrides for Emacs so that we follow Linus's tabbing style.
477  * ---------------------------------------------------------------------------
478  * Local variables:
479  * c-basic-offset: 8
480  * End:
481  */