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