File: /usr/src/linux/drivers/media/video/tuner.c

1     #include <linux/module.h>
2     #include <linux/kernel.h>
3     #include <linux/sched.h>
4     #include <linux/string.h>
5     #include <linux/timer.h>
6     #include <linux/delay.h>
7     #include <linux/errno.h>
8     #include <linux/slab.h>
9     #include <linux/poll.h>
10     #include <linux/i2c.h>
11     #include <linux/types.h>
12     #include <linux/videodev.h>
13     #include <linux/init.h>
14     
15     #include "tuner.h"
16     #include "audiochip.h"
17     
18     /* Addresses to scan */
19     static unsigned short normal_i2c[] = {I2C_CLIENT_END};
20     static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END};
21     static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
22     static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
23     static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
24     static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
25     static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
26     static struct i2c_client_address_data addr_data = {
27     	normal_i2c, normal_i2c_range, 
28     	probe, probe_range, 
29     	ignore, ignore_range, 
30     	force
31     };
32     
33     static int debug =  0; /* insmod parameter */
34     static int type  = -1; /* insmod parameter */
35     
36     static int addr  =  0;
37     static char *pal =  "b";
38     static int this_adap;
39     static int tv_range[2]    = { 44, 958 };
40     static int radio_range[2] = { 65, 108 };
41     
42     #define dprintk     if (debug) printk
43     
44     MODULE_PARM(debug,"i");
45     MODULE_PARM(type,"i");
46     MODULE_PARM(addr,"i");
47     MODULE_PARM(tv_range,"2i");
48     MODULE_PARM(radio_range,"2i");
49     MODULE_PARM(pal,"s");
50     
51     struct tuner
52     {
53     	int type;            /* chip type */
54     	int freq;            /* keep track of the current settings */
55     	int std;
56     
57     	int radio;
58     	int mode;            /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */
59     };
60     
61     static struct i2c_driver driver;
62     static struct i2c_client client_template;
63     
64     /* tv standard selection for Temic 4046 FM5
65        this value takes the low bits of control byte 2
66        from datasheet Rev.01, Feb.00 
67          standard     BG      I       L       L2      D
68          picture IF   38.9    38.9    38.9    33.95   38.9
69          sound 1      33.4    32.9    32.4    40.45   32.4
70          sound 2      33.16   
71          NICAM        33.05   32.348  33.05           33.05
72      */
73     #define TEMIC_SET_PAL_I         0x05
74     #define TEMIC_SET_PAL_DK        0x09
75     #define TEMIC_SET_PAL_L         0x0a // SECAM ?
76     #define TEMIC_SET_PAL_L2        0x0b // change IF !
77     #define TEMIC_SET_PAL_BG        0x0c
78     
79     /* tv tuner system standard selection for Philips FQ1216ME
80        this value takes the low bits of control byte 2
81        from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
82          standard 		BG	DK	I	L	L`
83          picture carrier	38.90	38.90	38.90	38.90	33.95
84          colour		34.47	34.47	34.47	34.47	38.38
85          sound 1		33.40	32.40	32.90	32.40	40.45
86          sound 2		33.16	-	-	-	-
87          NICAM		33.05	33.05	32.35	33.05	39.80
88      */
89     #define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
90     #define PHILIPS_SET_PAL_BGDK	0x09
91     #define PHILIPS_SET_PAL_L2	0x0a
92     #define PHILIPS_SET_PAL_L	0x0b	
93     
94     /* system switching for Philips FI1216MF MK2
95        from datasheet "1996 Jul 09",
96      */
97     #define PHILIPS_MF_SET_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
98     #define PHILIPS_MF_SET_PAL_L	0x03
99     #define PHILIPS_MF_SET_PAL_L2	0x02
100     
101     
102     /* ---------------------------------------------------------------------- */
103     
104     struct tunertype 
105     {
106     	char *name;
107     	unsigned char Vendor;
108     	unsigned char Type;
109       
110     	unsigned short thresh1;  /*  band switch VHF_LO <=> VHF_HI  */
111     	unsigned short thresh2;  /*  band switch VHF_HI <=> UHF     */
112     	unsigned char VHF_L;
113     	unsigned char VHF_H;
114     	unsigned char UHF;
115     	unsigned char config; 
116     	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, 732=16*45.75 NTSC */
117     };
118     
119     /*
120      *	The floats in the tuner struct are computed at compile time
121      *	by gcc and cast back to integers. Thus we don't violate the
122      *	"no float in kernel" rule.
123      */
124     static struct tunertype tuners[] = {
125             { "Temic PAL (4002 FH5)", TEMIC, PAL,
126     	  16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
127     	{ "Philips PAL_I", Philips, PAL_I,
128     	  16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
129     	{ "Philips NTSC", Philips, NTSC,
130     	  16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
131     	{ "Philips SECAM", Philips, SECAM,
132     	  16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
133     
134     	{ "NoTuner", NoTuner, NOTUNER,
135     	  0,0,0x00,0x00,0x00,0x00,0x00},
136     	{ "Philips PAL", Philips, PAL,
137     	  16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
138     	{ "Temic NTSC (4032 FY5)", TEMIC, NTSC,
139     	  16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
140     	{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
141     	  16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
142     
143      	{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
144     	  16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
145             { "Alps HSBH1", TEMIC, NTSC,
146     	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
147             { "Alps TSBE1",TEMIC,PAL,
148     	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
149             { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modtec MM205 */
150     	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
151     
152             { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
153     	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
154             { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
155     	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
156     	{ "Temic PAL_I (4006FH5)", TEMIC, PAL_I,
157     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 
158       	{ "Alps TSCH6",Alps,NTSC,
159       	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
160     
161       	{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
162       	  16*136.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
163       	{ "Philips NTSC_M (MK2)",Philips,NTSC,
164       	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
165             { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
166               16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
167             { "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
168               16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
169     
170             { "Temic PAL (4009 FR5)", TEMIC, PAL,
171               16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
172             { "Temic NTSC (4039 FR5)", TEMIC, NTSC,
173               16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
174             { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
175               16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
176             { "Philips PAL_DK", Philips, PAL,
177     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
178     
179     	{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
180     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
181     	{ "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
182     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
183     	{ "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I,
184     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
185     	{ "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
186     	  16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
187     
188     	{ "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
189     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
190     	{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
191     	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
192     	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
193     	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}
194     };
195     #define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
196     
197     /* ---------------------------------------------------------------------- */
198     
199     static int tuner_getstatus(struct i2c_client *c)
200     {
201     	unsigned char byte;
202     
203     	if (1 != i2c_master_recv(c,&byte,1))
204     		return 0;
205     	return byte;
206     }
207     
208     #define TUNER_POR       0x80
209     #define TUNER_FL        0x40
210     #define TUNER_MODE      0x38
211     #define TUNER_AFC       0x07
212     
213     #define TUNER_STEREO    0x10 /* radio mode */
214     #define TUNER_SIGNAL    0x07 /* radio mode */
215     
216     static int tuner_signal(struct i2c_client *c)
217     {
218     	return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
219     }
220     
221     static int tuner_stereo(struct i2c_client *c)
222     {
223     	return (tuner_getstatus (c) & TUNER_STEREO);
224     }
225     
226     
227     static int tuner_islocked (struct i2c_client *c)
228     {
229             return (tuner_getstatus (c) & TUNER_FL);
230     }
231     
232     static int tuner_afcstatus (struct i2c_client *c)
233     {
234             return (tuner_getstatus (c) & TUNER_AFC) - 2;
235     }
236     
237     #if 0 /* unused */
238     static int tuner_mode (struct i2c_client *c)
239     {
240             return (tuner_getstatus (c) & TUNER_MODE) >> 3;
241     }
242     #endif
243     
244     // Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
245     static void set_tv_freq(struct i2c_client *c, int freq)
246     {
247     	u8 config;
248     	u16 div;
249     	struct tunertype *tun;
250     	struct tuner *t = c->data;
251             unsigned char buffer[4];
252     	int rc;
253     
254     	if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
255     		/* FIXME: better do that chip-specific, but
256     		   right now we don't have that in the config
257     		   struct and this way is still better than no
258     		   check at all */
259     		printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n",
260     		       freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
261     	}
262     
263     	if (t->type == -1) {
264     		printk("tuner: tuner type not set\n");
265     		return;
266     	}
267     
268     	tun=&tuners[t->type];
269     	if (freq < tun->thresh1) 
270     		config = tun->VHF_L;
271     	else if (freq < tun->thresh2) 
272     		config = tun->VHF_H;
273     	else
274     		config = tun->UHF;
275     
276     
277     	/* tv norm specific stuff for multi-norm tuners */
278     	switch (t->type) {
279     	case TUNER_PHILIPS_SECAM:
280     		/* 0x01 -> ??? no change ??? */
281     		/* 0x02 -> PAL BDGHI / SECAM L */
282     		/* 0x04 -> ??? PAL others / SECAM others ??? */
283     		config &= ~0x02;
284     		if (t->mode)
285     			config |= 0x02;
286     		break;
287     
288     	case TUNER_TEMIC_4046FM5:
289     		config &= ~0x0f;
290     		switch (pal[0]) {
291     		case 'i':
292     		case 'I':
293     			config |= TEMIC_SET_PAL_I;
294     			break;
295     		case 'd':
296     		case 'D':
297     			config |= TEMIC_SET_PAL_DK;
298     			break;
299     		case 'l':
300     		case 'L':
301     			config |= TEMIC_SET_PAL_L;
302     			break;
303     		case 'b':
304     		case 'B':
305     		case 'g':
306     		case 'G':
307     		default:
308     			config |= TEMIC_SET_PAL_BG;
309     			break;
310     		break;
311     		}
312     	case TUNER_PHILIPS_FQ1216ME:
313     		config &= ~0x0f;
314     		switch (pal[0]) {
315     		case 'i':
316     		case 'I':
317     			config |= PHILIPS_SET_PAL_I;
318     			break;
319     		case 'l':
320     		case 'L':
321     			config |= PHILIPS_SET_PAL_L;
322     			break;
323     		case 'd':
324     		case 'D':
325     		case 'b':
326     		case 'B':
327     		case 'g':
328     		case 'G':
329     			config |= PHILIPS_SET_PAL_BGDK;
330     			break;
331     		break;
332     		}
333     	}
334     
335     	
336     	/*
337     	 * Philips FI1216MK2 remark from specification :
338     	 * for channel selection involving band switching, and to ensure
339     	 * smooth tuning to the desired channel without causing
340     	 * unnecessary charge pump action, it is recommended to consider
341     	 * the difference between wanted channel frequency and the
342     	 * current channel frequency.  Unnecessary charge pump action
343     	 * will result in very low tuning voltage which may drive the
344     	 * oscillator to extreme conditions.
345     	 *
346     	 * Progfou: specification says to send config data before
347     	 * frequency in case (wanted frequency < current frequency).
348     	 */
349     
350     	div=freq + tun->IFPCoff;
351     	if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
352     		buffer[0] = tun->config;
353     		buffer[1] = config;
354     		buffer[2] = (div>>8) & 0x7f;
355     		buffer[3] = div      & 0xff;
356     	} else {
357     		buffer[0] = (div>>8) & 0x7f;
358     		buffer[1] = div      & 0xff;
359     		buffer[2] = tun->config;
360     		buffer[3] = config;
361     	}
362     
363             if (4 != (rc = i2c_master_send(c,buffer,4)))
364                     printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
365     
366     }
367     
368     static void set_radio_freq(struct i2c_client *c, int freq)
369     {
370     	u8 config;
371     	u16 div;
372     	struct tunertype *tun;
373     	struct tuner *t = (struct tuner*)c->data;
374             unsigned char buffer[4];
375     	int rc;
376     
377     	if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
378     		printk("tuner: radio freq (%d.%02d) out of range (%d-%d)\n",
379     		       freq/16,freq%16*100/16,
380     		       radio_range[0],radio_range[1]);
381     		return;
382     	}
383     	if (t->type == -1) {
384     		printk("tuner: tuner type not set\n");
385     		return;
386     	}
387     
388     	tun=&tuners[t->type];
389     	config = 0xa4 /* 0xa5 */; /* bit 0 is AFC (set) vs. RF-Signal (clear) */
390     	div=freq + (int)(16*10.7);
391       	div&=0x7fff;
392     
393             buffer[0] = (div>>8) & 0x7f;
394             buffer[1] = div      & 0xff;
395             buffer[2] = tun->config;
396             buffer[3] = config;
397             if (4 != (rc = i2c_master_send(c,buffer,4)))
398                     printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
399     
400     	if (debug) {
401     		current->state   = TASK_INTERRUPTIBLE;
402     		schedule_timeout(HZ/10);
403     		
404     		if (tuner_islocked (c))
405     			printk ("tuner: PLL locked\n");
406     		else
407     			printk ("tuner: PLL not locked\n");
408     
409     		if (config & 1) {
410     			printk ("tuner: AFC: %d\n", tuner_afcstatus(c));
411     		} else {
412     			printk ("tuner: Signal: %d\n", tuner_signal(c));
413     		}
414     	}
415     }
416     /* ---------------------------------------------------------------------- */
417     
418     
419     static int tuner_attach(struct i2c_adapter *adap, int addr,
420     			unsigned short flags, int kind)
421     {
422     	struct tuner *t;
423     	struct i2c_client *client;
424     
425     	if (this_adap > 0)
426     		return -1;
427     	this_adap++;
428     	
429             client_template.adapter = adap;
430             client_template.addr = addr;
431     
432             printk("tuner: chip found @ 0x%x\n", addr<<1);
433     
434             if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
435                     return -ENOMEM;
436             memcpy(client,&client_template,sizeof(struct i2c_client));
437             client->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
438             if (NULL == t) {
439                     kfree(client);
440                     return -ENOMEM;
441             }
442             memset(t,0,sizeof(struct tuner));
443     	if (type >= 0 && type < TUNERS) {
444     		t->type = type;
445     		strncpy(client->name, tuners[t->type].name, sizeof(client->name));
446     	} else {
447     		t->type = -1;
448     	}
449             i2c_attach_client(client);
450     	MOD_INC_USE_COUNT;
451     
452     	return 0;
453     }
454     
455     static int tuner_probe(struct i2c_adapter *adap)
456     {
457     	if (0 != addr) {
458     		normal_i2c_range[0] = addr;
459     		normal_i2c_range[1] = addr;
460     	}
461     	this_adap = 0;
462     	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
463     		return i2c_probe(adap, &addr_data, tuner_attach);
464     	return 0;
465     }
466     
467     static int tuner_detach(struct i2c_client *client)
468     {
469     	struct tuner *t = (struct tuner*)client->data;
470     
471     	i2c_detach_client(client);
472     	kfree(t);
473     	kfree(client);
474     	MOD_DEC_USE_COUNT;
475     	return 0;
476     }
477     
478     static int
479     tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
480     {
481     	struct tuner *t = (struct tuner*)client->data;
482             int   *iarg = (int*)arg;
483     #if 0
484             __u16 *sarg = (__u16*)arg;
485     #endif
486     
487             switch (cmd) {
488     
489     	/* --- configuration --- */
490     	case TUNER_SET_TYPE:
491     		if (t->type != -1)
492     			return 0;
493     		if (*iarg < 0 || *iarg >= TUNERS)
494     			return 0;
495     		t->type = *iarg;
496     		dprintk("tuner: type set to %d (%s)\n",
497                             t->type,tuners[t->type].name);
498     		strncpy(client->name, tuners[t->type].name, sizeof(client->name));
499     		break;
500     	case AUDC_SET_RADIO:
501     		t->radio = 1;
502     		break;
503     		
504     	/* --- v4l ioctls --- */
505     	/* take care: bttv does userspace copying, we'll get a
506     	   kernel pointer here... */
507     	case VIDIOCSCHAN:
508     	{
509     		struct video_channel *vc = arg;
510     		
511     		t->radio = 0;
512     		if (t->type == TUNER_PHILIPS_SECAM) {
513     			t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0;
514     			set_tv_freq(client,t->freq);
515     		}
516     		return 0;
517     	}
518     	case VIDIOCSFREQ:
519     	{
520     		unsigned long *v = arg;
521     
522     		if (t->radio) {
523     			dprintk("tuner: radio freq set to %d.%02d\n",
524     				(*iarg)/16,(*iarg)%16*100/16);
525     			set_radio_freq(client,*v);
526     		} else {
527     			dprintk("tuner: tv freq set to %d.%02d\n",
528     				(*iarg)/16,(*iarg)%16*100/16);
529     			set_tv_freq(client,*v);
530     		}
531     		t->freq = *v;
532     		return 0;
533     	}
534     	case VIDIOCGTUNER:
535     	{
536     		struct video_tuner *vt = arg;
537     
538     		if (t->radio)
539     			vt->signal = tuner_signal(client);
540     		return 0;
541     	}
542     	case VIDIOCGAUDIO:
543     	{
544     		struct video_audio *va = arg;
545     		if (t->radio)
546     			va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
547     		return 0;
548     	}
549     	
550     #if 0
551     	/* --- old, obsolete interface --- */
552     	case TUNER_SET_TVFREQ:
553     		dprintk("tuner: tv freq set to %d.%02d\n",
554     			(*iarg)/16,(*iarg)%16*100/16);
555     		set_tv_freq(client,*iarg);
556     		t->radio = 0;
557     		t->freq = *iarg;
558     		break;
559     
560     	case TUNER_SET_RADIOFREQ:
561     		dprintk("tuner: radio freq set to %d.%02d\n",
562     			(*iarg)/16,(*iarg)%16*100/16);
563     		set_radio_freq(client,*iarg);
564     		t->radio = 1;
565     		t->freq = *iarg;
566     		break;
567     	case TUNER_SET_MODE:
568     		if (t->type != TUNER_PHILIPS_SECAM) {
569     			dprintk("tuner: trying to change mode for other than TUNER_PHILIPS_SECAM\n");
570     		} else {
571     			int mode=(*sarg==VIDEO_MODE_SECAM)?1:0;
572     			dprintk("tuner: mode set to %d\n", *sarg);
573     			t->mode = mode;
574     			set_tv_freq(client,t->freq);
575     		}
576     		break;
577     #endif
578     	default:
579     		/* nothing */
580     		break;
581     	}
582     	
583     	return 0;
584     }
585     
586     /* ----------------------------------------------------------------------- */
587     
588     static struct i2c_driver driver = {
589             "i2c TV tuner driver",
590             I2C_DRIVERID_TUNER,
591             I2C_DF_NOTIFY,
592             tuner_probe,
593             tuner_detach,
594             tuner_command,
595     };
596     
597     static struct i2c_client client_template =
598     {
599             "(unset)",		/* name       */
600             -1,
601             0,
602             0,
603             NULL,
604             &driver
605     };
606     
607     EXPORT_NO_SYMBOLS;
608     
609     int tuner_init_module(void)
610     {
611     	i2c_add_driver(&driver);
612     	return 0;
613     }
614     
615     void tuner_cleanup_module(void)
616     {
617     	i2c_del_driver(&driver);
618     }
619     
620     module_init(tuner_init_module);
621     module_exit(tuner_cleanup_module);
622     
623     /*
624      * Overrides for Emacs so that we follow Linus's tabbing style.
625      * ---------------------------------------------------------------------------
626      * Local variables:
627      * c-basic-offset: 8
628      * End:
629      */
630