diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 17:18:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 17:18:45 -0400 |
| commit | aa5bc2b58e3344da57f26b62e99e13e91c9e0a94 (patch) | |
| tree | c6e9ea1b3ee8af88b3a050b3fba160ea2f77e404 /drivers/media/dvb/frontends/tda1004x.c | |
| parent | d868772fff6c4b881d66af8640251714e1aefa98 (diff) | |
| parent | d455cf5d0db9e3eb1b204cd4a61d8c5ccfe4305f (diff) | |
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (184 commits)
V4L/DVB (5563): Radio-maestro.c Replace radio_ioctl to use video_ioctl2
V4L/DVB (5562): Radio-gemtek-pci.c Replace gemtek_pci_ioctl to use video_ioctl2
V4L/DVB (5560): Ivtv: fix incorrect bitwise-and for command flags.
V4L/DVB (5558): Opera: use 7-bit i2c addresses
V4L/DVB (5557): Cafe_ccic: check return value of pci_enable_device
V4L/DVB (5556): Radio-gemtek.c Replace gemtek_ioctl to use video_ioctl2
V4L/DVB (5555): Radio-aimslab.c Replace rt_ioctl to use video_ioctl2
V4L/DVB (5554): Fix: vidioc_g_parm were not zeroing the memory
V4L/DVB (5553): Replace typhoon_do_ioctl to use video_ioctl2
V4L/DVB (5552): Plan-b: Switch to refcounting PCI API
V4L/DVB (5551): Plan-b: header change
V4L/DVB (5550): Radio-sf16fmi.c Replace fmi_do_ioctl to use video_ioctl2
V4L/DVB (5549): Radio-sf16fmr2.c Replace fmr2_do_ioctl to use video_ioctl2
V4L/DVB (5548): Fix v4l2 buffer to the length
V4L/DVB (5547): Add ENUM_FRAMESIZES and ENUM_FRAMEINTERVALS ioctls
V4L/DVB (5546): Radio-terratec.c Replace tt_do_ioctl to use video_ioctl2
V4L/DVB (5545): Saa7146: Release capture buffers on device close
V4L/DVB (5544): Budget-av: Make inversion setting configurable, add KNC ONE V1.0 card
V4L/DVB (5543): Tda10023: Add support for frontend TDA10023
V4L/DVB (5542): Budget-av: Remove polarity switching of the clock for DVB-C
...
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 | } |
