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 | ||
