V4L/DVB (4203): Explicitly set the enum values.
[deliverable/linux.git] / drivers / media / video / tuner-core.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 *
3 * i2c tv tuner chip device driver
4 * core core, i.e. kernel interfaces, registering and so on
5 */
6
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/string.h>
12#include <linux/timer.h>
13#include <linux/delay.h>
14#include <linux/errno.h>
15#include <linux/slab.h>
16#include <linux/poll.h>
17#include <linux/i2c.h>
18#include <linux/types.h>
19#include <linux/videodev.h>
20#include <linux/init.h>
21
22#include <media/tuner.h>
5e453dc7 23#include <media/v4l2-common.h>
1da177e4
LT
24
25#define UNSET (-1U)
26
27/* standard i2c insmod options */
28static unsigned short normal_i2c[] = {
de48eebc 29 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
f5bec396
MCC
30 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
31 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1da177e4
LT
32 I2C_CLIENT_END
33};
f7ce3cc6 34
1da177e4
LT
35I2C_CLIENT_INSMOD;
36
37/* insmod options used at init time => read/only */
f7ce3cc6 38static unsigned int addr = 0;
c5287ba1 39static unsigned int no_autodetect = 0;
fd3113e8 40static unsigned int show_i2c = 0;
fd3113e8 41
1da177e4 42/* insmod options used at runtime => read/write */
f9195ded
HV
43static unsigned int tuner_debug_old = 0;
44int tuner_debug = 0;
1da177e4 45
f7ce3cc6 46static unsigned int tv_range[2] = { 44, 958 };
1da177e4
LT
47static unsigned int radio_range[2] = { 65, 108 };
48
7e578191
MCC
49static char pal[] = "--";
50static char secam[] = "--";
51static char ntsc[] = "-";
52
f9195ded 53
7e578191
MCC
54module_param(addr, int, 0444);
55module_param(no_autodetect, int, 0444);
56module_param(show_i2c, int, 0444);
fac9e899 57/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */
f9195ded
HV
58module_param_named(tuner_debug,tuner_debug_old, int, 0444);
59module_param_named(debug,tuner_debug, int, 0644);
7e578191
MCC
60module_param_string(pal, pal, sizeof(pal), 0644);
61module_param_string(secam, secam, sizeof(secam), 0644);
62module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
f7ce3cc6 63module_param_array(tv_range, int, NULL, 0644);
1da177e4
LT
64module_param_array(radio_range, int, NULL, 0644);
65
66MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
67MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
68MODULE_LICENSE("GPL");
69
1da177e4
LT
70static struct i2c_driver driver;
71static struct i2c_client client_template;
72
73/* ---------------------------------------------------------------------- */
74
56fc08ca 75/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
1da177e4
LT
76static void set_tv_freq(struct i2c_client *c, unsigned int freq)
77{
78 struct tuner *t = i2c_get_clientdata(c);
79
80 if (t->type == UNSET) {
f7ce3cc6 81 tuner_warn ("tuner type not set\n");
1da177e4
LT
82 return;
83 }
27487d44 84 if (NULL == t->set_tv_freq) {
f7ce3cc6 85 tuner_warn ("Tuner has no way to set tv freq\n");
1da177e4
LT
86 return;
87 }
f7ce3cc6
MCC
88 if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
89 tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
90 freq / 16, freq % 16 * 100 / 16, tv_range[0],
91 tv_range[1]);
27487d44
HV
92 /* V4L2 spec: if the freq is not possible then the closest
93 possible value should be selected */
94 if (freq < tv_range[0] * 16)
95 freq = tv_range[0] * 16;
96 else
97 freq = tv_range[1] * 16;
1da177e4 98 }
27487d44 99 t->set_tv_freq(c, freq);
1da177e4
LT
100}
101
102static void set_radio_freq(struct i2c_client *c, unsigned int freq)
103{
104 struct tuner *t = i2c_get_clientdata(c);
105
106 if (t->type == UNSET) {
f7ce3cc6 107 tuner_warn ("tuner type not set\n");
1da177e4
LT
108 return;
109 }
27487d44 110 if (NULL == t->set_radio_freq) {
f7ce3cc6 111 tuner_warn ("tuner has no way to set radio frequency\n");
1da177e4
LT
112 return;
113 }
27487d44 114 if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
f7ce3cc6
MCC
115 tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
116 freq / 16000, freq % 16000 * 100 / 16000,
117 radio_range[0], radio_range[1]);
27487d44
HV
118 /* V4L2 spec: if the freq is not possible then the closest
119 possible value should be selected */
120 if (freq < radio_range[0] * 16000)
121 freq = radio_range[0] * 16000;
122 else
123 freq = radio_range[1] * 16000;
1da177e4 124 }
586b0cab 125
27487d44 126 t->set_radio_freq(c, freq);
1da177e4
LT
127}
128
129static void set_freq(struct i2c_client *c, unsigned long freq)
130{
131 struct tuner *t = i2c_get_clientdata(c);
132
133 switch (t->mode) {
134 case V4L2_TUNER_RADIO:
135 tuner_dbg("radio freq set to %lu.%02lu\n",
f7ce3cc6
MCC
136 freq / 16000, freq % 16000 * 100 / 16000);
137 set_radio_freq(c, freq);
27487d44 138 t->radio_freq = freq;
1da177e4
LT
139 break;
140 case V4L2_TUNER_ANALOG_TV:
141 case V4L2_TUNER_DIGITAL_TV:
142 tuner_dbg("tv freq set to %lu.%02lu\n",
f7ce3cc6 143 freq / 16, freq % 16 * 100 / 16);
1da177e4 144 set_tv_freq(c, freq);
27487d44 145 t->tv_freq = freq;
1da177e4
LT
146 break;
147 }
1da177e4
LT
148}
149
f7ce3cc6
MCC
150static void set_type(struct i2c_client *c, unsigned int type,
151 unsigned int new_mode_mask)
1da177e4
LT
152{
153 struct tuner *t = i2c_get_clientdata(c);
586b0cab 154 unsigned char buffer[4];
1da177e4 155
f7ce3cc6
MCC
156 if (type == UNSET || type == TUNER_ABSENT) {
157 tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr);
1da177e4 158 return;
f7ce3cc6
MCC
159 }
160
161 if (type >= tuner_count) {
162 tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
1da177e4 163 return;
f7ce3cc6 164 }
1da177e4 165
f7ce3cc6 166 /* This code detects calls by card attach_inform */
1da177e4 167 if (NULL == t->i2c.dev.driver) {
f7ce3cc6
MCC
168 tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr);
169
170 t->type=type;
1da177e4
LT
171 return;
172 }
56fc08ca 173
1da177e4
LT
174 t->type = type;
175 switch (t->type) {
176 case TUNER_MT2032:
177 microtune_init(c);
178 break;
179 case TUNER_PHILIPS_TDA8290:
180 tda8290_init(c);
181 break;
586b0cab 182 case TUNER_TEA5767:
f7ce3cc6
MCC
183 if (tea5767_tuner_init(c) == EINVAL) {
184 t->type = TUNER_ABSENT;
185 t->mode_mask = T_UNINITIALIZED;
186 return;
187 }
188 t->mode_mask = T_RADIO;
586b0cab
MCC
189 break;
190 case TUNER_PHILIPS_FMD1216ME_MK3:
191 buffer[0] = 0x0b;
192 buffer[1] = 0xdc;
193 buffer[2] = 0x9c;
194 buffer[3] = 0x60;
f7ce3cc6 195 i2c_master_send(c, buffer, 4);
586b0cab
MCC
196 mdelay(1);
197 buffer[2] = 0x86;
198 buffer[3] = 0x54;
f7ce3cc6 199 i2c_master_send(c, buffer, 4);
586b0cab
MCC
200 default_tuner_init(c);
201 break;
9c26c8b1 202 case TUNER_LG_TDVS_H06XF:
793cf9e6
MCC
203 /* Set the Auxiliary Byte. */
204 buffer[2] &= ~0x20;
205 buffer[2] |= 0x18;
206 buffer[3] = 0x20;
207 i2c_master_send(c, buffer, 4);
208 default_tuner_init(c);
209 break;
93df3413
HH
210 case TUNER_PHILIPS_TD1316:
211 buffer[0] = 0x0b;
212 buffer[1] = 0xdc;
213 buffer[2] = 0x86;
214 buffer[3] = 0xa4;
215 i2c_master_send(c,buffer,4);
216 default_tuner_init(c);
ac272ed7 217 break;
1da177e4
LT
218 default:
219 default_tuner_init(c);
220 break;
221 }
f7ce3cc6
MCC
222
223 if (t->mode_mask == T_UNINITIALIZED)
224 t->mode_mask = new_mode_mask;
225
27487d44 226 set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
f7ce3cc6 227 tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
604f28e2 228 c->adapter->name, c->driver->driver.name, c->addr << 1, type,
f7ce3cc6 229 t->mode_mask);
1da177e4
LT
230}
231
f7ce3cc6
MCC
232/*
233 * This function apply tuner config to tuner specified
234 * by tun_setup structure. I addr is unset, then admin status
235 * and tun addr status is more precise then current status,
236 * it's applied. Otherwise status and type are applied only to
237 * tuner with exactly the same addr.
238*/
239
240static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
241{
242 struct tuner *t = i2c_get_clientdata(c);
243
291d1d73 244 if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET &&
793cf9e6 245 (t->mode_mask & tun_setup->mode_mask)) ||
291d1d73 246 tun_setup->addr == c->addr)) {
f7ce3cc6 247 set_type(c, tun_setup->type, tun_setup->mode_mask);
f7ce3cc6
MCC
248 }
249}
56fc08ca 250
f7ce3cc6 251static inline int check_mode(struct tuner *t, char *cmd)
56fc08ca 252{
793cf9e6
MCC
253 if ((1 << t->mode & t->mode_mask) == 0) {
254 return EINVAL;
255 }
256
257 switch (t->mode) {
258 case V4L2_TUNER_RADIO:
259 tuner_dbg("Cmd %s accepted for radio\n", cmd);
260 break;
261 case V4L2_TUNER_ANALOG_TV:
262 tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
263 break;
264 case V4L2_TUNER_DIGITAL_TV:
265 tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
266 break;
56fc08ca 267 }
793cf9e6 268 return 0;
56fc08ca 269}
56fc08ca 270
f7ce3cc6 271/* get more precise norm info from insmod option */
1da177e4
LT
272static int tuner_fixup_std(struct tuner *t)
273{
274 if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
1da177e4
LT
275 switch (pal[0]) {
276 case 'b':
277 case 'B':
278 case 'g':
279 case 'G':
f7ce3cc6 280 tuner_dbg ("insmod fixup: PAL => PAL-BG\n");
1da177e4
LT
281 t->std = V4L2_STD_PAL_BG;
282 break;
283 case 'i':
284 case 'I':
f7ce3cc6 285 tuner_dbg ("insmod fixup: PAL => PAL-I\n");
1da177e4
LT
286 t->std = V4L2_STD_PAL_I;
287 break;
288 case 'd':
289 case 'D':
290 case 'k':
291 case 'K':
f7ce3cc6 292 tuner_dbg ("insmod fixup: PAL => PAL-DK\n");
1da177e4
LT
293 t->std = V4L2_STD_PAL_DK;
294 break;
f7ce3cc6
MCC
295 case 'M':
296 case 'm':
297 tuner_dbg ("insmod fixup: PAL => PAL-M\n");
298 t->std = V4L2_STD_PAL_M;
299 break;
300 case 'N':
301 case 'n':
7e578191
MCC
302 if (pal[1] == 'c' || pal[1] == 'C') {
303 tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
304 t->std = V4L2_STD_PAL_Nc;
305 } else {
306 tuner_dbg ("insmod fixup: PAL => PAL-N\n");
307 t->std = V4L2_STD_PAL_N;
308 }
f7ce3cc6 309 break;
21d4df37
MCC
310 case '-':
311 /* default parameter, do nothing */
312 break;
313 default:
314 tuner_warn ("pal= argument not recognised\n");
315 break;
1da177e4
LT
316 }
317 }
f7ce3cc6
MCC
318 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
319 switch (secam[0]) {
7e578191
MCC
320 case 'b':
321 case 'B':
322 case 'g':
323 case 'G':
324 case 'h':
325 case 'H':
326 tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
327 t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
328 break;
f7ce3cc6
MCC
329 case 'd':
330 case 'D':
331 case 'k':
332 case 'K':
333 tuner_dbg ("insmod fixup: SECAM => SECAM-DK\n");
334 t->std = V4L2_STD_SECAM_DK;
335 break;
336 case 'l':
337 case 'L':
800d3c6f
MCC
338 if ((secam[1]=='C')||(secam[1]=='c')) {
339 tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n");
340 t->std = V4L2_STD_SECAM_LC;
341 } else {
342 tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
343 t->std = V4L2_STD_SECAM_L;
344 }
f7ce3cc6 345 break;
21d4df37
MCC
346 case '-':
347 /* default parameter, do nothing */
348 break;
349 default:
350 tuner_warn ("secam= argument not recognised\n");
351 break;
f7ce3cc6
MCC
352 }
353 }
354
7e578191
MCC
355 if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
356 switch (ntsc[0]) {
357 case 'm':
358 case 'M':
359 tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
360 t->std = V4L2_STD_NTSC_M;
361 break;
362 case 'j':
363 case 'J':
364 tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
365 t->std = V4L2_STD_NTSC_M_JP;
366 break;
d97a11e0
HV
367 case 'k':
368 case 'K':
369 tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
370 t->std = V4L2_STD_NTSC_M_KR;
371 break;
7e578191
MCC
372 case '-':
373 /* default parameter, do nothing */
374 break;
375 default:
376 tuner_info("ntsc= argument not recognised\n");
377 break;
378 }
379 }
1da177e4
LT
380 return 0;
381}
382
7e578191
MCC
383static void tuner_status(struct i2c_client *client)
384{
385 struct tuner *t = i2c_get_clientdata(client);
386 unsigned long freq, freq_fraction;
387 const char *p;
388
389 switch (t->mode) {
390 case V4L2_TUNER_RADIO: p = "radio"; break;
391 case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break;
392 case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
393 default: p = "undefined"; break;
394 }
395 if (t->mode == V4L2_TUNER_RADIO) {
27487d44
HV
396 freq = t->radio_freq / 16000;
397 freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
7e578191 398 } else {
27487d44
HV
399 freq = t->tv_freq / 16;
400 freq_fraction = (t->tv_freq % 16) * 100 / 16;
7e578191
MCC
401 }
402 tuner_info("Tuner mode: %s\n", p);
403 tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
4ae5c2e5 404 tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
8a4b275f
HV
405 if (t->mode != V4L2_TUNER_RADIO)
406 return;
407 if (t->has_signal) {
408 tuner_info("Signal strength: %d\n", t->has_signal(client));
409 }
410 if (t->is_stereo) {
411 tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no");
7e578191
MCC
412 }
413}
8a4b275f 414
1da177e4
LT
415/* ---------------------------------------------------------------------- */
416
f7ce3cc6
MCC
417/* static var Used only in tuner_attach and tuner_probe */
418static unsigned default_mode_mask;
419
420/* During client attach, set_type is called by adapter's attach_inform callback.
421 set_type must then be completed by tuner_attach.
422 */
1da177e4
LT
423static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
424{
425 struct tuner *t;
426
f7ce3cc6
MCC
427 client_template.adapter = adap;
428 client_template.addr = addr;
1da177e4 429
7408187d 430 t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
f7ce3cc6
MCC
431 if (NULL == t)
432 return -ENOMEM;
f7ce3cc6 433 memcpy(&t->i2c, &client_template, sizeof(struct i2c_client));
1da177e4 434 i2c_set_clientdata(&t->i2c, t);
f7ce3cc6
MCC
435 t->type = UNSET;
436 t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
437 t->audmode = V4L2_TUNER_MODE_STEREO;
438 t->mode_mask = T_UNINITIALIZED;
f9195ded
HV
439 if (tuner_debug_old) {
440 tuner_debug = tuner_debug_old;
fac9e899
HV
441 printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
442 printk(KERN_ERR "tuner: use the debug option instead.\n");
443 }
f7ce3cc6 444
fd3113e8
MCC
445 if (show_i2c) {
446 unsigned char buffer[16];
447 int i,rc;
448
449 memset(buffer, 0, sizeof(buffer));
450 rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer));
67678360 451 tuner_info("I2C RECV = ");
fd3113e8
MCC
452 for (i=0;i<rc;i++)
453 printk("%02x ",buffer[i]);
454 printk("\n");
455 }
257c645d 456 /* autodetection code based on the i2c addr */
c5287ba1 457 if (!no_autodetect) {
13dd38d0 458 switch (addr) {
13dd38d0
MCC
459 case 0x42:
460 case 0x43:
461 case 0x4a:
95736034 462 case 0x4b:
67678360
MCC
463 /* If chip is not tda8290, don't register.
464 since it can be tda9887*/
95736034 465 if (tda8290_probe(&t->i2c) != 0) {
b228ede4 466 tuner_dbg("chip at addr %x is not a tda8290\n", addr);
13dd38d0
MCC
467 kfree(t);
468 return 0;
469 }
07345f5d
HH
470 break;
471 case 0x60:
472 if (tea5767_autodetection(&t->i2c) != EINVAL) {
473 t->type = TUNER_TEA5767;
474 t->mode_mask = T_RADIO;
475 t->mode = T_STANDBY;
27487d44 476 t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
07345f5d 477 default_mode_mask &= ~T_RADIO;
13dd38d0 478
07345f5d
HH
479 goto register_client;
480 }
481 break;
f7ce3cc6
MCC
482 }
483 }
1da177e4 484
f7ce3cc6
MCC
485 /* Initializes only the first adapter found */
486 if (default_mode_mask != T_UNINITIALIZED) {
487 tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask);
488 t->mode_mask = default_mode_mask;
27487d44
HV
489 t->tv_freq = 400 * 16; /* Sets freq to VHF High */
490 t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
f7ce3cc6
MCC
491 default_mode_mask = T_UNINITIALIZED;
492 }
56fc08ca 493
f7ce3cc6 494 /* Should be just before return */
67678360
MCC
495register_client:
496 tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
f7ce3cc6
MCC
497 i2c_attach_client (&t->i2c);
498 set_type (&t->i2c,t->type, t->mode_mask);
1da177e4
LT
499 return 0;
500}
501
502static int tuner_probe(struct i2c_adapter *adap)
503{
504 if (0 != addr) {
f5bec396
MCC
505 normal_i2c[0] = addr;
506 normal_i2c[1] = I2C_CLIENT_END;
1da177e4 507 }
1da177e4 508
f7ce3cc6 509 default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
391cd727 510
1da177e4
LT
511 if (adap->class & I2C_CLASS_TV_ANALOG)
512 return i2c_probe(adap, &addr_data, tuner_attach);
513 return 0;
514}
515
516static int tuner_detach(struct i2c_client *client)
517{
518 struct tuner *t = i2c_get_clientdata(client);
391cd727
MCC
519 int err;
520
f7ce3cc6 521 err = i2c_detach_client(&t->i2c);
391cd727 522 if (err) {
f7ce3cc6
MCC
523 tuner_warn
524 ("Client deregistration failed, client not detached.\n");
391cd727
MCC
525 return err;
526 }
1da177e4 527
1da177e4
LT
528 kfree(t);
529 return 0;
530}
531
f7ce3cc6
MCC
532/*
533 * Switch tuner to other mode. If tuner support both tv and radio,
534 * set another frequency to some value (This is needed for some pal
535 * tuners to avoid locking). Otherwise, just put second tuner in
536 * standby mode.
537 */
538
539static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
540{
4ac97914
MCC
541 if (mode == t->mode)
542 return 0;
543
544 t->mode = mode;
545
546 if (check_mode(t, cmd) == EINVAL) {
547 t->mode = T_STANDBY;
548 if (t->standby)
549 t->standby (client);
550 return EINVAL;
551 }
552 return 0;
f7ce3cc6
MCC
553}
554
555#define switch_v4l2() if (!t->using_v4l2) \
4ac97914
MCC
556 tuner_dbg("switching to v4l2\n"); \
557 t->using_v4l2 = 1;
f7ce3cc6
MCC
558
559static inline int check_v4l2(struct tuner *t)
560{
3bbe5a83
HV
561 /* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
562 TV, v4l1 for radio), until that is fixed this code is disabled.
563 Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
564 first. */
f7ce3cc6
MCC
565 return 0;
566}
1da177e4 567
f7ce3cc6 568static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
1da177e4
LT
569{
570 struct tuner *t = i2c_get_clientdata(client);
1da177e4 571
f9195ded 572 if (tuner_debug>1)
5e453dc7
MK
573 v4l_i2c_print_ioctl(&(t->i2c),cmd);
574
f7ce3cc6 575 switch (cmd) {
1da177e4 576 /* --- configuration --- */
56fc08ca 577 case TUNER_SET_TYPE_ADDR:
f7ce3cc6
MCC
578 tuner_dbg ("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x\n",
579 ((struct tuner_setup *)arg)->type,
580 ((struct tuner_setup *)arg)->addr,
581 ((struct tuner_setup *)arg)->mode_mask);
582
583 set_addr(client, (struct tuner_setup *)arg);
391cd727 584 break;
1da177e4 585 case AUDC_SET_RADIO:
27487d44
HV
586 if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
587 == EINVAL)
588 return 0;
589 if (t->radio_freq)
590 set_freq(client, t->radio_freq);
1da177e4 591 break;
793cf9e6 592 case TUNER_SET_STANDBY:
27487d44
HV
593 if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
594 return 0;
595 if (t->standby)
596 t->standby (client);
597 break;
fd3113e8
MCC
598 case VIDIOCSAUDIO:
599 if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
600 return 0;
601 if (check_v4l2(t) == EINVAL)
602 return 0;
603
604 /* Should be implemented, since bttv calls it */
605 tuner_dbg("VIDIOCSAUDIO not implemented.\n");
f7ce3cc6 606 break;
1da177e4
LT
607 /* --- v4l ioctls --- */
608 /* take care: bttv does userspace copying, we'll get a
609 kernel pointer here... */
610 case VIDIOCSCHAN:
f7ce3cc6
MCC
611 {
612 static const v4l2_std_id map[] = {
613 [VIDEO_MODE_PAL] = V4L2_STD_PAL,
614 [VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M,
615 [VIDEO_MODE_SECAM] = V4L2_STD_SECAM,
616 [4 /* bttv */ ] = V4L2_STD_PAL_M,
617 [5 /* bttv */ ] = V4L2_STD_PAL_N,
618 [6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
619 };
620 struct video_channel *vc = arg;
621
622 if (check_v4l2(t) == EINVAL)
623 return 0;
624
625 if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL)
626 return 0;
627
628 if (vc->norm < ARRAY_SIZE(map))
629 t->std = map[vc->norm];
630 tuner_fixup_std(t);
27487d44
HV
631 if (t->tv_freq)
632 set_tv_freq(client, t->tv_freq);
f7ce3cc6
MCC
633 return 0;
634 }
1da177e4 635 case VIDIOCSFREQ:
f7ce3cc6
MCC
636 {
637 unsigned long *v = arg;
1da177e4 638
f7ce3cc6
MCC
639 if (check_mode(t, "VIDIOCSFREQ") == EINVAL)
640 return 0;
641 if (check_v4l2(t) == EINVAL)
642 return 0;
643
644 set_freq(client, *v);
645 return 0;
646 }
1da177e4 647 case VIDIOCGTUNER:
f7ce3cc6
MCC
648 {
649 struct video_tuner *vt = arg;
650
651 if (check_mode(t, "VIDIOCGTUNER") == EINVAL)
652 return 0;
653 if (check_v4l2(t) == EINVAL)
654 return 0;
655
656 if (V4L2_TUNER_RADIO == t->mode) {
657 if (t->has_signal)
658 vt->signal = t->has_signal(client);
659 if (t->is_stereo) {
660 if (t->is_stereo(client))
661 vt->flags |=
662 VIDEO_TUNER_STEREO_ON;
663 else
664 vt->flags &=
665 ~VIDEO_TUNER_STEREO_ON;
666 }
667 vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */
586b0cab 668
f7ce3cc6
MCC
669 vt->rangelow = radio_range[0] * 16000;
670 vt->rangehigh = radio_range[1] * 16000;
586b0cab 671
f7ce3cc6
MCC
672 } else {
673 vt->rangelow = tv_range[0] * 16;
674 vt->rangehigh = tv_range[1] * 16;
675 }
56fc08ca 676
f7ce3cc6
MCC
677 return 0;
678 }
1da177e4 679 case VIDIOCGAUDIO:
f7ce3cc6
MCC
680 {
681 struct video_audio *va = arg;
682
683 if (check_mode(t, "VIDIOCGAUDIO") == EINVAL)
684 return 0;
685 if (check_v4l2(t) == EINVAL)
686 return 0;
687
688 if (V4L2_TUNER_RADIO == t->mode && t->is_stereo)
689 va->mode = t->is_stereo(client)
690 ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
691 return 0;
692 }
1da177e4
LT
693
694 case VIDIOC_S_STD:
f7ce3cc6
MCC
695 {
696 v4l2_std_id *id = arg;
1da177e4 697
f7ce3cc6
MCC
698 if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
699 == EINVAL)
700 return 0;
56fc08ca 701
f7ce3cc6
MCC
702 switch_v4l2();
703
704 t->std = *id;
705 tuner_fixup_std(t);
27487d44
HV
706 if (t->tv_freq)
707 set_freq(client, t->tv_freq);
f7ce3cc6
MCC
708 break;
709 }
1da177e4 710 case VIDIOC_S_FREQUENCY:
f7ce3cc6
MCC
711 {
712 struct v4l2_frequency *f = arg;
713
f7ce3cc6 714 switch_v4l2();
df8cf706
HH
715 if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode)
716 || (V4L2_TUNER_DIGITAL_TV == f->type
717 && V4L2_TUNER_DIGITAL_TV != t->mode)) {
4ac97914 718 if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
f7ce3cc6
MCC
719 == EINVAL)
720 return 0;
721 }
27487d44 722 set_freq(client,f->frequency);
c184ca36 723
f7ce3cc6
MCC
724 break;
725 }
726 case VIDIOC_G_FREQUENCY:
727 {
728 struct v4l2_frequency *f = arg;
729
730 if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL)
731 return 0;
732 switch_v4l2();
733 f->type = t->mode;
27487d44
HV
734 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
735 t->radio_freq : t->tv_freq;
f7ce3cc6
MCC
736 break;
737 }
1da177e4 738 case VIDIOC_G_TUNER:
f7ce3cc6
MCC
739 {
740 struct v4l2_tuner *tuner = arg;
741
742 if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL)
743 return 0;
744 switch_v4l2();
745
8a4b275f 746 tuner->type = t->mode;
ab4cecf9
HV
747 if (t->mode == V4L2_TUNER_ANALOG_TV)
748 tuner->capability |= V4L2_TUNER_CAP_NORM;
8a4b275f 749 if (t->mode != V4L2_TUNER_RADIO) {
f7ce3cc6
MCC
750 tuner->rangelow = tv_range[0] * 16;
751 tuner->rangehigh = tv_range[1] * 16;
8a4b275f
HV
752 break;
753 }
754
755 /* radio mode */
756 if (t->has_signal)
757 tuner->signal = t->has_signal(client);
758
759 tuner->rxsubchans =
760 V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
761 if (t->is_stereo) {
762 tuner->rxsubchans = t->is_stereo(client) ?
763 V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
56fc08ca 764 }
8a4b275f
HV
765
766 tuner->capability |=
767 V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
768 tuner->audmode = t->audmode;
769 tuner->rangelow = radio_range[0] * 16000;
770 tuner->rangehigh = radio_range[1] * 16000;
f7ce3cc6
MCC
771 break;
772 }
773 case VIDIOC_S_TUNER:
774 {
775 struct v4l2_tuner *tuner = arg;
776
777 if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL)
778 return 0;
779
780 switch_v4l2();
781
8a4b275f
HV
782 /* do nothing unless we're a radio tuner */
783 if (t->mode != V4L2_TUNER_RADIO)
784 break;
785 t->audmode = tuner->audmode;
786 set_radio_freq(client, t->radio_freq);
f7ce3cc6 787 break;
56fc08ca 788 }
cd43c3f6
HV
789 case VIDIOC_LOG_STATUS:
790 tuner_status(client);
791 break;
1da177e4
LT
792 }
793
794 return 0;
795}
796
9480e307 797static int tuner_suspend(struct device *dev, pm_message_t state)
1da177e4 798{
f7ce3cc6
MCC
799 struct i2c_client *c = container_of (dev, struct i2c_client, dev);
800 struct tuner *t = i2c_get_clientdata (c);
1da177e4 801
f7ce3cc6 802 tuner_dbg ("suspend\n");
1da177e4
LT
803 /* FIXME: power down ??? */
804 return 0;
805}
806
9480e307 807static int tuner_resume(struct device *dev)
1da177e4 808{
f7ce3cc6
MCC
809 struct i2c_client *c = container_of (dev, struct i2c_client, dev);
810 struct tuner *t = i2c_get_clientdata (c);
1da177e4 811
f7ce3cc6 812 tuner_dbg ("resume\n");
27487d44
HV
813 if (V4L2_TUNER_RADIO == t->mode) {
814 if (t->radio_freq)
815 set_freq(c, t->radio_freq);
816 } else {
817 if (t->tv_freq)
818 set_freq(c, t->tv_freq);
819 }
1da177e4
LT
820 return 0;
821}
822
823/* ----------------------------------------------------------------------- */
824
825static struct i2c_driver driver = {
f7ce3cc6 826 .id = I2C_DRIVERID_TUNER,
f7ce3cc6
MCC
827 .attach_adapter = tuner_probe,
828 .detach_client = tuner_detach,
829 .command = tuner_command,
1da177e4 830 .driver = {
cab462f7
MCC
831 .name = "tuner",
832 .suspend = tuner_suspend,
833 .resume = tuner_resume,
834 },
1da177e4 835};
f7ce3cc6 836static struct i2c_client client_template = {
fae91e72 837 .name = "(tuner unset)",
f7ce3cc6 838 .driver = &driver,
1da177e4
LT
839};
840
841static int __init tuner_init_module(void)
842{
843 return i2c_add_driver(&driver);
844}
845
846static void __exit tuner_cleanup_module(void)
847{
848 i2c_del_driver(&driver);
849}
850
851module_init(tuner_init_module);
852module_exit(tuner_cleanup_module);
853
854/*
855 * Overrides for Emacs so that we follow Linus's tabbing style.
856 * ---------------------------------------------------------------------------
857 * Local variables:
858 * c-basic-offset: 8
859 * End:
860 */
This page took 0.609092 seconds and 5 git commands to generate.