diff options
Diffstat (limited to 'linux/drivers/media/dvb/frontends/tda10045h.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda10045h.c | 824 |
1 files changed, 408 insertions, 416 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda10045h.c b/linux/drivers/media/dvb/frontends/tda10045h.c index 8319e547b..0d030bc60 100644 --- a/linux/drivers/media/dvb/frontends/tda10045h.c +++ b/linux/drivers/media/dvb/frontends/tda10045h.c @@ -1,5 +1,5 @@ /* - Driver for Philips TDA10045H OFDM Frontend + Driver for Philips tda10045h OFDM Frontend This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,12 +20,12 @@ /* This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend - windows driver saved as '/usr/lib/DVB/driver/frontends/tda10045h.mc'. - You can also pass the complete file name with the module parameter 'tda10045h_firmware'. - + windows driver saved as '/usr/lib/DVB/driver/frontends/tda1004x.mc'. + You can also pass the complete file name with the module parameter 'tda1004x_firmware'. + Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can be added reasonably painlessly. - + Windows driver URL: http://www.technotrend.de/ */ @@ -44,66 +44,66 @@ #include "dvb_frontend.h" #include "dvb_functions.h" -static int tda10045h_debug = 0; -static char *tda10045h_firmware = - "/usr/lib/DVB/driver/frontends/tda10045h.mc"; - - -#define TDA10045H_ADDRESS 0x08 -#define TDA10045H_TUNERA_ADDRESS 0x61 -#define TDA10045H_TDM1316L_ADDRESS 0x63 -#define TDA10045H_MC44BC374_ADDRESS 0x65 - -#define TDA10045H_CHIPID 0x00 -#define TDA10045H_AUTO 0x01 -#define TDA10045H_IN_CONF1 0x02 -#define TDA10045H_IN_CONF2 0x03 -#define TDA10045H_OUT_CONF1 0x04 -#define TDA10045H_OUT_CONF2 0x05 -#define TDA10045H_STATUS_CD 0x06 -#define TDA10045H_CONFC4 0x07 -#define TDA10045H_REG0C 0x0C -#define TDA10045H_CODE_IN 0x0D -#define TDA10045H_FWPAGE 0x0E -#define TDA10045H_SCAN_CPT 0x10 -#define TDA10045H_DSP_CMD 0x11 -#define TDA10045H_DSP_ARG 0x12 -#define TDA10045H_DSP_DATA1 0x13 -#define TDA10045H_DSP_DATA2 0x14 -#define TDA10045H_CONFADC1 0x15 -#define TDA10045H_CONFC1 0x16 -#define TDA10045H_SIGNAL_STRENGTH 0x1a -#define TDA10045H_SNR 0x1c -#define TDA10045H_REG1E 0x1e -#define TDA10045H_REG1F 0x1f -#define TDA10045H_CBER_MSB 0x21 -#define TDA10045H_CBER_LSB 0x22 -#define TDA10045H_CVBER_LUT 0x23 -#define TDA10045H_VBER_MSB 0x24 -#define TDA10045H_VBER_MID 0x25 -#define TDA10045H_VBER_LSB 0x26 -#define TDA10045H_UNCOR 0x27 -#define TDA10045H_CONFPLL_P 0x2D -#define TDA10045H_CONFPLL_M_MSB 0x2E -#define TDA10045H_CONFPLL_M_LSB 0x2F -#define TDA10045H_CONFPLL_N 0x30 -#define TDA10045H_UNSURW_MSB 0x31 -#define TDA10045H_UNSURW_LSB 0x32 -#define TDA10045H_WREF_MSB 0x33 -#define TDA10045H_WREF_MID 0x34 -#define TDA10045H_WREF_LSB 0x35 -#define TDA10045H_MUXOUT 0x36 -#define TDA10045H_CONFADC2 0x37 -#define TDA10045H_IOFFSET 0x38 - - -#define dprintk if (tda10045h_debug) printk +static int tda1004x_debug = 0; +static char *tda1004x_firmware = "/usr/lib/DVB/driver/frontends/tda1004x.mc"; + + +#define TDA10045H_ADDRESS 0x08 +#define TD1344_ADDRESS 0x61 +#define TDM1316L_ADDRESS 0x63 +#define MC44BC374_ADDRESS 0x65 + +#define TDA1004X_CHIPID 0x00 +#define TDA1004X_AUTO 0x01 +#define TDA1004X_IN_CONF1 0x02 +#define TDA1004X_IN_CONF2 0x03 +#define TDA1004X_OUT_CONF1 0x04 +#define TDA1004X_OUT_CONF2 0x05 +#define TDA1004X_STATUS_CD 0x06 +#define TDA1004X_CONFC4 0x07 +#define TDA1004X_REG0C 0x0C +#define TDA1004X_CODE_IN 0x0D +#define TDA1004X_FWPAGE 0x0E +#define TDA1004X_SCAN_CPT 0x10 +#define TDA1004X_DSP_CMD 0x11 +#define TDA1004X_DSP_ARG 0x12 +#define TDA1004X_DSP_DATA1 0x13 +#define TDA1004X_DSP_DATA2 0x14 +#define TDA1004X_CONFADC1 0x15 +#define TDA1004X_CONFC1 0x16 +#define TDA1004X_SIGNAL_STRENGTH 0x1a +#define TDA1004X_SNR 0x1c +#define TDA1004X_REG1E 0x1e +#define TDA1004X_REG1F 0x1f +#define TDA1004X_CBER_RESET 0x20 +#define TDA1004X_CBER_MSB 0x21 +#define TDA1004X_CBER_LSB 0x22 +#define TDA1004X_CVBER_LUT 0x23 +#define TDA1004X_VBER_MSB 0x24 +#define TDA1004X_VBER_MID 0x25 +#define TDA1004X_VBER_LSB 0x26 +#define TDA1004X_UNCOR 0x27 +#define TDA1004X_CONFPLL_P 0x2D +#define TDA1004X_CONFPLL_M_MSB 0x2E +#define TDA1004X_CONFPLL_M_LSB 0x2F +#define TDA1004X_CONFPLL_N 0x30 +#define TDA1004X_UNSURW_MSB 0x31 +#define TDA1004X_UNSURW_LSB 0x32 +#define TDA1004X_WREF_MSB 0x33 +#define TDA1004X_WREF_MID 0x34 +#define TDA1004X_WREF_LSB 0x35 +#define TDA1004X_MUXOUT 0x36 +#define TDA1004X_CONFADC2 0x37 +#define TDA1004X_IOFFSET 0x38 + + +#define dprintk if (tda1004x_debug) printk static struct dvb_frontend_info tda10045h_info = { .name = "Philips TDA10045H", .type = FE_OFDM, - .frequency_min = 87000000, - .frequency_max = 895000000, + .frequency_min = 51000000, + .frequency_max = 858000000, .frequency_stepsize = 166667, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | @@ -113,7 +113,8 @@ static struct dvb_frontend_info tda10045h_info = { }; #pragma pack(1) -struct tda10045h_state { +struct tda1004x_state { + u8 tda1004x_address; u8 tuner_address; u8 initialised; }; @@ -124,33 +125,25 @@ struct fwinfo { int fw_offset; int fw_size; }; -static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555}, /* 2.15a */ -}; -static int tda10045h_fwinfo_count = - sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo); - - -static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; -static u8 bandwidth_8mhz[] = - { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; -static u8 bandwidth_7mhz[] = - { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; -static u8 bandwidth_6mhz[] = - { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; -static u8 tuner_data[] = { 0x0b, 0xf5, 0x88, 0xab, 0x00 }; +static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555} }; +static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo); + + +static u8 tda10045h_bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; +static u8 tda10045h_bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; +static u8 tda10045h_bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; static int errno; -static -int tda10045h_write_byte(struct dvb_i2c_bus *i2c, int reg, int data) + +static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data) { int ret; u8 buf[] = { reg, data }; - struct i2c_msg msg = {.addr = TDA10045H_ADDRESS,.flags = 0,.buf = - buf,.len = 2 - }; + struct i2c_msg msg = { .addr=0, .flags=0, .buf=buf, .len=2 }; dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data); + msg.addr = tda_state->tda1004x_address; ret = i2c->xfer(i2c, &msg, 1); if (ret != 1) @@ -162,19 +155,18 @@ int tda10045h_write_byte(struct dvb_i2c_bus *i2c, int reg, int data) return (ret != 1) ? -1 : 0; } -static -int tda10045h_read_byte(struct dvb_i2c_bus *i2c, int reg) +static int tda1004x_read_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg) { int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; - struct i2c_msg msg[] = { {.addr = TDA10045H_ADDRESS,.flags = - 0,.buf = b0,.len = 1}, - {.addr = TDA10045H_ADDRESS,.flags = I2C_M_RD,.buf = b1,.len = 1} - }; + struct i2c_msg msg[] = {{ .addr=0, .flags=0, .buf=b0, .len=1}, + { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}}; dprintk("%s: reg=0x%x\n", __FUNCTION__, reg); + msg[0].addr = tda_state->tda1004x_address; + msg[1].addr = tda_state->tda1004x_address; ret = i2c->xfer(i2c, msg, 2); if (ret != 2) { @@ -188,16 +180,14 @@ int tda10045h_read_byte(struct dvb_i2c_bus *i2c, int reg) return b1[0]; } -static -int tda10045h_write_mask(struct dvb_i2c_bus *i2c, int reg, int mask, - int data) +static int tda1004x_write_mask(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int mask, int data) { int val; dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg, mask, data); // read a byte and check - val = tda10045h_read_byte(i2c, reg); + val = tda1004x_read_byte(i2c, tda_state, reg); if (val < 0) return val; @@ -206,12 +196,10 @@ int tda10045h_write_mask(struct dvb_i2c_bus *i2c, int reg, int mask, val |= data & 0xff; // write it out again - return tda10045h_write_byte(i2c, reg, val); + return tda1004x_write_byte(i2c, tda_state, reg, val); } -static -int tda10045h_write_buf(struct dvb_i2c_bus *i2c, int reg, - unsigned char *buf, int len) +static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, unsigned char *buf, int len) { int i; int result; @@ -220,7 +208,7 @@ int tda10045h_write_buf(struct dvb_i2c_bus *i2c, int reg, result = 0; for (i = 0; i < len; i++) { - result = tda10045h_write_byte(i2c, reg + i, buf[i]); + result = tda1004x_write_byte(i2c, tda_state, reg + i, buf[i]); if (result != 0) break; } @@ -228,28 +216,25 @@ int tda10045h_write_buf(struct dvb_i2c_bus *i2c, int reg, return result; } -static -int tda10045h_enable_tuner_i2c(struct dvb_i2c_bus *i2c) +static int tda1004x_enable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) { int result; dprintk("%s\n", __FUNCTION__); - result = tda10045h_write_mask(i2c, TDA10045H_CONFC4, 2, 2); + result = tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 2); dvb_delay(1); return result; } -static -int tda10045h_disable_tuner_i2c(struct dvb_i2c_bus *i2c) +static int tda1004x_disable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) { dprintk("%s\n", __FUNCTION__); - return tda10045h_write_mask(i2c, TDA10045H_CONFC4, 2, 0); + return tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 0); } -static -int tda10045h_dsp_command(struct dvb_i2c_bus *i2c, int cmd, int arg) +static int tda1004x_dsp_command(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int cmd, int arg) { int counter; int data1; @@ -258,9 +243,9 @@ int tda10045h_dsp_command(struct dvb_i2c_bus *i2c, int cmd, int arg) dprintk("%s: cmd=0x%x, arg=0x%x\n", __FUNCTION__, cmd, arg); // send command and argument - if (tda10045h_write_byte(i2c, TDA10045H_DSP_ARG, arg) < 0) + if (tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_ARG, arg) < 0) return -1; - if (tda10045h_write_byte(i2c, TDA10045H_DSP_CMD, cmd) < 0) + if (tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, cmd) < 0) return -1; // command retry loop @@ -268,8 +253,8 @@ int tda10045h_dsp_command(struct dvb_i2c_bus *i2c, int cmd, int arg) while (counter++ < 5) { // read in the two data bytes - data1 = tda10045h_read_byte(i2c, TDA10045H_DSP_DATA1); - data2 = tda10045h_read_byte(i2c, TDA10045H_DSP_DATA2); + data1 = tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1); + data2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2); if ((data1 < 0) || (data2 < 0)) return -1; @@ -280,7 +265,7 @@ int tda10045h_dsp_command(struct dvb_i2c_bus *i2c, int cmd, int arg) continue; // OK, resend command - if (tda10045h_write_byte(i2c, TDA10045H_DSP_CMD, cmd) < 0) + if (tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, cmd) < 0) return -1; } @@ -295,18 +280,15 @@ int tda10045h_dsp_command(struct dvb_i2c_bus *i2c, int cmd, int arg) } -static -int tda10045h_init(struct dvb_i2c_bus *i2c) +static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) { int fw_pos; int tx_size; int counter; u8 fw_buf[65]; - struct i2c_msg fw_msg = {.addr = TDA10045H_ADDRESS,.flags = - 0,.buf = fw_buf,.len = 0 - }; - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 - }; + struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 }; + struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; + u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; unsigned char *firmware = NULL; int filesize; int fw_size = 0; @@ -319,28 +301,27 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) // Load the firmware set_fs(get_ds()); - fd = open(tda10045h_firmware, 0, 0); + fd = open(tda1004x_firmware, 0, 0); if (fd < 0) { printk("%s: Unable to open firmware %s\n", __FUNCTION__, - tda10045h_firmware); + tda1004x_firmware); return -EIO; } filesize = lseek(fd, 0L, 2); if (filesize <= 0) { printk("%s: Firmware %s is empty\n", __FUNCTION__, - tda10045h_firmware); + tda1004x_firmware); sys_close(fd); return -EIO; } + // find extraction parameters - for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; - fwinfo_idx++) { + for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; fwinfo_idx++) { if (tda10045h_fwinfo[fwinfo_idx].file_size == filesize) break; } if (fwinfo_idx >= tda10045h_fwinfo_count) { - printk("%s: Unsupported firmware %s\n", __FUNCTION__, - tda10045h_firmware); + printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware); sys_close(fd); return -EIO; } @@ -354,6 +335,7 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) sys_close(fd); return -EIO; } + // read it! lseek(fd, tda10045h_fwinfo[fwinfo_idx].fw_offset, 0); if (read(fd, firmware, fw_size) != fw_size) { @@ -366,23 +348,23 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) set_fs(fs); // Disable the MC44BC374C - tda10045h_enable_tuner_i2c(i2c); - tuner_msg.addr = TDA10045H_MC44BC374_ADDRESS; + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = MC44BC374_ADDRESS; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { i2c->xfer(i2c, &tuner_msg, 1); } - tda10045h_disable_tuner_i2c(i2c); + tda1004x_disable_tuner_i2c(i2c, tda_state); - // setup for firmware upload - tda10045h_write_buf(i2c, TDA10045H_CONFPLL_P, bandwidth_8mhz, - sizeof(bandwidth_8mhz)); - tda10045h_write_byte(i2c, TDA10045H_IOFFSET, 0); + // setup some valid bandwidth parameters + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, tda10045h_bandwidth_8mhz, sizeof(tda10045h_bandwidth_8mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_IOFFSET, 0); dvb_delay(500); // do the firmware upload - tda10045h_write_byte(i2c, TDA10045H_FWPAGE, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_FWPAGE, 0); + fw_msg.addr = tda_state->tda1004x_address; fw_pos = 0; while (fw_pos != fw_size) { // work out how much to send this time @@ -391,7 +373,7 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) tx_size = 64; } // send the chunk - fw_buf[0] = TDA10045H_CODE_IN; + fw_buf[0] = TDA1004X_CODE_IN; memcpy(fw_buf + 1, firmware + fw_pos, tx_size); fw_msg.len = tx_size + 1; if (i2c->xfer(i2c, &fw_msg, 1) != 1) { @@ -406,33 +388,22 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) vfree(firmware); // Initialise the DSP and check upload was OK - tda10045h_write_mask(i2c, TDA10045H_CONFC4, 0x10, 0); - tda10045h_write_byte(i2c, TDA10045H_DSP_CMD, 0x67); - if ((tda10045h_read_byte(i2c, TDA10045H_DSP_DATA1) != 0x67) || - (tda10045h_read_byte(i2c, TDA10045H_DSP_DATA2) != 0x2c)) { + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67); + if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) || + (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != 0x2c)) { printk("%s: firmware upload failed!\n", __FUNCTION__); return -EIO; } - // tda setup - tda10045h_write_byte(i2c, TDA10045H_CONFADC1, 0x2e); - tda10045h_write_mask(i2c, TDA10045H_CONFC1, 0x40, 0); - tda10045h_write_mask(i2c, TDA10045H_CONFC4, 0x20, 0); - tda10045h_write_mask(i2c, TDA10045H_VBER_MSB, 0xe0, 0xa0); - tda10045h_write_byte(i2c, TDA10045H_REG1F, 0); - tda10045h_write_byte(i2c, TDA10045H_REG1E, 0); - tda10045h_write_mask(i2c, TDA10045H_CONFC1, 0x80, 0x80); - - // DSP init - tda10045h_write_mask(i2c, TDA10045H_CONFC4, 0x10, 0); - if (tda10045h_write_byte(i2c, TDA10045H_DSP_CMD, 0x61) < 0) - return -1; - // command retry loop + // DSP init + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); + if (tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x61) < 0) + return -1; counter = 0; while (counter++ < 5) { - // read in the data byte - data1 = tda10045h_read_byte(i2c, TDA10045H_DSP_DATA1); + data1 = tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1); if (data1 < 0) return data1; @@ -441,31 +412,37 @@ int tda10045h_init(struct dvb_i2c_bus *i2c) continue; // OK, resend command - if (tda10045h_write_byte(i2c, TDA10045H_DSP_CMD, 0x61) < 0) + if (tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x61) < 0) return -1; } - tda10045h_write_byte(i2c, TDA10045H_DSP_DATA1, 0x01); - tda10045h_write_byte(i2c, TDA10045H_DSP_DATA2, 0x0e); - tda10045h_dsp_command(i2c, 0x69, 0); - tda10045h_write_byte(i2c, TDA10045H_DSP_DATA2, 0x01); - tda10045h_dsp_command(i2c, 0x69, 1); - tda10045h_write_byte(i2c, TDA10045H_DSP_DATA2, 0x03); - tda10045h_dsp_command(i2c, 0x69, 2); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_DATA1, 0x01); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_DATA2, 0x0e); + tda1004x_dsp_command(i2c, tda_state, 0x69, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_DATA2, 0x01); + tda1004x_dsp_command(i2c, tda_state, 0x69, 1); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_DATA2, 0x03); + tda1004x_dsp_command(i2c, tda_state, 0x69, 2); // tda setup - tda10045h_write_mask(i2c, TDA10045H_CONFADC2, 0x20, 0x20); - tda10045h_write_mask(i2c, TDA10045H_CONFADC1, 0x80, 0); - tda10045h_write_mask(i2c, TDA10045H_CONFC1, 0x10, 0); - tda10045h_write_mask(i2c, TDA10045H_AUTO, 0x10, 0x10); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF2, 0xC0, 0x0); - tda10045h_write_mask(i2c, TDA10045H_AUTO, 8, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC2, 0x20, 0x20); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1E, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1F, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // done return 0; } -static -int tda10045h_encode_fec(int fec) +static int tda1004x_encode_fec(int fec) { // convert known FEC values switch (fec) { @@ -485,8 +462,7 @@ int tda10045h_encode_fec(int fec) return -EINVAL; } -static -int tda10045h_decode_fec(int tdafec) +static int tda1004x_decode_fec(int tdafec) { // convert known FEC values switch (tdafec) { @@ -506,28 +482,27 @@ int tda10045h_decode_fec(int tdafec) return -1; } -static -int tda10045h_set_frequency(struct dvb_i2c_bus *i2c, - struct tda10045h_state *tda_state, - struct dvb_frontend_parameters *fe_params) +static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + struct dvb_frontend_parameters *fe_params) { int counter, counter2; - u8 tuner_buf[5]; - u8 v1, v2, v3; - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = - tuner_buf,.len = sizeof(tuner_buf) - }; + u8 tuner_buf[4]; + u8 band; + u8 cp; + u8 filter; + struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; int tuner_frequency; dprintk("%s\n", __FUNCTION__); // setup the frequency buffer switch (tda_state->tuner_address) { - case TDA10045H_TUNERA_ADDRESS: + case TD1344_ADDRESS: // setup tuner buffer tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217502) / 1000; + (((fe_params->frequency / 1000) * 6) + 217502) / 1000; tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0x88; @@ -538,7 +513,7 @@ int tda10045h_set_frequency(struct dvb_i2c_bus *i2c, } // tune it - tda10045h_enable_tuner_i2c(i2c); + tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = tda_state->tuner_address; tuner_msg.len = 4; i2c->xfer(i2c, &tuner_msg, 1); @@ -561,61 +536,63 @@ int tda10045h_set_frequency(struct dvb_i2c_bus *i2c, break; } } - tda10045h_disable_tuner_i2c(i2c); + tda1004x_disable_tuner_i2c(i2c, tda_state); break; - case TDA10045H_TDM1316L_ADDRESS: - // determine settings - tuner_frequency = fe_params->frequency + 36167000; + case TDM1316L_ADDRESS: + // determine charge pump + tuner_frequency = fe_params->frequency + 36130000; if (tuner_frequency < 87000000) { return -EINVAL; } else if (tuner_frequency < 130000000) { - v1 = 1; - v2 = 3; + cp = 3; } else if (tuner_frequency < 160000000) { - v1 = 1; - v2 = 5; + cp = 5; } else if (tuner_frequency < 200000000) { - v1 = 1; - v2 = 6; + cp = 6; } else if (tuner_frequency < 290000000) { - v1 = 2; - v2 = 3; + cp = 3; } else if (tuner_frequency < 420000000) { - v1 = 2; - v2 = 5; + cp = 5; } else if (tuner_frequency < 480000000) { - v1 = 2; - v2 = 6; + cp = 6; } else if (tuner_frequency < 620000000) { - v1 = 4; - v2 = 3; + cp = 3; } else if (tuner_frequency < 830000000) { - v1 = 4; - v2 = 5; + cp = 5; } else if (tuner_frequency < 895000000) { - v1 = 4; - v2 = 7; + cp = 7; } else { return -EINVAL; } - // work out v3 - switch (fe_params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: // FIXME: IS THIS CORRECT??????? - if (fe_params->frequency <= 300000000) { - v3 = 0; - } else { - v3 = 1; - } - break; + // determine band + if (fe_params->frequency < 49000000) { + return -EINVAL; + } else if (tuner_frequency < 159000000) { + band = 1; + } else if (tuner_frequency < 444000000) { + band = 2; + } else if (tuner_frequency < 861000000) { + band = 4; + } else { + return -EINVAL; + } - case BANDWIDTH_7_MHZ: - v3 = 0; + // work out filter + switch (fe_params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + // 6 MHz isn't supported directly, but set this to + // the 8 MHz setting in case we can fiddle it later + filter = 1; + break; + + case BANDWIDTH_7_MHZ: + filter = 0; break; case BANDWIDTH_8_MHZ: - v3 = 1; + filter = 1; break; default: @@ -624,27 +601,21 @@ int tda10045h_set_frequency(struct dvb_i2c_bus *i2c, // calculate tuner parameters tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217502) / 1000; + (((fe_params->frequency / 1000) * 6) + 217280) / 1000; tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0xca; - tuner_buf[3] = (3 << 5) | (v3 << 3) | v1; - tuner_buf[4] = 0x85; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; // tune it - tda10045h_enable_tuner_i2c(i2c); + tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = tda_state->tuner_address; - tuner_msg.len = 5; - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { - return -EIO; - } - dvb_delay(50); - tuner_buf[3] = (v2 << 5) | (v3 << 3) | v1; - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + tuner_msg.len = 4; + if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { return -EIO; } dvb_delay(1); - tda10045h_disable_tuner_i2c(i2c); + tda1004x_disable_tuner_i2c(i2c, tda_state); break; default: @@ -657,17 +628,16 @@ int tda10045h_set_frequency(struct dvb_i2c_bus *i2c, return 0; } -static -int tda10045h_set_fe(struct dvb_i2c_bus *i2c, - struct tda10045h_state *tda_state, - struct dvb_frontend_parameters *fe_params) +static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + struct dvb_frontend_parameters *fe_params) { int tmp; dprintk("%s\n", __FUNCTION__); // set frequency - tmp = tda10045h_set_frequency(i2c, tda_state, fe_params); + tmp = tda1004x_set_frequency(i2c, tda_state, fe_params); if (tmp < 0) return tmp; @@ -675,50 +645,43 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; - + // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || (fe_params->u.ofdm.constellation == QAM_AUTO) || (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { - tda10045h_write_mask(i2c, TDA10045H_AUTO, 1, 1); // enable auto - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x03, 0); // turn off constellation bits - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x60, 0); // turn off hierarchy bits - tda10045h_write_mask(i2c, TDA10045H_IN_CONF2, 0x3f, 0); // turn off FEC bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1); // enable auto + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits } else { - tda10045h_write_mask(i2c, TDA10045H_AUTO, 1, 0); // disable auto + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0); // disable auto // set HP FEC - tmp = tda10045h_encode_fec(fe_params->u.ofdm.code_rate_HP); - if (tmp < 0) - return tmp; - tda10045h_write_mask(i2c, TDA10045H_IN_CONF2, 7, tmp); + tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP); + if (tmp < 0) return tmp; + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp); // set LP FEC if (fe_params->u.ofdm.code_rate_LP != FEC_NONE) { - tmp = - tda10045h_encode_fec(fe_params->u.ofdm. - code_rate_LP); - if (tmp < 0) - return tmp; - tda10045h_write_mask(i2c, TDA10045H_IN_CONF2, - 0x38, tmp << 3); + tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); + if (tmp < 0) return tmp; + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3); } + // set constellation switch (fe_params->u.ofdm.constellation) { case QPSK: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 3, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0); break; case QAM_16: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 3, 1); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1); break; case QAM_64: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 3, 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2); break; default: @@ -728,23 +691,19 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, // set hierarchy switch (fe_params->u.ofdm.hierarchy_information) { case HIERARCHY_NONE: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 0x60, 0 << 5); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5); break; case HIERARCHY_1: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 0x60, 1 << 5); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5); break; case HIERARCHY_2: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 0x60, 2 << 5); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5); break; case HIERARCHY_4: - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, - 0x60, 3 << 5); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5); break; default: @@ -755,24 +714,18 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, // set bandwidth switch (fe_params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - tda10045h_write_byte(i2c, TDA10045H_REG0C, 0x14); - tda10045h_write_buf(i2c, TDA10045H_CONFPLL_P, - bandwidth_6mhz, - sizeof(bandwidth_6mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG0C, 0x14); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, tda10045h_bandwidth_6mhz, sizeof(tda10045h_bandwidth_6mhz)); break; case BANDWIDTH_7_MHZ: - tda10045h_write_byte(i2c, TDA10045H_REG0C, 0x80); - tda10045h_write_buf(i2c, TDA10045H_CONFPLL_P, - bandwidth_7mhz, - sizeof(bandwidth_7mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG0C, 0x80); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, tda10045h_bandwidth_7mhz, sizeof(tda10045h_bandwidth_7mhz)); break; case BANDWIDTH_8_MHZ: - tda10045h_write_byte(i2c, TDA10045H_REG0C, 0x14); - tda10045h_write_buf(i2c, TDA10045H_CONFPLL_P, - bandwidth_8mhz, - sizeof(bandwidth_8mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG0C, 0x14); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, tda10045h_bandwidth_8mhz, sizeof(tda10045h_bandwidth_8mhz)); break; default: @@ -782,11 +735,11 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, // set inversion switch (fe_params->inversion) { case INVERSION_OFF: - tda10045h_write_mask(i2c, TDA10045H_CONFC1, 0x20, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); break; case INVERSION_ON: - tda10045h_write_mask(i2c, TDA10045H_CONFC1, 0x20, 0x20); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20); break; default: @@ -796,33 +749,28 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, // set guard interval switch (fe_params->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_32: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 2, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x0c, - 0 << 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; case GUARD_INTERVAL_1_16: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 2, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x0c, - 1 << 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); break; case GUARD_INTERVAL_1_8: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 2, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x0c, - 2 << 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); break; case GUARD_INTERVAL_1_4: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 2, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x0c, - 3 << 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); break; case GUARD_INTERVAL_AUTO: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 2, 2); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x0c, - 0 << 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; default: @@ -832,20 +780,18 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, // set transmission mode switch (fe_params->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 4, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x10, - 0 << 4); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4); break; case TRANSMISSION_MODE_8K: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 4, 0); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x10, - 1 << 4); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4); break; case TRANSMISSION_MODE_AUTO: - tda10045h_write_mask(i2c, TDA10045H_AUTO, 4, 4); - tda10045h_write_mask(i2c, TDA10045H_IN_CONF1, 0x10, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0); break; default: @@ -853,8 +799,8 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, } // reset DSP - tda10045h_write_mask(i2c, TDA10045H_CONFC4, 8, 8); - tda10045h_write_mask(i2c, TDA10045H_CONFC4, 8, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); dvb_delay(10); // done @@ -862,20 +808,19 @@ int tda10045h_set_fe(struct dvb_i2c_bus *i2c, } -static -int tda10045h_get_fe(struct dvb_i2c_bus *i2c, - struct dvb_frontend_parameters *fe_params) +static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params) { dprintk("%s\n", __FUNCTION__); // inversion status fe_params->inversion = INVERSION_OFF; - if (tda10045h_read_byte(i2c, TDA10045H_CONFC1) & 0x20) { + if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) { fe_params->inversion = INVERSION_ON; } + // bandwidth - switch (tda10045h_read_byte(i2c, TDA10045H_WREF_LSB)) { + switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_WREF_LSB)) { case 0x14: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; @@ -889,14 +834,12 @@ int tda10045h_get_fe(struct dvb_i2c_bus *i2c, // FEC fe_params->u.ofdm.code_rate_HP = - tda10045h_decode_fec(tda10045h_read_byte - (i2c, TDA10045H_OUT_CONF2) & 7); + tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7); fe_params->u.ofdm.code_rate_LP = - tda10045h_decode_fec((tda10045h_read_byte - (i2c, TDA10045H_OUT_CONF2) >> 3) & 7); + tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7); // constellation - switch (tda10045h_read_byte(i2c, TDA10045H_OUT_CONF1) & 3) { + switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) { case 0: fe_params->u.ofdm.constellation = QPSK; break; @@ -910,12 +853,12 @@ int tda10045h_get_fe(struct dvb_i2c_bus *i2c, // transmission mode fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; - if (tda10045h_read_byte(i2c, TDA10045H_OUT_CONF1) & 0x10) { + if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) { fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; } + // guard interval - switch ((tda10045h_read_byte(i2c, TDA10045H_OUT_CONF1) & 0x0c) >> - 2) { + switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { case 0: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; @@ -931,8 +874,7 @@ int tda10045h_get_fe(struct dvb_i2c_bus *i2c, } // hierarchy - switch ((tda10045h_read_byte(i2c, TDA10045H_OUT_CONF1) & 0x60) >> - 5) { + switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { case 0: fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; break; @@ -952,44 +894,76 @@ int tda10045h_get_fe(struct dvb_i2c_bus *i2c, } -static -int tda10045h_read_status(struct dvb_i2c_bus *i2c, fe_status_t * fe_status) +static int tda1004x_read_status(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status) { int status; + int cber; + int vber; dprintk("%s\n", __FUNCTION__); // read status - status = tda10045h_read_byte(i2c, TDA10045H_STATUS_CD); + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD); if (status == -1) { return -EIO; } - // decode - *fe_status = 0; - if (status == 0x2f) { - *fe_status = - FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_LOCK; - } - // FIXME: decode statuses better - dprintk("%s: ------------------ raw_status=0x%x\n", __FUNCTION__, status); + // decode + *fe_status = 0; + if (status & 4) *fe_status |= FE_HAS_SIGNAL; + if (status & 2) *fe_status |= FE_HAS_CARRIER; + if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + + // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi + // is getting anything valid + if (!(*fe_status & FE_HAS_VITERBI)) { + // read the CBER + cber = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + if (cber == -1) return -EIO; + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + if (status == -1) return -EIO; + cber |= (status << 8); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + + if (cber != 65535) { + *fe_status |= FE_HAS_VITERBI; + } + } + + // if we DO have some valid VITERBI output, but don't already have SYNC + // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. + if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { + // read the VBER + vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB); + if (vber == -1) return -EIO; + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID); + if (status == -1) return -EIO; + vber |= (status << 8); + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB); + if (status == -1) return -EIO; + vber |= ((status << 16) & 0x0f); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT); + + // if RS has passed some valid TS packets, then we must be + // getting some SYNC bytes + if (vber < 16632) { + *fe_status |= FE_HAS_SYNC; + } + } // success dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status); return 0; } -static -int tda10045h_read_signal_strength(struct dvb_i2c_bus *i2c, u16 * signal) +static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal) { int tmp; dprintk("%s\n", __FUNCTION__); // read it - tmp = tda10045h_read_byte(i2c, TDA10045H_SIGNAL_STRENGTH); - + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SIGNAL_STRENGTH); if (tmp < 0) return -EIO; @@ -1000,27 +974,27 @@ int tda10045h_read_signal_strength(struct dvb_i2c_bus *i2c, u16 * signal) } -static -int tda10045h_read_snr(struct dvb_i2c_bus *i2c, u16 * snr) +static int tda1004x_read_snr(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * snr) { int tmp; dprintk("%s\n", __FUNCTION__); // read it - tmp = tda10045h_read_byte(i2c, TDA10045H_SNR); + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR); if (tmp < 0) return -EIO; - // FIXME: calculate this properly + if (tmp) { + tmp = 255 - tmp; + } - // done - *snr = ~((tmp << 8) | tmp); + // done + *snr = ((tmp << 8) | tmp); dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr); return 0; } -static -int tda10045h_read_ucblocks(struct dvb_i2c_bus *i2c, u32 * ucblocks) +static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ucblocks) { int tmp; int tmp2; @@ -1030,23 +1004,22 @@ int tda10045h_read_ucblocks(struct dvb_i2c_bus *i2c, u32 * ucblocks) // read the UCBLOCKS and reset counter = 0; - tmp = tda10045h_read_byte(i2c, TDA10045H_UNCOR); + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); if (tmp < 0) return -EIO; tmp &= 0x7f; while (counter++ < 5) { - tda10045h_write_mask(i2c, TDA10045H_UNCOR, 0x80, 0); - tda10045h_write_mask(i2c, TDA10045H_UNCOR, 0x80, 0); - tda10045h_write_mask(i2c, TDA10045H_UNCOR, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); - tmp2 = tda10045h_read_byte(i2c, TDA10045H_UNCOR); + tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); if (tmp2 < 0) return -EIO; tmp2 &= 0x7f; if ((tmp2 < tmp) || (tmp2 == 0)) break; } - // FIXME: calculate this properly // done if (tmp != 0x7f) { @@ -1058,67 +1031,63 @@ int tda10045h_read_ucblocks(struct dvb_i2c_bus *i2c, u32 * ucblocks) return 0; } -static -int tda10045h_read_vber(struct dvb_i2c_bus *i2c, u32 * vber) +static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ber) { + int tmp; dprintk("%s\n", __FUNCTION__); // read it in - *vber = 0; - *vber |= tda10045h_read_byte(i2c, TDA10045H_VBER_LSB); - *vber |= tda10045h_read_byte(i2c, TDA10045H_VBER_MID) << 8; - *vber |= - (tda10045h_read_byte(i2c, TDA10045H_VBER_MSB) & 0x0f) << 16; - - // reset counter - tda10045h_read_byte(i2c, TDA10045H_CVBER_LUT); - // FIXME: calculate this properly - + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + if (tmp < 0) return -EIO; + *ber = tmp << 1; + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + if (tmp < 0) return -EIO; + *ber |= (tmp << 9); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + // done - dprintk("%s: vber=0x%x\n", __FUNCTION__, *vber); + dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); return 0; } -static -int tda10045h_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { - int status; + int status = 0; struct dvb_i2c_bus *i2c = fe->i2c; - struct tda10045h_state *tda_state = (struct tda10045h_state *) &(fe->data); + struct tda1004x_state *tda_state = (struct tda1004x_state *) &(fe->data); dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd); switch (cmd) { case FE_GET_INFO: - memcpy(arg, &tda10045h_info, - sizeof(struct dvb_frontend_info)); + switch(tda_state->tda1004x_address) { + case TDA10045H_ADDRESS: + memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); + break; + } break; case FE_READ_STATUS: - return tda10045h_read_status(i2c, (fe_status_t *) arg); + return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg); case FE_READ_BER: - return tda10045h_read_vber(i2c, (u32 *) arg); + return tda1004x_read_ber(i2c, tda_state, (u32 *) arg); case FE_READ_SIGNAL_STRENGTH: - return tda10045h_read_signal_strength(i2c, (u16 *) arg); + return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg); case FE_READ_SNR: - return tda10045h_read_snr(i2c, (u16 *) arg); + return tda1004x_read_snr(i2c, tda_state, (u16 *) arg); case FE_READ_UNCORRECTED_BLOCKS: - return tda10045h_read_ucblocks(i2c, (u32 *) arg); + return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg); case FE_SET_FRONTEND: - return tda10045h_set_fe(i2c, tda_state, - (struct dvb_frontend_parameters - *) arg); + return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); case FE_GET_FRONTEND: - return tda10045h_get_fe(i2c, - (struct dvb_frontend_parameters - *) arg); + return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); case FE_SLEEP: break; @@ -1129,7 +1098,11 @@ int tda10045h_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) return 0; // OK, perform initialisation - status = tda10045h_init(i2c); + switch(tda_state->tda1004x_address) { + case TDA10045H_ADDRESS: + status = tda10045h_init(i2c, tda_state); + break; + } if (status == 0) tda_state->initialised = 1; return status; @@ -1142,52 +1115,72 @@ int tda10045h_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) } -static -int tda10045h_attach(struct dvb_i2c_bus *i2c) +static int tda1004x_attach(struct dvb_i2c_bus *i2c) { + int tda1004x_address = -1; int tuner_address = -1; - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 - }; - struct tda10045h_state tda_state; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 }; + struct tda1004x_state tda_state; dprintk("%s\n", __FUNCTION__); - // supported frontend? - if (tda10045h_read_byte(i2c, TDA10045H_CHIPID) != 0x25) + // probe for frontend + tda_state.tda1004x_address = TDA10045H_ADDRESS; + if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) { + tda1004x_address = TDA10045H_ADDRESS; + printk("tda1004x: Detected Philips TDA10045H.\n"); + } + + // did we find a frontend? + if (tda1004x_address == -1) { return -ENODEV; + } // supported tuner? - tda10045h_enable_tuner_i2c(i2c); - tuner_msg.addr = TDA10045H_TUNERA_ADDRESS; - tuner_msg.buf = tuner_data; + tda1004x_enable_tuner_i2c(i2c, &tda_state); + tuner_msg.addr = TD1344_ADDRESS; + tuner_msg.buf = tuner_buf; tuner_msg.len = 4; + tuner_buf[0] = 0x0b; + tuner_buf[1] = 0xf5; + tuner_buf[2] = 0x88; + tuner_buf[3] = 0xab; if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - tuner_address = TDA10045H_TUNERA_ADDRESS; - printk("tda10045h: Detected, tuner type A.\n"); + tuner_address = TD1344_ADDRESS; + dvb_delay(1); + printk("tda1004x: Detected Philips TD1344 tuner. PLEASE CHECK THIS AND REPORT BACK!.\n"); } else { - tuner_msg.addr = TDA10045H_TDM1316L_ADDRESS; - tuner_msg.buf = tuner_data; - tuner_msg.len = 5; - if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - tuner_address = TDA10045H_TDM1316L_ADDRESS; - printk - ("tda10045h: Detected Philips TDM1316L tuner.\n"); + tuner_msg.addr = TDM1316L_ADDRESS; + tuner_buf[0] = 0x0b; + tuner_buf[1] = 0xf5; + tuner_buf[2] = 0x85; + tuner_buf[3] = 0xab; + if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { + dvb_delay(1); + tuner_address = TDM1316L_ADDRESS; + printk("tda1004x: Detected Philips TDM1316L tuner.\n"); } } - tda10045h_disable_tuner_i2c(i2c); + tda1004x_disable_tuner_i2c(i2c, &tda_state); // did we find a tuner? if (tuner_address == -1) { - printk("tda10045h: Detected, but with unknown tuner.\n"); + printk("tda1004x: Detected, but with unknown tuner.\n"); return -ENODEV; } - // create state + + // create state + tda_state.tda1004x_address = tda1004x_address; tda_state.tuner_address = tuner_address; tda_state.initialised = 0; // register - dvb_register_frontend(tda10045h_ioctl, i2c, (void *)(*((u32*) &tda_state)), - &tda10045h_info); + switch(tda_state.tda1004x_address) { + case TDA10045H_ADDRESS: + dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); + break; + } // success return 0; @@ -1195,37 +1188,36 @@ int tda10045h_attach(struct dvb_i2c_bus *i2c) static -void tda10045h_detach(struct dvb_i2c_bus *i2c) +void tda1004x_detach(struct dvb_i2c_bus *i2c) { dprintk("%s\n", __FUNCTION__); - dvb_unregister_frontend(tda10045h_ioctl, i2c); + dvb_unregister_frontend(tda1004x_ioctl, i2c); } static -int __init init_tda10045h(void) +int __init init_tda1004x(void) { - return dvb_register_i2c_device(THIS_MODULE, tda10045h_attach, - tda10045h_detach); + return dvb_register_i2c_device(THIS_MODULE, tda1004x_attach, tda1004x_detach); } static -void __exit exit_tda10045h(void) +void __exit exit_tda1004x(void) { - dvb_unregister_i2c_device(tda10045h_attach); + dvb_unregister_i2c_device(tda1004x_attach); } -module_init(init_tda10045h); -module_exit(exit_tda10045h); +module_init(init_tda1004x); +module_exit(exit_tda1004x); MODULE_DESCRIPTION("Philips TDA10045H DVB-T Frontend"); MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); MODULE_LICENSE("GPL"); -MODULE_PARM(tda10045h_debug, "i"); -MODULE_PARM_DESC(tda10045h_debug, "enable verbose debug messages"); +MODULE_PARM(tda1004x_debug, "i"); +MODULE_PARM_DESC(tda1004x_debug, "enable verbose debug messages"); -MODULE_PARM(tda10045h_firmware, "s"); -MODULE_PARM_DESC(tda10045h_firmware, "where to find the firmware file"); +MODULE_PARM(tda1004x_firmware, "s"); +MODULE_PARM_DESC(tda1004x_firmware, "Where to find the firmware file"); |