Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] tuner-core.c improvments and Ymec Tvision TVF8533MF support

tuner-core.c, tuner.h:

- tuner-core changed to support multiple I2C devices used on some
adapters;

- Kconfig now has an option (CONFIG_TUNER_MULTI_I2C) to enable this new
behavor;

- By default, even enabling CONFIG_TUNER_MULTI_I2C, tuner-core emulates
the old behavor, using first I2C device for both FM and TV;

- There is a new i2c command (TUNER_SET_ADDR) to allow tuner clients to
select I2C address for FM or TV tuner;

- Tuner I2C dettach now generates a warning on syslog if failed.

tuner-simple.c:

- TVision TVF-8531MF and TVF-5533 MF tuner included. It uses, by
default, I2C on 0xC2 address for TV and on 0xC0 for Radio. Both TV and
FM Radio mode are working.

Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Mauro Carvalho Chehab and committed by
Linus Torvalds
391cd727 55f51efd

+126 -4
+13
drivers/media/video/Kconfig
··· 7 7 8 8 comment "Video Adapters" 9 9 10 + config CONFIG_TUNER_MULTI_I2C 11 + bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)" 12 + depends on VIDEO_DEV && EXPERIMENTAL 13 + ---help--- 14 + Some video adapters have more than one tuner inside. This patch 15 + enables support for using more than one tuner. This is required 16 + for some cards to allow tunning both video and radio. 17 + It also improves I2C autodetection for these cards. 18 + 19 + Only few tuners currently is supporting this. More to come. 20 + 21 + It is safe to say 'Y' here even if your card has only one I2C tuner. 22 + 10 23 config VIDEO_BT848 11 24 tristate "BT848 Video For Linux" 12 25 depends on VIDEO_DEV && PCI && I2C
+76 -3
drivers/media/video/tuner-core.c
··· 1 1 /* 2 - * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $ 2 + * $Id: tuner-core.c,v 1.7 2005/05/30 02:02:47 mchehab Exp $ 3 3 * 4 4 * i2c tv tuner chip device driver 5 5 * core core, i.e. kernel interfaces, registering and so on ··· 22 22 23 23 #include <media/tuner.h> 24 24 #include <media/audiochip.h> 25 + 26 + /* 27 + * comment line bellow to return to old behavor, where only one I2C device is supported 28 + */ 29 + /* #define CONFIG_TUNER_MULTI_I2C */ 25 30 26 31 #define UNSET (-1U) 27 32 ··· 58 53 MODULE_LICENSE("GPL"); 59 54 60 55 static int this_adap; 56 + #ifdef CONFIG_TUNER_MULTI_I2C 57 + static unsigned short tv_tuner, radio_tuner; 58 + #endif 61 59 62 60 static struct i2c_driver driver; 63 61 static struct i2c_client client_template; ··· 132 124 } 133 125 t->freq = freq; 134 126 } 127 + 128 + #ifdef CONFIG_TUNER_MULTI_I2C 129 + static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) 130 + { 131 + struct tuner *t = i2c_get_clientdata(c); 132 + 133 + switch (tun_addr->type) { 134 + case V4L2_TUNER_RADIO: 135 + radio_tuner=tun_addr->addr; 136 + tuner_dbg("radio tuner set to I2C address 0x%02x\n",radio_tuner<<1); 137 + 138 + break; 139 + default: 140 + tv_tuner=tun_addr->addr; 141 + tuner_dbg("TV tuner set to I2C address 0x%02x\n",tv_tuner<<1); 142 + break; 143 + } 144 + } 145 + #else 146 + #define set_addr(c,tun_addr) \ 147 + tuner_warn("It is recommended to enable CONFIG_TUNER_MULTI_I2C for this card.\n"); 148 + #endif 135 149 136 150 static void set_type(struct i2c_client *c, unsigned int type) 137 151 { ··· 227 197 { 228 198 struct tuner *t; 229 199 200 + #ifndef CONFIG_TUNER_MULTI_I2C 230 201 if (this_adap > 0) 231 202 return -1; 203 + #else 204 + /* by default, first I2C card is both tv and radio tuner */ 205 + if (this_adap == 0) { 206 + tv_tuner = addr; 207 + radio_tuner = addr; 208 + } 209 + #endif 232 210 this_adap++; 233 211 234 212 client_template.adapter = adap; ··· 266 228 } 267 229 this_adap = 0; 268 230 231 + #ifdef CONFIG_TUNER_MULTI_I2C 232 + tv_tuner = 0; 233 + radio_tuner = 0; 234 + #endif 235 + 269 236 if (adap->class & I2C_CLASS_TV_ANALOG) 270 237 return i2c_probe(adap, &addr_data, tuner_attach); 271 238 return 0; ··· 279 236 static int tuner_detach(struct i2c_client *client) 280 237 { 281 238 struct tuner *t = i2c_get_clientdata(client); 239 + int err; 282 240 283 - i2c_detach_client(&t->i2c); 241 + err=i2c_detach_client(&t->i2c); 242 + if (err) { 243 + tuner_warn ("Client deregistration failed, client not detached.\n"); 244 + return err; 245 + } 246 + 284 247 kfree(t); 285 248 return 0; 286 249 } ··· 298 249 tuner_info("ignore v4l1 call\n"); \ 299 250 return 0; } 300 251 252 + #ifdef CONFIG_TUNER_MULTI_I2C 253 + #define CHECK_ADDR(tp,cmd) if (client->addr!=tp) { \ 254 + tuner_info ("Cmd %s to addr 0x%02x rejected.\n",cmd,client->addr<<1); \ 255 + return 0; } 256 + #define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ 257 + CHECK_ADDR(radio_tuner,cmd) } else { CHECK_ADDR(tv_tuner,cmd); } 258 + #else 259 + #define CHECK_ADDR(tp,cmd) 260 + #define CHECK_MODE(cmd) 261 + #endif 262 + 301 263 static int 302 264 tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) 303 265 { ··· 316 256 unsigned int *iarg = (int*)arg; 317 257 318 258 switch (cmd) { 319 - 320 259 /* --- configuration --- */ 321 260 case TUNER_SET_TYPE: 322 261 set_type(client,*iarg); 323 262 break; 263 + case TUNER_SET_ADDR: 264 + set_addr(client,(struct tuner_addr *)arg); 265 + break; 324 266 case AUDC_SET_RADIO: 267 + CHECK_ADDR(radio_tuner,"AUDC_SET_RADIO"); 268 + 325 269 if (V4L2_TUNER_RADIO != t->mode) { 326 270 set_tv_freq(client,400 * 16); 327 271 t->mode = V4L2_TUNER_RADIO; 328 272 } 329 273 break; 330 274 case AUDC_CONFIG_PINNACLE: 275 + CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE"); 331 276 switch (*iarg) { 332 277 case 2: 333 278 tuner_dbg("pinnacle pal\n"); ··· 360 295 }; 361 296 struct video_channel *vc = arg; 362 297 298 + CHECK_ADDR(tv_tuner,"VIDIOCSCHAN"); 363 299 CHECK_V4L2; 364 300 t->mode = V4L2_TUNER_ANALOG_TV; 365 301 if (vc->norm < ARRAY_SIZE(map)) ··· 374 308 { 375 309 unsigned long *v = arg; 376 310 311 + CHECK_MODE("VIDIOCSFREQ"); 377 312 CHECK_V4L2; 378 313 set_freq(client,*v); 379 314 return 0; ··· 383 316 { 384 317 struct video_tuner *vt = arg; 385 318 319 + CHECK_ADDR(radio_tuner,"VIDIOCGTUNER:"); 386 320 CHECK_V4L2; 387 321 if (V4L2_TUNER_RADIO == t->mode && t->has_signal) 388 322 vt->signal = t->has_signal(client); ··· 393 325 { 394 326 struct video_audio *va = arg; 395 327 328 + CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO"); 396 329 CHECK_V4L2; 397 330 if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) 398 331 va->mode = t->is_stereo(client) ··· 406 337 { 407 338 v4l2_std_id *id = arg; 408 339 340 + CHECK_ADDR(tv_tuner,"VIDIOC_S_STD"); 409 341 SWITCH_V4L2; 410 342 t->mode = V4L2_TUNER_ANALOG_TV; 411 343 t->std = *id; ··· 419 349 { 420 350 struct v4l2_frequency *f = arg; 421 351 352 + CHECK_MODE("VIDIOC_S_FREQUENCY"); 422 353 SWITCH_V4L2; 423 354 if (V4L2_TUNER_RADIO == f->type && 424 355 V4L2_TUNER_RADIO != t->mode) ··· 432 361 { 433 362 struct v4l2_frequency *f = arg; 434 363 364 + CHECK_MODE("VIDIOC_G_FREQUENCY"); 435 365 SWITCH_V4L2; 436 366 f->type = t->mode; 437 367 f->frequency = t->freq; ··· 442 370 { 443 371 struct v4l2_tuner *tuner = arg; 444 372 373 + CHECK_MODE("VIDIOC_G_TUNER"); 445 374 SWITCH_V4L2; 446 375 if (V4L2_TUNER_RADIO == t->mode && t->has_signal) 447 376 tuner->signal = t->has_signal(client);
+27 -1
drivers/media/video/tuner-simple.c
··· 1 1 /* 2 - * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $ 2 + * $Id: tuner-simple.c,v 1.14 2005/05/30 02:02:47 mchehab Exp $ 3 3 * 4 4 * i2c tv tuner chip device driver 5 5 * controls all those simple 4-control-bytes style tuners. ··· 212 212 { "Philips FQ1236A MK4", Philips, NTSC, 213 213 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, 214 214 215 + /* Should work for TVF8531MF, TVF8831MF, TVF8731MF */ 216 + { "Ymec TVision TVF-8531MF", Philips, NTSC, 217 + 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, 218 + { "Ymec TVision TVF-5533MF", Philips, NTSC, 219 + 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, 215 220 }; 216 221 unsigned const int tuner_count = ARRAY_SIZE(tuners); 217 222 ··· 429 424 buffer[2] = tun->config; 430 425 431 426 switch (t->type) { 427 + case TUNER_YMEC_TVF_5533MF: 428 + 429 + /*These values are empirically determinated */ 430 + div = (freq*122)/16 - 20; 431 + buffer[2] = 0x88; /* could be also 0x80 */ 432 + buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */ 433 + break; 432 434 case TUNER_PHILIPS_FM1216ME_MK3: 433 435 case TUNER_PHILIPS_FM1236_MK3: 434 436 buffer[3] = 0x19; ··· 469 457 tuner_info("type set to %d (%s)\n", 470 458 t->type, tuners[t->type].name); 471 459 strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); 460 + 461 + switch (t->type) { 462 + case TUNER_YMEC_TVF_5533MF: 463 + { 464 + struct tuner_addr tun_addr = { V4L2_TUNER_ANALOG_TV, 0xc2>>1 }; 465 + 466 + if (c->driver->command) { 467 + c->driver->command(c, TUNER_SET_ADDR, &tun_addr); 468 + } else { 469 + tuner_warn("Couldn't set TV tuner I2C address to 0x%02x\n",tun_addr.addr<<1); 470 + } 471 + break; 472 + } 473 + } 472 474 473 475 t->tv_freq = default_set_tv_freq; 474 476 t->radio_freq = default_set_radio_freq;
+10
include/media/tuner.h
··· 98 98 #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ 99 99 #define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ 100 100 101 + #define TUNER_YMEC_TVF_8531MF 58 102 + #define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */ 103 + 101 104 #define NOTUNER 0 102 105 #define PAL 1 /* PAL_BG */ 103 106 #define PAL_I 2 ··· 124 121 125 122 #define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ 126 123 #define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ 124 + #define TUNER_SET_ADDR _IOW('T',3,int) /* Chooses tuner I2C address */ 127 125 128 126 #define TDA9887_SET_CONFIG _IOW('t',5,int) 127 + 129 128 /* tv card specific */ 130 129 # define TDA9887_PRESENT (1<<0) 131 130 # define TDA9887_PORT1_INACTIVE (1<<1) ··· 147 142 148 143 #define I2C_ADDR_TDA8290 0x4b 149 144 #define I2C_ADDR_TDA8275 0x61 145 + 146 + struct tuner_addr { 147 + enum v4l2_tuner_type type; 148 + unsigned short addr; 149 + }; 150 150 151 151 struct tuner { 152 152 /* device */