diff options
Diffstat (limited to 'drivers/media/dvb/frontends/stv0299.c')
-rw-r--r-- | drivers/media/dvb/frontends/stv0299.c | 100 |
1 files changed, 19 insertions, 81 deletions
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 889d9257215d..29c48665e130 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
@@ -64,8 +64,12 @@ struct stv0299_state { | |||
64 | u32 tuner_frequency; | 64 | u32 tuner_frequency; |
65 | u32 symbol_rate; | 65 | u32 symbol_rate; |
66 | fe_code_rate_t fec_inner; | 66 | fe_code_rate_t fec_inner; |
67 | int errmode; | ||
67 | }; | 68 | }; |
68 | 69 | ||
70 | #define STATUS_BER 0 | ||
71 | #define STATUS_UCBLOCKS 1 | ||
72 | |||
69 | static int debug; | 73 | static int debug; |
70 | static int debug_legacy_dish_switch; | 74 | static int debug_legacy_dish_switch; |
71 | #define dprintk(args...) \ | 75 | #define dprintk(args...) \ |
@@ -383,36 +387,6 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag | |||
383 | }; | 387 | }; |
384 | } | 388 | } |
385 | 389 | ||
386 | static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime) | ||
387 | { | ||
388 | return ((curtime.tv_usec < lasttime.tv_usec) ? | ||
389 | 1000000 - lasttime.tv_usec + curtime.tv_usec : | ||
390 | curtime.tv_usec - lasttime.tv_usec); | ||
391 | } | ||
392 | |||
393 | static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec) | ||
394 | { | ||
395 | struct timeval lasttime; | ||
396 | s32 delta, newdelta; | ||
397 | |||
398 | waketime->tv_usec += add_usec; | ||
399 | if (waketime->tv_usec >= 1000000) { | ||
400 | waketime->tv_usec -= 1000000; | ||
401 | waketime->tv_sec++; | ||
402 | } | ||
403 | |||
404 | do_gettimeofday (&lasttime); | ||
405 | delta = stv0299_calc_usec_delay (lasttime, *waketime); | ||
406 | if (delta > 2500) { | ||
407 | msleep ((delta - 1500) / 1000); | ||
408 | do_gettimeofday (&lasttime); | ||
409 | newdelta = stv0299_calc_usec_delay (lasttime, *waketime); | ||
410 | delta = (newdelta > delta) ? 0 : newdelta; | ||
411 | } | ||
412 | if (delta > 0) | ||
413 | udelay (delta); | ||
414 | } | ||
415 | |||
416 | static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) | 390 | static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) |
417 | { | 391 | { |
418 | struct stv0299_state* state = fe->demodulator_priv; | 392 | struct stv0299_state* state = fe->demodulator_priv; |
@@ -440,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) | |||
440 | memcpy (&tv[0], &nexttime, sizeof (struct timeval)); | 414 | memcpy (&tv[0], &nexttime, sizeof (struct timeval)); |
441 | stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ | 415 | stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ |
442 | 416 | ||
443 | stv0299_sleep_until (&nexttime, 32000); | 417 | dvb_frontend_sleep_until(&nexttime, 32000); |
444 | 418 | ||
445 | for (i=0; i<9; i++) { | 419 | for (i=0; i<9; i++) { |
446 | if (debug_legacy_dish_switch) | 420 | if (debug_legacy_dish_switch) |
@@ -454,13 +428,13 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) | |||
454 | cmd = cmd >> 1; | 428 | cmd = cmd >> 1; |
455 | 429 | ||
456 | if (i != 8) | 430 | if (i != 8) |
457 | stv0299_sleep_until (&nexttime, 8000); | 431 | dvb_frontend_sleep_until(&nexttime, 8000); |
458 | } | 432 | } |
459 | if (debug_legacy_dish_switch) { | 433 | if (debug_legacy_dish_switch) { |
460 | printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", | 434 | printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", |
461 | __FUNCTION__, fe->dvb->num); | 435 | __FUNCTION__, fe->dvb->num); |
462 | for (i=1; i < 10; i++) | 436 | for (i = 1; i < 10; i++) |
463 | printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i])); | 437 | printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); |
464 | } | 438 | } |
465 | 439 | ||
466 | return 0; | 440 | return 0; |
@@ -517,8 +491,7 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) | |||
517 | { | 491 | { |
518 | struct stv0299_state* state = fe->demodulator_priv; | 492 | struct stv0299_state* state = fe->demodulator_priv; |
519 | 493 | ||
520 | stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10); | 494 | if (state->errmode != STATUS_BER) return 0; |
521 | msleep(100); | ||
522 | *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | 495 | *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); |
523 | 496 | ||
524 | return 0; | 497 | return 0; |
@@ -557,9 +530,8 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
557 | { | 530 | { |
558 | struct stv0299_state* state = fe->demodulator_priv; | 531 | struct stv0299_state* state = fe->demodulator_priv; |
559 | 532 | ||
560 | stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30); | 533 | if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; |
561 | msleep(100); | 534 | else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); |
562 | *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | ||
563 | 535 | ||
564 | return 0; | 536 | return 0; |
565 | } | 537 | } |
@@ -581,49 +553,14 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
581 | if (state->config->invert) invval = (~invval) & 1; | 553 | if (state->config->invert) invval = (~invval) & 1; |
582 | stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); | 554 | stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); |
583 | 555 | ||
584 | if (state->config->enhanced_tuning) { | 556 | stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ |
585 | /* check if we should do a finetune */ | 557 | state->config->pll_set(fe, state->i2c, p); |
586 | int frequency_delta = p->frequency - state->tuner_frequency; | 558 | stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ |
587 | int minmax = p->u.qpsk.symbol_rate / 2000; | ||
588 | if (minmax < 5000) minmax = 5000; | ||
589 | |||
590 | if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) && | ||
591 | (state->fec_inner == p->u.qpsk.fec_inner) && | ||
592 | (state->symbol_rate == p->u.qpsk.symbol_rate)) { | ||
593 | int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000); | ||
594 | |||
595 | // zap the derotator registers first | ||
596 | stv0299_writeregI(state, 0x22, 0x00); | ||
597 | stv0299_writeregI(state, 0x23, 0x00); | ||
598 | |||
599 | // now set them as we want | ||
600 | stv0299_writeregI(state, 0x22, Drot_freq >> 8); | ||
601 | stv0299_writeregI(state, 0x23, Drot_freq); | ||
602 | } else { | ||
603 | /* A "normal" tune is requested */ | ||
604 | stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ | ||
605 | state->config->pll_set(fe, state->i2c, p); | ||
606 | stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ | ||
607 | |||
608 | stv0299_writeregI(state, 0x32, 0x80); | ||
609 | stv0299_writeregI(state, 0x22, 0x00); | ||
610 | stv0299_writeregI(state, 0x23, 0x00); | ||
611 | stv0299_writeregI(state, 0x32, 0x19); | ||
612 | stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); | ||
613 | stv0299_set_FEC (state, p->u.qpsk.fec_inner); | ||
614 | } | ||
615 | } else { | ||
616 | stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ | ||
617 | state->config->pll_set(fe, state->i2c, p); | ||
618 | stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ | ||
619 | 559 | ||
620 | stv0299_set_FEC (state, p->u.qpsk.fec_inner); | 560 | stv0299_set_FEC (state, p->u.qpsk.fec_inner); |
621 | stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); | 561 | stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); |
622 | stv0299_writeregI(state, 0x22, 0x00); | 562 | stv0299_writeregI(state, 0x22, 0x00); |
623 | stv0299_writeregI(state, 0x23, 0x00); | 563 | stv0299_writeregI(state, 0x23, 0x00); |
624 | stv0299_readreg (state, 0x23); | ||
625 | stv0299_writeregI(state, 0x12, 0xb9); | ||
626 | } | ||
627 | 564 | ||
628 | state->tuner_frequency = p->frequency; | 565 | state->tuner_frequency = p->frequency; |
629 | state->fec_inner = p->u.qpsk.fec_inner; | 566 | state->fec_inner = p->u.qpsk.fec_inner; |
@@ -708,6 +645,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, | |||
708 | state->tuner_frequency = 0; | 645 | state->tuner_frequency = 0; |
709 | state->symbol_rate = 0; | 646 | state->symbol_rate = 0; |
710 | state->fec_inner = 0; | 647 | state->fec_inner = 0; |
648 | state->errmode = STATUS_BER; | ||
711 | 649 | ||
712 | /* check if the demod is there */ | 650 | /* check if the demod is there */ |
713 | stv0299_writeregI(state, 0x02, 0x34); /* standby off */ | 651 | stv0299_writeregI(state, 0x02, 0x34); /* standby off */ |