diff options
Diffstat (limited to 'drivers/media/dvb/frontends/stv0299.c')
-rw-r--r-- | drivers/media/dvb/frontends/stv0299.c | 114 |
1 files changed, 84 insertions, 30 deletions
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 15b40541b62d..cfa3928bb487 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
@@ -70,6 +70,7 @@ struct stv0299_state { | |||
70 | #define STATUS_UCBLOCKS 1 | 70 | #define STATUS_UCBLOCKS 1 |
71 | 71 | ||
72 | static int debug; | 72 | static int debug; |
73 | static int debug_legacy_dish_switch; | ||
73 | #define dprintk(args...) \ | 74 | #define dprintk(args...) \ |
74 | do { \ | 75 | do { \ |
75 | if (debug) printk(KERN_DEBUG "stv0299: " args); \ | 76 | if (debug) printk(KERN_DEBUG "stv0299: " args); \ |
@@ -93,7 +94,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) | |||
93 | 94 | ||
94 | int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data) | 95 | int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data) |
95 | { | 96 | { |
96 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 97 | struct stv0299_state* state = fe->demodulator_priv; |
97 | 98 | ||
98 | return stv0299_writeregI(state, reg, data); | 99 | return stv0299_writeregI(state, reg, data); |
99 | } | 100 | } |
@@ -218,7 +219,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) | |||
218 | 219 | ||
219 | static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate) | 220 | static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate) |
220 | { | 221 | { |
221 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 222 | struct stv0299_state* state = fe->demodulator_priv; |
222 | u64 big = srate; | 223 | u64 big = srate; |
223 | u32 ratio; | 224 | u32 ratio; |
224 | 225 | ||
@@ -269,7 +270,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state) | |||
269 | static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, | 270 | static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, |
270 | struct dvb_diseqc_master_cmd *m) | 271 | struct dvb_diseqc_master_cmd *m) |
271 | { | 272 | { |
272 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 273 | struct stv0299_state* state = fe->demodulator_priv; |
273 | u8 val; | 274 | u8 val; |
274 | int i; | 275 | int i; |
275 | 276 | ||
@@ -299,7 +300,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, | |||
299 | 300 | ||
300 | static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | 301 | static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) |
301 | { | 302 | { |
302 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 303 | struct stv0299_state* state = fe->demodulator_priv; |
303 | u8 val; | 304 | u8 val; |
304 | 305 | ||
305 | dprintk ("%s\n", __FUNCTION__); | 306 | dprintk ("%s\n", __FUNCTION__); |
@@ -326,7 +327,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t | |||
326 | 327 | ||
327 | static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | 328 | static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) |
328 | { | 329 | { |
329 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 330 | struct stv0299_state* state = fe->demodulator_priv; |
330 | u8 val; | 331 | u8 val; |
331 | 332 | ||
332 | if (stv0299_wait_diseqc_idle (state, 100) < 0) | 333 | if (stv0299_wait_diseqc_idle (state, 100) < 0) |
@@ -348,7 +349,7 @@ static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
348 | 349 | ||
349 | static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) | 350 | static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) |
350 | { | 351 | { |
351 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 352 | struct stv0299_state* state = fe->demodulator_priv; |
352 | u8 reg0x08; | 353 | u8 reg0x08; |
353 | u8 reg0x0c; | 354 | u8 reg0x0c; |
354 | 355 | ||
@@ -385,34 +386,84 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag | |||
385 | }; | 386 | }; |
386 | } | 387 | } |
387 | 388 | ||
388 | static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd) | 389 | static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime) |
389 | { | 390 | { |
391 | return ((curtime.tv_usec < lasttime.tv_usec) ? | ||
392 | 1000000 - lasttime.tv_usec + curtime.tv_usec : | ||
393 | curtime.tv_usec - lasttime.tv_usec); | ||
394 | } | ||
395 | |||
396 | static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec) | ||
397 | { | ||
398 | struct timeval lasttime; | ||
399 | s32 delta, newdelta; | ||
400 | |||
401 | waketime->tv_usec += add_usec; | ||
402 | if (waketime->tv_usec >= 1000000) { | ||
403 | waketime->tv_usec -= 1000000; | ||
404 | waketime->tv_sec++; | ||
405 | } | ||
406 | |||
407 | do_gettimeofday (&lasttime); | ||
408 | delta = stv0299_calc_usec_delay (lasttime, *waketime); | ||
409 | if (delta > 2500) { | ||
410 | msleep ((delta - 1500) / 1000); | ||
411 | do_gettimeofday (&lasttime); | ||
412 | newdelta = stv0299_calc_usec_delay (lasttime, *waketime); | ||
413 | delta = (newdelta > delta) ? 0 : newdelta; | ||
414 | } | ||
415 | if (delta > 0) | ||
416 | udelay (delta); | ||
417 | } | ||
418 | |||
419 | static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) | ||
420 | { | ||
421 | struct stv0299_state* state = fe->demodulator_priv; | ||
422 | u8 reg0x08; | ||
423 | u8 reg0x0c; | ||
424 | u8 lv_mask = 0x40; | ||
390 | u8 last = 1; | 425 | u8 last = 1; |
391 | int i; | 426 | int i; |
427 | struct timeval nexttime; | ||
428 | struct timeval tv[10]; | ||
392 | 429 | ||
393 | /* reset voltage at the end | 430 | reg0x08 = stv0299_readreg (state, 0x08); |
394 | if((0x50 & stv0299_readreg (i2c, 0x0c)) == 0x50) | 431 | reg0x0c = stv0299_readreg (state, 0x0c); |
395 | cmd |= 0x80; | 432 | reg0x0c &= 0x0f; |
396 | else | 433 | stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6)); |
397 | cmd &= 0x7F; | 434 | if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) |
398 | */ | 435 | lv_mask = 0x10; |
399 | 436 | ||
400 | cmd = cmd << 1; | 437 | cmd = cmd << 1; |
401 | dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd); | 438 | if (debug_legacy_dish_switch) |
439 | printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd); | ||
440 | |||
441 | do_gettimeofday (&nexttime); | ||
442 | if (debug_legacy_dish_switch) | ||
443 | memcpy (&tv[0], &nexttime, sizeof (struct timeval)); | ||
444 | stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ | ||
402 | 445 | ||
403 | stv0299_set_voltage(fe,SEC_VOLTAGE_18); | 446 | stv0299_sleep_until (&nexttime, 32000); |
404 | msleep(32); | ||
405 | 447 | ||
406 | for (i=0; i<9; i++) { | 448 | for (i=0; i<9; i++) { |
449 | if (debug_legacy_dish_switch) | ||
450 | do_gettimeofday (&tv[i+1]); | ||
407 | if((cmd & 0x01) != last) { | 451 | if((cmd & 0x01) != last) { |
408 | stv0299_set_voltage(fe, last ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); | 452 | /* set voltage to (last ? 13V : 18V) */ |
453 | stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50)); | ||
409 | last = (last) ? 0 : 1; | 454 | last = (last) ? 0 : 1; |
410 | } | 455 | } |
411 | 456 | ||
412 | cmd = cmd >> 1; | 457 | cmd = cmd >> 1; |
413 | 458 | ||
414 | if (i != 8) | 459 | if (i != 8) |
415 | msleep(8); | 460 | stv0299_sleep_until (&nexttime, 8000); |
461 | } | ||
462 | if (debug_legacy_dish_switch) { | ||
463 | printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", | ||
464 | __FUNCTION__, fe->dvb->num); | ||
465 | for (i=1; i < 10; i++) | ||
466 | printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i])); | ||
416 | } | 467 | } |
417 | 468 | ||
418 | return 0; | 469 | return 0; |
@@ -420,7 +471,7 @@ static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd) | |||
420 | 471 | ||
421 | static int stv0299_init (struct dvb_frontend* fe) | 472 | static int stv0299_init (struct dvb_frontend* fe) |
422 | { | 473 | { |
423 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 474 | struct stv0299_state* state = fe->demodulator_priv; |
424 | int i; | 475 | int i; |
425 | 476 | ||
426 | dprintk("stv0299: init chip\n"); | 477 | dprintk("stv0299: init chip\n"); |
@@ -439,7 +490,7 @@ static int stv0299_init (struct dvb_frontend* fe) | |||
439 | 490 | ||
440 | static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) | 491 | static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) |
441 | { | 492 | { |
442 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 493 | struct stv0299_state* state = fe->demodulator_priv; |
443 | 494 | ||
444 | u8 signal = 0xff - stv0299_readreg (state, 0x18); | 495 | u8 signal = 0xff - stv0299_readreg (state, 0x18); |
445 | u8 sync = stv0299_readreg (state, 0x1b); | 496 | u8 sync = stv0299_readreg (state, 0x1b); |
@@ -467,7 +518,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
467 | 518 | ||
468 | static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) | 519 | static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) |
469 | { | 520 | { |
470 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 521 | struct stv0299_state* state = fe->demodulator_priv; |
471 | 522 | ||
472 | if (state->errmode != STATUS_BER) return 0; | 523 | if (state->errmode != STATUS_BER) return 0; |
473 | *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | 524 | *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); |
@@ -477,7 +528,7 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) | |||
477 | 528 | ||
478 | static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 529 | static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
479 | { | 530 | { |
480 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 531 | struct stv0299_state* state = fe->demodulator_priv; |
481 | 532 | ||
482 | s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8) | 533 | s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8) |
483 | | stv0299_readreg (state, 0x19)); | 534 | | stv0299_readreg (state, 0x19)); |
@@ -494,7 +545,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) | |||
494 | 545 | ||
495 | static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr) | 546 | static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr) |
496 | { | 547 | { |
497 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 548 | struct stv0299_state* state = fe->demodulator_priv; |
498 | 549 | ||
499 | s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8) | 550 | s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8) |
500 | | stv0299_readreg (state, 0x25)); | 551 | | stv0299_readreg (state, 0x25)); |
@@ -506,7 +557,7 @@ static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr) | |||
506 | 557 | ||
507 | static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | 558 | static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) |
508 | { | 559 | { |
509 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 560 | struct stv0299_state* state = fe->demodulator_priv; |
510 | 561 | ||
511 | if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; | 562 | if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; |
512 | else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | 563 | else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); |
@@ -516,7 +567,7 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
516 | 567 | ||
517 | static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) | 568 | static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) |
518 | { | 569 | { |
519 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 570 | struct stv0299_state* state = fe->demodulator_priv; |
520 | int invval = 0; | 571 | int invval = 0; |
521 | 572 | ||
522 | dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); | 573 | dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); |
@@ -584,7 +635,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
584 | 635 | ||
585 | static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) | 636 | static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) |
586 | { | 637 | { |
587 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 638 | struct stv0299_state* state = fe->demodulator_priv; |
588 | s32 derot_freq; | 639 | s32 derot_freq; |
589 | int invval; | 640 | int invval; |
590 | 641 | ||
@@ -609,7 +660,7 @@ static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
609 | 660 | ||
610 | static int stv0299_sleep(struct dvb_frontend* fe) | 661 | static int stv0299_sleep(struct dvb_frontend* fe) |
611 | { | 662 | { |
612 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 663 | struct stv0299_state* state = fe->demodulator_priv; |
613 | 664 | ||
614 | stv0299_writeregI(state, 0x02, 0x80); | 665 | stv0299_writeregI(state, 0x02, 0x80); |
615 | state->initialised = 0; | 666 | state->initialised = 0; |
@@ -619,7 +670,7 @@ static int stv0299_sleep(struct dvb_frontend* fe) | |||
619 | 670 | ||
620 | static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) | 671 | static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) |
621 | { | 672 | { |
622 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 673 | struct stv0299_state* state = fe->demodulator_priv; |
623 | 674 | ||
624 | fesettings->min_delay_ms = state->config->min_delay_ms; | 675 | fesettings->min_delay_ms = state->config->min_delay_ms; |
625 | if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { | 676 | if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { |
@@ -634,7 +685,7 @@ static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten | |||
634 | 685 | ||
635 | static void stv0299_release(struct dvb_frontend* fe) | 686 | static void stv0299_release(struct dvb_frontend* fe) |
636 | { | 687 | { |
637 | struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; | 688 | struct stv0299_state* state = fe->demodulator_priv; |
638 | kfree(state); | 689 | kfree(state); |
639 | } | 690 | } |
640 | 691 | ||
@@ -647,7 +698,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, | |||
647 | int id; | 698 | int id; |
648 | 699 | ||
649 | /* allocate memory for the internal state */ | 700 | /* allocate memory for the internal state */ |
650 | state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); | 701 | state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); |
651 | if (state == NULL) goto error; | 702 | if (state == NULL) goto error; |
652 | 703 | ||
653 | /* setup the state */ | 704 | /* setup the state */ |
@@ -719,6 +770,9 @@ static struct dvb_frontend_ops stv0299_ops = { | |||
719 | .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd, | 770 | .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd, |
720 | }; | 771 | }; |
721 | 772 | ||
773 | module_param(debug_legacy_dish_switch, int, 0444); | ||
774 | MODULE_PARM_DESC(debug_legacy_dish_switch, "Enable timing analysis for Dish Network legacy switches"); | ||
775 | |||
722 | module_param(debug, int, 0644); | 776 | module_param(debug, int, 0644); |
723 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | 777 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); |
724 | 778 | ||