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/malloc.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 int this_adap;
38
39 #define dprintk if (debug) printk
40
41 MODULE_PARM(debug,"i");
42 MODULE_PARM(type,"i");
43 MODULE_PARM(addr,"i");
44
45 struct tuner
46 {
47 int type; /* chip type */
48 int freq; /* keep track of the current settings */
49 int std;
50
51 int radio;
52 int mode; /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */
53 };
54
55 static struct i2c_driver driver;
56 static struct i2c_client client_template;
57
58 /* ---------------------------------------------------------------------- */
59
60 struct tunertype
61 {
62 char *name;
63 unsigned char Vendor;
64 unsigned char Type;
65
66 unsigned short thresh1; /* frequency Range for UHF,VHF-L, VHF_H */
67 unsigned short thresh2;
68 unsigned char VHF_L;
69 unsigned char VHF_H;
70 unsigned char UHF;
71 unsigned char config;
72 unsigned short IFPCoff;
73 unsigned char mode; /* mode change value (tested PHILIPS_SECAM only) */
74 /* 0x01 -> ??? no change ??? */
75 /* 0x02 -> PAL BDGHI / SECAM L */
76 /* 0x04 -> ??? PAL others / SECAM others ??? */
77 int capability;
78 };
79
80 /*
81 * The floats in the tuner struct are computed at compile time
82 * by gcc and cast back to integers. Thus we don't violate the
83 * "no float in kernel" rule.
84 */
85 static struct tunertype tuners[] = {
86 { "Temic PAL", TEMIC, PAL,
87 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
88 { "Philips PAL_I", Philips, PAL_I,
89 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
90 { "Philips NTSC", Philips, NTSC,
91 16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
92 { "Philips SECAM", Philips, SECAM,
93 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623,0x02},
94 { "NoTuner", NoTuner, NOTUNER,
95 0,0,0x00,0x00,0x00,0x00,0x00,000},
96 { "Philips PAL", Philips, PAL,
97 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
98 { "Temic NTSC", TEMIC, NTSC,
99 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
100 { "Temic PAL_I", TEMIC, PAL_I,
101 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
102 { "Temic 4036 FY5 NTSC", TEMIC, NTSC,
103 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
104 { "Alps HSBH1", TEMIC, NTSC,
105 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
106 { "Alps TSBE1",TEMIC,PAL,
107 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
108 { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modtec MM205 */
109 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
110 { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
111 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
112 { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
113 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
114 { "Temic 4006FH5", TEMIC, PAL_I,
115 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
116 { "Alps TSCH6",Alps,NTSC,
117 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
118 };
119 #define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
120
121 /* ---------------------------------------------------------------------- */
122
123 static int tuner_getstatus(struct i2c_client *c)
124 {
125 unsigned char byte;
126
127 if (1 != i2c_master_recv(c,&byte,1))
128 return 0;
129 return byte;
130 }
131
132 #define TUNER_POR 0x80
133 #define TUNER_FL 0x40
134 #define TUNER_MODE 0x38
135 #define TUNER_AFC 0x07
136
137 #define TUNER_STEREO 0x10 /* radio mode */
138 #define TUNER_SIGNAL 0x07 /* radio mode */
139
140 static int tuner_signal(struct i2c_client *c)
141 {
142 return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
143 }
144
145 static int tuner_stereo(struct i2c_client *c)
146 {
147 return (tuner_getstatus (c) & TUNER_STEREO);
148 }
149
150
151 static int tuner_islocked (struct i2c_client *c)
152 {
153 return (tuner_getstatus (c) & TUNER_FL);
154 }
155
156 static int tuner_afcstatus (struct i2c_client *c)
157 {
158 return (tuner_getstatus (c) & TUNER_AFC) - 2;
159 }
160
161 #if 0 /* unused */
162 static int tuner_mode (struct i2c_client *c)
163 {
164 return (tuner_getstatus (c) & TUNER_MODE) >> 3;
165 }
166 #endif
167
168 static void set_tv_freq(struct i2c_client *c, int freq)
169 {
170 u8 config;
171 u16 div;
172 struct tunertype *tun;
173 struct tuner *t = c->data;
174 unsigned char buffer[4];
175 int rc;
176
177 if (t->type == -1) {
178 printk("tuner: tuner type not set\n");
179 return;
180 }
181
182 tun=&tuners[t->type];
183 if (freq < tun->thresh1)
184 config = tun->VHF_L;
185 else if (freq < tun->thresh2)
186 config = tun->VHF_H;
187 else
188 config = tun->UHF;
189
190 #if 1 // Fix colorstandard mode change
191 if (t->type == TUNER_PHILIPS_SECAM && t->mode)
192 config |= tun->mode;
193 else
194 config &= ~tun->mode;
195 #else
196 config &= ~tun->mode;
197 #endif
198
199 div=freq + tun->IFPCoff;
200
201 /*
202 * Philips FI1216MK2 remark from specification :
203 * for channel selection involving band switching, and to ensure
204 * smooth tuning to the desired channel without causing
205 * unnecessary charge pump action, it is recommended to consider
206 * the difference between wanted channel frequency and the
207 * current channel frequency. Unnecessary charge pump action
208 * will result in very low tuning voltage which may drive the
209 * oscillator to extreme conditions.
210 */
211 /*
212 * Progfou: specification says to send config data before
213 * frequency in case (wanted frequency < current frequency).
214 */
215
216 if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
217 buffer[0] = tun->config;
218 buffer[1] = config;
219 buffer[2] = (div>>8) & 0x7f;
220 buffer[3] = div & 0xff;
221 } else {
222 buffer[0] = (div>>8) & 0x7f;
223 buffer[1] = div & 0xff;
224 buffer[2] = tun->config;
225 buffer[3] = config;
226 }
227
228 if (4 != (rc = i2c_master_send(c,buffer,4)))
229 printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
230
231 }
232
233 static void set_radio_freq(struct i2c_client *c, int freq)
234 {
235 u8 config;
236 u16 div;
237 struct tunertype *tun;
238 struct tuner *t = (struct tuner*)c->data;
239 unsigned char buffer[4];
240 int rc;
241
242 if (t->type == -1) {
243 printk("tuner: tuner type not set\n");
244 return;
245 }
246
247 tun=&tuners[t->type];
248 config = 0xa4 /* 0xa5 */; /* bit 0 is AFC (set) vs. RF-Signal (clear) */
249 div=freq + (int)(16*10.7);
250 div&=0x7fff;
251
252 buffer[0] = (div>>8) & 0x7f;
253 buffer[1] = div & 0xff;
254 buffer[2] = tun->config;
255 buffer[3] = config;
256 if (4 != (rc = i2c_master_send(c,buffer,4)))
257 printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
258
259 if (debug) {
260 current->state = TASK_INTERRUPTIBLE;
261 schedule_timeout(HZ/10);
262
263 if (tuner_islocked (c))
264 printk ("tuner: PLL locked\n");
265 else
266 printk ("tuner: PLL not locked\n");
267
268 if (config & 1) {
269 printk ("tuner: AFC: %d\n", tuner_afcstatus(c));
270 } else {
271 printk ("tuner: Signal: %d\n", tuner_signal(c));
272 }
273 }
274 }
275 /* ---------------------------------------------------------------------- */
276
277
278 static int tuner_attach(struct i2c_adapter *adap, int addr,
279 unsigned short flags, int kind)
280 {
281 struct tuner *t;
282 struct i2c_client *client;
283
284 if (this_adap > 0)
285 return -1;
286 this_adap++;
287
288 client_template.adapter = adap;
289 client_template.addr = addr;
290
291 printk("tuner: chip found @ 0x%x\n",addr);
292
293 if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
294 return -ENOMEM;
295 memcpy(client,&client_template,sizeof(struct i2c_client));
296 client->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
297 if (NULL == t) {
298 kfree(client);
299 return -ENOMEM;
300 }
301 memset(t,0,sizeof(struct tuner));
302 if (type >= 0 && type < TUNERS) {
303 t->type = type;
304 strncpy(client->name, tuners[t->type].name, sizeof(client->name));
305 } else {
306 t->type = -1;
307 }
308 i2c_attach_client(client);
309 MOD_INC_USE_COUNT;
310
311 return 0;
312 }
313
314 static int tuner_probe(struct i2c_adapter *adap)
315 {
316 if (0 != addr) {
317 normal_i2c_range[0] = addr;
318 normal_i2c_range[1] = addr;
319 }
320 this_adap = 0;
321 if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
322 return i2c_probe(adap, &addr_data, tuner_attach);
323 return 0;
324 }
325
326 static int tuner_detach(struct i2c_client *client)
327 {
328 struct tuner *t = (struct tuner*)client->data;
329
330 i2c_detach_client(client);
331 kfree(t);
332 kfree(client);
333 MOD_DEC_USE_COUNT;
334 return 0;
335 }
336
337 static int
338 tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
339 {
340 struct tuner *t = (struct tuner*)client->data;
341 int *iarg = (int*)arg;
342 #if 0
343 __u16 *sarg = (__u16*)arg;
344 #endif
345
346 switch (cmd) {
347
348 /* --- configuration --- */
349 case TUNER_SET_TYPE:
350 if (t->type != -1)
351 return 0;
352 if (*iarg < 0 || *iarg >= TUNERS)
353 return 0;
354 t->type = *iarg;
355 dprintk("tuner: type set to %d (%s)\n",
356 t->type,tuners[t->type].name);
357 strncpy(client->name, tuners[t->type].name, sizeof(client->name));
358 break;
359 case AUDC_SET_RADIO:
360 t->radio = 1;
361 break;
362
363 /* --- v4l ioctls --- */
364 /* take care: bttv does userspace copying, we'll get a
365 kernel pointer here... */
366 case VIDIOCSCHAN:
367 {
368 struct video_channel *vc = arg;
369
370 t->radio = 0;
371 if (t->type == TUNER_PHILIPS_SECAM) {
372 t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0;
373 set_tv_freq(client,t->freq);
374 }
375 return 0;
376 }
377 case VIDIOCSFREQ:
378 {
379 unsigned long *v = arg;
380
381 t->freq = *v;
382 if (t->radio) {
383 dprintk("tuner: radio freq set to %d.%02d\n",
384 (*iarg)/16,(*iarg)%16*100/16);
385 set_radio_freq(client,t->freq);
386 } else {
387 dprintk("tuner: tv freq set to %d.%02d\n",
388 (*iarg)/16,(*iarg)%16*100/16);
389 set_tv_freq(client,t->freq);
390 }
391 return 0;
392 }
393 case VIDIOCGTUNER:
394 {
395 struct video_tuner *vt = arg;
396
397 if (t->radio)
398 vt->signal = tuner_signal(client);
399 return 0;
400 }
401 case VIDIOCGAUDIO:
402 {
403 struct video_audio *va = arg;
404 if (t->radio)
405 va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
406 return 0;
407 }
408
409 #if 0
410 /* --- old, obsolete interface --- */
411 case TUNER_SET_TVFREQ:
412 dprintk("tuner: tv freq set to %d.%02d\n",
413 (*iarg)/16,(*iarg)%16*100/16);
414 set_tv_freq(client,*iarg);
415 t->radio = 0;
416 t->freq = *iarg;
417 break;
418
419 case TUNER_SET_RADIOFREQ:
420 dprintk("tuner: radio freq set to %d.%02d\n",
421 (*iarg)/16,(*iarg)%16*100/16);
422 set_radio_freq(client,*iarg);
423 t->radio = 1;
424 t->freq = *iarg;
425 break;
426 case TUNER_SET_MODE:
427 if (t->type != TUNER_PHILIPS_SECAM) {
428 dprintk("tuner: trying to change mode for other than TUNER_PHILIPS_SECAM\n");
429 } else {
430 int mode=(*sarg==VIDEO_MODE_SECAM)?1:0;
431 dprintk("tuner: mode set to %d\n", *sarg);
432 t->mode = mode;
433 set_tv_freq(client,t->freq);
434 }
435 break;
436 #endif
437 default:
438 /* nothing */
439 }
440
441 return 0;
442 }
443
444 /* ----------------------------------------------------------------------- */
445
446 static struct i2c_driver driver = {
447 "i2c TV tuner driver",
448 I2C_DRIVERID_TUNER,
449 I2C_DF_NOTIFY,
450 tuner_probe,
451 tuner_detach,
452 tuner_command,
453 };
454
455 static struct i2c_client client_template =
456 {
457 "(unset)", /* name */
458 -1,
459 0,
460 0,
461 NULL,
462 &driver
463 };
464
465 EXPORT_NO_SYMBOLS;
466
467 int tuner_init_module(void)
468 {
469 i2c_add_driver(&driver);
470 return 0;
471 }
472
473 void tuner_cleanup_module(void)
474 {
475 i2c_del_driver(&driver);
476 }
477
478 module_init(tuner_init_module);
479 module_exit(tuner_cleanup_module);
480
481 /*
482 * Overrides for Emacs so that we follow Linus's tabbing style.
483 * ---------------------------------------------------------------------------
484 * Local variables:
485 * c-basic-offset: 8
486 * End:
487 */
488
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.