diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 196 |
1 files changed, 113 insertions, 83 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 3f485bf13121..efb4a6c2b57a 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -175,23 +175,23 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe, | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static void skystar2_rev23_attach(struct flexcop_device *fc, | 178 | static int skystar2_rev23_attach(struct flexcop_device *fc, |
179 | struct i2c_adapter *i2c) | 179 | struct i2c_adapter *i2c) |
180 | { | 180 | { |
181 | fc->fe = dvb_attach(mt312_attach, | 181 | fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c); |
182 | &skystar23_samsung_tbdu18132_config, i2c); | ||
183 | if (fc->fe != NULL) { | 182 | if (fc->fe != NULL) { |
184 | struct dvb_frontend_ops *ops = &fc->fe->ops; | 183 | struct dvb_frontend_ops *ops = &fc->fe->ops; |
185 | ops->tuner_ops.set_params \ | 184 | ops->tuner_ops.set_params = |
186 | = skystar23_samsung_tbdu18132_tuner_set_params; | 185 | skystar23_samsung_tbdu18132_tuner_set_params; |
187 | ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; | 186 | ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; |
188 | ops->diseqc_send_burst = flexcop_diseqc_send_burst; | 187 | ops->diseqc_send_burst = flexcop_diseqc_send_burst; |
189 | ops->set_tone = flexcop_set_tone; | 188 | ops->set_tone = flexcop_set_tone; |
190 | ops->set_voltage = flexcop_set_voltage; | 189 | ops->set_voltage = flexcop_set_voltage; |
191 | fc->fe_sleep = ops->sleep; | 190 | fc->fe_sleep = ops->sleep; |
192 | ops->sleep = flexcop_sleep; | 191 | ops->sleep = flexcop_sleep; |
193 | fc->dev_type = FC_SKY_REV23; | 192 | return 1; |
194 | } | 193 | } |
194 | return 0; | ||
195 | } | 195 | } |
196 | #endif | 196 | #endif |
197 | 197 | ||
@@ -307,7 +307,7 @@ static struct stv0299_config samsung_tbmu24112_config = { | |||
307 | .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, | 307 | .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, |
308 | }; | 308 | }; |
309 | 309 | ||
310 | static void skystar2_rev26_attach(struct flexcop_device *fc, | 310 | static int skystar2_rev26_attach(struct flexcop_device *fc, |
311 | struct i2c_adapter *i2c) | 311 | struct i2c_adapter *i2c) |
312 | { | 312 | { |
313 | fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); | 313 | fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); |
@@ -317,7 +317,9 @@ static void skystar2_rev26_attach(struct flexcop_device *fc, | |||
317 | ops->set_voltage = flexcop_set_voltage; | 317 | ops->set_voltage = flexcop_set_voltage; |
318 | fc->fe_sleep = ops->sleep; | 318 | fc->fe_sleep = ops->sleep; |
319 | ops->sleep = flexcop_sleep; | 319 | ops->sleep = flexcop_sleep; |
320 | return 1; | ||
320 | } | 321 | } |
322 | return 0; | ||
321 | } | 323 | } |
322 | #endif | 324 | #endif |
323 | 325 | ||
@@ -334,43 +336,54 @@ static struct itd1000_config skystar2_rev2_7_itd1000_config = { | |||
334 | .i2c_address = 0x61, | 336 | .i2c_address = 0x61, |
335 | }; | 337 | }; |
336 | 338 | ||
337 | static void skystar2_rev27_attach(struct flexcop_device *fc, | 339 | static int skystar2_rev27_attach(struct flexcop_device *fc, |
338 | struct i2c_adapter *i2c) | 340 | struct i2c_adapter *i2c) |
339 | { | 341 | { |
342 | flexcop_ibi_value r108; | ||
343 | struct i2c_adapter *i2c_tuner; | ||
344 | |||
340 | /* enable no_base_addr - no repeated start when reading */ | 345 | /* enable no_base_addr - no repeated start when reading */ |
341 | fc->fc_i2c_adap[0].no_base_addr = 1; | 346 | fc->fc_i2c_adap[0].no_base_addr = 1; |
342 | fc->fe = dvb_attach(s5h1420_attach, | 347 | fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, |
343 | &skystar2_rev2_7_s5h1420_config, i2c); | 348 | i2c); |
344 | if (fc->fe != NULL) { | 349 | if (!fc->fe) |
345 | flexcop_ibi_value r108; | 350 | goto fail; |
346 | struct i2c_adapter *i2c_tuner \ | ||
347 | = s5h1420_get_tuner_i2c_adapter(fc->fe); | ||
348 | struct dvb_frontend_ops *ops = &fc->fe->ops; | ||
349 | 351 | ||
350 | fc->fe_sleep = ops->sleep; | 352 | i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); |
351 | ops->sleep = flexcop_sleep; | 353 | if (!i2c_tuner) |
352 | 354 | goto fail; | |
353 | /* enable no_base_addr - no repeated start when reading */ | 355 | |
354 | fc->fc_i2c_adap[2].no_base_addr = 1; | 356 | fc->fe_sleep = fc->fe->ops.sleep; |
355 | if (dvb_attach(isl6421_attach, fc->fe, | 357 | fc->fe->ops.sleep = flexcop_sleep; |
356 | &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) | 358 | |
357 | err("ISL6421 could NOT be attached"); | 359 | /* enable no_base_addr - no repeated start when reading */ |
358 | else | 360 | fc->fc_i2c_adap[2].no_base_addr = 1; |
359 | info("ISL6421 successfully attached"); | 361 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, |
360 | 362 | 0x08, 1, 1)) { | |
361 | /* the ITD1000 requires a lower i2c clock - is it a problem ? */ | 363 | err("ISL6421 could NOT be attached"); |
362 | r108.raw = 0x00000506; | 364 | goto fail_isl; |
363 | fc->write_ibi_reg(fc, tw_sm_c_108, r108); | 365 | } |
364 | if (i2c_tuner) { | 366 | info("ISL6421 successfully attached"); |
365 | if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, | 367 | |
366 | &skystar2_rev2_7_itd1000_config) == NULL) | 368 | /* the ITD1000 requires a lower i2c clock - is it a problem ? */ |
367 | err("ITD1000 could NOT be attached"); | 369 | r108.raw = 0x00000506; |
368 | else | 370 | fc->write_ibi_reg(fc, tw_sm_c_108, r108); |
369 | info("ITD1000 successfully attached"); | 371 | if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner, |
370 | } | 372 | &skystar2_rev2_7_itd1000_config)) { |
371 | } else | 373 | err("ITD1000 could NOT be attached"); |
372 | fc->fc_i2c_adap[0].no_base_addr = 0; | 374 | /* Should i2c clock be restored? */ |
373 | /* for the next devices we need it again */ | 375 | goto fail_isl; |
376 | } | ||
377 | info("ITD1000 successfully attached"); | ||
378 | |||
379 | return 1; | ||
380 | |||
381 | fail_isl: | ||
382 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
383 | fail: | ||
384 | /* for the next devices we need it again */ | ||
385 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
386 | return 0; | ||
374 | } | 387 | } |
375 | #endif | 388 | #endif |
376 | 389 | ||
@@ -387,32 +400,38 @@ static const struct cx24113_config skystar2_rev2_8_cx24113_config = { | |||
387 | .xtal_khz = 10111, | 400 | .xtal_khz = 10111, |
388 | }; | 401 | }; |
389 | 402 | ||
390 | static void skystar2_rev28_attach(struct flexcop_device *fc, | 403 | static int skystar2_rev28_attach(struct flexcop_device *fc, |
391 | struct i2c_adapter *i2c) | 404 | struct i2c_adapter *i2c) |
392 | { | 405 | { |
393 | fc->fe = dvb_attach(cx24123_attach, | 406 | struct i2c_adapter *i2c_tuner; |
394 | &skystar2_rev2_8_cx24123_config, i2c); | 407 | |
395 | if (fc->fe != NULL) { | 408 | fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config, |
396 | struct i2c_adapter *i2c_tuner \ | 409 | i2c); |
397 | = cx24123_get_tuner_i2c_adapter(fc->fe); | 410 | if (!fc->fe) |
398 | if (i2c_tuner != NULL) { | 411 | return 0; |
399 | if (dvb_attach(cx24113_attach, fc->fe, | 412 | |
400 | &skystar2_rev2_8_cx24113_config, | 413 | i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);; |
401 | i2c_tuner) == NULL) | 414 | if (!i2c_tuner) |
402 | err("CX24113 could NOT be attached"); | 415 | return 0; |
403 | else | ||
404 | info("CX24113 successfully attached"); | ||
405 | } | ||
406 | 416 | ||
407 | fc->fc_i2c_adap[2].no_base_addr = 1; | 417 | if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config, |
408 | if (dvb_attach(isl6421_attach, fc->fe, | 418 | i2c_tuner)) { |
409 | &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) | 419 | err("CX24113 could NOT be attached"); |
410 | err("ISL6421 could NOT be attached"); | 420 | return 0; |
411 | else | 421 | } |
412 | info("ISL6421 successfully attached"); | 422 | info("CX24113 successfully attached"); |
423 | |||
424 | fc->fc_i2c_adap[2].no_base_addr = 1; | ||
425 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, | ||
426 | 0x08, 0, 0)) { | ||
427 | err("ISL6421 could NOT be attached"); | ||
428 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
429 | return 0; | ||
430 | } | ||
431 | info("ISL6421 successfully attached"); | ||
413 | /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an | 432 | /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an |
414 | * IR-receiver (PIC16F818) - but the card has no input for that ??? */ | 433 | * IR-receiver (PIC16F818) - but the card has no input for that ??? */ |
415 | } | 434 | return 1; |
416 | } | 435 | } |
417 | #endif | 436 | #endif |
418 | 437 | ||
@@ -466,12 +485,15 @@ static struct mt352_config samsung_tdtc9251dh0_config = { | |||
466 | .demod_init = samsung_tdtc9251dh0_demod_init, | 485 | .demod_init = samsung_tdtc9251dh0_demod_init, |
467 | }; | 486 | }; |
468 | 487 | ||
469 | static void airstar_dvbt_attach(struct flexcop_device *fc, | 488 | static int airstar_dvbt_attach(struct flexcop_device *fc, |
470 | struct i2c_adapter *i2c) | 489 | struct i2c_adapter *i2c) |
471 | { | 490 | { |
472 | fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); | 491 | fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); |
473 | if (fc->fe != NULL) | 492 | if (fc->fe != NULL) { |
474 | fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; | 493 | fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; |
494 | return 1; | ||
495 | } | ||
496 | return 0; | ||
475 | } | 497 | } |
476 | #endif | 498 | #endif |
477 | 499 | ||
@@ -489,10 +511,11 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = { | |||
489 | .request_firmware = flexcop_fe_request_firmware, | 511 | .request_firmware = flexcop_fe_request_firmware, |
490 | }; | 512 | }; |
491 | 513 | ||
492 | static void airstar_atsc1_attach(struct flexcop_device *fc, | 514 | static int airstar_atsc1_attach(struct flexcop_device *fc, |
493 | struct i2c_adapter *i2c) | 515 | struct i2c_adapter *i2c) |
494 | { | 516 | { |
495 | fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); | 517 | fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); |
518 | return fc->fe != NULL; | ||
496 | } | 519 | } |
497 | #endif | 520 | #endif |
498 | 521 | ||
@@ -502,13 +525,15 @@ static struct nxt200x_config samsung_tbmv_config = { | |||
502 | .demod_address = 0x0a, | 525 | .demod_address = 0x0a, |
503 | }; | 526 | }; |
504 | 527 | ||
505 | static void airstar_atsc2_attach(struct flexcop_device *fc, | 528 | static int airstar_atsc2_attach(struct flexcop_device *fc, |
506 | struct i2c_adapter *i2c) | 529 | struct i2c_adapter *i2c) |
507 | { | 530 | { |
508 | fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); | 531 | fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); |
509 | if (fc->fe != NULL) | 532 | if (!fc->fe) |
510 | dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | 533 | return 0; |
511 | DVB_PLL_SAMSUNG_TBMV); | 534 | |
535 | return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | ||
536 | DVB_PLL_SAMSUNG_TBMV); | ||
512 | } | 537 | } |
513 | #endif | 538 | #endif |
514 | 539 | ||
@@ -521,14 +546,15 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { | |||
521 | .clock_polarity_flip = 1, | 546 | .clock_polarity_flip = 1, |
522 | }; | 547 | }; |
523 | 548 | ||
524 | static void airstar_atsc3_attach(struct flexcop_device *fc, | 549 | static int airstar_atsc3_attach(struct flexcop_device *fc, |
525 | struct i2c_adapter *i2c) | 550 | struct i2c_adapter *i2c) |
526 | { | 551 | { |
527 | fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); | 552 | fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); |
528 | if (fc->fe != NULL) { | 553 | if (!fc->fe) |
529 | dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, | 554 | return 0; |
530 | TUNER_LG_TDVS_H06XF); | 555 | |
531 | } | 556 | return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, |
557 | TUNER_LG_TDVS_H06XF); | ||
532 | } | 558 | } |
533 | #endif | 559 | #endif |
534 | 560 | ||
@@ -659,22 +685,24 @@ static struct stv0297_config alps_tdee4_stv0297_config = { | |||
659 | .inittab = alps_tdee4_stv0297_inittab, | 685 | .inittab = alps_tdee4_stv0297_inittab, |
660 | }; | 686 | }; |
661 | 687 | ||
662 | static void cablestar2_attach(struct flexcop_device *fc, | 688 | static int cablestar2_attach(struct flexcop_device *fc, |
663 | struct i2c_adapter *i2c) | 689 | struct i2c_adapter *i2c) |
664 | { | 690 | { |
665 | fc->fc_i2c_adap[0].no_base_addr = 1; | 691 | fc->fc_i2c_adap[0].no_base_addr = 1; |
666 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); | 692 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); |
667 | if (fc->fe != NULL) | 693 | if (!fc->fe) { |
668 | fc->fe->ops.tuner_ops.set_params \ | 694 | /* Reset for next frontend to try */ |
669 | = alps_tdee4_stv0297_tuner_set_params; | ||
670 | else | ||
671 | fc->fc_i2c_adap[0].no_base_addr = 0; | 695 | fc->fc_i2c_adap[0].no_base_addr = 0; |
696 | return 0; | ||
697 | } | ||
698 | fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; | ||
699 | return 1; | ||
672 | } | 700 | } |
673 | #endif | 701 | #endif |
674 | 702 | ||
675 | static struct { | 703 | static struct { |
676 | flexcop_device_type_t type; | 704 | flexcop_device_type_t type; |
677 | void (*attach)(struct flexcop_device *, struct i2c_adapter *); | 705 | int (*attach)(struct flexcop_device *, struct i2c_adapter *); |
678 | } flexcop_frontends[] = { | 706 | } flexcop_frontends[] = { |
679 | #if defined(CONFIG_DVB_S5H1420_MODULE) | 707 | #if defined(CONFIG_DVB_S5H1420_MODULE) |
680 | { FC_SKY_REV27, skystar2_rev27_attach }, | 708 | { FC_SKY_REV27, skystar2_rev27_attach }, |
@@ -713,9 +741,13 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
713 | /* type needs to be set before, because of some workarounds | 741 | /* type needs to be set before, because of some workarounds |
714 | * done based on the probed card type */ | 742 | * done based on the probed card type */ |
715 | fc->dev_type = flexcop_frontends[i].type; | 743 | fc->dev_type = flexcop_frontends[i].type; |
716 | flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap); | 744 | if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap)) |
717 | if (fc->fe != NULL) | ||
718 | goto fe_found; | 745 | goto fe_found; |
746 | /* Clean up partially attached frontend */ | ||
747 | if (fc->fe) { | ||
748 | dvb_frontend_detach(fc->fe); | ||
749 | fc->fe = NULL; | ||
750 | } | ||
719 | } | 751 | } |
720 | fc->dev_type = FC_UNK; | 752 | fc->dev_type = FC_UNK; |
721 | err("no frontend driver found for this B2C2/FlexCop adapter"); | 753 | err("no frontend driver found for this B2C2/FlexCop adapter"); |
@@ -724,10 +756,8 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
724 | fe_found: | 756 | fe_found: |
725 | info("found '%s' .", fc->fe->ops.info.name); | 757 | info("found '%s' .", fc->fe->ops.info.name); |
726 | if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { | 758 | if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { |
727 | struct dvb_frontend_ops *ops = &fc->fe->ops; | ||
728 | err("frontend registration failed!"); | 759 | err("frontend registration failed!"); |
729 | if (ops->release != NULL) | 760 | dvb_frontend_detach(fc->fe); |
730 | ops->release(fc->fe); | ||
731 | fc->fe = NULL; | 761 | fc->fe = NULL; |
732 | return -EINVAL; | 762 | return -EINVAL; |
733 | } | 763 | } |