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.c97
1 files changed, 76 insertions, 21 deletions
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 562d9208857a..819433485d3b 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -42,6 +42,7 @@ struct s5h1409_state {
42 fe_modulation_t current_modulation; 42 fe_modulation_t current_modulation;
43 43
44 u32 current_frequency; 44 u32 current_frequency;
45 int if_freq;
45 46
46 u32 is_qam_locked; 47 u32 is_qam_locked;
47 u32 qam_state; 48 u32 qam_state;
@@ -97,7 +98,7 @@ static struct init_tab {
97 { 0xac, 0x1003, }, 98 { 0xac, 0x1003, },
98 { 0xad, 0x103f, }, 99 { 0xad, 0x103f, },
99 { 0xe2, 0x0100, }, 100 { 0xe2, 0x0100, },
100 { 0xe3, 0x0000, }, 101 { 0xe3, 0x1000, },
101 { 0x28, 0x1010, }, 102 { 0x28, 0x1010, },
102 { 0xb1, 0x000e, }, 103 { 0xb1, 0x000e, },
103}; 104};
@@ -348,28 +349,32 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
348 return 0; 349 return 0;
349} 350}
350 351
352#define S5H1409_VSB_IF_FREQ 5380
353#define S5H1409_QAM_IF_FREQ state->config->qam_if
354
351static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) 355static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
352{ 356{
353 struct s5h1409_state* state = fe->demodulator_priv; 357 struct s5h1409_state* state = fe->demodulator_priv;
354 int ret = 0;
355 358
356 dprintk("%s(%d KHz)\n", __FUNCTION__, KHz); 359 dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
357 360
358 if( (KHz == 44000) || (KHz == 5380) ) { 361 switch (KHz) {
359 s5h1409_writereg(state, 0x87, 0x01be); 362 case 4000:
360 s5h1409_writereg(state, 0x88, 0x0436);
361 s5h1409_writereg(state, 0x89, 0x054d);
362 } else
363 if (KHz == 4000) {
364 s5h1409_writereg(state, 0x87, 0x014b); 363 s5h1409_writereg(state, 0x87, 0x014b);
365 s5h1409_writereg(state, 0x88, 0x0cb5); 364 s5h1409_writereg(state, 0x88, 0x0cb5);
366 s5h1409_writereg(state, 0x89, 0x03e2); 365 s5h1409_writereg(state, 0x89, 0x03e2);
367 } else { 366 break;
368 printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz); 367 case 5380:
369 ret = -1; 368 case 44000:
369 default:
370 s5h1409_writereg(state, 0x87, 0x01be);
371 s5h1409_writereg(state, 0x88, 0x0436);
372 s5h1409_writereg(state, 0x89, 0x054d);
373 break;
370 } 374 }
375 state->if_freq = KHz;
371 376
372 return ret; 377 return 0;
373} 378}
374 379
375static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) 380static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
@@ -394,11 +399,15 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
394 switch(m) { 399 switch(m) {
395 case VSB_8: 400 case VSB_8:
396 dprintk("%s() VSB_8\n", __FUNCTION__); 401 dprintk("%s() VSB_8\n", __FUNCTION__);
402 if (state->if_freq != S5H1409_VSB_IF_FREQ)
403 s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
397 s5h1409_writereg(state, 0xf4, 0); 404 s5h1409_writereg(state, 0xf4, 0);
398 break; 405 break;
399 case QAM_64: 406 case QAM_64:
400 case QAM_256: 407 case QAM_256:
401 dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__); 408 dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
409 if (state->if_freq != S5H1409_QAM_IF_FREQ)
410 s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
402 s5h1409_writereg(state, 0xf4, 1); 411 s5h1409_writereg(state, 0xf4, 1);
403 s5h1409_writereg(state, 0x85, 0x110); 412 s5h1409_writereg(state, 0x85, 0x110);
404 break; 413 break;
@@ -432,9 +441,11 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
432 dprintk("%s(%d)\n", __FUNCTION__, enable); 441 dprintk("%s(%d)\n", __FUNCTION__, enable);
433 442
434 if (enable) 443 if (enable)
435 return s5h1409_writereg(state, 0xe3, 0x1100); 444 return s5h1409_writereg(state, 0xe3,
445 s5h1409_readreg(state, 0xe3) | 0x1100);
436 else 446 else
437 return s5h1409_writereg(state, 0xe3, 0x1000); 447 return s5h1409_writereg(state, 0xe3,
448 s5h1409_readreg(state, 0xe3) & 0xeeff);
438} 449}
439 450
440static int s5h1409_sleep(struct dvb_frontend* fe, int enable) 451static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
@@ -504,13 +515,15 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
504 s5h1409_writereg(state, 0x96, 0x20); 515 s5h1409_writereg(state, 0x96, 0x20);
505 s5h1409_writereg(state, 0xad, 516 s5h1409_writereg(state, 0xad,
506 ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) ); 517 ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
507 s5h1409_writereg(state, 0xab, 0x1100); 518 s5h1409_writereg(state, 0xab,
519 s5h1409_readreg(state, 0xab) & 0xeffe);
508 } 520 }
509 } else { 521 } else {
510 if (state->qam_state != 1) { 522 if (state->qam_state != 1) {
511 state->qam_state = 1; 523 state->qam_state = 1;
512 s5h1409_writereg(state, 0x96, 0x08); 524 s5h1409_writereg(state, 0x96, 0x08);
513 s5h1409_writereg(state, 0xab, 0x1101); 525 s5h1409_writereg(state, 0xab,
526 s5h1409_readreg(state, 0xab) | 0x1001);
514 } 527 }
515 } 528 }
516} 529}
@@ -547,6 +560,36 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
547 return 0; 560 return 0;
548} 561}
549 562
563static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
564{
565 struct s5h1409_state *state = fe->demodulator_priv;
566 u16 val;
567
568 dprintk("%s(%d)\n", __FUNCTION__, mode);
569
570 val = s5h1409_readreg(state, 0xac) & 0xcfff;
571 switch (mode) {
572 case S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
573 val |= 0x0000;
574 break;
575 case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
576 dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
577 val |= 0x1000;
578 break;
579 case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
580 val |= 0x2000;
581 break;
582 case S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
583 val |= 0x3000;
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 /* Configure MPEG Signal Timing charactistics */
590 return s5h1409_writereg(state, 0xac, val);
591}
592
550/* Reset the demod hardware and reset all of the configuration registers 593/* Reset the demod hardware and reset all of the configuration registers
551 to a default state. */ 594 to a default state. */
552static int s5h1409_init (struct dvb_frontend* fe) 595static int s5h1409_init (struct dvb_frontend* fe)
@@ -566,13 +609,16 @@ static int s5h1409_init (struct dvb_frontend* fe)
566 state->current_modulation = VSB_8; 609 state->current_modulation = VSB_8;
567 610
568 if (state->config->output_mode == S5H1409_SERIAL_OUTPUT) 611 if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
569 s5h1409_writereg(state, 0xab, 0x100); /* Serial */ 612 s5h1409_writereg(state, 0xab,
613 s5h1409_readreg(state, 0xab) | 0x100); /* Serial */
570 else 614 else
571 s5h1409_writereg(state, 0xab, 0x0); /* Parallel */ 615 s5h1409_writereg(state, 0xab,
616 s5h1409_readreg(state, 0xab) & 0xfeff); /* Parallel */
572 617
573 s5h1409_set_spectralinversion(fe, state->config->inversion); 618 s5h1409_set_spectralinversion(fe, state->config->inversion);
574 s5h1409_set_if_freq(fe, state->config->if_freq); 619 s5h1409_set_if_freq(fe, state->if_freq);
575 s5h1409_set_gpio(fe, state->config->gpio); 620 s5h1409_set_gpio(fe, state->config->gpio);
621 s5h1409_set_mpeg_timing(fe, state->config->mpeg_timing);
576 s5h1409_softreset(fe); 622 s5h1409_softreset(fe);
577 623
578 /* Note: Leaving the I2C gate closed. */ 624 /* Note: Leaving the I2C gate closed. */
@@ -741,6 +787,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
741 struct i2c_adapter* i2c) 787 struct i2c_adapter* i2c)
742{ 788{
743 struct s5h1409_state* state = NULL; 789 struct s5h1409_state* state = NULL;
790 u16 reg;
744 791
745 /* allocate memory for the internal state */ 792 /* allocate memory for the internal state */
746 state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL); 793 state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
@@ -751,9 +798,11 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
751 state->config = config; 798 state->config = config;
752 state->i2c = i2c; 799 state->i2c = i2c;
753 state->current_modulation = 0; 800 state->current_modulation = 0;
801 state->if_freq = S5H1409_VSB_IF_FREQ;
754 802
755 /* check if the demod exists */ 803 /* check if the demod exists */
756 if (s5h1409_readreg(state, 0x04) != 0x0066) 804 reg = s5h1409_readreg(state, 0x04);
805 if ((reg != 0x0066) && (reg != 0x007f))
757 goto error; 806 goto error;
758 807
759 /* create dvb_frontend */ 808 /* create dvb_frontend */
@@ -761,8 +810,14 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
761 sizeof(struct dvb_frontend_ops)); 810 sizeof(struct dvb_frontend_ops));
762 state->frontend.demodulator_priv = state; 811 state->frontend.demodulator_priv = state;
763 812
813 if (s5h1409_init(&state->frontend) != 0) {
814 printk(KERN_ERR "%s: Failed to initialize correctly\n",
815 __FUNCTION__);
816 goto error;
817 }
818
764 /* Note: Leaving the I2C gate open here. */ 819 /* Note: Leaving the I2C gate open here. */
765 s5h1409_writereg(state, 0xf3, 1); 820 s5h1409_i2c_gate_ctrl(&state->frontend, 1);
766 821
767 return &state->frontend; 822 return &state->frontend;
768 823