aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/mb86a20s.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-01-09 15:16:36 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-01-10 19:35:29 -0500
commit959a119f86d51085ba4e0ec5a68dee6a21c48dfe (patch)
tree5979a70ccefc685ebfc5535306874b7d7376a54e /drivers/media/dvb/frontends/mb86a20s.c
parent90bf3aab42937f760e5b645ab63df46d26b5e620 (diff)
[media] mb86a20s: implement get_frontend()
Reports the auto-detected parameters to userspace. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends/mb86a20s.c')
-rw-r--r--drivers/media/dvb/frontends/mb86a20s.c196
1 files changed, 193 insertions, 3 deletions
diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
index 82d3301a1c18..38778a87702e 100644
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -525,16 +525,206 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
525 return rc; 525 return rc;
526} 526}
527 527
528static int mb86a20s_get_modulation(struct mb86a20s_state *state,
529 unsigned layer)
530{
531 int rc;
532 static unsigned char reg[] = {
533 [0] = 0x86, /* Layer A */
534 [1] = 0x8a, /* Layer B */
535 [2] = 0x8e, /* Layer C */
536 };
537
538 if (layer > ARRAY_SIZE(reg))
539 return -EINVAL;
540 rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
541 if (rc < 0)
542 return rc;
543 rc = mb86a20s_readreg(state, 0x6e);
544 if (rc < 0)
545 return rc;
546 switch ((rc & 0x70) >> 4) {
547 case 0:
548 return DQPSK;
549 case 1:
550 return QPSK;
551 case 2:
552 return QAM_16;
553 case 3:
554 return QAM_64;
555 default:
556 return QAM_AUTO;
557 }
558}
559
560static int mb86a20s_get_fec(struct mb86a20s_state *state,
561 unsigned layer)
562{
563 int rc;
564
565 static unsigned char reg[] = {
566 [0] = 0x87, /* Layer A */
567 [1] = 0x8b, /* Layer B */
568 [2] = 0x8f, /* Layer C */
569 };
570
571 if (layer > ARRAY_SIZE(reg))
572 return -EINVAL;
573 rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
574 if (rc < 0)
575 return rc;
576 rc = mb86a20s_readreg(state, 0x6e);
577 if (rc < 0)
578 return rc;
579 switch (rc) {
580 case 0:
581 return FEC_1_2;
582 case 1:
583 return FEC_2_3;
584 case 2:
585 return FEC_3_4;
586 case 3:
587 return FEC_5_6;
588 case 4:
589 return FEC_7_8;
590 default:
591 return FEC_AUTO;
592 }
593}
594
595static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
596 unsigned layer)
597{
598 int rc;
599
600 static unsigned char reg[] = {
601 [0] = 0x88, /* Layer A */
602 [1] = 0x8c, /* Layer B */
603 [2] = 0x90, /* Layer C */
604 };
605
606 if (layer > ARRAY_SIZE(reg))
607 return -EINVAL;
608 rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
609 if (rc < 0)
610 return rc;
611 rc = mb86a20s_readreg(state, 0x6e);
612 if (rc < 0)
613 return rc;
614 if (rc > 3)
615 return -EINVAL; /* Not used */
616 return rc;
617}
618
619static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
620 unsigned layer)
621{
622 int rc, count;
623
624 static unsigned char reg[] = {
625 [0] = 0x89, /* Layer A */
626 [1] = 0x8d, /* Layer B */
627 [2] = 0x91, /* Layer C */
628 };
629
630 if (layer > ARRAY_SIZE(reg))
631 return -EINVAL;
632 rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
633 if (rc < 0)
634 return rc;
635 rc = mb86a20s_readreg(state, 0x6e);
636 if (rc < 0)
637 return rc;
638 count = (rc >> 4) & 0x0f;
639
640 return count;
641}
642
528static int mb86a20s_get_frontend(struct dvb_frontend *fe) 643static int mb86a20s_get_frontend(struct dvb_frontend *fe)
529{ 644{
645 struct mb86a20s_state *state = fe->demodulator_priv;
530 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 646 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
647 int i, rc;
531 648
532 /* FIXME: For now, it does nothing */ 649 /* Fixed parameters */
533 650 p->delivery_system = SYS_ISDBT;
534 p->bandwidth_hz = 6000000; 651 p->bandwidth_hz = 6000000;
652
653 if (fe->ops.i2c_gate_ctrl)
654 fe->ops.i2c_gate_ctrl(fe, 0);
655
656 /* Check for partial reception */
657 rc = mb86a20s_writereg(state, 0x6d, 0x85);
658 if (rc >= 0)
659 rc = mb86a20s_readreg(state, 0x6e);
660 if (rc >= 0)
661 p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
662
663 /* Get per-layer data */
664 p->isdbt_layer_enabled = 0;
665 for (i = 0; i < 3; i++) {
666 rc = mb86a20s_get_segment_count(state, i);
667 if (rc >= 0 && rc < 14)
668 p->layer[i].segment_count = rc;
669 if (rc == 0x0f)
670 continue;
671 p->isdbt_layer_enabled |= 1 << i;
672 rc = mb86a20s_get_modulation(state, i);
673 if (rc >= 0)
674 p->layer[i].modulation = rc;
675 rc = mb86a20s_get_fec(state, i);
676 if (rc >= 0)
677 p->layer[i].fec = rc;
678 rc = mb86a20s_get_interleaving(state, i);
679 if (rc >= 0)
680 p->layer[i].interleaving = rc;
681 }
682
683 p->isdbt_sb_mode = 0;
684 rc = mb86a20s_writereg(state, 0x6d, 0x84);
685 if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
686 p->isdbt_sb_mode = 1;
687 /* At least, one segment should exist */
688 if (!p->isdbt_sb_segment_count)
689 p->isdbt_sb_segment_count = 1;
690 } else
691 p->isdbt_sb_segment_count = 0;
692
693 /* Get transmission mode and guard interval */
535 p->transmission_mode = TRANSMISSION_MODE_AUTO; 694 p->transmission_mode = TRANSMISSION_MODE_AUTO;
536 p->guard_interval = GUARD_INTERVAL_AUTO; 695 p->guard_interval = GUARD_INTERVAL_AUTO;
537 p->isdbt_partial_reception = 0; 696 rc = mb86a20s_readreg(state, 0x07);
697 if (rc >= 0) {
698 if ((rc & 0x60) == 0x20) {
699 switch (rc & 0x0c >> 2) {
700 case 0:
701 p->transmission_mode = TRANSMISSION_MODE_2K;
702 break;
703 case 1:
704 p->transmission_mode = TRANSMISSION_MODE_4K;
705 break;
706 case 2:
707 p->transmission_mode = TRANSMISSION_MODE_8K;
708 break;
709 }
710 }
711 if (!(rc & 0x10)) {
712 switch (rc & 0x3) {
713 case 0:
714 p->guard_interval = GUARD_INTERVAL_1_4;
715 break;
716 case 1:
717 p->guard_interval = GUARD_INTERVAL_1_8;
718 break;
719 case 2:
720 p->guard_interval = GUARD_INTERVAL_1_16;
721 break;
722 }
723 }
724 }
725
726 if (fe->ops.i2c_gate_ctrl)
727 fe->ops.i2c_gate_ctrl(fe, 1);
538 728
539 return 0; 729 return 0;
540} 730}