aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/s5h1409.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/s5h1409.c')
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c136
1 files changed, 128 insertions, 8 deletions
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 85fba581c5ab..5507159a23b1 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -44,7 +44,15 @@ struct s5h1409_state {
44 int if_freq; 44 int if_freq;
45 45
46 u32 is_qam_locked; 46 u32 is_qam_locked;
47 u32 qam_state; 47
48 /* QAM tuning state goes through the following state transitions */
49#define QAM_STATE_UNTUNED 0
50#define QAM_STATE_TUNING_STARTED 1
51#define QAM_STATE_INTERLEAVE_SET 2
52#define QAM_STATE_QAM_OPTIMIZED_L1 3
53#define QAM_STATE_QAM_OPTIMIZED_L2 4
54#define QAM_STATE_QAM_OPTIMIZED_L3 5
55 u8 qam_state;
48}; 56};
49 57
50static int debug; 58static int debug;
@@ -347,7 +355,7 @@ static int s5h1409_softreset(struct dvb_frontend *fe)
347 s5h1409_writereg(state, 0xf5, 0); 355 s5h1409_writereg(state, 0xf5, 0);
348 s5h1409_writereg(state, 0xf5, 1); 356 s5h1409_writereg(state, 0xf5, 1);
349 state->is_qam_locked = 0; 357 state->is_qam_locked = 0;
350 state->qam_state = 0; 358 state->qam_state = QAM_STATE_UNTUNED;
351 return 0; 359 return 0;
352} 360}
353 361
@@ -474,6 +482,59 @@ static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
474 struct s5h1409_state *state = fe->demodulator_priv; 482 struct s5h1409_state *state = fe->demodulator_priv;
475 u16 reg; 483 u16 reg;
476 484
485 if (state->qam_state < QAM_STATE_INTERLEAVE_SET) {
486 /* We should not perform amhum optimization until
487 the interleave mode has been configured */
488 return;
489 }
490
491 if (state->qam_state == QAM_STATE_QAM_OPTIMIZED_L3) {
492 /* We've already reached the maximum optimization level, so
493 dont bother banging on the status registers */
494 return;
495 }
496
497 /* QAM EQ lock check */
498 reg = s5h1409_readreg(state, 0xf0);
499
500 if ((reg >> 13) & 0x1) {
501 reg &= 0xff;
502
503 s5h1409_writereg(state, 0x96, 0x000c);
504 if (reg < 0x68) {
505 if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L3) {
506 dprintk("%s() setting QAM state to OPT_L3\n",
507 __func__);
508 s5h1409_writereg(state, 0x93, 0x3130);
509 s5h1409_writereg(state, 0x9e, 0x2836);
510 state->qam_state = QAM_STATE_QAM_OPTIMIZED_L3;
511 }
512 } else {
513 if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L2) {
514 dprintk("%s() setting QAM state to OPT_L2\n",
515 __func__);
516 s5h1409_writereg(state, 0x93, 0x3332);
517 s5h1409_writereg(state, 0x9e, 0x2c37);
518 state->qam_state = QAM_STATE_QAM_OPTIMIZED_L2;
519 }
520 }
521
522 } else {
523 if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L1) {
524 dprintk("%s() setting QAM state to OPT_L1\n", __func__);
525 s5h1409_writereg(state, 0x96, 0x0008);
526 s5h1409_writereg(state, 0x93, 0x3332);
527 s5h1409_writereg(state, 0x9e, 0x2c37);
528 state->qam_state = QAM_STATE_QAM_OPTIMIZED_L1;
529 }
530 }
531}
532
533static void s5h1409_set_qam_amhum_mode_legacy(struct dvb_frontend *fe)
534{
535 struct s5h1409_state *state = fe->demodulator_priv;
536 u16 reg;
537
477 if (state->is_qam_locked) 538 if (state->is_qam_locked)
478 return; 539 return;
479 540
@@ -506,6 +567,46 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
506 struct s5h1409_state *state = fe->demodulator_priv; 567 struct s5h1409_state *state = fe->demodulator_priv;
507 u16 reg, reg1, reg2; 568 u16 reg, reg1, reg2;
508 569
570 if (state->qam_state >= QAM_STATE_INTERLEAVE_SET) {
571 /* We've done the optimization already */
572 return;
573 }
574
575 reg = s5h1409_readreg(state, 0xf1);
576
577 /* Master lock */
578 if ((reg >> 15) & 0x1) {
579 if (state->qam_state == QAM_STATE_UNTUNED ||
580 state->qam_state == QAM_STATE_TUNING_STARTED) {
581 dprintk("%s() setting QAM state to INTERLEAVE_SET\n",
582 __func__);
583 reg1 = s5h1409_readreg(state, 0xb2);
584 reg2 = s5h1409_readreg(state, 0xad);
585
586 s5h1409_writereg(state, 0x96, 0x0020);
587 s5h1409_writereg(state, 0xad,
588 (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
589 s5h1409_writereg(state, 0xab,
590 s5h1409_readreg(state, 0xab) & 0xeffe);
591 state->qam_state = QAM_STATE_INTERLEAVE_SET;
592 }
593 } else {
594 if (state->qam_state == QAM_STATE_UNTUNED) {
595 dprintk("%s() setting QAM state to TUNING_STARTED\n",
596 __func__);
597 s5h1409_writereg(state, 0x96, 0x08);
598 s5h1409_writereg(state, 0xab,
599 s5h1409_readreg(state, 0xab) | 0x1001);
600 state->qam_state = QAM_STATE_TUNING_STARTED;
601 }
602 }
603}
604
605static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe)
606{
607 struct s5h1409_state *state = fe->demodulator_priv;
608 u16 reg, reg1, reg2;
609
509 reg = s5h1409_readreg(state, 0xf1); 610 reg = s5h1409_readreg(state, 0xf1);
510 611
511 /* Master lock */ 612 /* Master lock */
@@ -553,16 +654,24 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
553 fe->ops.i2c_gate_ctrl(fe, 0); 654 fe->ops.i2c_gate_ctrl(fe, 0);
554 } 655 }
555 656
556 /* Optimize the demod for QAM */
557 if (p->u.vsb.modulation != VSB_8) {
558 s5h1409_set_qam_amhum_mode(fe);
559 s5h1409_set_qam_interleave_mode(fe);
560 }
561
562 /* Issue a reset to the demod so it knows to resync against the 657 /* Issue a reset to the demod so it knows to resync against the
563 newly tuned frequency */ 658 newly tuned frequency */
564 s5h1409_softreset(fe); 659 s5h1409_softreset(fe);
565 660
661 /* Optimize the demod for QAM */
662 if (state->current_modulation != VSB_8) {
663 /* This almost certainly applies to all boards, but for now
664 only do it for the HVR-1600. Once the other boards are
665 tested, the "legacy" versions can just go away */
666 if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
667 s5h1409_set_qam_amhum_mode(fe);
668 s5h1409_set_qam_interleave_mode(fe);
669 } else {
670 s5h1409_set_qam_amhum_mode_legacy(fe);
671 s5h1409_set_qam_interleave_mode_legacy(fe);
672 }
673 }
674
566 return 0; 675 return 0;
567} 676}
568 677
@@ -656,6 +765,17 @@ static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
656 765
657 *status = 0; 766 *status = 0;
658 767
768 /* Optimize the demod for QAM */
769 if (state->current_modulation != VSB_8) {
770 /* This almost certainly applies to all boards, but for now
771 only do it for the HVR-1600. Once the other boards are
772 tested, the "legacy" versions can just go away */
773 if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
774 s5h1409_set_qam_amhum_mode(fe);
775 s5h1409_set_qam_interleave_mode(fe);
776 }
777 }
778
659 /* Get the demodulator status */ 779 /* Get the demodulator status */
660 reg = s5h1409_readreg(state, 0xf1); 780 reg = s5h1409_readreg(state, 0xf1);
661 if (reg & 0x1000) 781 if (reg & 0x1000)