summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/frontends/tda1004x.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/dvb/frontends/tda1004x.c')
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.c253
1 files changed, 97 insertions, 156 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c
index 2522b076a..213755246 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.c
+++ b/linux/drivers/media/dvb/frontends/tda1004x.c
@@ -359,11 +359,10 @@ static int tda10046h_set_bandwidth(struct dvb_i2c_bus *i2c,
}
-static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
+static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
{
u8 fw_buf[65];
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 };
unsigned char *firmware = NULL;
int filesize;
int fd;
@@ -371,16 +370,30 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
int fw_size = 0;
int fw_pos, fw_offset;
int tx_size;
- static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
mm_segment_t fs = get_fs();
- int dspCodeCounterReg, dspCodeInReg, dspVersion;
-
- dprintk("%s\n", __FUNCTION__);
+ int dspCodeCounterReg=0, dspCodeInReg=0, dspVersion=0;
+ int fwInfoCount=0;
+ struct fwinfo* fwInfo = NULL;
+ unsigned long timeout;
// DSP parameters
- dspCodeCounterReg = TDA10045H_FWPAGE;
- dspCodeInReg = TDA10045H_CODE_IN;
- dspVersion = 0x2c;
+ switch(tda_state->fe_type) {
+ case FE_TYPE_TDA10045H:
+ dspCodeCounterReg = TDA10045H_FWPAGE;
+ dspCodeInReg = TDA10045H_CODE_IN;
+ dspVersion = 0x2c;
+ fwInfoCount = tda10045h_fwinfo_count;
+ fwInfo = tda10045h_fwinfo;
+ break;
+
+ case FE_TYPE_TDA10046H:
+ dspCodeCounterReg = TDA10046H_CODE_CPT;
+ dspCodeInReg = TDA10046H_CODE_IN;
+ dspVersion = 0x20;
+ fwInfoCount = tda10046h_fwinfo_count;
+ fwInfo = tda10046h_fwinfo;
+ break;
+ }
// Load the firmware
set_fs(get_ds());
@@ -399,25 +412,25 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
}
// find extraction parameters for firmware
- for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; fwinfo_idx++) {
- if (tda10045h_fwinfo[fwinfo_idx].file_size == filesize)
+ for (fwinfo_idx = 0; fwinfo_idx < fwInfoCount; fwinfo_idx++) {
+ if (fwInfo[fwinfo_idx].file_size == filesize)
break;
}
- if (fwinfo_idx >= tda10045h_fwinfo_count) {
+ if (fwinfo_idx >= fwInfoCount) {
printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware);
sys_close(fd);
return -EIO;
}
- fw_size = tda10045h_fwinfo[fwinfo_idx].fw_size;
- fw_offset = tda10045h_fwinfo[fwinfo_idx].fw_offset;
+ fw_size = fwInfo[fwinfo_idx].fw_size;
+ fw_offset = fwInfo[fwinfo_idx].fw_offset;
// allocate buffer for it
firmware = vmalloc(fw_size);
if (firmware == NULL) {
- printk("%s: Out of memory loading firmware\n",
- __FUNCTION__);
- sys_close(fd);
- return -EIO;
+ printk("%s: Out of memory loading firmware\n",
+ __FUNCTION__);
+ sys_close(fd);
+ return -EIO;
}
// read it!
@@ -431,19 +444,22 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
sys_close(fd);
set_fs(fs);
- // Disable the MC44BC374C
- 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);
- }
- tda1004x_disable_tuner_i2c(i2c, tda_state);
-
// set some valid bandwith parameters before uploading
- tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ);
- dvb_delay(500);
+ switch(tda_state->fe_type) {
+ case FE_TYPE_TDA10045H:
+ tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ);
+ dvb_delay(500);
+ break;
+
+ case FE_TYPE_TDA10046H:
+ tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10);
+ tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0);
+ tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99);
+ tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
+ tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
+ tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
+ break;
+ }
// do the firmware upload
tda1004x_write_byte(i2c, tda_state, dspCodeCounterReg, 0); // clear code counter
@@ -470,9 +486,27 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos);
}
- dvb_delay(100);
vfree(firmware);
+ // wait for DSP to initialise
+ switch(tda_state->fe_type) {
+ case FE_TYPE_TDA10045H:
+ dvb_delay(100);
+ break;
+
+ case FE_TYPE_TDA10046H:
+ timeout = jiffies + HZ;
+ while(!(tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD) & 0x20)) {
+ if (time_after(jiffies, timeout)) {
+ printk("tda1004x: DSP failed to initialised.\n");
+ return -EIO;
+ }
+
+ dvb_delay(1);
+ }
+ break;
+ }
+
// check upload was OK
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67);
@@ -482,6 +516,28 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
return -EIO;
}
+ // success
+ return 0;
+}
+
+
+static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
+{
+ struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 };
+ static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
+
+ dprintk("%s\n", __FUNCTION__);
+
+ // Disable the MC44BC374C
+ 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);
+ }
+ tda1004x_disable_tuner_i2c(i2c, tda_state);
+
// tda setup
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream
@@ -503,81 +559,15 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
{
- u8 fw_buf[65];
- 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 };
- unsigned char *firmware = NULL;
- int filesize;
- int fd;
- int fwinfo_idx;
- int fw_size = 0;
- int fw_pos, fw_offset;
- int tx_size;
static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
- mm_segment_t fs = get_fs();
- int dspCodeCounterReg, dspCodeInReg, dspVersion;
- unsigned long timeout;
dprintk("%s\n", __FUNCTION__);
- // determine DSP parameters
- dspCodeCounterReg = TDA10046H_CODE_CPT;
- dspCodeInReg = TDA10046H_CODE_IN;
- dspVersion = 0x20;
-
// reset chip
tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0);
dvb_delay(10);
- // Load the firmware
- set_fs(get_ds());
- fd = open(tda1004x_firmware, 0, 0);
- if (fd < 0) {
- printk("%s: Unable to open firmware %s\n", __FUNCTION__,
- tda1004x_firmware);
- return -EIO;
- }
- filesize = lseek(fd, 0L, 2);
- if (filesize <= 0) {
- printk("%s: Firmware %s is empty\n", __FUNCTION__,
- tda1004x_firmware);
- sys_close(fd);
- return -EIO;
- }
-
- // find extraction parameters for firmware
- for (fwinfo_idx = 0; fwinfo_idx < tda10046h_fwinfo_count; fwinfo_idx++) {
- if (tda10046h_fwinfo[fwinfo_idx].file_size == filesize)
- break;
- }
- if (fwinfo_idx >= tda10046h_fwinfo_count) {
- printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware);
- sys_close(fd);
- return -EIO;
- }
- fw_size = tda10046h_fwinfo[fwinfo_idx].fw_size;
- fw_offset = tda10046h_fwinfo[fwinfo_idx].fw_offset;
-
- // allocate buffer for it
- firmware = vmalloc(fw_size);
- if (firmware == NULL) {
- printk("%s: Out of memory loading firmware\n",
- __FUNCTION__);
- sys_close(fd);
- return -EIO;
- }
-
- // read it!
- lseek(fd, fw_offset, 0);
- if (read(fd, firmware, fw_size) != fw_size) {
- printk("%s: Failed to read firmware\n", __FUNCTION__);
- vfree(firmware);
- sys_close(fd);
- return -EIO;
- }
- sys_close(fd);
- set_fs(fs);
-
// Disable the MC44BC374C
tda1004x_enable_tuner_i2c(i2c, tda_state);
tuner_msg.addr = MC44BC374_ADDRESS;
@@ -588,61 +578,6 @@ static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
}
tda1004x_disable_tuner_i2c(i2c, tda_state);
- // set some valid bandwith parameters before uploading
- tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10);
- tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0);
- tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99);
- tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
-
- // do the firmware upload
- tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
- tda1004x_write_byte(i2c, tda_state, dspCodeCounterReg, 0); // clear code counter
- fw_msg.addr = tda_state->tda1004x_address;
- fw_pos = 0;
- while (fw_pos != fw_size) {
-
- // work out how much to send this time
- tx_size = fw_size - fw_pos;
- if (tx_size > 0x10) {
- tx_size = 0x10;
- }
-
- // send the chunk
- fw_buf[0] = dspCodeInReg;
- memcpy(fw_buf + 1, firmware + fw_pos, tx_size);
- fw_msg.len = tx_size + 1;
- if (i2c->xfer(i2c, &fw_msg, 1) != 1) {
- printk("tda1004x: Error during firmware upload\n");
- vfree(firmware);
- return -EIO;
- }
- fw_pos += tx_size;
-
- dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos);
- }
- vfree(firmware);
-
- // wait for DSP to initialise
- timeout = jiffies + HZ;
- while(!(tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD) & 0x20)) {
- if (time_after(jiffies, timeout)) {
- printk("tda1004x: DSP failed to initialised.\n");
- return -EIO;
- }
-
- dvb_delay(1);
- }
-
- // check upload was OK
- tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
- 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) != dspVersion)) {
- printk("%s: firmware upload failed!\n", __FUNCTION__);
- return -EIO;
- }
-
// tda setup
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0x40); // TT TDA10046H needs inversion ON
@@ -733,8 +668,9 @@ static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c,
case TUNER_TYPE_TD1344:
// setup tuner buffer
+ // ((Fif+((1000000/6)/2)) + Finput)/(1000000/6)
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;
@@ -830,6 +766,7 @@ static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c,
}
// calculate divisor
+ // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
tuner_frequency =
(((fe_params->frequency / 1000) * 6) + 217280) / 1000;
@@ -1410,6 +1347,7 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab };
static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
static u8 td1316_init_tda10046h[] = { 0x0b, 0xf5, 0x80, 0xab };
+ int status;
dprintk("%s\n", __FUNCTION__);
@@ -1494,6 +1432,9 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
tda_state.tuner_type = tuner_type;
tda_state.initialised = 0;
+ // upload firmware
+ if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status;
+
// register
switch(tda_state.fe_type) {
case FE_TYPE_TDA10045H:
@@ -1501,10 +1442,10 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
case FE_TYPE_TDA10046H:
return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10046h_info);
-
- default:
- return -ENODEV;
}
+
+ // should not get here
+ return -EINVAL;
}