aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tuner-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tuner-core.c')
-rw-r--r--drivers/media/video/tuner-core.c163
1 files changed, 85 insertions, 78 deletions
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index eaabfc85870..6f6bf4a633f 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $ 2 * $Id: tuner-core.c,v 1.29 2005/06/21 15:40:33 mchehab Exp $
3 * 3 *
4 * i2c tv tuner chip device driver 4 * i2c tv tuner chip device driver
5 * core core, i.e. kernel interfaces, registering and so on 5 * core core, i.e. kernel interfaces, registering and so on
@@ -26,7 +26,6 @@
26/* 26/*
27 * comment line bellow to return to old behavor, where only one I2C device is supported 27 * comment line bellow to return to old behavor, where only one I2C device is supported
28 */ 28 */
29#define CONFIG_TUNER_MULTI_I2C /**/
30 29
31#define UNSET (-1U) 30#define UNSET (-1U)
32 31
@@ -58,9 +57,7 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
58MODULE_LICENSE("GPL"); 57MODULE_LICENSE("GPL");
59 58
60static int this_adap; 59static int this_adap;
61#ifdef CONFIG_TUNER_MULTI_I2C
62static unsigned short first_tuner, tv_tuner, radio_tuner; 60static unsigned short first_tuner, tv_tuner, radio_tuner;
63#endif
64 61
65static struct i2c_driver driver; 62static struct i2c_driver driver;
66static struct i2c_client client_template; 63static struct i2c_client client_template;
@@ -81,26 +78,9 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
81 return; 78 return;
82 } 79 }
83 if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { 80 if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
84
85 if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
86 /* V4L2_TUNER_CAP_LOW frequency */
87
88 tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
89
90 t->tv_freq(c,freq>>10);
91
92 return;
93 } else {
94 /* FIXME: better do that chip-specific, but
95 right now we don't have that in the config
96 struct and this way is still better than no
97 check at all */
98 tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", 81 tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
99 freq/16,freq%16*100/16,tv_range[0],tv_range[1]); 82 freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
100 return;
101 }
102 } 83 }
103 tuner_dbg("62.5 Khz freq step selected for TV.\n");
104 t->tv_freq(c,freq); 84 t->tv_freq(c,freq);
105} 85}
106 86
@@ -116,31 +96,18 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
116 tuner_info("no radio tuning for this one, sorry.\n"); 96 tuner_info("no radio tuning for this one, sorry.\n");
117 return; 97 return;
118 } 98 }
119 if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { 99 if (freq >= radio_range[0]*16000 && freq <= radio_range[1]*16000) {
120 if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) { 100 if (tuner_debug)
121 /* V4L2_TUNER_CAP_LOW frequency */ 101 tuner_info("radio freq step 62.5Hz (%d.%06d)\n",
122 if (t->type == TUNER_TEA5767) { 102 freq/16000,freq%16000*1000/16);
123 tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000); 103 t->radio_freq(c,freq);
124 t->radio_freq(c,freq>>10); 104 } else {
125 return; 105 tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
126 } 106 freq/16,freq%16*100/16,
127 107 radio_range[0],radio_range[1]);
128 tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
129
130 tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
131
132 t->radio_freq(c,freq>>10);
133 return;
134
135 } else {
136 tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
137 freq/16,freq%16*100/16,
138 radio_range[0],radio_range[1]);
139 return;
140 }
141 } 108 }
142 tuner_dbg("62.5 Khz freq step selected for Radio.\n"); 109
143 t->radio_freq(c,freq); 110 return;
144} 111}
145 112
146static void set_freq(struct i2c_client *c, unsigned long freq) 113static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -166,8 +133,8 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
166static void set_type(struct i2c_client *c, unsigned int type) 133static void set_type(struct i2c_client *c, unsigned int type)
167{ 134{
168 struct tuner *t = i2c_get_clientdata(c); 135 struct tuner *t = i2c_get_clientdata(c);
136 unsigned char buffer[4];
169 137
170 tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
171 /* sanity check */ 138 /* sanity check */
172 if (type == UNSET || type == TUNER_ABSENT) 139 if (type == UNSET || type == TUNER_ABSENT)
173 return; 140 return;
@@ -179,8 +146,8 @@ static void set_type(struct i2c_client *c, unsigned int type)
179 t->type = type; 146 t->type = type;
180 return; 147 return;
181 } 148 }
182 if (t->initialized) 149 if ((t->initialized) && (t->type == type))
183 /* run only once */ 150 /* run only once except type change Hac 04/05*/
184 return; 151 return;
185 152
186 t->initialized = 1; 153 t->initialized = 1;
@@ -193,25 +160,42 @@ static void set_type(struct i2c_client *c, unsigned int type)
193 case TUNER_PHILIPS_TDA8290: 160 case TUNER_PHILIPS_TDA8290:
194 tda8290_init(c); 161 tda8290_init(c);
195 break; 162 break;
163 case TUNER_TEA5767:
164 if (tea5767_tuner_init(c)==EINVAL) t->type=TUNER_ABSENT;
165 break;
166 case TUNER_PHILIPS_FMD1216ME_MK3:
167 buffer[0] = 0x0b;
168 buffer[1] = 0xdc;
169 buffer[2] = 0x9c;
170 buffer[3] = 0x60;
171 i2c_master_send(c,buffer,4);
172 mdelay(1);
173 buffer[2] = 0x86;
174 buffer[3] = 0x54;
175 i2c_master_send(c,buffer,4);
176 default_tuner_init(c);
177 break;
196 default: 178 default:
179 /* TEA5767 autodetection code */
180 if (tea5767_tuner_init(c)!=EINVAL) {
181 t->type = TUNER_TEA5767;
182 if (first_tuner == 0x60)
183 first_tuner++;
184 break;
185 }
186
197 default_tuner_init(c); 187 default_tuner_init(c);
198 break; 188 break;
199 } 189 }
190 tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
200} 191}
201 192
202#ifdef CONFIG_TUNER_MULTI_I2C
203#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \ 193#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
204 return 0; } else \ 194 return 0; } else if (tuner_debug) \
205 tuner_info ("Cmd %s accepted to "tun"\n",cmd); 195 tuner_info ("Cmd %s accepted to "tun"\n",cmd);
206#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ 196#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \
207 CHECK_ADDR(radio_tuner,cmd,"radio") } else \ 197 CHECK_ADDR(radio_tuner,cmd,"radio") } else \
208 { CHECK_ADDR(tv_tuner,cmd,"TV"); } 198 { CHECK_ADDR(tv_tuner,cmd,"TV"); }
209#else
210#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
211#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
212#endif
213
214#ifdef CONFIG_TUNER_MULTI_I2C
215 199
216static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) 200static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
217{ 201{
@@ -242,9 +226,6 @@ static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
242 } 226 }
243 set_type(c,tun_addr->type); 227 set_type(c,tun_addr->type);
244} 228}
245#else
246#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
247#endif
248 229
249static char pal[] = "-"; 230static char pal[] = "-";
250module_param_string(pal, pal, sizeof(pal), 0644); 231module_param_string(pal, pal, sizeof(pal), 0644);
@@ -284,17 +265,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
284{ 265{
285 struct tuner *t; 266 struct tuner *t;
286 267
287#ifndef CONFIG_TUNER_MULTI_I2C
288 if (this_adap > 0)
289 return -1;
290#else
291 /* by default, first I2C card is both tv and radio tuner */ 268 /* by default, first I2C card is both tv and radio tuner */
292 if (this_adap == 0) { 269 if (this_adap == 0) {
293 first_tuner = addr; 270 first_tuner = addr;
294 tv_tuner = addr; 271 tv_tuner = addr;
295 radio_tuner = addr; 272 radio_tuner = addr;
296 } 273 }
297#endif
298 this_adap++; 274 this_adap++;
299 275
300 client_template.adapter = adap; 276 client_template.adapter = adap;
@@ -308,6 +284,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
308 i2c_set_clientdata(&t->i2c, t); 284 i2c_set_clientdata(&t->i2c, t);
309 t->type = UNSET; 285 t->type = UNSET;
310 t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */ 286 t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */
287 t->audmode = V4L2_TUNER_MODE_STEREO;
311 288
312 i2c_attach_client(&t->i2c); 289 i2c_attach_client(&t->i2c);
313 tuner_info("chip found @ 0x%x (%s)\n", 290 tuner_info("chip found @ 0x%x (%s)\n",
@@ -325,11 +302,9 @@ static int tuner_probe(struct i2c_adapter *adap)
325 } 302 }
326 this_adap = 0; 303 this_adap = 0;
327 304
328#ifdef CONFIG_TUNER_MULTI_I2C
329 first_tuner = 0; 305 first_tuner = 0;
330 tv_tuner = 0; 306 tv_tuner = 0;
331 radio_tuner = 0; 307 radio_tuner = 0;
332#endif
333 308
334 if (adap->class & I2C_CLASS_TV_ANALOG) 309 if (adap->class & I2C_CLASS_TV_ANALOG)
335 return i2c_probe(adap, &addr_data, tuner_attach); 310 return i2c_probe(adap, &addr_data, tuner_attach);
@@ -392,8 +367,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
392 t->radio_if2 = 41300 * 1000; 367 t->radio_if2 = 41300 * 1000;
393 break; 368 break;
394 } 369 }
395 break; 370 break;
396
397 /* --- v4l ioctls --- */ 371 /* --- v4l ioctls --- */
398 /* take care: bttv does userspace copying, we'll get a 372 /* take care: bttv does userspace copying, we'll get a
399 kernel pointer here... */ 373 kernel pointer here... */
@@ -440,11 +414,18 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
440 vt->signal = t->has_signal(client); 414 vt->signal = t->has_signal(client);
441 if (t->is_stereo) { 415 if (t->is_stereo) {
442 if (t->is_stereo(client)) 416 if (t->is_stereo(client))
443 vt-> flags |= VIDEO_TUNER_STEREO_ON; 417 vt->flags |= VIDEO_TUNER_STEREO_ON;
444 else 418 else
445 vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON; 419 vt->flags &= ~VIDEO_TUNER_STEREO_ON;
446 } 420 }
447 vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */ 421 vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
422
423 vt->rangelow = radio_range[0] * 16000;
424 vt->rangehigh = radio_range[1] * 16000;
425
426 } else {
427 vt->rangelow = tv_range[0] * 16;
428 vt->rangehigh = tv_range[1] * 16;
448 } 429 }
449 430
450 return 0; 431 return 0;
@@ -510,20 +491,46 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
510 tuner -> signal = t->has_signal(client); 491 tuner -> signal = t->has_signal(client);
511 if (t->is_stereo) { 492 if (t->is_stereo) {
512 if (t->is_stereo(client)) { 493 if (t->is_stereo(client)) {
513 tuner -> capability |= V4L2_TUNER_CAP_STEREO; 494 tuner -> rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
514 tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
515 } else { 495 } else {
516 tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO; 496 tuner -> rxsubchans = V4L2_TUNER_SUB_MONO;
517 } 497 }
518 } 498 }
499 tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
500 tuner->audmode = t->audmode;
501
502 tuner->rangelow = radio_range[0] * 16000;
503 tuner->rangehigh = radio_range[1] * 16000;
504 } else {
505 tuner->rangelow = tv_range[0] * 16;
506 tuner->rangehigh = tv_range[1] * 16;
519 } 507 }
520 /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */
521 tuner->rangelow = tv_range[0] * 16;
522// tuner->rangehigh = tv_range[1] * 16;
523// tuner->rangelow = tv_range[0] * 16384;
524 tuner->rangehigh = tv_range[1] * 16384;
525 break; 508 break;
526 } 509 }
510 case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */
511 {
512 struct v4l2_tuner *tuner = arg;
513
514 CHECK_ADDR(radio_tuner,"VIDIOC_S_TUNER","radio");
515 SWITCH_V4L2;
516
517 /* To switch the audio mode, applications initialize the
518 index and audmode fields and the reserved array and
519 call the VIDIOC_S_TUNER ioctl. */
520 /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
521 V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
522 V4L2_TUNER_MODE_SAP */
523
524 if (tuner->audmode == V4L2_TUNER_MODE_MONO)
525 t->audmode = V4L2_TUNER_MODE_MONO;
526 else
527 t->audmode = V4L2_TUNER_MODE_STEREO;
528
529 set_radio_freq(client, t->freq);
530 break;
531 }
532 case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */
533 break;
527 default: 534 default:
528 tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd); 535 tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
529 /* nothing */ 536 /* nothing */