diff options
Diffstat (limited to 'drivers/media/dvb/frontends/tda1004x.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda1004x.c | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index f4a9cf9d26d0..33a84372c9e6 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -40,20 +40,6 @@ | |||
40 | #include "dvb_frontend.h" | 40 | #include "dvb_frontend.h" |
41 | #include "tda1004x.h" | 41 | #include "tda1004x.h" |
42 | 42 | ||
43 | enum tda1004x_demod { | ||
44 | TDA1004X_DEMOD_TDA10045, | ||
45 | TDA1004X_DEMOD_TDA10046, | ||
46 | }; | ||
47 | |||
48 | struct tda1004x_state { | ||
49 | struct i2c_adapter* i2c; | ||
50 | const struct tda1004x_config* config; | ||
51 | struct dvb_frontend frontend; | ||
52 | |||
53 | /* private demod data */ | ||
54 | enum tda1004x_demod demod_type; | ||
55 | }; | ||
56 | |||
57 | static int debug; | 43 | static int debug; |
58 | #define dprintk(args...) \ | 44 | #define dprintk(args...) \ |
59 | do { \ | 45 | do { \ |
@@ -507,35 +493,51 @@ static int tda10046_fwupload(struct dvb_frontend* fe) | |||
507 | tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); | 493 | tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); |
508 | } | 494 | } |
509 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); | 495 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); |
496 | /* set GPIO 1 and 3 */ | ||
497 | if (state->config->gpio_config != TDA10046_GPTRI) { | ||
498 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33); | ||
499 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f); | ||
500 | } | ||
510 | /* let the clocks recover from sleep */ | 501 | /* let the clocks recover from sleep */ |
511 | msleep(5); | 502 | msleep(10); |
512 | 503 | ||
513 | /* The PLLs need to be reprogrammed after sleep */ | 504 | /* The PLLs need to be reprogrammed after sleep */ |
514 | tda10046_init_plls(fe); | 505 | tda10046_init_plls(fe); |
506 | tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0); | ||
515 | 507 | ||
516 | /* don't re-upload unless necessary */ | 508 | /* don't re-upload unless necessary */ |
517 | if (tda1004x_check_upload_ok(state) == 0) | 509 | if (tda1004x_check_upload_ok(state) == 0) |
518 | return 0; | 510 | return 0; |
519 | 511 | ||
512 | printk(KERN_INFO "tda1004x: trying to boot from eeprom\n"); | ||
513 | tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); | ||
514 | msleep(300); | ||
515 | /* don't re-upload unless necessary */ | ||
516 | if (tda1004x_check_upload_ok(state) == 0) | ||
517 | return 0; | ||
518 | |||
520 | if (state->config->request_firmware != NULL) { | 519 | if (state->config->request_firmware != NULL) { |
521 | /* request the firmware, this will block until someone uploads it */ | 520 | /* request the firmware, this will block until someone uploads it */ |
522 | printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); | 521 | printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); |
523 | ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); | 522 | ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); |
524 | if (ret) { | 523 | if (ret) { |
525 | printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); | 524 | /* remain compatible to old bug: try to load with tda10045 image name */ |
526 | return ret; | 525 | ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); |
526 | if (ret) { | ||
527 | printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); | ||
528 | return ret; | ||
529 | } else { | ||
530 | printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", | ||
531 | TDA10046_DEFAULT_FIRMWARE); | ||
532 | } | ||
527 | } | 533 | } |
528 | tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST | ||
529 | ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); | ||
530 | release_firmware(fw); | ||
531 | if (ret) | ||
532 | return ret; | ||
533 | } else { | 534 | } else { |
534 | /* boot from firmware eeprom */ | 535 | printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n"); |
535 | printk(KERN_INFO "tda1004x: booting from eeprom\n"); | 536 | return -EIO; |
536 | tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); | ||
537 | msleep(300); | ||
538 | } | 537 | } |
538 | tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST | ||
539 | ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); | ||
540 | release_firmware(fw); | ||
539 | return tda1004x_check_upload_ok(state); | 541 | return tda1004x_check_upload_ok(state); |
540 | } | 542 | } |
541 | 543 | ||
@@ -638,37 +640,33 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
638 | switch (state->config->agc_config) { | 640 | switch (state->config->agc_config) { |
639 | case TDA10046_AGC_DEFAULT: | 641 | case TDA10046_AGC_DEFAULT: |
640 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup | 642 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup |
641 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | 643 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities |
642 | break; | 644 | break; |
643 | case TDA10046_AGC_IFO_AUTO_NEG: | 645 | case TDA10046_AGC_IFO_AUTO_NEG: |
644 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup | 646 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup |
645 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | 647 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities |
646 | break; | 648 | break; |
647 | case TDA10046_AGC_IFO_AUTO_POS: | 649 | case TDA10046_AGC_IFO_AUTO_POS: |
648 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup | 650 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup |
649 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities | 651 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00); // set AGC polarities |
650 | break; | ||
651 | case TDA10046_AGC_TDA827X_GP11: | ||
652 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | ||
653 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | ||
654 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | ||
655 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities | ||
656 | break; | ||
657 | case TDA10046_AGC_TDA827X_GP00: | ||
658 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | ||
659 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | ||
660 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | ||
661 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | ||
662 | break; | 652 | break; |
663 | case TDA10046_AGC_TDA827X_GP01: | 653 | case TDA10046_AGC_TDA827X: |
664 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | 654 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup |
665 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | 655 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold |
666 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 656 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
667 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities | 657 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities |
668 | break; | 658 | break; |
669 | } | 659 | } |
660 | if (state->config->ts_mode == 0) { | ||
661 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40); | ||
662 | tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); | ||
663 | } else { | ||
664 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80); | ||
665 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10, | ||
666 | state->config->invert_oclk << 4); | ||
667 | } | ||
670 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); | 668 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); |
671 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on | 669 | tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on |
672 | tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } | 670 | tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } |
673 | tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values | 671 | tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values |
674 | tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } | 672 | tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } |
@@ -678,7 +676,6 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
678 | tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config | 676 | tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config |
679 | tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config | 677 | tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config |
680 | // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes | 678 | // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes |
681 | tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); | ||
682 | 679 | ||
683 | return 0; | 680 | return 0; |
684 | } | 681 | } |
@@ -705,7 +702,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, | |||
705 | // set frequency | 702 | // set frequency |
706 | if (fe->ops.tuner_ops.set_params) { | 703 | if (fe->ops.tuner_ops.set_params) { |
707 | fe->ops.tuner_ops.set_params(fe, fe_params); | 704 | fe->ops.tuner_ops.set_params(fe, fe_params); |
708 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); | 705 | if (fe->ops.i2c_gate_ctrl) |
706 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
709 | } | 707 | } |
710 | 708 | ||
711 | // Hardcoded to use auto as much as possible on the TDA10045 as it | 709 | // Hardcoded to use auto as much as possible on the TDA10045 as it |
@@ -1165,6 +1163,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) | |||
1165 | static int tda1004x_sleep(struct dvb_frontend* fe) | 1163 | static int tda1004x_sleep(struct dvb_frontend* fe) |
1166 | { | 1164 | { |
1167 | struct tda1004x_state* state = fe->demodulator_priv; | 1165 | struct tda1004x_state* state = fe->demodulator_priv; |
1166 | int gpio_conf; | ||
1168 | 1167 | ||
1169 | switch (state->demod_type) { | 1168 | switch (state->demod_type) { |
1170 | case TDA1004X_DEMOD_TDA10045: | 1169 | case TDA1004X_DEMOD_TDA10045: |
@@ -1174,6 +1173,13 @@ static int tda1004x_sleep(struct dvb_frontend* fe) | |||
1174 | case TDA1004X_DEMOD_TDA10046: | 1173 | case TDA1004X_DEMOD_TDA10046: |
1175 | /* set outputs to tristate */ | 1174 | /* set outputs to tristate */ |
1176 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); | 1175 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); |
1176 | /* invert GPIO 1 and 3 if desired*/ | ||
1177 | gpio_conf = state->config->gpio_config; | ||
1178 | if (gpio_conf >= TDA10046_GP00_I) | ||
1179 | tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, | ||
1180 | (gpio_conf & 0x0f) ^ 0x0a); | ||
1181 | |||
1182 | tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0); | ||
1177 | tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); | 1183 | tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); |
1178 | break; | 1184 | break; |
1179 | } | 1185 | } |