18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Afatech AF9035 DVB USB driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 68c2ecf20Sopenharmony_ci * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "af9035.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */ 128c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE 64 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic u16 af9035_checksum(const u8 *buf, size_t len) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci size_t i; 198c2ecf20Sopenharmony_ci u16 checksum = 0; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci for (i = 1; i < len; i++) { 228c2ecf20Sopenharmony_ci if (i % 2) 238c2ecf20Sopenharmony_ci checksum += buf[i] << 8; 248c2ecf20Sopenharmony_ci else 258c2ecf20Sopenharmony_ci checksum += buf[i]; 268c2ecf20Sopenharmony_ci } 278c2ecf20Sopenharmony_ci checksum = ~checksum; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return checksum; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci#define REQ_HDR_LEN 4 /* send header size */ 358c2ecf20Sopenharmony_ci#define ACK_HDR_LEN 3 /* rece header size */ 368c2ecf20Sopenharmony_ci#define CHECKSUM_LEN 2 378c2ecf20Sopenharmony_ci#define USB_TIMEOUT 2000 388c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 398c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 408c2ecf20Sopenharmony_ci int ret, wlen, rlen; 418c2ecf20Sopenharmony_ci u16 checksum, tmp_checksum; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci mutex_lock(&d->usb_mutex); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* buffer overflow check */ 468c2ecf20Sopenharmony_ci if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || 478c2ecf20Sopenharmony_ci req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { 488c2ecf20Sopenharmony_ci dev_err(&intf->dev, "too much data wlen=%d rlen=%d\n", 498c2ecf20Sopenharmony_ci req->wlen, req->rlen); 508c2ecf20Sopenharmony_ci ret = -EINVAL; 518c2ecf20Sopenharmony_ci goto exit; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; 558c2ecf20Sopenharmony_ci state->buf[1] = req->mbox; 568c2ecf20Sopenharmony_ci state->buf[2] = req->cmd; 578c2ecf20Sopenharmony_ci state->buf[3] = state->seq++; 588c2ecf20Sopenharmony_ci memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; 618c2ecf20Sopenharmony_ci rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* calc and add checksum */ 648c2ecf20Sopenharmony_ci checksum = af9035_checksum(state->buf, state->buf[0] - 1); 658c2ecf20Sopenharmony_ci state->buf[state->buf[0] - 1] = (checksum >> 8); 668c2ecf20Sopenharmony_ci state->buf[state->buf[0] - 0] = (checksum & 0xff); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* no ack for these packets */ 698c2ecf20Sopenharmony_ci if (req->cmd == CMD_FW_DL) 708c2ecf20Sopenharmony_ci rlen = 0; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci ret = dvb_usbv2_generic_rw_locked(d, 738c2ecf20Sopenharmony_ci state->buf, wlen, state->buf, rlen); 748c2ecf20Sopenharmony_ci if (ret) 758c2ecf20Sopenharmony_ci goto exit; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* no ack for those packets */ 788c2ecf20Sopenharmony_ci if (req->cmd == CMD_FW_DL) 798c2ecf20Sopenharmony_ci goto exit; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* verify checksum */ 828c2ecf20Sopenharmony_ci checksum = af9035_checksum(state->buf, rlen - 2); 838c2ecf20Sopenharmony_ci tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; 848c2ecf20Sopenharmony_ci if (tmp_checksum != checksum) { 858c2ecf20Sopenharmony_ci dev_err(&intf->dev, "command=%02x checksum mismatch (%04x != %04x)\n", 868c2ecf20Sopenharmony_ci req->cmd, tmp_checksum, checksum); 878c2ecf20Sopenharmony_ci ret = -EIO; 888c2ecf20Sopenharmony_ci goto exit; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* check status */ 928c2ecf20Sopenharmony_ci if (state->buf[2]) { 938c2ecf20Sopenharmony_ci /* fw returns status 1 when IR code was not received */ 948c2ecf20Sopenharmony_ci if (req->cmd == CMD_IR_GET || state->buf[2] == 1) { 958c2ecf20Sopenharmony_ci ret = 1; 968c2ecf20Sopenharmony_ci goto exit; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "command=%02x failed fw error=%d\n", 1008c2ecf20Sopenharmony_ci req->cmd, state->buf[2]); 1018c2ecf20Sopenharmony_ci ret = -EIO; 1028c2ecf20Sopenharmony_ci goto exit; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* read request, copy returned data to return buf */ 1068c2ecf20Sopenharmony_ci if (req->rlen) 1078c2ecf20Sopenharmony_ci memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen); 1088c2ecf20Sopenharmony_ciexit: 1098c2ecf20Sopenharmony_ci mutex_unlock(&d->usb_mutex); 1108c2ecf20Sopenharmony_ci return ret; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/* write multiple registers */ 1148c2ecf20Sopenharmony_cistatic int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 1178c2ecf20Sopenharmony_ci u8 wbuf[MAX_XFER_SIZE]; 1188c2ecf20Sopenharmony_ci u8 mbox = (reg >> 16) & 0xff; 1198c2ecf20Sopenharmony_ci struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL }; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (6 + len > sizeof(wbuf)) { 1228c2ecf20Sopenharmony_ci dev_warn(&intf->dev, "i2c wr: len=%d is too big!\n", len); 1238c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci wbuf[0] = len; 1278c2ecf20Sopenharmony_ci wbuf[1] = 2; 1288c2ecf20Sopenharmony_ci wbuf[2] = 0; 1298c2ecf20Sopenharmony_ci wbuf[3] = 0; 1308c2ecf20Sopenharmony_ci wbuf[4] = (reg >> 8) & 0xff; 1318c2ecf20Sopenharmony_ci wbuf[5] = (reg >> 0) & 0xff; 1328c2ecf20Sopenharmony_ci memcpy(&wbuf[6], val, len); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci return af9035_ctrl_msg(d, &req); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* read multiple registers */ 1388c2ecf20Sopenharmony_cistatic int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; 1418c2ecf20Sopenharmony_ci u8 mbox = (reg >> 16) & 0xff; 1428c2ecf20Sopenharmony_ci struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci return af9035_ctrl_msg(d, &req); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/* write single register */ 1488c2ecf20Sopenharmony_cistatic int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci return af9035_wr_regs(d, reg, &val, 1); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* read single register */ 1548c2ecf20Sopenharmony_cistatic int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci return af9035_rd_regs(d, reg, val, 1); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/* write single register with mask */ 1608c2ecf20Sopenharmony_cistatic int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, 1618c2ecf20Sopenharmony_ci u8 mask) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci int ret; 1648c2ecf20Sopenharmony_ci u8 tmp; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* no need for read if whole reg is written */ 1678c2ecf20Sopenharmony_ci if (mask != 0xff) { 1688c2ecf20Sopenharmony_ci ret = af9035_rd_regs(d, reg, &tmp, 1); 1698c2ecf20Sopenharmony_ci if (ret) 1708c2ecf20Sopenharmony_ci return ret; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci val &= mask; 1738c2ecf20Sopenharmony_ci tmp &= ~mask; 1748c2ecf20Sopenharmony_ci val |= tmp; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return af9035_wr_regs(d, reg, &val, 1); 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type, 1818c2ecf20Sopenharmony_ci u8 addr, void *platform_data, struct i2c_adapter *adapter) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci int ret, num; 1848c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 1858c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 1868c2ecf20Sopenharmony_ci struct i2c_client *client; 1878c2ecf20Sopenharmony_ci struct i2c_board_info board_info = { 1888c2ecf20Sopenharmony_ci .addr = addr, 1898c2ecf20Sopenharmony_ci .platform_data = platform_data, 1908c2ecf20Sopenharmony_ci }; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci strscpy(board_info.type, type, I2C_NAME_SIZE); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* find first free client */ 1958c2ecf20Sopenharmony_ci for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) { 1968c2ecf20Sopenharmony_ci if (state->i2c_client[num] == NULL) 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "num=%d\n", num); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (num == AF9035_I2C_CLIENT_MAX) { 2038c2ecf20Sopenharmony_ci dev_err(&intf->dev, "I2C client out of index\n"); 2048c2ecf20Sopenharmony_ci ret = -ENODEV; 2058c2ecf20Sopenharmony_ci goto err; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci request_module("%s", board_info.type); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* register I2C device */ 2118c2ecf20Sopenharmony_ci client = i2c_new_client_device(adapter, &board_info); 2128c2ecf20Sopenharmony_ci if (!i2c_client_has_driver(client)) { 2138c2ecf20Sopenharmony_ci ret = -ENODEV; 2148c2ecf20Sopenharmony_ci goto err; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* increase I2C driver usage count */ 2188c2ecf20Sopenharmony_ci if (!try_module_get(client->dev.driver->owner)) { 2198c2ecf20Sopenharmony_ci i2c_unregister_device(client); 2208c2ecf20Sopenharmony_ci ret = -ENODEV; 2218c2ecf20Sopenharmony_ci goto err; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci state->i2c_client[num] = client; 2258c2ecf20Sopenharmony_ci return 0; 2268c2ecf20Sopenharmony_cierr: 2278c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 2288c2ecf20Sopenharmony_ci return ret; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic void af9035_del_i2c_dev(struct dvb_usb_device *d) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci int num; 2348c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 2358c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 2368c2ecf20Sopenharmony_ci struct i2c_client *client; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* find last used client */ 2398c2ecf20Sopenharmony_ci num = AF9035_I2C_CLIENT_MAX; 2408c2ecf20Sopenharmony_ci while (num--) { 2418c2ecf20Sopenharmony_ci if (state->i2c_client[num] != NULL) 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "num=%d\n", num); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (num == -1) { 2488c2ecf20Sopenharmony_ci dev_err(&intf->dev, "I2C client out of index\n"); 2498c2ecf20Sopenharmony_ci goto err; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci client = state->i2c_client[num]; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* decrease I2C driver usage count */ 2558c2ecf20Sopenharmony_ci module_put(client->dev.driver->owner); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* unregister I2C device */ 2588c2ecf20Sopenharmony_ci i2c_unregister_device(client); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci state->i2c_client[num] = NULL; 2618c2ecf20Sopenharmony_ci return; 2628c2ecf20Sopenharmony_cierr: 2638c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed\n"); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic int af9035_i2c_master_xfer(struct i2c_adapter *adap, 2678c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci struct dvb_usb_device *d = i2c_get_adapdata(adap); 2708c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 2718c2ecf20Sopenharmony_ci int ret; 2728c2ecf20Sopenharmony_ci u32 reg; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 2758c2ecf20Sopenharmony_ci return -EAGAIN; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* 2788c2ecf20Sopenharmony_ci * AF9035 I2C sub header is 5 bytes long. Meaning of those bytes are: 2798c2ecf20Sopenharmony_ci * 0: data len 2808c2ecf20Sopenharmony_ci * 1: I2C addr << 1 2818c2ecf20Sopenharmony_ci * 2: reg addr len 2828c2ecf20Sopenharmony_ci * byte 3 and 4 can be used as reg addr 2838c2ecf20Sopenharmony_ci * 3: reg addr MSB 2848c2ecf20Sopenharmony_ci * used when reg addr len is set to 2 2858c2ecf20Sopenharmony_ci * 4: reg addr LSB 2868c2ecf20Sopenharmony_ci * used when reg addr len is set to 1 or 2 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * For the simplify we do not use register addr at all. 2898c2ecf20Sopenharmony_ci * NOTE: As a firmware knows tuner type there is very small possibility 2908c2ecf20Sopenharmony_ci * there could be some tuner I2C hacks done by firmware and this may 2918c2ecf20Sopenharmony_ci * lead problems if firmware expects those bytes are used. 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * TODO: Here is few hacks. AF9035 chip integrates AF9033 demodulator. 2948c2ecf20Sopenharmony_ci * IT9135 chip integrates AF9033 demodulator and RF tuner. For dual 2958c2ecf20Sopenharmony_ci * tuner devices, there is also external AF9033 demodulator connected 2968c2ecf20Sopenharmony_ci * via external I2C bus. All AF9033 demod I2C traffic, both single and 2978c2ecf20Sopenharmony_ci * dual tuner configuration, is covered by firmware - actual USB IO 2988c2ecf20Sopenharmony_ci * looks just like a memory access. 2998c2ecf20Sopenharmony_ci * In case of IT913x chip, there is own tuner driver. It is implemented 3008c2ecf20Sopenharmony_ci * currently as a I2C driver, even tuner IP block is likely build 3018c2ecf20Sopenharmony_ci * directly into the demodulator memory space and there is no own I2C 3028c2ecf20Sopenharmony_ci * bus. I2C subsystem does not allow register multiple devices to same 3038c2ecf20Sopenharmony_ci * bus, having same slave address. Due to that we reuse demod address, 3048c2ecf20Sopenharmony_ci * shifted by one bit, on that case. 3058c2ecf20Sopenharmony_ci * 3068c2ecf20Sopenharmony_ci * For IT930x we use a different command and the sub header is 3078c2ecf20Sopenharmony_ci * different as well: 3088c2ecf20Sopenharmony_ci * 0: data len 3098c2ecf20Sopenharmony_ci * 1: I2C bus (0x03 seems to be only value used) 3108c2ecf20Sopenharmony_ci * 2: I2C addr << 1 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_WRITE_READ(_msg, _num) \ 3138c2ecf20Sopenharmony_ci (_num == 2 && !(_msg[0].flags & I2C_M_RD) && (_msg[1].flags & I2C_M_RD)) 3148c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_WRITE(_msg, _num) \ 3158c2ecf20Sopenharmony_ci (_num == 1 && !(_msg[0].flags & I2C_M_RD)) 3168c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_READ(_msg, _num) \ 3178c2ecf20Sopenharmony_ci (_num == 1 && (_msg[0].flags & I2C_M_RD)) 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (AF9035_IS_I2C_XFER_WRITE_READ(msg, num)) { 3208c2ecf20Sopenharmony_ci if (msg[0].len > 40 || msg[1].len > 40) { 3218c2ecf20Sopenharmony_ci /* TODO: correct limits > 40 */ 3228c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 3238c2ecf20Sopenharmony_ci } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || 3248c2ecf20Sopenharmony_ci (msg[0].addr == state->af9033_i2c_addr[1])) { 3258c2ecf20Sopenharmony_ci if (msg[0].len < 3 || msg[1].len < 1) { 3268c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 3278c2ecf20Sopenharmony_ci goto unlock; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci /* demod access via firmware interface */ 3308c2ecf20Sopenharmony_ci reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 3318c2ecf20Sopenharmony_ci msg[0].buf[2]; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (msg[0].addr == state->af9033_i2c_addr[1]) 3348c2ecf20Sopenharmony_ci reg |= 0x100000; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci ret = af9035_rd_regs(d, reg, &msg[1].buf[0], 3378c2ecf20Sopenharmony_ci msg[1].len); 3388c2ecf20Sopenharmony_ci } else if (state->no_read) { 3398c2ecf20Sopenharmony_ci memset(msg[1].buf, 0, msg[1].len); 3408c2ecf20Sopenharmony_ci ret = 0; 3418c2ecf20Sopenharmony_ci } else { 3428c2ecf20Sopenharmony_ci /* I2C write + read */ 3438c2ecf20Sopenharmony_ci u8 buf[MAX_XFER_SIZE]; 3448c2ecf20Sopenharmony_ci struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len, 3458c2ecf20Sopenharmony_ci buf, msg[1].len, msg[1].buf }; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 3488c2ecf20Sopenharmony_ci req.cmd = CMD_GENERIC_I2C_RD; 3498c2ecf20Sopenharmony_ci req.wlen = 3 + msg[0].len; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci req.mbox |= ((msg[0].addr & 0x80) >> 3); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci buf[0] = msg[1].len; 3548c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 3558c2ecf20Sopenharmony_ci buf[1] = 0x03; /* I2C bus */ 3568c2ecf20Sopenharmony_ci buf[2] = msg[0].addr << 1; 3578c2ecf20Sopenharmony_ci memcpy(&buf[3], msg[0].buf, msg[0].len); 3588c2ecf20Sopenharmony_ci } else { 3598c2ecf20Sopenharmony_ci buf[1] = msg[0].addr << 1; 3608c2ecf20Sopenharmony_ci buf[3] = 0x00; /* reg addr MSB */ 3618c2ecf20Sopenharmony_ci buf[4] = 0x00; /* reg addr LSB */ 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* Keep prev behavior for write req len > 2*/ 3648c2ecf20Sopenharmony_ci if (msg[0].len > 2) { 3658c2ecf20Sopenharmony_ci buf[2] = 0x00; /* reg addr len */ 3668c2ecf20Sopenharmony_ci memcpy(&buf[5], msg[0].buf, msg[0].len); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* Use reg addr fields if write req len <= 2 */ 3698c2ecf20Sopenharmony_ci } else { 3708c2ecf20Sopenharmony_ci req.wlen = 5; 3718c2ecf20Sopenharmony_ci buf[2] = msg[0].len; 3728c2ecf20Sopenharmony_ci if (msg[0].len == 2) { 3738c2ecf20Sopenharmony_ci buf[3] = msg[0].buf[0]; 3748c2ecf20Sopenharmony_ci buf[4] = msg[0].buf[1]; 3758c2ecf20Sopenharmony_ci } else if (msg[0].len == 1) { 3768c2ecf20Sopenharmony_ci buf[4] = msg[0].buf[0]; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci } else if (AF9035_IS_I2C_XFER_WRITE(msg, num)) { 3838c2ecf20Sopenharmony_ci if (msg[0].len > 40) { 3848c2ecf20Sopenharmony_ci /* TODO: correct limits > 40 */ 3858c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 3868c2ecf20Sopenharmony_ci } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || 3878c2ecf20Sopenharmony_ci (msg[0].addr == state->af9033_i2c_addr[1])) { 3888c2ecf20Sopenharmony_ci if (msg[0].len < 3) { 3898c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 3908c2ecf20Sopenharmony_ci goto unlock; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci /* demod access via firmware interface */ 3938c2ecf20Sopenharmony_ci reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 3948c2ecf20Sopenharmony_ci msg[0].buf[2]; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if (msg[0].addr == state->af9033_i2c_addr[1]) 3978c2ecf20Sopenharmony_ci reg |= 0x100000; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3); 4008c2ecf20Sopenharmony_ci } else { 4018c2ecf20Sopenharmony_ci /* I2C write */ 4028c2ecf20Sopenharmony_ci u8 buf[MAX_XFER_SIZE]; 4038c2ecf20Sopenharmony_ci struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len, 4048c2ecf20Sopenharmony_ci buf, 0, NULL }; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 4078c2ecf20Sopenharmony_ci req.cmd = CMD_GENERIC_I2C_WR; 4088c2ecf20Sopenharmony_ci req.wlen = 3 + msg[0].len; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci req.mbox |= ((msg[0].addr & 0x80) >> 3); 4128c2ecf20Sopenharmony_ci buf[0] = msg[0].len; 4138c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 4148c2ecf20Sopenharmony_ci buf[1] = 0x03; /* I2C bus */ 4158c2ecf20Sopenharmony_ci buf[2] = msg[0].addr << 1; 4168c2ecf20Sopenharmony_ci memcpy(&buf[3], msg[0].buf, msg[0].len); 4178c2ecf20Sopenharmony_ci } else { 4188c2ecf20Sopenharmony_ci buf[1] = msg[0].addr << 1; 4198c2ecf20Sopenharmony_ci buf[2] = 0x00; /* reg addr len */ 4208c2ecf20Sopenharmony_ci buf[3] = 0x00; /* reg addr MSB */ 4218c2ecf20Sopenharmony_ci buf[4] = 0x00; /* reg addr LSB */ 4228c2ecf20Sopenharmony_ci memcpy(&buf[5], msg[0].buf, msg[0].len); 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci } else if (AF9035_IS_I2C_XFER_READ(msg, num)) { 4278c2ecf20Sopenharmony_ci if (msg[0].len > 40) { 4288c2ecf20Sopenharmony_ci /* TODO: correct limits > 40 */ 4298c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 4308c2ecf20Sopenharmony_ci } else if (state->no_read) { 4318c2ecf20Sopenharmony_ci memset(msg[0].buf, 0, msg[0].len); 4328c2ecf20Sopenharmony_ci ret = 0; 4338c2ecf20Sopenharmony_ci } else { 4348c2ecf20Sopenharmony_ci /* I2C read */ 4358c2ecf20Sopenharmony_ci u8 buf[5]; 4368c2ecf20Sopenharmony_ci struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), 4378c2ecf20Sopenharmony_ci buf, msg[0].len, msg[0].buf }; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 4408c2ecf20Sopenharmony_ci req.cmd = CMD_GENERIC_I2C_RD; 4418c2ecf20Sopenharmony_ci req.wlen = 3; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci req.mbox |= ((msg[0].addr & 0x80) >> 3); 4448c2ecf20Sopenharmony_ci buf[0] = msg[0].len; 4458c2ecf20Sopenharmony_ci if (state->chip_type == 0x9306) { 4468c2ecf20Sopenharmony_ci buf[1] = 0x03; /* I2C bus */ 4478c2ecf20Sopenharmony_ci buf[2] = msg[0].addr << 1; 4488c2ecf20Sopenharmony_ci } else { 4498c2ecf20Sopenharmony_ci buf[1] = msg[0].addr << 1; 4508c2ecf20Sopenharmony_ci buf[2] = 0x00; /* reg addr len */ 4518c2ecf20Sopenharmony_ci buf[3] = 0x00; /* reg addr MSB */ 4528c2ecf20Sopenharmony_ci buf[4] = 0x00; /* reg addr LSB */ 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci } else { 4578c2ecf20Sopenharmony_ci /* 4588c2ecf20Sopenharmony_ci * We support only three kind of I2C transactions: 4598c2ecf20Sopenharmony_ci * 1) 1 x write + 1 x read (repeated start) 4608c2ecf20Sopenharmony_ci * 2) 1 x write 4618c2ecf20Sopenharmony_ci * 3) 1 x read 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ciunlock: 4678c2ecf20Sopenharmony_ci mutex_unlock(&d->i2c_mutex); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (ret < 0) 4708c2ecf20Sopenharmony_ci return ret; 4718c2ecf20Sopenharmony_ci else 4728c2ecf20Sopenharmony_ci return num; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic u32 af9035_i2c_functionality(struct i2c_adapter *adapter) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci return I2C_FUNC_I2C; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic struct i2c_algorithm af9035_i2c_algo = { 4818c2ecf20Sopenharmony_ci .master_xfer = af9035_i2c_master_xfer, 4828c2ecf20Sopenharmony_ci .functionality = af9035_i2c_functionality, 4838c2ecf20Sopenharmony_ci}; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int af9035_identify_state(struct dvb_usb_device *d, const char **name) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 4888c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 4898c2ecf20Sopenharmony_ci int ret, i, ts_mode_invalid; 4908c2ecf20Sopenharmony_ci unsigned int utmp, eeprom_addr; 4918c2ecf20Sopenharmony_ci u8 tmp; 4928c2ecf20Sopenharmony_ci u8 wbuf[1] = { 1 }; 4938c2ecf20Sopenharmony_ci u8 rbuf[4]; 4948c2ecf20Sopenharmony_ci struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, 4958c2ecf20Sopenharmony_ci sizeof(rbuf), rbuf }; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci ret = af9035_rd_regs(d, 0x1222, rbuf, 3); 4988c2ecf20Sopenharmony_ci if (ret < 0) 4998c2ecf20Sopenharmony_ci goto err; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci state->chip_version = rbuf[0]; 5028c2ecf20Sopenharmony_ci state->chip_type = rbuf[2] << 8 | rbuf[1] << 0; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci ret = af9035_rd_reg(d, 0x384f, &state->prechip_version); 5058c2ecf20Sopenharmony_ci if (ret < 0) 5068c2ecf20Sopenharmony_ci goto err; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci dev_info(&intf->dev, "prechip_version=%02x chip_version=%02x chip_type=%04x\n", 5098c2ecf20Sopenharmony_ci state->prechip_version, state->chip_version, state->chip_type); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (state->chip_type == 0x9135) { 5128c2ecf20Sopenharmony_ci if (state->chip_version == 0x02) { 5138c2ecf20Sopenharmony_ci *name = AF9035_FIRMWARE_IT9135_V2; 5148c2ecf20Sopenharmony_ci utmp = 0x00461d; 5158c2ecf20Sopenharmony_ci } else { 5168c2ecf20Sopenharmony_ci *name = AF9035_FIRMWARE_IT9135_V1; 5178c2ecf20Sopenharmony_ci utmp = 0x00461b; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* Check if eeprom exists */ 5218c2ecf20Sopenharmony_ci ret = af9035_rd_reg(d, utmp, &tmp); 5228c2ecf20Sopenharmony_ci if (ret < 0) 5238c2ecf20Sopenharmony_ci goto err; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci if (tmp == 0x00) { 5268c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "no eeprom\n"); 5278c2ecf20Sopenharmony_ci state->no_eeprom = true; 5288c2ecf20Sopenharmony_ci goto check_firmware_status; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci eeprom_addr = EEPROM_BASE_IT9135; 5328c2ecf20Sopenharmony_ci } else if (state->chip_type == 0x9306) { 5338c2ecf20Sopenharmony_ci *name = AF9035_FIRMWARE_IT9303; 5348c2ecf20Sopenharmony_ci state->no_eeprom = true; 5358c2ecf20Sopenharmony_ci goto check_firmware_status; 5368c2ecf20Sopenharmony_ci } else { 5378c2ecf20Sopenharmony_ci *name = AF9035_FIRMWARE_AF9035; 5388c2ecf20Sopenharmony_ci eeprom_addr = EEPROM_BASE_AF9035; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* Read and store eeprom */ 5428c2ecf20Sopenharmony_ci for (i = 0; i < 256; i += 32) { 5438c2ecf20Sopenharmony_ci ret = af9035_rd_regs(d, eeprom_addr + i, &state->eeprom[i], 32); 5448c2ecf20Sopenharmony_ci if (ret < 0) 5458c2ecf20Sopenharmony_ci goto err; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "eeprom dump:\n"); 5498c2ecf20Sopenharmony_ci for (i = 0; i < 256; i += 16) 5508c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%*ph\n", 16, &state->eeprom[i]); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* check for dual tuner mode */ 5538c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_TS_MODE]; 5548c2ecf20Sopenharmony_ci ts_mode_invalid = 0; 5558c2ecf20Sopenharmony_ci switch (tmp) { 5568c2ecf20Sopenharmony_ci case 0: 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case 1: 5598c2ecf20Sopenharmony_ci case 3: 5608c2ecf20Sopenharmony_ci state->dual_mode = true; 5618c2ecf20Sopenharmony_ci break; 5628c2ecf20Sopenharmony_ci case 5: 5638c2ecf20Sopenharmony_ci if (state->chip_type != 0x9135 && state->chip_type != 0x9306) 5648c2ecf20Sopenharmony_ci state->dual_mode = true; /* AF9035 */ 5658c2ecf20Sopenharmony_ci else 5668c2ecf20Sopenharmony_ci ts_mode_invalid = 1; 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci default: 5698c2ecf20Sopenharmony_ci ts_mode_invalid = 1; 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "ts mode=%d dual mode=%d\n", tmp, state->dual_mode); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (ts_mode_invalid) 5758c2ecf20Sopenharmony_ci dev_info(&intf->dev, "ts mode=%d not supported, defaulting to single tuner mode!", tmp); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cicheck_firmware_status: 5788c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 5798c2ecf20Sopenharmony_ci if (ret < 0) 5808c2ecf20Sopenharmony_ci goto err; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "reply=%*ph\n", 4, rbuf); 5838c2ecf20Sopenharmony_ci if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) 5848c2ecf20Sopenharmony_ci ret = WARM; 5858c2ecf20Sopenharmony_ci else 5868c2ecf20Sopenharmony_ci ret = COLD; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci return ret; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_cierr: 5918c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci return ret; 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_cistatic int af9035_download_firmware_old(struct dvb_usb_device *d, 5978c2ecf20Sopenharmony_ci const struct firmware *fw) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 6008c2ecf20Sopenharmony_ci int ret, i, j, len; 6018c2ecf20Sopenharmony_ci u8 wbuf[1]; 6028c2ecf20Sopenharmony_ci struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 6038c2ecf20Sopenharmony_ci struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; 6048c2ecf20Sopenharmony_ci u8 hdr_core; 6058c2ecf20Sopenharmony_ci u16 hdr_addr, hdr_data_len, hdr_checksum; 6068c2ecf20Sopenharmony_ci #define MAX_DATA 58 6078c2ecf20Sopenharmony_ci #define HDR_SIZE 7 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* 6108c2ecf20Sopenharmony_ci * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! 6118c2ecf20Sopenharmony_ci * 6128c2ecf20Sopenharmony_ci * byte 0: MCS 51 core 6138c2ecf20Sopenharmony_ci * There are two inside the AF9035 (1=Link and 2=OFDM) with separate 6148c2ecf20Sopenharmony_ci * address spaces 6158c2ecf20Sopenharmony_ci * byte 1-2: Big endian destination address 6168c2ecf20Sopenharmony_ci * byte 3-4: Big endian number of data bytes following the header 6178c2ecf20Sopenharmony_ci * byte 5-6: Big endian header checksum, apparently ignored by the chip 6188c2ecf20Sopenharmony_ci * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) 6198c2ecf20Sopenharmony_ci */ 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci for (i = fw->size; i > HDR_SIZE;) { 6228c2ecf20Sopenharmony_ci hdr_core = fw->data[fw->size - i + 0]; 6238c2ecf20Sopenharmony_ci hdr_addr = fw->data[fw->size - i + 1] << 8; 6248c2ecf20Sopenharmony_ci hdr_addr |= fw->data[fw->size - i + 2] << 0; 6258c2ecf20Sopenharmony_ci hdr_data_len = fw->data[fw->size - i + 3] << 8; 6268c2ecf20Sopenharmony_ci hdr_data_len |= fw->data[fw->size - i + 4] << 0; 6278c2ecf20Sopenharmony_ci hdr_checksum = fw->data[fw->size - i + 5] << 8; 6288c2ecf20Sopenharmony_ci hdr_checksum |= fw->data[fw->size - i + 6] << 0; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "core=%d addr=%04x data_len=%d checksum=%04x\n", 6318c2ecf20Sopenharmony_ci hdr_core, hdr_addr, hdr_data_len, hdr_checksum); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (((hdr_core != 1) && (hdr_core != 2)) || 6348c2ecf20Sopenharmony_ci (hdr_data_len > i)) { 6358c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "bad firmware\n"); 6368c2ecf20Sopenharmony_ci break; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci /* download begin packet */ 6408c2ecf20Sopenharmony_ci req.cmd = CMD_FW_DL_BEGIN; 6418c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 6428c2ecf20Sopenharmony_ci if (ret < 0) 6438c2ecf20Sopenharmony_ci goto err; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* download firmware packet(s) */ 6468c2ecf20Sopenharmony_ci for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { 6478c2ecf20Sopenharmony_ci len = j; 6488c2ecf20Sopenharmony_ci if (len > MAX_DATA) 6498c2ecf20Sopenharmony_ci len = MAX_DATA; 6508c2ecf20Sopenharmony_ci req_fw_dl.wlen = len; 6518c2ecf20Sopenharmony_ci req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + 6528c2ecf20Sopenharmony_ci HDR_SIZE + hdr_data_len - j]; 6538c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req_fw_dl); 6548c2ecf20Sopenharmony_ci if (ret < 0) 6558c2ecf20Sopenharmony_ci goto err; 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* download end packet */ 6598c2ecf20Sopenharmony_ci req.cmd = CMD_FW_DL_END; 6608c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 6618c2ecf20Sopenharmony_ci if (ret < 0) 6628c2ecf20Sopenharmony_ci goto err; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci i -= hdr_data_len + HDR_SIZE; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "data uploaded=%zu\n", fw->size - i); 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci /* print warn if firmware is bad, continue and see what happens */ 6708c2ecf20Sopenharmony_ci if (i) 6718c2ecf20Sopenharmony_ci dev_warn(&intf->dev, "bad firmware\n"); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci return 0; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cierr: 6768c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci return ret; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic int af9035_download_firmware_new(struct dvb_usb_device *d, 6828c2ecf20Sopenharmony_ci const struct firmware *fw) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 6858c2ecf20Sopenharmony_ci int ret, i, i_prev; 6868c2ecf20Sopenharmony_ci struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; 6878c2ecf20Sopenharmony_ci #define HDR_SIZE 7 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* 6908c2ecf20Sopenharmony_ci * There seems to be following firmware header. Meaning of bytes 0-3 6918c2ecf20Sopenharmony_ci * is unknown. 6928c2ecf20Sopenharmony_ci * 6938c2ecf20Sopenharmony_ci * 0: 3 6948c2ecf20Sopenharmony_ci * 1: 0, 1 6958c2ecf20Sopenharmony_ci * 2: 0 6968c2ecf20Sopenharmony_ci * 3: 1, 2, 3 6978c2ecf20Sopenharmony_ci * 4: addr MSB 6988c2ecf20Sopenharmony_ci * 5: addr LSB 6998c2ecf20Sopenharmony_ci * 6: count of data bytes ? 7008c2ecf20Sopenharmony_ci */ 7018c2ecf20Sopenharmony_ci for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { 7028c2ecf20Sopenharmony_ci if (i == fw->size || 7038c2ecf20Sopenharmony_ci (fw->data[i + 0] == 0x03 && 7048c2ecf20Sopenharmony_ci (fw->data[i + 1] == 0x00 || 7058c2ecf20Sopenharmony_ci fw->data[i + 1] == 0x01) && 7068c2ecf20Sopenharmony_ci fw->data[i + 2] == 0x00)) { 7078c2ecf20Sopenharmony_ci req_fw_dl.wlen = i - i_prev; 7088c2ecf20Sopenharmony_ci req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; 7098c2ecf20Sopenharmony_ci i_prev = i; 7108c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req_fw_dl); 7118c2ecf20Sopenharmony_ci if (ret < 0) 7128c2ecf20Sopenharmony_ci goto err; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "data uploaded=%d\n", i); 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci return 0; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_cierr: 7218c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci return ret; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic int af9035_download_firmware(struct dvb_usb_device *d, 7278c2ecf20Sopenharmony_ci const struct firmware *fw) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 7308c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 7318c2ecf20Sopenharmony_ci int ret; 7328c2ecf20Sopenharmony_ci u8 wbuf[1]; 7338c2ecf20Sopenharmony_ci u8 rbuf[4]; 7348c2ecf20Sopenharmony_ci u8 tmp; 7358c2ecf20Sopenharmony_ci struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 7368c2ecf20Sopenharmony_ci struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "\n"); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* 7418c2ecf20Sopenharmony_ci * In case of dual tuner configuration we need to do some extra 7428c2ecf20Sopenharmony_ci * initialization in order to download firmware to slave demod too, 7438c2ecf20Sopenharmony_ci * which is done by master demod. 7448c2ecf20Sopenharmony_ci * Master feeds also clock and controls power via GPIO. 7458c2ecf20Sopenharmony_ci */ 7468c2ecf20Sopenharmony_ci if (state->dual_mode) { 7478c2ecf20Sopenharmony_ci /* configure gpioh1, reset & power slave demod */ 7488c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); 7498c2ecf20Sopenharmony_ci if (ret < 0) 7508c2ecf20Sopenharmony_ci goto err; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01); 7538c2ecf20Sopenharmony_ci if (ret < 0) 7548c2ecf20Sopenharmony_ci goto err; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01); 7578c2ecf20Sopenharmony_ci if (ret < 0) 7588c2ecf20Sopenharmony_ci goto err; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci usleep_range(10000, 50000); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01); 7638c2ecf20Sopenharmony_ci if (ret < 0) 7648c2ecf20Sopenharmony_ci goto err; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci /* tell the slave I2C address */ 7678c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* Use default I2C address if eeprom has no address set */ 7708c2ecf20Sopenharmony_ci if (!tmp) 7718c2ecf20Sopenharmony_ci tmp = 0x1d << 1; /* 8-bit format used by chip */ 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if ((state->chip_type == 0x9135) || 7748c2ecf20Sopenharmony_ci (state->chip_type == 0x9306)) { 7758c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x004bfb, tmp); 7768c2ecf20Sopenharmony_ci if (ret < 0) 7778c2ecf20Sopenharmony_ci goto err; 7788c2ecf20Sopenharmony_ci } else { 7798c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00417f, tmp); 7808c2ecf20Sopenharmony_ci if (ret < 0) 7818c2ecf20Sopenharmony_ci goto err; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* enable clock out */ 7848c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); 7858c2ecf20Sopenharmony_ci if (ret < 0) 7868c2ecf20Sopenharmony_ci goto err; 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (fw->data[0] == 0x01) 7918c2ecf20Sopenharmony_ci ret = af9035_download_firmware_old(d, fw); 7928c2ecf20Sopenharmony_ci else 7938c2ecf20Sopenharmony_ci ret = af9035_download_firmware_new(d, fw); 7948c2ecf20Sopenharmony_ci if (ret < 0) 7958c2ecf20Sopenharmony_ci goto err; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci /* firmware loaded, request boot */ 7988c2ecf20Sopenharmony_ci req.cmd = CMD_FW_BOOT; 7998c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 8008c2ecf20Sopenharmony_ci if (ret < 0) 8018c2ecf20Sopenharmony_ci goto err; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci /* ensure firmware starts */ 8048c2ecf20Sopenharmony_ci wbuf[0] = 1; 8058c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req_fw_ver); 8068c2ecf20Sopenharmony_ci if (ret < 0) 8078c2ecf20Sopenharmony_ci goto err; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 8108c2ecf20Sopenharmony_ci dev_err(&intf->dev, "firmware did not run\n"); 8118c2ecf20Sopenharmony_ci ret = -ENODEV; 8128c2ecf20Sopenharmony_ci goto err; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci dev_info(&intf->dev, "firmware version=%d.%d.%d.%d", 8168c2ecf20Sopenharmony_ci rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci return 0; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cierr: 8218c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci return ret; 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_cistatic int af9035_read_config(struct dvb_usb_device *d) 8278c2ecf20Sopenharmony_ci{ 8288c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 8298c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 8308c2ecf20Sopenharmony_ci int ret, i; 8318c2ecf20Sopenharmony_ci u8 tmp; 8328c2ecf20Sopenharmony_ci u16 tmp16; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Demod I2C address */ 8358c2ecf20Sopenharmony_ci state->af9033_i2c_addr[0] = 0x1c; 8368c2ecf20Sopenharmony_ci state->af9033_i2c_addr[1] = 0x1d; 8378c2ecf20Sopenharmony_ci state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 8388c2ecf20Sopenharmony_ci state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 8398c2ecf20Sopenharmony_ci state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; 8408c2ecf20Sopenharmony_ci state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; 8418c2ecf20Sopenharmony_ci state->it930x_addresses = 0; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (state->chip_type == 0x9135) { 8448c2ecf20Sopenharmony_ci /* feed clock for integrated RF tuner */ 8458c2ecf20Sopenharmony_ci state->af9033_config[0].dyn0_clk = true; 8468c2ecf20Sopenharmony_ci state->af9033_config[1].dyn0_clk = true; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci if (state->chip_version == 0x02) { 8498c2ecf20Sopenharmony_ci state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; 8508c2ecf20Sopenharmony_ci state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60; 8518c2ecf20Sopenharmony_ci } else { 8528c2ecf20Sopenharmony_ci state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; 8538c2ecf20Sopenharmony_ci state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38; 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci if (state->no_eeprom) { 8578c2ecf20Sopenharmony_ci /* Remote controller to NEC polling by default */ 8588c2ecf20Sopenharmony_ci state->ir_mode = 0x05; 8598c2ecf20Sopenharmony_ci state->ir_type = 0x00; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci goto skip_eeprom; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci } else if (state->chip_type == 0x9306) { 8648c2ecf20Sopenharmony_ci /* 8658c2ecf20Sopenharmony_ci * IT930x is an USB bridge, only single demod-single tuner 8668c2ecf20Sopenharmony_ci * configurations seen so far. 8678c2ecf20Sopenharmony_ci */ 8688c2ecf20Sopenharmony_ci if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) && 8698c2ecf20Sopenharmony_ci (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_AVERMEDIA_TD310)) { 8708c2ecf20Sopenharmony_ci state->it930x_addresses = 1; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci return 0; 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* Remote controller */ 8768c2ecf20Sopenharmony_ci state->ir_mode = state->eeprom[EEPROM_IR_MODE]; 8778c2ecf20Sopenharmony_ci state->ir_type = state->eeprom[EEPROM_IR_TYPE]; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (state->dual_mode) { 8808c2ecf20Sopenharmony_ci /* Read 2nd demodulator I2C address. 8-bit format on eeprom */ 8818c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; 8828c2ecf20Sopenharmony_ci if (tmp) 8838c2ecf20Sopenharmony_ci state->af9033_i2c_addr[1] = tmp >> 1; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "2nd demod I2C addr=%02x\n", 8868c2ecf20Sopenharmony_ci state->af9033_i2c_addr[1]); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci for (i = 0; i < state->dual_mode + 1; i++) { 8908c2ecf20Sopenharmony_ci unsigned int eeprom_offset = 0; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* tuner */ 8938c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_1_TUNER_ID + eeprom_offset]; 8948c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "[%d]tuner=%02x\n", i, tmp); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci /* tuner sanity check */ 8978c2ecf20Sopenharmony_ci if (state->chip_type == 0x9135) { 8988c2ecf20Sopenharmony_ci if (state->chip_version == 0x02) { 8998c2ecf20Sopenharmony_ci /* IT9135 BX (v2) */ 9008c2ecf20Sopenharmony_ci switch (tmp) { 9018c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 9028c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 9038c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 9048c2ecf20Sopenharmony_ci state->af9033_config[i].tuner = tmp; 9058c2ecf20Sopenharmony_ci break; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci } else { 9088c2ecf20Sopenharmony_ci /* IT9135 AX (v1) */ 9098c2ecf20Sopenharmony_ci switch (tmp) { 9108c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 9118c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 9128c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 9138c2ecf20Sopenharmony_ci state->af9033_config[i].tuner = tmp; 9148c2ecf20Sopenharmony_ci break; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci } else { 9188c2ecf20Sopenharmony_ci /* AF9035 */ 9198c2ecf20Sopenharmony_ci state->af9033_config[i].tuner = tmp; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci if (state->af9033_config[i].tuner != tmp) { 9238c2ecf20Sopenharmony_ci dev_info(&intf->dev, "[%d] overriding tuner from %02x to %02x\n", 9248c2ecf20Sopenharmony_ci i, tmp, state->af9033_config[i].tuner); 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci switch (state->af9033_config[i].tuner) { 9288c2ecf20Sopenharmony_ci case AF9033_TUNER_TUA9001: 9298c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0011: 9308c2ecf20Sopenharmony_ci case AF9033_TUNER_MXL5007T: 9318c2ecf20Sopenharmony_ci case AF9033_TUNER_TDA18218: 9328c2ecf20Sopenharmony_ci case AF9033_TUNER_FC2580: 9338c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0012: 9348c2ecf20Sopenharmony_ci state->af9033_config[i].spec_inv = 1; 9358c2ecf20Sopenharmony_ci break; 9368c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 9378c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 9388c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 9398c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 9408c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 9418c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 9428c2ecf20Sopenharmony_ci break; 9438c2ecf20Sopenharmony_ci default: 9448c2ecf20Sopenharmony_ci dev_warn(&intf->dev, "tuner id=%02x not supported, please report!", 9458c2ecf20Sopenharmony_ci tmp); 9468c2ecf20Sopenharmony_ci } 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci /* disable dual mode if driver does not support it */ 9498c2ecf20Sopenharmony_ci if (i == 1) 9508c2ecf20Sopenharmony_ci switch (state->af9033_config[i].tuner) { 9518c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0012: 9528c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 9538c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 9548c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 9558c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 9568c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 9578c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 9588c2ecf20Sopenharmony_ci case AF9033_TUNER_MXL5007T: 9598c2ecf20Sopenharmony_ci break; 9608c2ecf20Sopenharmony_ci default: 9618c2ecf20Sopenharmony_ci state->dual_mode = false; 9628c2ecf20Sopenharmony_ci dev_info(&intf->dev, "driver does not support 2nd tuner and will disable it"); 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* tuner IF frequency */ 9668c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_1_IF_L + eeprom_offset]; 9678c2ecf20Sopenharmony_ci tmp16 = tmp << 0; 9688c2ecf20Sopenharmony_ci tmp = state->eeprom[EEPROM_1_IF_H + eeprom_offset]; 9698c2ecf20Sopenharmony_ci tmp16 |= tmp << 8; 9708c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "[%d]IF=%d\n", i, tmp16); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci eeprom_offset += 0x10; /* shift for the 2nd tuner params */ 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ciskip_eeprom: 9768c2ecf20Sopenharmony_ci /* get demod clock */ 9778c2ecf20Sopenharmony_ci ret = af9035_rd_reg(d, 0x00d800, &tmp); 9788c2ecf20Sopenharmony_ci if (ret < 0) 9798c2ecf20Sopenharmony_ci goto err; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci tmp = (tmp >> 0) & 0x0f; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) { 9848c2ecf20Sopenharmony_ci if (state->chip_type == 0x9135) 9858c2ecf20Sopenharmony_ci state->af9033_config[i].clock = clock_lut_it9135[tmp]; 9868c2ecf20Sopenharmony_ci else 9878c2ecf20Sopenharmony_ci state->af9033_config[i].clock = clock_lut_af9035[tmp]; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci state->no_read = false; 9918c2ecf20Sopenharmony_ci /* Some MXL5007T devices cannot properly handle tuner I2C read ops. */ 9928c2ecf20Sopenharmony_ci if (state->af9033_config[0].tuner == AF9033_TUNER_MXL5007T && 9938c2ecf20Sopenharmony_ci le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci switch (le16_to_cpu(d->udev->descriptor.idProduct)) { 9968c2ecf20Sopenharmony_ci case USB_PID_AVERMEDIA_A867: 9978c2ecf20Sopenharmony_ci case USB_PID_AVERMEDIA_TWINSTAR: 9988c2ecf20Sopenharmony_ci dev_info(&intf->dev, 9998c2ecf20Sopenharmony_ci "Device may have issues with I2C read operations. Enabling fix.\n"); 10008c2ecf20Sopenharmony_ci state->no_read = true; 10018c2ecf20Sopenharmony_ci break; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci return 0; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_cierr: 10078c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci return ret; 10108c2ecf20Sopenharmony_ci} 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_cistatic int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, 10138c2ecf20Sopenharmony_ci int cmd, int arg) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 10168c2ecf20Sopenharmony_ci int ret; 10178c2ecf20Sopenharmony_ci u8 val; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "cmd=%d arg=%d\n", cmd, arg); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci /* 10228c2ecf20Sopenharmony_ci * CEN always enabled by hardware wiring 10238c2ecf20Sopenharmony_ci * RESETN GPIOT3 10248c2ecf20Sopenharmony_ci * RXEN GPIOT2 10258c2ecf20Sopenharmony_ci */ 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci switch (cmd) { 10288c2ecf20Sopenharmony_ci case TUA9001_CMD_RESETN: 10298c2ecf20Sopenharmony_ci if (arg) 10308c2ecf20Sopenharmony_ci val = 0x00; 10318c2ecf20Sopenharmony_ci else 10328c2ecf20Sopenharmony_ci val = 0x01; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); 10358c2ecf20Sopenharmony_ci if (ret < 0) 10368c2ecf20Sopenharmony_ci goto err; 10378c2ecf20Sopenharmony_ci break; 10388c2ecf20Sopenharmony_ci case TUA9001_CMD_RXEN: 10398c2ecf20Sopenharmony_ci if (arg) 10408c2ecf20Sopenharmony_ci val = 0x01; 10418c2ecf20Sopenharmony_ci else 10428c2ecf20Sopenharmony_ci val = 0x00; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); 10458c2ecf20Sopenharmony_ci if (ret < 0) 10468c2ecf20Sopenharmony_ci goto err; 10478c2ecf20Sopenharmony_ci break; 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci return 0; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_cierr: 10538c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci return ret; 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_cistatic int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, 10608c2ecf20Sopenharmony_ci int cmd, int arg) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 10638c2ecf20Sopenharmony_ci int ret; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci switch (cmd) { 10668c2ecf20Sopenharmony_ci case FC0011_FE_CALLBACK_POWER: 10678c2ecf20Sopenharmony_ci /* Tuner enable */ 10688c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); 10698c2ecf20Sopenharmony_ci if (ret < 0) 10708c2ecf20Sopenharmony_ci goto err; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); 10738c2ecf20Sopenharmony_ci if (ret < 0) 10748c2ecf20Sopenharmony_ci goto err; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); 10778c2ecf20Sopenharmony_ci if (ret < 0) 10788c2ecf20Sopenharmony_ci goto err; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci /* LED */ 10818c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); 10828c2ecf20Sopenharmony_ci if (ret < 0) 10838c2ecf20Sopenharmony_ci goto err; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); 10868c2ecf20Sopenharmony_ci if (ret < 0) 10878c2ecf20Sopenharmony_ci goto err; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci usleep_range(10000, 50000); 10908c2ecf20Sopenharmony_ci break; 10918c2ecf20Sopenharmony_ci case FC0011_FE_CALLBACK_RESET: 10928c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0xd8e9, 1); 10938c2ecf20Sopenharmony_ci if (ret < 0) 10948c2ecf20Sopenharmony_ci goto err; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0xd8e8, 1); 10978c2ecf20Sopenharmony_ci if (ret < 0) 10988c2ecf20Sopenharmony_ci goto err; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0xd8e7, 1); 11018c2ecf20Sopenharmony_ci if (ret < 0) 11028c2ecf20Sopenharmony_ci goto err; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0xd8e7, 0); 11078c2ecf20Sopenharmony_ci if (ret < 0) 11088c2ecf20Sopenharmony_ci goto err; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 11118c2ecf20Sopenharmony_ci break; 11128c2ecf20Sopenharmony_ci default: 11138c2ecf20Sopenharmony_ci ret = -EINVAL; 11148c2ecf20Sopenharmony_ci goto err; 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci return 0; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_cierr: 11208c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci return ret; 11238c2ecf20Sopenharmony_ci} 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_cistatic int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) 11268c2ecf20Sopenharmony_ci{ 11278c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci switch (state->af9033_config[0].tuner) { 11308c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0011: 11318c2ecf20Sopenharmony_ci return af9035_fc0011_tuner_callback(d, cmd, arg); 11328c2ecf20Sopenharmony_ci case AF9033_TUNER_TUA9001: 11338c2ecf20Sopenharmony_ci return af9035_tua9001_tuner_callback(d, cmd, arg); 11348c2ecf20Sopenharmony_ci default: 11358c2ecf20Sopenharmony_ci break; 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci return 0; 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic int af9035_frontend_callback(void *adapter_priv, int component, 11428c2ecf20Sopenharmony_ci int cmd, int arg) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci struct i2c_adapter *adap = adapter_priv; 11458c2ecf20Sopenharmony_ci struct dvb_usb_device *d = i2c_get_adapdata(adap); 11468c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "component=%d cmd=%d arg=%d\n", 11498c2ecf20Sopenharmony_ci component, cmd, arg); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci switch (component) { 11528c2ecf20Sopenharmony_ci case DVB_FRONTEND_COMPONENT_TUNER: 11538c2ecf20Sopenharmony_ci return af9035_tuner_callback(d, cmd, arg); 11548c2ecf20Sopenharmony_ci default: 11558c2ecf20Sopenharmony_ci break; 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci return 0; 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_cistatic int af9035_get_adapter_count(struct dvb_usb_device *d) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return state->dual_mode + 1; 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic int af9035_frontend_attach(struct dvb_usb_adapter *adap) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 11718c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 11728c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 11738c2ecf20Sopenharmony_ci int ret; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (!state->af9033_config[adap->id].tuner) { 11788c2ecf20Sopenharmony_ci /* unsupported tuner */ 11798c2ecf20Sopenharmony_ci ret = -ENODEV; 11808c2ecf20Sopenharmony_ci goto err; 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci state->af9033_config[adap->id].fe = &adap->fe[0]; 11848c2ecf20Sopenharmony_ci state->af9033_config[adap->id].ops = &state->ops; 11858c2ecf20Sopenharmony_ci ret = af9035_add_i2c_dev(d, "af9033", state->af9033_i2c_addr[adap->id], 11868c2ecf20Sopenharmony_ci &state->af9033_config[adap->id], &d->i2c_adap); 11878c2ecf20Sopenharmony_ci if (ret) 11888c2ecf20Sopenharmony_ci goto err; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci if (adap->fe[0] == NULL) { 11918c2ecf20Sopenharmony_ci ret = -ENODEV; 11928c2ecf20Sopenharmony_ci goto err; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci /* disable I2C-gate */ 11968c2ecf20Sopenharmony_ci adap->fe[0]->ops.i2c_gate_ctrl = NULL; 11978c2ecf20Sopenharmony_ci adap->fe[0]->callback = af9035_frontend_callback; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci return 0; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_cierr: 12028c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci return ret; 12058c2ecf20Sopenharmony_ci} 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci/* 12088c2ecf20Sopenharmony_ci * The I2C speed register is calculated with: 12098c2ecf20Sopenharmony_ci * I2C speed register = (1000000000 / (24.4 * 16 * I2C_speed)) 12108c2ecf20Sopenharmony_ci * 12118c2ecf20Sopenharmony_ci * The default speed register for it930x is 7, with means a 12128c2ecf20Sopenharmony_ci * speed of ~366 kbps 12138c2ecf20Sopenharmony_ci */ 12148c2ecf20Sopenharmony_ci#define I2C_SPEED_366K 7 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_cistatic int it930x_frontend_attach(struct dvb_usb_adapter *adap) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 12198c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 12208c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 12218c2ecf20Sopenharmony_ci int ret; 12228c2ecf20Sopenharmony_ci struct si2168_config si2168_config; 12238c2ecf20Sopenharmony_ci struct i2c_adapter *adapter; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* I2C master bus 2 clock speed 366k */ 12288c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00f6a7, I2C_SPEED_366K); 12298c2ecf20Sopenharmony_ci if (ret < 0) 12308c2ecf20Sopenharmony_ci goto err; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci /* I2C master bus 1,3 clock speed 366k */ 12338c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00f103, I2C_SPEED_366K); 12348c2ecf20Sopenharmony_ci if (ret < 0) 12358c2ecf20Sopenharmony_ci goto err; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* set gpio11 low */ 12388c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8d4, 0x01, 0x01); 12398c2ecf20Sopenharmony_ci if (ret < 0) 12408c2ecf20Sopenharmony_ci goto err; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8d5, 0x01, 0x01); 12438c2ecf20Sopenharmony_ci if (ret < 0) 12448c2ecf20Sopenharmony_ci goto err; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8d3, 0x01, 0x01); 12478c2ecf20Sopenharmony_ci if (ret < 0) 12488c2ecf20Sopenharmony_ci goto err; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci /* Tuner enable using gpiot2_en, gpiot2_on and gpiot2_o (reset) */ 12518c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8b8, 0x01, 0x01); 12528c2ecf20Sopenharmony_ci if (ret < 0) 12538c2ecf20Sopenharmony_ci goto err; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8b9, 0x01, 0x01); 12568c2ecf20Sopenharmony_ci if (ret < 0) 12578c2ecf20Sopenharmony_ci goto err; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8b7, 0x00, 0x01); 12608c2ecf20Sopenharmony_ci if (ret < 0) 12618c2ecf20Sopenharmony_ci goto err; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci msleep(200); 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8b7, 0x01, 0x01); 12668c2ecf20Sopenharmony_ci if (ret < 0) 12678c2ecf20Sopenharmony_ci goto err; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci memset(&si2168_config, 0, sizeof(si2168_config)); 12708c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 12718c2ecf20Sopenharmony_ci si2168_config.fe = &adap->fe[0]; 12728c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_SERIAL; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci state->af9033_config[adap->id].fe = &adap->fe[0]; 12758c2ecf20Sopenharmony_ci state->af9033_config[adap->id].ops = &state->ops; 12768c2ecf20Sopenharmony_ci ret = af9035_add_i2c_dev(d, "si2168", 12778c2ecf20Sopenharmony_ci it930x_addresses_table[state->it930x_addresses].frontend_i2c_addr, 12788c2ecf20Sopenharmony_ci &si2168_config, &d->i2c_adap); 12798c2ecf20Sopenharmony_ci if (ret) 12808c2ecf20Sopenharmony_ci goto err; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci if (adap->fe[0] == NULL) { 12838c2ecf20Sopenharmony_ci ret = -ENODEV; 12848c2ecf20Sopenharmony_ci goto err; 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci state->i2c_adapter_demod = adapter; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci return 0; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cierr: 12918c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci return ret; 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_cistatic int af9035_frontend_detach(struct dvb_usb_adapter *adap) 12978c2ecf20Sopenharmony_ci{ 12988c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 12998c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 13008c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci if (adap->id == 1) { 13058c2ecf20Sopenharmony_ci if (state->i2c_client[1]) 13068c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 13078c2ecf20Sopenharmony_ci } else if (adap->id == 0) { 13088c2ecf20Sopenharmony_ci if (state->i2c_client[0]) 13098c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci return 0; 13138c2ecf20Sopenharmony_ci} 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cistatic const struct fc0011_config af9035_fc0011_config = { 13168c2ecf20Sopenharmony_ci .i2c_address = 0x60, 13178c2ecf20Sopenharmony_ci}; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_cistatic struct mxl5007t_config af9035_mxl5007t_config[] = { 13208c2ecf20Sopenharmony_ci { 13218c2ecf20Sopenharmony_ci .xtal_freq_hz = MxL_XTAL_24_MHZ, 13228c2ecf20Sopenharmony_ci .if_freq_hz = MxL_IF_4_57_MHZ, 13238c2ecf20Sopenharmony_ci .invert_if = 0, 13248c2ecf20Sopenharmony_ci .loop_thru_enable = 0, 13258c2ecf20Sopenharmony_ci .clk_out_enable = 0, 13268c2ecf20Sopenharmony_ci .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 13278c2ecf20Sopenharmony_ci }, { 13288c2ecf20Sopenharmony_ci .xtal_freq_hz = MxL_XTAL_24_MHZ, 13298c2ecf20Sopenharmony_ci .if_freq_hz = MxL_IF_4_57_MHZ, 13308c2ecf20Sopenharmony_ci .invert_if = 0, 13318c2ecf20Sopenharmony_ci .loop_thru_enable = 1, 13328c2ecf20Sopenharmony_ci .clk_out_enable = 1, 13338c2ecf20Sopenharmony_ci .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci}; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic struct tda18218_config af9035_tda18218_config = { 13388c2ecf20Sopenharmony_ci .i2c_address = 0x60, 13398c2ecf20Sopenharmony_ci .i2c_wr_max = 21, 13408c2ecf20Sopenharmony_ci}; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_cistatic const struct fc0012_config af9035_fc0012_config[] = { 13438c2ecf20Sopenharmony_ci { 13448c2ecf20Sopenharmony_ci .i2c_address = 0x63, 13458c2ecf20Sopenharmony_ci .xtal_freq = FC_XTAL_36_MHZ, 13468c2ecf20Sopenharmony_ci .dual_master = true, 13478c2ecf20Sopenharmony_ci .loop_through = true, 13488c2ecf20Sopenharmony_ci .clock_out = true, 13498c2ecf20Sopenharmony_ci }, { 13508c2ecf20Sopenharmony_ci .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ 13518c2ecf20Sopenharmony_ci .xtal_freq = FC_XTAL_36_MHZ, 13528c2ecf20Sopenharmony_ci .dual_master = true, 13538c2ecf20Sopenharmony_ci } 13548c2ecf20Sopenharmony_ci}; 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_cistatic int af9035_tuner_attach(struct dvb_usb_adapter *adap) 13578c2ecf20Sopenharmony_ci{ 13588c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 13598c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 13608c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 13618c2ecf20Sopenharmony_ci int ret; 13628c2ecf20Sopenharmony_ci struct dvb_frontend *fe; 13638c2ecf20Sopenharmony_ci struct i2c_msg msg[1]; 13648c2ecf20Sopenharmony_ci u8 tuner_addr; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci /* 13698c2ecf20Sopenharmony_ci * XXX: Hack used in that function: we abuse unused I2C address bit [7] 13708c2ecf20Sopenharmony_ci * to carry info about used I2C bus for dual tuner configuration. 13718c2ecf20Sopenharmony_ci */ 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci switch (state->af9033_config[adap->id].tuner) { 13748c2ecf20Sopenharmony_ci case AF9033_TUNER_TUA9001: { 13758c2ecf20Sopenharmony_ci struct tua9001_platform_data tua9001_pdata = { 13768c2ecf20Sopenharmony_ci .dvb_frontend = adap->fe[0], 13778c2ecf20Sopenharmony_ci }; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* 13808c2ecf20Sopenharmony_ci * AF9035 gpiot3 = TUA9001 RESETN 13818c2ecf20Sopenharmony_ci * AF9035 gpiot2 = TUA9001 RXEN 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci /* configure gpiot2 and gpiot2 as output */ 13858c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); 13868c2ecf20Sopenharmony_ci if (ret < 0) 13878c2ecf20Sopenharmony_ci goto err; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); 13908c2ecf20Sopenharmony_ci if (ret < 0) 13918c2ecf20Sopenharmony_ci goto err; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); 13948c2ecf20Sopenharmony_ci if (ret < 0) 13958c2ecf20Sopenharmony_ci goto err; 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); 13988c2ecf20Sopenharmony_ci if (ret < 0) 13998c2ecf20Sopenharmony_ci goto err; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci /* attach tuner */ 14028c2ecf20Sopenharmony_ci ret = af9035_add_i2c_dev(d, "tua9001", 0x60, &tua9001_pdata, 14038c2ecf20Sopenharmony_ci &d->i2c_adap); 14048c2ecf20Sopenharmony_ci if (ret) 14058c2ecf20Sopenharmony_ci goto err; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci fe = adap->fe[0]; 14088c2ecf20Sopenharmony_ci break; 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0011: 14118c2ecf20Sopenharmony_ci fe = dvb_attach(fc0011_attach, adap->fe[0], 14128c2ecf20Sopenharmony_ci &d->i2c_adap, &af9035_fc0011_config); 14138c2ecf20Sopenharmony_ci break; 14148c2ecf20Sopenharmony_ci case AF9033_TUNER_MXL5007T: 14158c2ecf20Sopenharmony_ci if (adap->id == 0) { 14168c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8e0, 1); 14178c2ecf20Sopenharmony_ci if (ret < 0) 14188c2ecf20Sopenharmony_ci goto err; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8e1, 1); 14218c2ecf20Sopenharmony_ci if (ret < 0) 14228c2ecf20Sopenharmony_ci goto err; 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8df, 0); 14258c2ecf20Sopenharmony_ci if (ret < 0) 14268c2ecf20Sopenharmony_ci goto err; 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci msleep(30); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8df, 1); 14318c2ecf20Sopenharmony_ci if (ret < 0) 14328c2ecf20Sopenharmony_ci goto err; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci msleep(300); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8c0, 1); 14378c2ecf20Sopenharmony_ci if (ret < 0) 14388c2ecf20Sopenharmony_ci goto err; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8c1, 1); 14418c2ecf20Sopenharmony_ci if (ret < 0) 14428c2ecf20Sopenharmony_ci goto err; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8bf, 0); 14458c2ecf20Sopenharmony_ci if (ret < 0) 14468c2ecf20Sopenharmony_ci goto err; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8b4, 1); 14498c2ecf20Sopenharmony_ci if (ret < 0) 14508c2ecf20Sopenharmony_ci goto err; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8b5, 1); 14538c2ecf20Sopenharmony_ci if (ret < 0) 14548c2ecf20Sopenharmony_ci goto err; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci ret = af9035_wr_reg(d, 0x00d8b3, 1); 14578c2ecf20Sopenharmony_ci if (ret < 0) 14588c2ecf20Sopenharmony_ci goto err; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci tuner_addr = 0x60; 14618c2ecf20Sopenharmony_ci } else { 14628c2ecf20Sopenharmony_ci tuner_addr = 0x60 | 0x80; /* I2C bus hack */ 14638c2ecf20Sopenharmony_ci } 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci /* attach tuner */ 14668c2ecf20Sopenharmony_ci fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, 14678c2ecf20Sopenharmony_ci tuner_addr, &af9035_mxl5007t_config[adap->id]); 14688c2ecf20Sopenharmony_ci break; 14698c2ecf20Sopenharmony_ci case AF9033_TUNER_TDA18218: 14708c2ecf20Sopenharmony_ci /* attach tuner */ 14718c2ecf20Sopenharmony_ci fe = dvb_attach(tda18218_attach, adap->fe[0], 14728c2ecf20Sopenharmony_ci &d->i2c_adap, &af9035_tda18218_config); 14738c2ecf20Sopenharmony_ci break; 14748c2ecf20Sopenharmony_ci case AF9033_TUNER_FC2580: { 14758c2ecf20Sopenharmony_ci struct fc2580_platform_data fc2580_pdata = { 14768c2ecf20Sopenharmony_ci .dvb_frontend = adap->fe[0], 14778c2ecf20Sopenharmony_ci }; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ 14808c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 14818c2ecf20Sopenharmony_ci if (ret < 0) 14828c2ecf20Sopenharmony_ci goto err; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 14858c2ecf20Sopenharmony_ci if (ret < 0) 14868c2ecf20Sopenharmony_ci goto err; 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 14898c2ecf20Sopenharmony_ci if (ret < 0) 14908c2ecf20Sopenharmony_ci goto err; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci usleep_range(10000, 50000); 14938c2ecf20Sopenharmony_ci /* attach tuner */ 14948c2ecf20Sopenharmony_ci ret = af9035_add_i2c_dev(d, "fc2580", 0x56, &fc2580_pdata, 14958c2ecf20Sopenharmony_ci &d->i2c_adap); 14968c2ecf20Sopenharmony_ci if (ret) 14978c2ecf20Sopenharmony_ci goto err; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci fe = adap->fe[0]; 15008c2ecf20Sopenharmony_ci break; 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0012: 15038c2ecf20Sopenharmony_ci /* 15048c2ecf20Sopenharmony_ci * AF9035 gpiot2 = FC0012 enable 15058c2ecf20Sopenharmony_ci * XXX: there seems to be something on gpioh8 too, but on my 15068c2ecf20Sopenharmony_ci * my test I didn't find any difference. 15078c2ecf20Sopenharmony_ci */ 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci if (adap->id == 0) { 15108c2ecf20Sopenharmony_ci /* configure gpiot2 as output and high */ 15118c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 15128c2ecf20Sopenharmony_ci if (ret < 0) 15138c2ecf20Sopenharmony_ci goto err; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 15168c2ecf20Sopenharmony_ci if (ret < 0) 15178c2ecf20Sopenharmony_ci goto err; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 15208c2ecf20Sopenharmony_ci if (ret < 0) 15218c2ecf20Sopenharmony_ci goto err; 15228c2ecf20Sopenharmony_ci } else { 15238c2ecf20Sopenharmony_ci /* 15248c2ecf20Sopenharmony_ci * FIXME: That belongs for the FC0012 driver. 15258c2ecf20Sopenharmony_ci * Write 02 to FC0012 master tuner register 0d directly 15268c2ecf20Sopenharmony_ci * in order to make slave tuner working. 15278c2ecf20Sopenharmony_ci */ 15288c2ecf20Sopenharmony_ci msg[0].addr = 0x63; 15298c2ecf20Sopenharmony_ci msg[0].flags = 0; 15308c2ecf20Sopenharmony_ci msg[0].len = 2; 15318c2ecf20Sopenharmony_ci msg[0].buf = "\x0d\x02"; 15328c2ecf20Sopenharmony_ci ret = i2c_transfer(&d->i2c_adap, msg, 1); 15338c2ecf20Sopenharmony_ci if (ret < 0) 15348c2ecf20Sopenharmony_ci goto err; 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci usleep_range(10000, 50000); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, 15408c2ecf20Sopenharmony_ci &af9035_fc0012_config[adap->id]); 15418c2ecf20Sopenharmony_ci break; 15428c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 15438c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 15448c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 15458c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 15468c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 15478c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 15488c2ecf20Sopenharmony_ci { 15498c2ecf20Sopenharmony_ci struct platform_device *pdev; 15508c2ecf20Sopenharmony_ci const char *name; 15518c2ecf20Sopenharmony_ci struct it913x_platform_data it913x_pdata = { 15528c2ecf20Sopenharmony_ci .regmap = state->af9033_config[adap->id].regmap, 15538c2ecf20Sopenharmony_ci .fe = adap->fe[0], 15548c2ecf20Sopenharmony_ci }; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci switch (state->af9033_config[adap->id].tuner) { 15578c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 15588c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 15598c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 15608c2ecf20Sopenharmony_ci name = "it9133ax-tuner"; 15618c2ecf20Sopenharmony_ci break; 15628c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 15638c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 15648c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 15658c2ecf20Sopenharmony_ci name = "it9133bx-tuner"; 15668c2ecf20Sopenharmony_ci break; 15678c2ecf20Sopenharmony_ci default: 15688c2ecf20Sopenharmony_ci ret = -ENODEV; 15698c2ecf20Sopenharmony_ci goto err; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci if (state->dual_mode) { 15738c2ecf20Sopenharmony_ci if (adap->id == 0) 15748c2ecf20Sopenharmony_ci it913x_pdata.role = IT913X_ROLE_DUAL_MASTER; 15758c2ecf20Sopenharmony_ci else 15768c2ecf20Sopenharmony_ci it913x_pdata.role = IT913X_ROLE_DUAL_SLAVE; 15778c2ecf20Sopenharmony_ci } else { 15788c2ecf20Sopenharmony_ci it913x_pdata.role = IT913X_ROLE_SINGLE; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci request_module("%s", "it913x"); 15828c2ecf20Sopenharmony_ci pdev = platform_device_register_data(&d->intf->dev, name, 15838c2ecf20Sopenharmony_ci PLATFORM_DEVID_AUTO, 15848c2ecf20Sopenharmony_ci &it913x_pdata, 15858c2ecf20Sopenharmony_ci sizeof(it913x_pdata)); 15868c2ecf20Sopenharmony_ci if (IS_ERR(pdev) || !pdev->dev.driver) { 15878c2ecf20Sopenharmony_ci ret = -ENODEV; 15888c2ecf20Sopenharmony_ci goto err; 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci if (!try_module_get(pdev->dev.driver->owner)) { 15918c2ecf20Sopenharmony_ci platform_device_unregister(pdev); 15928c2ecf20Sopenharmony_ci ret = -ENODEV; 15938c2ecf20Sopenharmony_ci goto err; 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci state->platform_device_tuner[adap->id] = pdev; 15978c2ecf20Sopenharmony_ci fe = adap->fe[0]; 15988c2ecf20Sopenharmony_ci break; 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci default: 16018c2ecf20Sopenharmony_ci fe = NULL; 16028c2ecf20Sopenharmony_ci } 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci if (fe == NULL) { 16058c2ecf20Sopenharmony_ci ret = -ENODEV; 16068c2ecf20Sopenharmony_ci goto err; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci return 0; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_cierr: 16128c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci return ret; 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_cistatic int it930x_tuner_attach(struct dvb_usb_adapter *adap) 16188c2ecf20Sopenharmony_ci{ 16198c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 16208c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 16218c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 16228c2ecf20Sopenharmony_ci int ret; 16238c2ecf20Sopenharmony_ci struct si2157_config si2157_config; 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci memset(&si2157_config, 0, sizeof(si2157_config)); 16288c2ecf20Sopenharmony_ci si2157_config.fe = adap->fe[0]; 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci /* 16318c2ecf20Sopenharmony_ci * HACK: The Logilink VG0022A and TerraTec TC2 Stick have 16328c2ecf20Sopenharmony_ci * a bug: when the si2157 firmware that came with the device 16338c2ecf20Sopenharmony_ci * is replaced by a new one, the I2C transfers to the tuner 16348c2ecf20Sopenharmony_ci * will return just 0xff. 16358c2ecf20Sopenharmony_ci * 16368c2ecf20Sopenharmony_ci * Probably, the vendor firmware has some patch specifically 16378c2ecf20Sopenharmony_ci * designed for this device. So, we can't replace by the 16388c2ecf20Sopenharmony_ci * generic firmware. The right solution would be to extract 16398c2ecf20Sopenharmony_ci * the si2157 firmware from the original driver and ask the 16408c2ecf20Sopenharmony_ci * driver to load the specifically designed firmware, but, 16418c2ecf20Sopenharmony_ci * while we don't have that, the next best solution is to just 16428c2ecf20Sopenharmony_ci * keep the original firmware at the device. 16438c2ecf20Sopenharmony_ci */ 16448c2ecf20Sopenharmony_ci if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_DEXATEK && 16458c2ecf20Sopenharmony_ci le16_to_cpu(d->udev->descriptor.idProduct) == 0x0100) || 16468c2ecf20Sopenharmony_ci (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_TERRATEC && 16478c2ecf20Sopenharmony_ci le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_TERRATEC_CINERGY_TC2_STICK)) 16488c2ecf20Sopenharmony_ci si2157_config.dont_load_firmware = true; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci si2157_config.if_port = it930x_addresses_table[state->it930x_addresses].tuner_if_port; 16518c2ecf20Sopenharmony_ci ret = af9035_add_i2c_dev(d, "si2157", 16528c2ecf20Sopenharmony_ci it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr, 16538c2ecf20Sopenharmony_ci &si2157_config, state->i2c_adapter_demod); 16548c2ecf20Sopenharmony_ci if (ret) 16558c2ecf20Sopenharmony_ci goto err; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci return 0; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_cierr: 16608c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci return ret; 16638c2ecf20Sopenharmony_ci} 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_cistatic int it930x_tuner_detach(struct dvb_usb_adapter *adap) 16678c2ecf20Sopenharmony_ci{ 16688c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 16698c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 16708c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci if (adap->id == 1) { 16758c2ecf20Sopenharmony_ci if (state->i2c_client[3]) 16768c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 16778c2ecf20Sopenharmony_ci } else if (adap->id == 0) { 16788c2ecf20Sopenharmony_ci if (state->i2c_client[1]) 16798c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci return 0; 16838c2ecf20Sopenharmony_ci} 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_cistatic int af9035_tuner_detach(struct dvb_usb_adapter *adap) 16878c2ecf20Sopenharmony_ci{ 16888c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 16898c2ecf20Sopenharmony_ci struct dvb_usb_device *d = adap_to_d(adap); 16908c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci switch (state->af9033_config[adap->id].tuner) { 16958c2ecf20Sopenharmony_ci case AF9033_TUNER_TUA9001: 16968c2ecf20Sopenharmony_ci case AF9033_TUNER_FC2580: 16978c2ecf20Sopenharmony_ci if (adap->id == 1) { 16988c2ecf20Sopenharmony_ci if (state->i2c_client[3]) 16998c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 17008c2ecf20Sopenharmony_ci } else if (adap->id == 0) { 17018c2ecf20Sopenharmony_ci if (state->i2c_client[1]) 17028c2ecf20Sopenharmony_ci af9035_del_i2c_dev(d); 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci break; 17058c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 17068c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 17078c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 17088c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 17098c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 17108c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 17118c2ecf20Sopenharmony_ci { 17128c2ecf20Sopenharmony_ci struct platform_device *pdev; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci pdev = state->platform_device_tuner[adap->id]; 17158c2ecf20Sopenharmony_ci if (pdev) { 17168c2ecf20Sopenharmony_ci module_put(pdev->dev.driver->owner); 17178c2ecf20Sopenharmony_ci platform_device_unregister(pdev); 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci break; 17208c2ecf20Sopenharmony_ci } 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci return 0; 17248c2ecf20Sopenharmony_ci} 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_cistatic int af9035_init(struct dvb_usb_device *d) 17278c2ecf20Sopenharmony_ci{ 17288c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 17298c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 17308c2ecf20Sopenharmony_ci int ret, i; 17318c2ecf20Sopenharmony_ci u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; 17328c2ecf20Sopenharmony_ci u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 17338c2ecf20Sopenharmony_ci struct reg_val_mask tab[] = { 17348c2ecf20Sopenharmony_ci { 0x80f99d, 0x01, 0x01 }, 17358c2ecf20Sopenharmony_ci { 0x80f9a4, 0x01, 0x01 }, 17368c2ecf20Sopenharmony_ci { 0x00dd11, 0x00, 0x20 }, 17378c2ecf20Sopenharmony_ci { 0x00dd11, 0x00, 0x40 }, 17388c2ecf20Sopenharmony_ci { 0x00dd13, 0x00, 0x20 }, 17398c2ecf20Sopenharmony_ci { 0x00dd13, 0x00, 0x40 }, 17408c2ecf20Sopenharmony_ci { 0x00dd11, 0x20, 0x20 }, 17418c2ecf20Sopenharmony_ci { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 17428c2ecf20Sopenharmony_ci { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 17438c2ecf20Sopenharmony_ci { 0x00dd0c, packet_size, 0xff}, 17448c2ecf20Sopenharmony_ci { 0x00dd11, state->dual_mode << 6, 0x40 }, 17458c2ecf20Sopenharmony_ci { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 17468c2ecf20Sopenharmony_ci { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 17478c2ecf20Sopenharmony_ci { 0x00dd0d, packet_size, 0xff }, 17488c2ecf20Sopenharmony_ci { 0x80f9a3, state->dual_mode, 0x01 }, 17498c2ecf20Sopenharmony_ci { 0x80f9cd, state->dual_mode, 0x01 }, 17508c2ecf20Sopenharmony_ci { 0x80f99d, 0x00, 0x01 }, 17518c2ecf20Sopenharmony_ci { 0x80f9a4, 0x00, 0x01 }, 17528c2ecf20Sopenharmony_ci }; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n", 17558c2ecf20Sopenharmony_ci d->udev->speed, frame_size, packet_size); 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci /* init endpoints */ 17588c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tab); i++) { 17598c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, 17608c2ecf20Sopenharmony_ci tab[i].mask); 17618c2ecf20Sopenharmony_ci if (ret < 0) 17628c2ecf20Sopenharmony_ci goto err; 17638c2ecf20Sopenharmony_ci } 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci return 0; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_cierr: 17688c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci return ret; 17718c2ecf20Sopenharmony_ci} 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_cistatic int it930x_init(struct dvb_usb_device *d) 17748c2ecf20Sopenharmony_ci{ 17758c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 17768c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 17778c2ecf20Sopenharmony_ci int ret, i; 17788c2ecf20Sopenharmony_ci u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 816) * 188 / 4; 17798c2ecf20Sopenharmony_ci u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 17808c2ecf20Sopenharmony_ci struct reg_val_mask tab[] = { 17818c2ecf20Sopenharmony_ci { 0x00da1a, 0x00, 0x01 }, /* ignore_sync_byte */ 17828c2ecf20Sopenharmony_ci { 0x00f41f, 0x04, 0x04 }, /* dvbt_inten */ 17838c2ecf20Sopenharmony_ci { 0x00da10, 0x00, 0x01 }, /* mpeg_full_speed */ 17848c2ecf20Sopenharmony_ci { 0x00f41a, 0x01, 0x01 }, /* dvbt_en */ 17858c2ecf20Sopenharmony_ci { 0x00da1d, 0x01, 0x01 }, /* mp2_sw_rst, reset EP4 */ 17868c2ecf20Sopenharmony_ci { 0x00dd11, 0x00, 0x20 }, /* ep4_tx_en, disable EP4 */ 17878c2ecf20Sopenharmony_ci { 0x00dd13, 0x00, 0x20 }, /* ep4_tx_nak, disable EP4 NAK */ 17888c2ecf20Sopenharmony_ci { 0x00dd11, 0x20, 0x20 }, /* ep4_tx_en, enable EP4 */ 17898c2ecf20Sopenharmony_ci { 0x00dd11, 0x00, 0x40 }, /* ep5_tx_en, disable EP5 */ 17908c2ecf20Sopenharmony_ci { 0x00dd13, 0x00, 0x40 }, /* ep5_tx_nak, disable EP5 NAK */ 17918c2ecf20Sopenharmony_ci { 0x00dd11, state->dual_mode << 6, 0x40 }, /* enable EP5 */ 17928c2ecf20Sopenharmony_ci { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 17938c2ecf20Sopenharmony_ci { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 17948c2ecf20Sopenharmony_ci { 0x00dd0c, packet_size, 0xff}, 17958c2ecf20Sopenharmony_ci { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 17968c2ecf20Sopenharmony_ci { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 17978c2ecf20Sopenharmony_ci { 0x00dd0d, packet_size, 0xff }, 17988c2ecf20Sopenharmony_ci { 0x00da1d, 0x00, 0x01 }, /* mp2_sw_rst, disable */ 17998c2ecf20Sopenharmony_ci { 0x00d833, 0x01, 0xff }, /* slew rate ctrl: slew rate boosts */ 18008c2ecf20Sopenharmony_ci { 0x00d830, 0x00, 0xff }, /* Bit 0 of output driving control */ 18018c2ecf20Sopenharmony_ci { 0x00d831, 0x01, 0xff }, /* Bit 1 of output driving control */ 18028c2ecf20Sopenharmony_ci { 0x00d832, 0x00, 0xff }, /* Bit 2 of output driving control */ 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci /* suspend gpio1 for TS-C */ 18058c2ecf20Sopenharmony_ci { 0x00d8b0, 0x01, 0xff }, /* gpio1 */ 18068c2ecf20Sopenharmony_ci { 0x00d8b1, 0x01, 0xff }, /* gpio1 */ 18078c2ecf20Sopenharmony_ci { 0x00d8af, 0x00, 0xff }, /* gpio1 */ 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci /* suspend gpio7 for TS-D */ 18108c2ecf20Sopenharmony_ci { 0x00d8c4, 0x01, 0xff }, /* gpio7 */ 18118c2ecf20Sopenharmony_ci { 0x00d8c5, 0x01, 0xff }, /* gpio7 */ 18128c2ecf20Sopenharmony_ci { 0x00d8c3, 0x00, 0xff }, /* gpio7 */ 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci /* suspend gpio13 for TS-B */ 18158c2ecf20Sopenharmony_ci { 0x00d8dc, 0x01, 0xff }, /* gpio13 */ 18168c2ecf20Sopenharmony_ci { 0x00d8dd, 0x01, 0xff }, /* gpio13 */ 18178c2ecf20Sopenharmony_ci { 0x00d8db, 0x00, 0xff }, /* gpio13 */ 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci /* suspend gpio14 for TS-E */ 18208c2ecf20Sopenharmony_ci { 0x00d8e4, 0x01, 0xff }, /* gpio14 */ 18218c2ecf20Sopenharmony_ci { 0x00d8e5, 0x01, 0xff }, /* gpio14 */ 18228c2ecf20Sopenharmony_ci { 0x00d8e3, 0x00, 0xff }, /* gpio14 */ 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci /* suspend gpio15 for TS-A */ 18258c2ecf20Sopenharmony_ci { 0x00d8e8, 0x01, 0xff }, /* gpio15 */ 18268c2ecf20Sopenharmony_ci { 0x00d8e9, 0x01, 0xff }, /* gpio15 */ 18278c2ecf20Sopenharmony_ci { 0x00d8e7, 0x00, 0xff }, /* gpio15 */ 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci { 0x00da58, 0x00, 0x01 }, /* ts_in_src, serial */ 18308c2ecf20Sopenharmony_ci { 0x00da73, 0x01, 0xff }, /* ts0_aggre_mode */ 18318c2ecf20Sopenharmony_ci { 0x00da78, 0x47, 0xff }, /* ts0_sync_byte */ 18328c2ecf20Sopenharmony_ci { 0x00da4c, 0x01, 0xff }, /* ts0_en */ 18338c2ecf20Sopenharmony_ci { 0x00da5a, 0x1f, 0xff }, /* ts_fail_ignore */ 18348c2ecf20Sopenharmony_ci }; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n", 18378c2ecf20Sopenharmony_ci d->udev->speed, frame_size, packet_size); 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci /* init endpoints */ 18408c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tab); i++) { 18418c2ecf20Sopenharmony_ci ret = af9035_wr_reg_mask(d, tab[i].reg, 18428c2ecf20Sopenharmony_ci tab[i].val, tab[i].mask); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci if (ret < 0) 18458c2ecf20Sopenharmony_ci goto err; 18468c2ecf20Sopenharmony_ci } 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci return 0; 18498c2ecf20Sopenharmony_cierr: 18508c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci return ret; 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_RC_CORE) 18578c2ecf20Sopenharmony_cistatic int af9035_rc_query(struct dvb_usb_device *d) 18588c2ecf20Sopenharmony_ci{ 18598c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 18608c2ecf20Sopenharmony_ci int ret; 18618c2ecf20Sopenharmony_ci enum rc_proto proto; 18628c2ecf20Sopenharmony_ci u32 key; 18638c2ecf20Sopenharmony_ci u8 buf[4]; 18648c2ecf20Sopenharmony_ci struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf }; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci ret = af9035_ctrl_msg(d, &req); 18678c2ecf20Sopenharmony_ci if (ret == 1) 18688c2ecf20Sopenharmony_ci return 0; 18698c2ecf20Sopenharmony_ci else if (ret < 0) 18708c2ecf20Sopenharmony_ci goto err; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci if ((buf[2] + buf[3]) == 0xff) { 18738c2ecf20Sopenharmony_ci if ((buf[0] + buf[1]) == 0xff) { 18748c2ecf20Sopenharmony_ci /* NEC standard 16bit */ 18758c2ecf20Sopenharmony_ci key = RC_SCANCODE_NEC(buf[0], buf[2]); 18768c2ecf20Sopenharmony_ci proto = RC_PROTO_NEC; 18778c2ecf20Sopenharmony_ci } else { 18788c2ecf20Sopenharmony_ci /* NEC extended 24bit */ 18798c2ecf20Sopenharmony_ci key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]); 18808c2ecf20Sopenharmony_ci proto = RC_PROTO_NECX; 18818c2ecf20Sopenharmony_ci } 18828c2ecf20Sopenharmony_ci } else { 18838c2ecf20Sopenharmony_ci /* NEC full code 32bit */ 18848c2ecf20Sopenharmony_ci key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 | 18858c2ecf20Sopenharmony_ci buf[2] << 8 | buf[3]); 18868c2ecf20Sopenharmony_ci proto = RC_PROTO_NEC32; 18878c2ecf20Sopenharmony_ci } 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%*ph\n", 4, buf); 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci rc_keydown(d->rc_dev, proto, key, 0); 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci return 0; 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_cierr: 18968c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "failed=%d\n", ret); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci return ret; 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_cistatic int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 19028c2ecf20Sopenharmony_ci{ 19038c2ecf20Sopenharmony_ci struct state *state = d_to_priv(d); 19048c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "ir_mode=%02x ir_type=%02x\n", 19078c2ecf20Sopenharmony_ci state->ir_mode, state->ir_type); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci /* don't activate rc if in HID mode or if not available */ 19108c2ecf20Sopenharmony_ci if (state->ir_mode == 0x05) { 19118c2ecf20Sopenharmony_ci switch (state->ir_type) { 19128c2ecf20Sopenharmony_ci case 0: /* NEC */ 19138c2ecf20Sopenharmony_ci default: 19148c2ecf20Sopenharmony_ci rc->allowed_protos = RC_PROTO_BIT_NEC | 19158c2ecf20Sopenharmony_ci RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32; 19168c2ecf20Sopenharmony_ci break; 19178c2ecf20Sopenharmony_ci case 1: /* RC6 */ 19188c2ecf20Sopenharmony_ci rc->allowed_protos = RC_PROTO_BIT_RC6_MCE; 19198c2ecf20Sopenharmony_ci break; 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci rc->query = af9035_rc_query; 19238c2ecf20Sopenharmony_ci rc->interval = 500; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* load empty to enable rc */ 19268c2ecf20Sopenharmony_ci if (!rc->map_name) 19278c2ecf20Sopenharmony_ci rc->map_name = RC_MAP_EMPTY; 19288c2ecf20Sopenharmony_ci } 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci return 0; 19318c2ecf20Sopenharmony_ci} 19328c2ecf20Sopenharmony_ci#else 19338c2ecf20Sopenharmony_ci #define af9035_get_rc_config NULL 19348c2ecf20Sopenharmony_ci#endif 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_cistatic int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, 19378c2ecf20Sopenharmony_ci struct usb_data_stream_properties *stream) 19388c2ecf20Sopenharmony_ci{ 19398c2ecf20Sopenharmony_ci struct dvb_usb_device *d = fe_to_d(fe); 19408c2ecf20Sopenharmony_ci struct usb_interface *intf = d->intf; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "adap=%d\n", fe_to_adap(fe)->id); 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci if (d->udev->speed == USB_SPEED_FULL) 19458c2ecf20Sopenharmony_ci stream->u.bulk.buffersize = 5 * 188; 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci return 0; 19488c2ecf20Sopenharmony_ci} 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_cistatic int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) 19518c2ecf20Sopenharmony_ci{ 19528c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci return state->ops.pid_filter_ctrl(adap->fe[0], onoff); 19558c2ecf20Sopenharmony_ci} 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_cistatic int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, 19588c2ecf20Sopenharmony_ci int onoff) 19598c2ecf20Sopenharmony_ci{ 19608c2ecf20Sopenharmony_ci struct state *state = adap_to_priv(adap); 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci return state->ops.pid_filter(adap->fe[0], index, pid, onoff); 19638c2ecf20Sopenharmony_ci} 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_cistatic int af9035_probe(struct usb_interface *intf, 19668c2ecf20Sopenharmony_ci const struct usb_device_id *id) 19678c2ecf20Sopenharmony_ci{ 19688c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(intf); 19698c2ecf20Sopenharmony_ci char manufacturer[sizeof("Afatech")]; 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci memset(manufacturer, 0, sizeof(manufacturer)); 19728c2ecf20Sopenharmony_ci usb_string(udev, udev->descriptor.iManufacturer, 19738c2ecf20Sopenharmony_ci manufacturer, sizeof(manufacturer)); 19748c2ecf20Sopenharmony_ci /* 19758c2ecf20Sopenharmony_ci * There is two devices having same ID but different chipset. One uses 19768c2ecf20Sopenharmony_ci * AF9015 and the other IT9135 chipset. Only difference seen on lsusb 19778c2ecf20Sopenharmony_ci * is iManufacturer string. 19788c2ecf20Sopenharmony_ci * 19798c2ecf20Sopenharmony_ci * idVendor 0x0ccd TerraTec Electronic GmbH 19808c2ecf20Sopenharmony_ci * idProduct 0x0099 19818c2ecf20Sopenharmony_ci * bcdDevice 2.00 19828c2ecf20Sopenharmony_ci * iManufacturer 1 Afatech 19838c2ecf20Sopenharmony_ci * iProduct 2 DVB-T 2 19848c2ecf20Sopenharmony_ci * 19858c2ecf20Sopenharmony_ci * idVendor 0x0ccd TerraTec Electronic GmbH 19868c2ecf20Sopenharmony_ci * idProduct 0x0099 19878c2ecf20Sopenharmony_ci * bcdDevice 2.00 19888c2ecf20Sopenharmony_ci * iManufacturer 1 ITE Technologies, Inc. 19898c2ecf20Sopenharmony_ci * iProduct 2 DVB-T TV Stick 19908c2ecf20Sopenharmony_ci */ 19918c2ecf20Sopenharmony_ci if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && 19928c2ecf20Sopenharmony_ci (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { 19938c2ecf20Sopenharmony_ci if (!strcmp("Afatech", manufacturer)) { 19948c2ecf20Sopenharmony_ci dev_dbg(&udev->dev, "rejecting device\n"); 19958c2ecf20Sopenharmony_ci return -ENODEV; 19968c2ecf20Sopenharmony_ci } 19978c2ecf20Sopenharmony_ci } 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci return dvb_usbv2_probe(intf, id); 20008c2ecf20Sopenharmony_ci} 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci/* interface 0 is used by DVB-T receiver and 20038c2ecf20Sopenharmony_ci interface 1 is for remote controller (HID) */ 20048c2ecf20Sopenharmony_cistatic const struct dvb_usb_device_properties af9035_props = { 20058c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 20068c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 20078c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 20088c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct state), 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x02, 20118c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci .identify_state = af9035_identify_state, 20148c2ecf20Sopenharmony_ci .download_firmware = af9035_download_firmware, 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci .i2c_algo = &af9035_i2c_algo, 20178c2ecf20Sopenharmony_ci .read_config = af9035_read_config, 20188c2ecf20Sopenharmony_ci .frontend_attach = af9035_frontend_attach, 20198c2ecf20Sopenharmony_ci .frontend_detach = af9035_frontend_detach, 20208c2ecf20Sopenharmony_ci .tuner_attach = af9035_tuner_attach, 20218c2ecf20Sopenharmony_ci .tuner_detach = af9035_tuner_detach, 20228c2ecf20Sopenharmony_ci .init = af9035_init, 20238c2ecf20Sopenharmony_ci .get_rc_config = af9035_get_rc_config, 20248c2ecf20Sopenharmony_ci .get_stream_config = af9035_get_stream_config, 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci .get_adapter_count = af9035_get_adapter_count, 20278c2ecf20Sopenharmony_ci .adapter = { 20288c2ecf20Sopenharmony_ci { 20298c2ecf20Sopenharmony_ci .caps = DVB_USB_ADAP_HAS_PID_FILTER | 20308c2ecf20Sopenharmony_ci DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci .pid_filter_count = 32, 20338c2ecf20Sopenharmony_ci .pid_filter_ctrl = af9035_pid_filter_ctrl, 20348c2ecf20Sopenharmony_ci .pid_filter = af9035_pid_filter, 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), 20378c2ecf20Sopenharmony_ci }, { 20388c2ecf20Sopenharmony_ci .caps = DVB_USB_ADAP_HAS_PID_FILTER | 20398c2ecf20Sopenharmony_ci DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci .pid_filter_count = 32, 20428c2ecf20Sopenharmony_ci .pid_filter_ctrl = af9035_pid_filter_ctrl, 20438c2ecf20Sopenharmony_ci .pid_filter = af9035_pid_filter, 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), 20468c2ecf20Sopenharmony_ci }, 20478c2ecf20Sopenharmony_ci }, 20488c2ecf20Sopenharmony_ci}; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_cistatic const struct dvb_usb_device_properties it930x_props = { 20518c2ecf20Sopenharmony_ci .driver_name = KBUILD_MODNAME, 20528c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 20538c2ecf20Sopenharmony_ci .adapter_nr = adapter_nr, 20548c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct state), 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x02, 20578c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint_response = 0x81, 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci .identify_state = af9035_identify_state, 20608c2ecf20Sopenharmony_ci .download_firmware = af9035_download_firmware, 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci .i2c_algo = &af9035_i2c_algo, 20638c2ecf20Sopenharmony_ci .read_config = af9035_read_config, 20648c2ecf20Sopenharmony_ci .frontend_attach = it930x_frontend_attach, 20658c2ecf20Sopenharmony_ci .frontend_detach = af9035_frontend_detach, 20668c2ecf20Sopenharmony_ci .tuner_attach = it930x_tuner_attach, 20678c2ecf20Sopenharmony_ci .tuner_detach = it930x_tuner_detach, 20688c2ecf20Sopenharmony_ci .init = it930x_init, 20698c2ecf20Sopenharmony_ci .get_stream_config = af9035_get_stream_config, 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci .get_adapter_count = af9035_get_adapter_count, 20728c2ecf20Sopenharmony_ci .adapter = { 20738c2ecf20Sopenharmony_ci { 20748c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x84, 4, 816 * 188), 20758c2ecf20Sopenharmony_ci }, { 20768c2ecf20Sopenharmony_ci .stream = DVB_USB_STREAM_BULK(0x85, 4, 816 * 188), 20778c2ecf20Sopenharmony_ci }, 20788c2ecf20Sopenharmony_ci }, 20798c2ecf20Sopenharmony_ci}; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_cistatic const struct usb_device_id af9035_id_table[] = { 20828c2ecf20Sopenharmony_ci /* AF9035 devices */ 20838c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, 20848c2ecf20Sopenharmony_ci &af9035_props, "Afatech AF9035 reference design", NULL) }, 20858c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, 20868c2ecf20Sopenharmony_ci &af9035_props, "Afatech AF9035 reference design", NULL) }, 20878c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, 20888c2ecf20Sopenharmony_ci &af9035_props, "Afatech AF9035 reference design", NULL) }, 20898c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, 20908c2ecf20Sopenharmony_ci &af9035_props, "Afatech AF9035 reference design", NULL) }, 20918c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, 20928c2ecf20Sopenharmony_ci &af9035_props, "Afatech AF9035 reference design", NULL) }, 20938c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, 20948c2ecf20Sopenharmony_ci &af9035_props, "TerraTec Cinergy T Stick", NULL) }, 20958c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, 20968c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 20978c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, 20988c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 20998c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, 21008c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 21018c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, 21028c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 21038c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, 21048c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, 21058c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, 21068c2ecf20Sopenharmony_ci &af9035_props, "Asus U3100Mini Plus", NULL) }, 21078c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, 21088c2ecf20Sopenharmony_ci &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, 21098c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, 0x0337, 21108c2ecf20Sopenharmony_ci &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 21118c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_EVOLVEO_XTRATV_STICK, 21128c2ecf20Sopenharmony_ci &af9035_props, "EVOLVEO XtraTV stick", NULL) }, 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci /* IT9135 devices */ 21158c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, 21168c2ecf20Sopenharmony_ci &af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) }, 21178c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, 21188c2ecf20Sopenharmony_ci &af9035_props, "ITE 9135(9005) Generic", RC_MAP_IT913X_V2) }, 21198c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, 21208c2ecf20Sopenharmony_ci &af9035_props, "ITE 9135(9006) Generic", RC_MAP_IT913X_V1) }, 21218c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835, 21228c2ecf20Sopenharmony_ci &af9035_props, "Avermedia A835B(1835)", RC_MAP_IT913X_V2) }, 21238c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835, 21248c2ecf20Sopenharmony_ci &af9035_props, "Avermedia A835B(2835)", RC_MAP_IT913X_V2) }, 21258c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835, 21268c2ecf20Sopenharmony_ci &af9035_props, "Avermedia A835B(3835)", RC_MAP_IT913X_V2) }, 21278c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, 21288c2ecf20Sopenharmony_ci &af9035_props, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, 21298c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD110, 21308c2ecf20Sopenharmony_ci &af9035_props, "Avermedia AverTV Volar HD 2 (TD110)", RC_MAP_AVERMEDIA_RM_KS) }, 21318c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335, 21328c2ecf20Sopenharmony_ci &af9035_props, "Avermedia H335", RC_MAP_IT913X_V2) }, 21338c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, 21348c2ecf20Sopenharmony_ci &af9035_props, "Kworld UB499-2T T09", RC_MAP_IT913X_V1) }, 21358c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, 21368c2ecf20Sopenharmony_ci &af9035_props, "Sveon STV22 Dual DVB-T HDTV", 21378c2ecf20Sopenharmony_ci RC_MAP_IT913X_V1) }, 21388c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, 21398c2ecf20Sopenharmony_ci &af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2", 21408c2ecf20Sopenharmony_ci RC_MAP_IT913X_V1) }, 21418c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T1, 21428c2ecf20Sopenharmony_ci &af9035_props, "TerraTec T1", RC_MAP_IT913X_V1) }, 21438c2ecf20Sopenharmony_ci /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ 21448c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, 21458c2ecf20Sopenharmony_ci &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", 21468c2ecf20Sopenharmony_ci NULL) }, 21478c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, 21488c2ecf20Sopenharmony_ci &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, 21498c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, 21508c2ecf20Sopenharmony_ci &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, 21518c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E, 21528c2ecf20Sopenharmony_ci &af9035_props, "PCTV AndroiDTV (78e)", RC_MAP_IT913X_V1) }, 21538c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E, 21548c2ecf20Sopenharmony_ci &af9035_props, "PCTV microStick (79e)", RC_MAP_IT913X_V2) }, 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci /* IT930x devices */ 21578c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303, 21588c2ecf20Sopenharmony_ci &it930x_props, "ITE 9303 Generic", NULL) }, 21598c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD310, 21608c2ecf20Sopenharmony_ci &it930x_props, "AVerMedia TD310 DVB-T2", NULL) }, 21618c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x0100, 21628c2ecf20Sopenharmony_ci &it930x_props, "Logilink VG0022A", NULL) }, 21638c2ecf20Sopenharmony_ci { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_TC2_STICK, 21648c2ecf20Sopenharmony_ci &it930x_props, "TerraTec Cinergy TC2 Stick", NULL) }, 21658c2ecf20Sopenharmony_ci { } 21668c2ecf20Sopenharmony_ci}; 21678c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, af9035_id_table); 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_cistatic struct usb_driver af9035_usb_driver = { 21708c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 21718c2ecf20Sopenharmony_ci .id_table = af9035_id_table, 21728c2ecf20Sopenharmony_ci .probe = af9035_probe, 21738c2ecf20Sopenharmony_ci .disconnect = dvb_usbv2_disconnect, 21748c2ecf20Sopenharmony_ci .suspend = dvb_usbv2_suspend, 21758c2ecf20Sopenharmony_ci .resume = dvb_usbv2_resume, 21768c2ecf20Sopenharmony_ci .reset_resume = dvb_usbv2_reset_resume, 21778c2ecf20Sopenharmony_ci .no_dynamic_id = 1, 21788c2ecf20Sopenharmony_ci .soft_unbind = 1, 21798c2ecf20Sopenharmony_ci}; 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_cimodule_usb_driver(af9035_usb_driver); 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_ciMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 21848c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Afatech AF9035 driver"); 21858c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 21868c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); 21878c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); 21888c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); 21898c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9303); 2190