diff options
author | Andrew de Quincy <devnull@localhost> | 2004-01-28 00:20:56 +0000 |
---|---|---|
committer | Andrew de Quincy <devnull@localhost> | 2004-01-28 00:20:56 +0000 |
commit | f80c89b4cc50b4972ff789a6e86ee74c10e82b4a (patch) | |
tree | f313e4489ab053564e206882d88353b451b6f1f3 | |
parent | d3fe8f0717db19bbee67abc86c0a542678e0c2ad (diff) | |
download | mediapointer-dvb-s2-f80c89b4cc50b4972ff789a6e86ee74c10e82b4a.tar.gz mediapointer-dvb-s2-f80c89b4cc50b4972ff789a6e86ee74c10e82b4a.tar.bz2 |
Had to split firmware upload off from frontend init... the initial tune attempt
was taking too long.
Also, provided explanation of tuner frequency calculations.
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda1004x.c | 253 |
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; } |