diff options
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9035.c | 141 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9035.h | 14 |
2 files changed, 154 insertions, 1 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c index 7bb8817864a..5ae5cc167c9 100644 --- a/drivers/media/dvb/dvb-usb/af9035.c +++ b/drivers/media/dvb/dvb-usb/af9035.c @@ -29,7 +29,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static DEFINE_MUTEX(af9035_usb_mutex); static struct config af9035_config; -static struct dvb_usb_device_properties af9035_properties[1]; +static struct dvb_usb_device_properties af9035_properties[2]; static int af9035_properties_count = ARRAY_SIZE(af9035_properties); static struct af9033_config af9035_af9033_config[] = { { @@ -493,6 +493,76 @@ err: return ret; } +static int af9035_download_firmware_it9135(struct usb_device *udev, + const struct firmware *fw) +{ + int ret, i, i_prev; + u8 wbuf[1]; + u8 rbuf[4]; + struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; + #define HDR_SIZE 7 + + /* + * There seems to be following firmware header. Meaning of bytes 0-3 + * is unknown. + * + * 0: 3 + * 1: 0, 1 + * 2: 0 + * 3: 1, 2, 3 + * 4: addr MSB + * 5: addr LSB + * 6: count of data bytes ? + */ + + for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { + if (i == fw->size || + (fw->data[i + 0] == 0x03 && + (fw->data[i + 1] == 0x00 || + fw->data[i + 1] == 0x01) && + fw->data[i + 2] == 0x00)) { + req_fw_dl.wlen = i - i_prev; + req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; + i_prev = i; + ret = af9035_ctrl_msg(udev, &req_fw_dl); + if (ret < 0) + goto err; + + pr_debug("%s: data uploaded=%d\n", __func__, i); + } + } + + /* firmware loaded, request boot */ + req.cmd = CMD_FW_BOOT; + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + /* ensure firmware starts */ + wbuf[0] = 1; + ret = af9035_ctrl_msg(udev, &req_fw_ver); + if (ret < 0) + goto err; + + if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { + info("firmware did not run"); + ret = -ENODEV; + goto err; + } + + info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], + rbuf[3]); + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + /* abuse that callback as there is no better one for reading eeprom */ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) { @@ -566,6 +636,32 @@ err: return ret; } +/* abuse that callback as there is no better one for reading eeprom */ +static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) +{ + int ret, i; + u8 tmp; + + af9035_config.dual_mode = 0; + + /* get demod clock */ + ret = af9035_rd_reg(d, 0x00d800, &tmp); + if (ret < 0) + goto err; + + tmp = (tmp >> 0) & 0x0f; + + for (i = 0; i < af9035_properties[0].num_adapters; i++) + af9035_af9033_config[i].clock = clock_lut_it9135[tmp]; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { @@ -914,6 +1010,49 @@ static struct dvb_usb_device_properties af9035_properties[] = { }, } }, + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9035_download_firmware_it9135, + .firmware = "dvb-usb-it9135-01.fw", + .no_reconnect = 1, + + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = { + { + .frontend_attach = af9035_frontend_attach, + .tuner_attach = af9035_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + .u = { + .bulk = { + .buffersize = (87 * 188), + } + } + } + } + } + } + }, + + .identify_state = af9035_identify_state, + .read_mac_address = af9035_read_mac_address_it9135, + + .i2c_algo = &af9035_i2c_algo, + + .num_device_descs = 0, /* disabled as no support for IT9135 */ + .devices = { + { + .name = "ITE Tech. IT9135 reference design", + }, + } + }, }; static int af9035_usb_probe(struct usb_interface *intf, diff --git a/drivers/media/dvb/dvb-usb/af9035.h b/drivers/media/dvb/dvb-usb/af9035.h index 0df24cdf250..031bd9cf0cb 100644 --- a/drivers/media/dvb/dvb-usb/af9035.h +++ b/drivers/media/dvb/dvb-usb/af9035.h @@ -81,6 +81,19 @@ u32 clock_lut[] = { 12000000, /* 12.00 MHz */ }; +u32 clock_lut_it9135[] = { + 12000000, /* 12.00 MHz */ + 20480000, /* 20.48 MHz */ + 36000000, /* 36.00 MHz */ + 30000000, /* 30.00 MHz */ + 26000000, /* 26.00 MHz */ + 28000000, /* 28.00 MHz */ + 32000000, /* 32.00 MHz */ + 34000000, /* 34.00 MHz */ + 24000000, /* 24.00 MHz */ + 22000000, /* 22.00 MHz */ +}; + /* EEPROM locations */ #define EEPROM_IR_MODE 0x430d #define EEPROM_DUAL_MODE 0x4326 @@ -102,5 +115,6 @@ u32 clock_lut[] = { #define CMD_FW_BOOT 0x23 #define CMD_FW_DL_BEGIN 0x24 #define CMD_FW_DL_END 0x25 +#define CMD_FW_SCATTER_WR 0x29 #endif |