diff options
author | Michael Hunold <devnull@localhost> | 2004-05-04 13:41:01 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2004-05-04 13:41:01 +0000 |
commit | ec65d122e49831c688ba59e1362ef10d5af375fd (patch) | |
tree | b04e74235813aeb00077bb3f379d7703a4284cd6 /linux/drivers/media/dvb/frontends | |
parent | 03a29ff4de02959cf5f9ece8128c13851b8dafb8 (diff) | |
download | mediapointer-dvb-s2-ec65d122e49831c688ba59e1362ef10d5af375fd.tar.gz mediapointer-dvb-s2-ec65d122e49831c688ba59e1362ef10d5af375fd.tar.bz2 |
- restructured firmware loading
- code cleanup
- whitespace and comment cleanup
Diffstat (limited to 'linux/drivers/media/dvb/frontends')
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda1004x.c | 269 |
1 files changed, 147 insertions, 122 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c index 357b676bb..2457c2455 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.c +++ b/linux/drivers/media/dvb/frontends/tda1004x.c @@ -23,7 +23,7 @@ /* This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend windows driver. - + Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can be added reasonably painlessly. @@ -39,7 +39,7 @@ #include <linux/firmware.h> /* fixme: add this to i2c-id.h */ -#define I2C_DRIVERID_TDA1004X I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_TDA1004X I2C_DRIVERID_EXP2 #include "dvb_frontend.h" #include "dvb_functions.h" @@ -168,6 +168,10 @@ struct tda1004x_state { u8 fe_type; struct i2c_adapter *i2c; struct dvb_adapter *dvb; + + int dspCodeCounterReg; + int dspCodeInReg; + int dspVersion; }; struct fwinfo { @@ -177,7 +181,7 @@ struct fwinfo { }; static struct fwinfo tda10045h_fwinfo[] = { - { + { .file_size = 286720, .fw_offset = 0x34cc5, .fw_size = 30555 @@ -358,147 +362,153 @@ static int tda10046h_set_bandwidth(struct i2c_adapter *i2c, return 0; } -static int tda1004x_fwupload(struct i2c_adapter *i2c, struct tda1004x_state *tda_state, const struct firmware *fw) +static int tda1004x_do_upload(struct i2c_adapter *i2c, struct tda1004x_state *state, unsigned char *mem, unsigned int len) { - u8 fw_buf[65]; - struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 }; - unsigned char *firmware = NULL; - int filesize; - - int fwinfo_idx; - int fw_size = 0; - int fw_pos, fw_offset; + u8 buf[65]; + struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = buf,.len = 0 }; int tx_size; - int dspCodeCounterReg=0, dspCodeInReg=0, dspVersion=0; - int fwInfoCount=0; - struct fwinfo* fwInfo = NULL; - unsigned long timeout; + int pos = 0; - u8 data1, data2; + /* clear code counter */ + tda1004x_write_byte(i2c, state, state->dspCodeCounterReg, 0); + fw_msg.addr = state->tda1004x_address; - // DSP parameters - 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; + buf[0] = state->dspCodeInReg; + while (pos != len) { - case FE_TYPE_TDA10046H: - dspCodeCounterReg = TDA10046H_CODE_CPT; - dspCodeInReg = TDA10046H_CODE_IN; - dspVersion = 0x20; - fwInfoCount = tda10046h_fwinfo_count; - fwInfo = tda10046h_fwinfo; - break; + // work out how much to send this time + tx_size = len - pos; + if (tx_size > 0x10) { + tx_size = 0x10; + } + + // send the chunk + memcpy(buf + 1, mem + pos, tx_size); + fw_msg.len = tx_size + 1; + if (i2c_transfer(i2c, &fw_msg, 1) != 1) { + printk("tda1004x: Error during firmware upload\n"); + return -EIO; + } + pos += tx_size; + + dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos); } + return 0; +} - filesize = fw->size; - firmware = fw->data; +static int tda1004x_find_extraction_params(struct fwinfo* fwInfo, int fwInfoCount, int size) +{ + int fwinfo_idx; - // find extraction parameters for firmware for (fwinfo_idx = 0; fwinfo_idx < fwInfoCount; fwinfo_idx++) { - if (fwInfo[fwinfo_idx].file_size == filesize) + if (fwInfo[fwinfo_idx].file_size == size) break; } if (fwinfo_idx >= fwInfoCount) { - printk("%s: Unsupported firmware uploaded.\n", __FUNCTION__); + printk("tda1004x: Unsupported firmware uploaded.\n"); return -EIO; } - fw_size = fwInfo[fwinfo_idx].fw_size; - fw_offset = fwInfo[fwinfo_idx].fw_offset; + return fwinfo_idx; +} - firmware = fw->data + fw_offset; +static int tda1004x_check_upload_ok(struct i2c_adapter *i2c, struct tda1004x_state *state) +{ + u8 data1, data2; - // set some valid bandwith parameters before uploading - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - // reset chip - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); - dvb_delay(10); + // check upload was OK + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP + tda1004x_write_byte(i2c, state, TDA1004X_DSP_CMD, 0x67); - // set parameters - tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); - break; + data1 = tda1004x_read_byte(i2c, state, TDA1004X_DSP_DATA1); + data2 = tda1004x_read_byte(i2c, state, TDA1004X_DSP_DATA2); + if (data1 != 0x67 || data2 != state->dspVersion) { + printk("tda1004x: firmware upload failed!\n"); + return -EIO; + } - case FE_TYPE_TDA10046H: - // reset chip - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0); - dvb_delay(10); + return 0; +} - // set parameters - 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 - fw_msg.addr = tda_state->tda1004x_address; - fw_pos = 0; - while (fw_pos != fw_size) { +static int tda10045_fwupload(struct i2c_adapter *i2c, struct tda1004x_state *state, const struct firmware *fw) +{ + int index; + int ret; - // work out how much to send this time - tx_size = fw_size - fw_pos; - if (tx_size > 0x10) { - tx_size = 0x10; - } + index = tda1004x_find_extraction_params(tda10045h_fwinfo, tda10045h_fwinfo_count, fw->size); + if (index < 0) + return index; - // send the chunk - fw_buf[0] = dspCodeInReg; - memcpy(fw_buf + 1, firmware + fw_pos, tx_size); - fw_msg.len = tx_size + 1; - if (i2c_transfer(i2c, &fw_msg, 1) != 1) { - printk("tda1004x: Error during firmware upload\n"); - return -EIO; - } - fw_pos += tx_size; + /* set some valid bandwith parameters before uploading */ - dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos); - } + /* reset chip */ + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 0x10, 0); + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 0); + dvb_delay(10); - // wait for DSP to initialise - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - // DSPREADY doesn't seem to work on the TDA10045H - dvb_delay(100); - break; + /* set parameters */ + tda10045h_set_bandwidth(i2c, state, BANDWIDTH_8_MHZ); - 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; - } + ret = tda1004x_do_upload(i2c, state, fw->data + tda10045h_fwinfo[index].fw_offset, tda10045h_fwinfo[index].fw_size); + if (ret) + return ret; - dvb_delay(1); + /* wait for DSP to initialise */ + /* DSPREADY doesn't seem to work on the TDA10045H */ + dvb_delay(100); + + ret = tda1004x_check_upload_ok(i2c, state); + if (ret) + return ret; + + return 0; +} + +static int tda10046_fwupload(struct i2c_adapter *i2c, struct tda1004x_state *state, const struct firmware *fw) +{ + unsigned long timeout; + int index; + int ret; + + index = tda1004x_find_extraction_params(tda10046h_fwinfo, tda10046h_fwinfo_count, fw->size); + if (index < 0) + return index; + + /* set some valid bandwith parameters before uploading */ + + /* reset chip */ + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 1, 0); + tda1004x_write_mask(i2c, state, TDA10046H_CONF_TRISTATE1, 1, 0); + dvb_delay(10); + + /* set parameters */ + tda1004x_write_byte(i2c, state, TDA10046H_CONFPLL2, 10); + tda1004x_write_byte(i2c, state, TDA10046H_CONFPLL3, 0); + tda1004x_write_byte(i2c, state, TDA10046H_FREQ_OFFSET, 99); + tda1004x_write_byte(i2c, state, TDA10046H_FREQ_PHY2_MSB, 0xd4); + tda1004x_write_byte(i2c, state, TDA10046H_FREQ_PHY2_LSB, 0x2c); + tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST + + ret = tda1004x_do_upload(i2c, state, fw->data + tda10046h_fwinfo[index].fw_offset, tda10046h_fwinfo[index].fw_size); + if (ret) + return ret; + + /* wait for DSP to initialise */ + timeout = jiffies + HZ; + while(!(tda1004x_read_byte(i2c, state, TDA1004X_STATUS_CD) & 0x20)) { + if (time_after(jiffies, timeout)) { + printk("tda1004x: DSP failed to initialised.\n"); + return -EIO; } - break; + 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); - - data1 = tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1); - data2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2); - if (data1 != 0x67 || data2 != dspVersion) { - printk("%s: firmware upload failed!\n", __FUNCTION__); - return -EIO; - } + ret = tda1004x_check_upload_ok(i2c, state); + if (ret) + return ret; - // success return 0; } @@ -1324,7 +1334,7 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) fesettings->max_drift = 166667*2; return 0; } - + default: return -EOPNOTSUPP; } @@ -1425,7 +1435,7 @@ static int tda1004x_attach(struct i2c_adapter *i2c, struct tda1004x_state* state state->tuner_address = tuner_address; state->tuner_type = tuner_type; state->initialised = 0; - + return 0; } @@ -1437,7 +1447,7 @@ static int attach_adapter(struct i2c_adapter *adapter) struct tda1004x_state *state; const struct firmware *fw; int ret; - + dprintk ("%s\n", __FUNCTION__); if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { @@ -1479,17 +1489,32 @@ static int attach_adapter(struct i2c_adapter *adapter) printk("tda1004x: firmware upload timeout\n"); goto out; } - ret = tda1004x_fwupload(adapter, state, fw); - if (ret) { - printk("tda1004x: firmware upload failed\n"); - goto out; - } switch(state->fe_type) { case FE_TYPE_TDA10045H: + state->dspCodeCounterReg = TDA10045H_FWPAGE; + state->dspCodeInReg = TDA10045H_CODE_IN; + state->dspVersion = 0x2c; + + ret = tda10045_fwupload(adapter, state, fw); + if (ret) { + printk("tda1004x: firmware upload failed\n"); + goto out; + } + ret = dvb_register_frontend_new (tda1004x_ioctl, state->dvb, (void*) state, &tda10045h_info); break; case FE_TYPE_TDA10046H: + state->dspCodeCounterReg = TDA10046H_CODE_CPT; + state->dspCodeInReg = TDA10046H_CODE_IN; + state->dspVersion = 0x20; + + ret = tda10046_fwupload(adapter, state, fw); + if (ret) { + printk("tda1004x: firmware upload failed\n"); + goto out; + } + ret = dvb_register_frontend_new (tda1004x_ioctl, state->dvb, (void*) state, &tda10046h_info); break; default: @@ -1502,7 +1527,7 @@ static int attach_adapter(struct i2c_adapter *adapter) } return 0; -out: +out: i2c_detach_client(client); kfree(client); kfree(state); |