aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tda8290.c
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2007-10-27 01:00:57 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:01:30 -0500
commit8c125f2ceb3ec1ba01e96fffd8558ef163b40fe8 (patch)
tree04ba00ab3874035ec554fcd1a5b5812f42463082 /drivers/media/video/tda8290.c
parent393bf5573269979aa3fb55d1bdd0db4fcb288f99 (diff)
V4L/DVB (6468): tda8290: auto-detect tda8290 or tda8295
Consolidate tda8290_attach() and tda8295_attach() into a single function, tda829x_attach(), which will detect chip combinations tda8290 or tda8295 with tda8275, tda8275a or tda18271. Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tda8290.c')
-rw-r--r--drivers/media/video/tda8290.c257
1 files changed, 124 insertions, 133 deletions
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 5975c548b8a6..ed22be0f5941 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -41,7 +41,13 @@ struct tda8290_priv {
41 unsigned char tda8290_easy_mode; 41 unsigned char tda8290_easy_mode;
42 42
43 unsigned char tda827x_addr; 43 unsigned char tda827x_addr;
44 unsigned char tda827x_ver; 44
45 unsigned char ver;
46#define TDA8290 1
47#define TDA8295 2
48#define TDA8275 4
49#define TDA8275A 8
50#define TDA18271 16
45 51
46 struct tda827x_config cfg; 52 struct tda827x_config cfg;
47 53
@@ -136,7 +142,7 @@ static void set_audio(struct dvb_frontend *fe)
136 mode = "xx"; 142 mode = "xx";
137 } 143 }
138 144
139 tuner_dbg("setting tda8290 to system %s\n", mode); 145 tuner_dbg("setting tda829x to system %s\n", mode);
140} 146}
141 147
142static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) 148static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq)
@@ -429,7 +435,7 @@ static void tda8290_standby(struct dvb_frontend *fe)
429 struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; 435 struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
430 436
431 tda8290_i2c_bridge(fe, 1); 437 tda8290_i2c_bridge(fe, 1);
432 if (priv->tda827x_ver != 0) 438 if (priv->ver & TDA8275A)
433 cb1[1] = 0x90; 439 cb1[1] = 0x90;
434 i2c_transfer(priv->i2c_props.adap, &msg, 1); 440 i2c_transfer(priv->i2c_props.adap, &msg, 1);
435 tda8290_i2c_bridge(fe, 0); 441 tda8290_i2c_bridge(fe, 0);
@@ -498,7 +504,7 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
498 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; 504 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
499 struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, 505 struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
500 .buf=tda8275_init, .len = 14}; 506 .buf=tda8275_init, .len = 14};
501 if (priv->tda827x_ver != 0) 507 if (priv->ver & TDA8275A)
502 msg.buf = tda8275a_init; 508 msg.buf = tda8275a_init;
503 509
504 tda8290_i2c_bridge(fe, 1); 510 tda8290_i2c_bridge(fe, 1);
@@ -517,48 +523,25 @@ static void tda829x_release(struct dvb_frontend *fe)
517 fe->analog_demod_priv = NULL; 523 fe->analog_demod_priv = NULL;
518} 524}
519 525
520static struct analog_tuner_ops tda8290_tuner_ops = { 526static int tda829x_find_tuner(struct dvb_frontend *fe)
521 .set_tv_freq = tda8290_set_freq,
522 .set_radio_freq = tda8290_set_freq,
523 .has_signal = tda8290_has_signal,
524 .standby = tda8290_standby,
525 .release = tda829x_release,
526 .i2c_gate_ctrl = tda8290_i2c_bridge,
527};
528
529static struct analog_tuner_ops tda8295_tuner_ops = {
530 .set_tv_freq = tda8295_set_freq,
531 .set_radio_freq = tda8295_set_freq,
532 .has_signal = tda8295_has_signal,
533 .standby = tda8295_standby,
534 .release = tda829x_release,
535 .i2c_gate_ctrl = tda8295_i2c_bridge,
536};
537
538int tda8290_attach(struct tuner *t)
539{ 527{
540 struct tda8290_priv *priv = NULL; 528 struct tda8290_priv *priv = fe->analog_demod_priv;
541 u8 data; 529 struct analog_tuner_ops *ops = fe->ops.analog_demod_ops;
530 struct tuner *t = priv->t;
542 int i, ret, tuners_found; 531 int i, ret, tuners_found;
543 u32 tuner_addrs; 532 u32 tuner_addrs;
544 struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; 533 u8 data;
534 struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
545 535
546 priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); 536 if (NULL == ops)
547 if (priv == NULL) 537 return -EINVAL;
548 return -ENOMEM;
549 t->fe.analog_demod_priv = priv;
550 538
551 priv->i2c_props.addr = t->i2c.addr; 539 ops->i2c_gate_ctrl(fe, 1);
552 priv->i2c_props.adap = t->i2c.adapter;
553 priv->cfg.config = &t->config;
554 priv->cfg.tuner_callback = t->tuner_callback;
555 priv->t = t;
556 540
557 tda8290_i2c_bridge(&t->fe, 1);
558 /* probe for tuner chip */ 541 /* probe for tuner chip */
559 tuners_found = 0; 542 tuners_found = 0;
560 tuner_addrs = 0; 543 tuner_addrs = 0;
561 for (i=0x60; i<= 0x63; i++) { 544 for (i = 0x60; i <= 0x63; i++) {
562 msg.addr = i; 545 msg.addr = i;
563 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); 546 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
564 if (ret == 1) { 547 if (ret == 1) {
@@ -570,20 +553,23 @@ int tda8290_attach(struct tuner *t)
570 behind the bridge and we choose the highest address that doesn't 553 behind the bridge and we choose the highest address that doesn't
571 give a response now 554 give a response now
572 */ 555 */
573 tda8290_i2c_bridge(&t->fe, 0); 556
574 if(tuners_found > 1) 557 ops->i2c_gate_ctrl(fe, 0);
558
559 if (tuners_found > 1)
575 for (i = 0; i < tuners_found; i++) { 560 for (i = 0; i < tuners_found; i++) {
576 msg.addr = tuner_addrs & 0xff; 561 msg.addr = tuner_addrs & 0xff;
577 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); 562 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
578 if(ret == 1) 563 if (ret == 1)
579 tuner_addrs = tuner_addrs >> 8; 564 tuner_addrs = tuner_addrs >> 8;
580 else 565 else
581 break; 566 break;
582 } 567 }
568
583 if (tuner_addrs == 0) { 569 if (tuner_addrs == 0) {
584 tuner_addrs = 0x61; 570 tuner_addrs = 0x60;
585 tuner_info("could not clearly identify tuner address, defaulting to %x\n", 571 tuner_info("could not clearly identify tuner address, "
586 tuner_addrs); 572 "defaulting to %x\n", tuner_addrs);
587 } else { 573 } else {
588 tuner_addrs = tuner_addrs & 0xff; 574 tuner_addrs = tuner_addrs & 0xff;
589 tuner_info("setting tuner address to %x\n", tuner_addrs); 575 tuner_info("setting tuner address to %x\n", tuner_addrs);
@@ -591,127 +577,132 @@ int tda8290_attach(struct tuner *t)
591 priv->tda827x_addr = tuner_addrs; 577 priv->tda827x_addr = tuner_addrs;
592 msg.addr = tuner_addrs; 578 msg.addr = tuner_addrs;
593 579
594 tda8290_i2c_bridge(&t->fe, 1); 580 ops->i2c_gate_ctrl(fe, 1);
595
596 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); 581 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
597 if( ret != 1)
598 tuner_warn("TDA827x access failed!\n");
599 582
600 if ((data & 0x3c) == 0) { 583 if (ret != 1) {
601 strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); 584 tuner_warn("tuner access failed!\n");
602 priv->tda827x_ver = 0; 585 return -EREMOTEIO;
603 } else {
604 strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name));
605 priv->tda827x_ver = 2;
606 } 586 }
607 tda827x_attach(&t->fe, priv->tda827x_addr,
608 priv->i2c_props.adap, &priv->cfg);
609 587
610 /* FIXME: tda827x module doesn't probe the tuner until 588 if (data == 0x83) {
611 * tda827x_initial_sleep is called 589 priv->ver |= TDA18271;
612 */ 590 tda18271_attach(&t->fe, priv->tda827x_addr,
613 if (t->fe.ops.tuner_ops.sleep) 591 priv->i2c_props.adap);
614 t->fe.ops.tuner_ops.sleep(&t->fe); 592 } else {
593 if ((data & 0x3c) == 0)
594 priv->ver |= TDA8275;
595 else
596 priv->ver |= TDA8275A;
615 597
616 t->fe.ops.analog_demod_ops = &tda8290_tuner_ops; 598 tda827x_attach(&t->fe, priv->tda827x_addr,
599 priv->i2c_props.adap, &priv->cfg);
617 600
618 tuner_info("type set to %s\n", t->i2c.name); 601 /* FIXME: tda827x module doesn't probe the tuner until
602 * tda827x_initial_sleep is called
603 */
604 if (t->fe.ops.tuner_ops.sleep)
605 t->fe.ops.tuner_ops.sleep(&t->fe);
606 }
607 ops->i2c_gate_ctrl(fe, 0);
619 608
620 t->mode = V4L2_TUNER_ANALOG_TV; 609 switch (priv->ver) {
610 case TDA8290 | TDA8275:
611 strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name));
612 break;
613 case TDA8295 | TDA8275:
614 strlcpy(t->i2c.name, "tda8295+75", sizeof(t->i2c.name));
615 break;
616 case TDA8290 | TDA8275A:
617 strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name));
618 break;
619 case TDA8295 | TDA8275A:
620 strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name));
621 break;
622 case TDA8290 | TDA18271:
623 strlcpy(t->i2c.name, "tda8290+18271", sizeof(t->i2c.name));
624 break;
625 case TDA8295 | TDA18271:
626 strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name));
627 break;
628 default:
629 return -EINVAL;
630 }
621 631
622 tda8290_init_tuner(&t->fe);
623 tda8290_init_if(&t->fe);
624 return 0; 632 return 0;
625} 633}
626EXPORT_SYMBOL_GPL(tda8290_attach);
627 634
628int tda8295_attach(struct tuner *t) 635static struct analog_tuner_ops tda8290_tuner_ops = {
636 .set_tv_freq = tda8290_set_freq,
637 .set_radio_freq = tda8290_set_freq,
638 .has_signal = tda8290_has_signal,
639 .standby = tda8290_standby,
640 .release = tda829x_release,
641 .i2c_gate_ctrl = tda8290_i2c_bridge,
642};
643
644static struct analog_tuner_ops tda8295_tuner_ops = {
645 .set_tv_freq = tda8295_set_freq,
646 .set_radio_freq = tda8295_set_freq,
647 .has_signal = tda8295_has_signal,
648 .standby = tda8295_standby,
649 .release = tda829x_release,
650 .i2c_gate_ctrl = tda8295_i2c_bridge,
651};
652
653int tda829x_attach(struct tuner *t)
629{ 654{
655 struct dvb_frontend *fe = &t->fe;
630 struct tda8290_priv *priv = NULL; 656 struct tda8290_priv *priv = NULL;
631 u8 data; 657
632 int i, ret, tuners_found; 658 unsigned char tda8290_id[] = { 0x1f, 0x00 };
633 u32 tuner_addrs; 659#define TDA8290_ID 0x89
634 struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; 660 unsigned char tda8295_id[] = { 0x2f, 0x00 };
661#define TDA8295_ID 0x8a
635 662
636 priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); 663 priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
637 if (priv == NULL) 664 if (priv == NULL)
638 return -ENOMEM; 665 return -ENOMEM;
639 t->fe.analog_demod_priv = priv; 666 fe->analog_demod_priv = priv;
640 667
641 priv->i2c_props.addr = t->i2c.addr; 668 priv->i2c_props.addr = t->i2c.addr;
642 priv->i2c_props.adap = t->i2c.adapter; 669 priv->i2c_props.adap = t->i2c.adapter;
670 priv->cfg.config = &t->config;
671 priv->cfg.tuner_callback = t->tuner_callback;
643 priv->t = t; 672 priv->t = t;
644 673
645 tda8295_i2c_bridge(&t->fe, 1); 674 /* detect tda8290 */
646 /* probe for tuner chip */ 675 tuner_i2c_xfer_send(&priv->i2c_props, &tda8290_id[0], 1);
647 tuners_found = 0; 676 tuner_i2c_xfer_recv(&priv->i2c_props, &tda8290_id[1], 1);
648 tuner_addrs = 0; 677 if (tda8290_id[1] == TDA8290_ID) {
649 for (i = 0x60; i <= 0x63; i++) { 678 priv->ver = TDA8290;
650 msg.addr = i; 679 fe->ops.analog_demod_ops = &tda8290_tuner_ops;
651 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
652 if (ret == 1) {
653 tuners_found++;
654 tuner_addrs = (tuner_addrs << 8) + i;
655 }
656 } 680 }
657 /* if there is more than one tuner, we expect the right one is 681
658 behind the bridge and we choose the highest address that doesn't 682 /* detect tda8295 */
659 give a response now 683 tuner_i2c_xfer_send(&priv->i2c_props, &tda8295_id[0], 1);
660 */ 684 tuner_i2c_xfer_recv(&priv->i2c_props, &tda8295_id[1], 1);
661 tda8295_i2c_bridge(&t->fe, 0); 685 if (tda8295_id[1] == TDA8295_ID) {
662 if (tuners_found > 1) 686 priv->ver = TDA8295;
663 for (i = 0; i < tuners_found; i++) { 687 fe->ops.analog_demod_ops = &tda8295_tuner_ops;
664 msg.addr = tuner_addrs & 0xff;
665 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
666 if (ret == 1)
667 tuner_addrs = tuner_addrs >> 8;
668 else
669 break;
670 }
671 if (tuner_addrs == 0) {
672 tuner_addrs = 0x60;
673 tuner_info("could not clearly identify tuner address, "
674 "defaulting to %x\n", tuner_addrs);
675 } else {
676 tuner_addrs = tuner_addrs & 0xff;
677 tuner_info("setting tuner address to %x\n", tuner_addrs);
678 } 688 }
679 priv->tda827x_addr = tuner_addrs;
680 msg.addr = tuner_addrs;
681 689
682 tda8295_i2c_bridge(&t->fe, 1); 690 if (tda829x_find_tuner(fe) < 0)
683 ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); 691 return -EINVAL;
684 tda8295_i2c_bridge(&t->fe, 0);
685 if (ret != 1)
686 tuner_warn("TDA827x access failed!\n");
687 if ((data & 0x3c) == 0) {
688 strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name));
689 tda18271_attach(&t->fe, priv->tda827x_addr,
690 priv->i2c_props.adap);
691 priv->tda827x_ver = 4;
692 } else {
693 strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name));
694 tda827x_attach(&t->fe, priv->tda827x_addr,
695 priv->i2c_props.adap, &priv->cfg);
696 692
697 /* FIXME: tda827x module doesn't probe the tuner until 693 if (priv->ver & TDA8290) {
698 * tda827x_initial_sleep is called 694 tda8290_init_tuner(fe);
699 */ 695 tda8290_init_if(fe);
700 if (t->fe.ops.tuner_ops.sleep) 696 } else if (priv->ver & TDA8295)
701 t->fe.ops.tuner_ops.sleep(&t->fe); 697 tda8295_init_if(fe);
702 priv->tda827x_ver = 2;
703 }
704 priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */
705 tuner_info("type set to %s\n", t->i2c.name);
706 698
707 t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; 699 tuner_info("type set to %s\n", t->i2c.name);
708 700
709 t->mode = V4L2_TUNER_ANALOG_TV; 701 t->mode = V4L2_TUNER_ANALOG_TV;
710 702
711 tda8295_init_if(&t->fe);
712 return 0; 703 return 0;
713} 704}
714EXPORT_SYMBOL_GPL(tda8295_attach); 705EXPORT_SYMBOL_GPL(tda829x_attach);
715 706
716int tda8290_probe(struct tuner *t) 707int tda8290_probe(struct tuner *t)
717{ 708{
@@ -745,7 +736,7 @@ int tda8290_probe(struct tuner *t)
745} 736}
746EXPORT_SYMBOL_GPL(tda8290_probe); 737EXPORT_SYMBOL_GPL(tda8290_probe);
747 738
748MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); 739MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
749MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); 740MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
750MODULE_LICENSE("GPL"); 741MODULE_LICENSE("GPL");
751 742