116216333SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2786baecfSMauro Carvalho Chehab /* 3786baecfSMauro Carvalho Chehab * Afatech AF9035 DVB USB driver 4786baecfSMauro Carvalho Chehab * 5786baecfSMauro Carvalho Chehab * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 6786baecfSMauro Carvalho Chehab * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 7786baecfSMauro Carvalho Chehab */ 8786baecfSMauro Carvalho Chehab 9786baecfSMauro Carvalho Chehab #include "af9035.h" 10786baecfSMauro Carvalho Chehab 117760e148SMauro Carvalho Chehab /* Max transfer size done by I2C transfer functions */ 127760e148SMauro Carvalho Chehab #define MAX_XFER_SIZE 64 137760e148SMauro Carvalho Chehab 14786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 15786baecfSMauro Carvalho Chehab 16786baecfSMauro Carvalho Chehab static u16 af9035_checksum(const u8 *buf, size_t len) 17786baecfSMauro Carvalho Chehab { 18786baecfSMauro Carvalho Chehab size_t i; 19786baecfSMauro Carvalho Chehab u16 checksum = 0; 20786baecfSMauro Carvalho Chehab 21786baecfSMauro Carvalho Chehab for (i = 1; i < len; i++) { 22786baecfSMauro Carvalho Chehab if (i % 2) 23786baecfSMauro Carvalho Chehab checksum += buf[i] << 8; 24786baecfSMauro Carvalho Chehab else 25786baecfSMauro Carvalho Chehab checksum += buf[i]; 26786baecfSMauro Carvalho Chehab } 27786baecfSMauro Carvalho Chehab checksum = ~checksum; 28786baecfSMauro Carvalho Chehab 29786baecfSMauro Carvalho Chehab return checksum; 30786baecfSMauro Carvalho Chehab } 31786baecfSMauro Carvalho Chehab 32786baecfSMauro Carvalho Chehab static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) 33786baecfSMauro Carvalho Chehab { 34786baecfSMauro Carvalho Chehab #define REQ_HDR_LEN 4 /* send header size */ 35786baecfSMauro Carvalho Chehab #define ACK_HDR_LEN 3 /* rece header size */ 36786baecfSMauro Carvalho Chehab #define CHECKSUM_LEN 2 37786baecfSMauro Carvalho Chehab #define USB_TIMEOUT 2000 38786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 392b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 40786baecfSMauro Carvalho Chehab int ret, wlen, rlen; 41786baecfSMauro Carvalho Chehab u16 checksum, tmp_checksum; 42786baecfSMauro Carvalho Chehab 433484d37aSAntti Palosaari mutex_lock(&d->usb_mutex); 443484d37aSAntti Palosaari 45786baecfSMauro Carvalho Chehab /* buffer overflow check */ 46786baecfSMauro Carvalho Chehab if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || 47786baecfSMauro Carvalho Chehab req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { 482b987ea7SAntti Palosaari dev_err(&intf->dev, "too much data wlen=%d rlen=%d\n", 492b987ea7SAntti Palosaari req->wlen, req->rlen); 503484d37aSAntti Palosaari ret = -EINVAL; 510170a39bSWei Yongjun goto exit; 52786baecfSMauro Carvalho Chehab } 53786baecfSMauro Carvalho Chehab 543484d37aSAntti Palosaari state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; 553484d37aSAntti Palosaari state->buf[1] = req->mbox; 563484d37aSAntti Palosaari state->buf[2] = req->cmd; 573484d37aSAntti Palosaari state->buf[3] = state->seq++; 583484d37aSAntti Palosaari memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen); 59786baecfSMauro Carvalho Chehab 60786baecfSMauro Carvalho Chehab wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; 61786baecfSMauro Carvalho Chehab rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; 62786baecfSMauro Carvalho Chehab 63786baecfSMauro Carvalho Chehab /* calc and add checksum */ 643484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, state->buf[0] - 1); 653484d37aSAntti Palosaari state->buf[state->buf[0] - 1] = (checksum >> 8); 663484d37aSAntti Palosaari state->buf[state->buf[0] - 0] = (checksum & 0xff); 67786baecfSMauro Carvalho Chehab 68786baecfSMauro Carvalho Chehab /* no ack for these packets */ 69786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 70786baecfSMauro Carvalho Chehab rlen = 0; 71786baecfSMauro Carvalho Chehab 723484d37aSAntti Palosaari ret = dvb_usbv2_generic_rw_locked(d, 733484d37aSAntti Palosaari state->buf, wlen, state->buf, rlen); 74786baecfSMauro Carvalho Chehab if (ret) 750170a39bSWei Yongjun goto exit; 76786baecfSMauro Carvalho Chehab 77786baecfSMauro Carvalho Chehab /* no ack for those packets */ 78786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 79786baecfSMauro Carvalho Chehab goto exit; 80786baecfSMauro Carvalho Chehab 81786baecfSMauro Carvalho Chehab /* verify checksum */ 823484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, rlen - 2); 833484d37aSAntti Palosaari tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; 84786baecfSMauro Carvalho Chehab if (tmp_checksum != checksum) { 852b987ea7SAntti Palosaari dev_err(&intf->dev, "command=%02x checksum mismatch (%04x != %04x)\n", 862b987ea7SAntti Palosaari req->cmd, tmp_checksum, checksum); 87786baecfSMauro Carvalho Chehab ret = -EIO; 880170a39bSWei Yongjun goto exit; 89786baecfSMauro Carvalho Chehab } 90786baecfSMauro Carvalho Chehab 91786baecfSMauro Carvalho Chehab /* check status */ 923484d37aSAntti Palosaari if (state->buf[2]) { 931bfd5294SAntti Palosaari /* fw returns status 1 when IR code was not received */ 940170a39bSWei Yongjun if (req->cmd == CMD_IR_GET || state->buf[2] == 1) { 950170a39bSWei Yongjun ret = 1; 960170a39bSWei Yongjun goto exit; 970170a39bSWei Yongjun } 981bfd5294SAntti Palosaari 992b987ea7SAntti Palosaari dev_dbg(&intf->dev, "command=%02x failed fw error=%d\n", 1002b987ea7SAntti Palosaari req->cmd, state->buf[2]); 101786baecfSMauro Carvalho Chehab ret = -EIO; 1020170a39bSWei Yongjun goto exit; 103786baecfSMauro Carvalho Chehab } 104786baecfSMauro Carvalho Chehab 105786baecfSMauro Carvalho Chehab /* read request, copy returned data to return buf */ 106786baecfSMauro Carvalho Chehab if (req->rlen) 1073484d37aSAntti Palosaari memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen); 108786baecfSMauro Carvalho Chehab exit: 1093484d37aSAntti Palosaari mutex_unlock(&d->usb_mutex); 110786baecfSMauro Carvalho Chehab return ret; 111786baecfSMauro Carvalho Chehab } 112786baecfSMauro Carvalho Chehab 113786baecfSMauro Carvalho Chehab /* write multiple registers */ 114786baecfSMauro Carvalho Chehab static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 115786baecfSMauro Carvalho Chehab { 1162b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1177760e148SMauro Carvalho Chehab u8 wbuf[MAX_XFER_SIZE]; 118786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 1199323297dSAntti Palosaari struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL }; 120786baecfSMauro Carvalho Chehab 1217760e148SMauro Carvalho Chehab if (6 + len > sizeof(wbuf)) { 1222b987ea7SAntti Palosaari dev_warn(&intf->dev, "i2c wr: len=%d is too big!\n", len); 1237760e148SMauro Carvalho Chehab return -EOPNOTSUPP; 1247760e148SMauro Carvalho Chehab } 1257760e148SMauro Carvalho Chehab 126786baecfSMauro Carvalho Chehab wbuf[0] = len; 127786baecfSMauro Carvalho Chehab wbuf[1] = 2; 128786baecfSMauro Carvalho Chehab wbuf[2] = 0; 129786baecfSMauro Carvalho Chehab wbuf[3] = 0; 130786baecfSMauro Carvalho Chehab wbuf[4] = (reg >> 8) & 0xff; 131786baecfSMauro Carvalho Chehab wbuf[5] = (reg >> 0) & 0xff; 132786baecfSMauro Carvalho Chehab memcpy(&wbuf[6], val, len); 133786baecfSMauro Carvalho Chehab 134786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 135786baecfSMauro Carvalho Chehab } 136786baecfSMauro Carvalho Chehab 137786baecfSMauro Carvalho Chehab /* read multiple registers */ 138786baecfSMauro Carvalho Chehab static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 139786baecfSMauro Carvalho Chehab { 140786baecfSMauro Carvalho Chehab u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; 141786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 142786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; 143786baecfSMauro Carvalho Chehab 144786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 145786baecfSMauro Carvalho Chehab } 146786baecfSMauro Carvalho Chehab 147786baecfSMauro Carvalho Chehab /* write single register */ 148786baecfSMauro Carvalho Chehab static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) 149786baecfSMauro Carvalho Chehab { 150786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 151786baecfSMauro Carvalho Chehab } 152786baecfSMauro Carvalho Chehab 153786baecfSMauro Carvalho Chehab /* read single register */ 154786baecfSMauro Carvalho Chehab static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) 155786baecfSMauro Carvalho Chehab { 156786baecfSMauro Carvalho Chehab return af9035_rd_regs(d, reg, val, 1); 157786baecfSMauro Carvalho Chehab } 158786baecfSMauro Carvalho Chehab 159786baecfSMauro Carvalho Chehab /* write single register with mask */ 160786baecfSMauro Carvalho Chehab static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, 161786baecfSMauro Carvalho Chehab u8 mask) 162786baecfSMauro Carvalho Chehab { 163786baecfSMauro Carvalho Chehab int ret; 164786baecfSMauro Carvalho Chehab u8 tmp; 165786baecfSMauro Carvalho Chehab 166786baecfSMauro Carvalho Chehab /* no need for read if whole reg is written */ 167786baecfSMauro Carvalho Chehab if (mask != 0xff) { 168786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &tmp, 1); 169786baecfSMauro Carvalho Chehab if (ret) 170786baecfSMauro Carvalho Chehab return ret; 171786baecfSMauro Carvalho Chehab 172786baecfSMauro Carvalho Chehab val &= mask; 173786baecfSMauro Carvalho Chehab tmp &= ~mask; 174786baecfSMauro Carvalho Chehab val |= tmp; 175786baecfSMauro Carvalho Chehab } 176786baecfSMauro Carvalho Chehab 177786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 178786baecfSMauro Carvalho Chehab } 179786baecfSMauro Carvalho Chehab 180a1ecf3c4SKees Cook static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type, 181a1ecf3c4SKees Cook u8 addr, void *platform_data, struct i2c_adapter *adapter) 1823b2a5e8cSAntti Palosaari { 1833b2a5e8cSAntti Palosaari int ret, num; 1843b2a5e8cSAntti Palosaari struct state *state = d_to_priv(d); 1852b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1863b2a5e8cSAntti Palosaari struct i2c_client *client; 1873b2a5e8cSAntti Palosaari struct i2c_board_info board_info = { 1883b2a5e8cSAntti Palosaari .addr = addr, 1893b2a5e8cSAntti Palosaari .platform_data = platform_data, 1903b2a5e8cSAntti Palosaari }; 1913b2a5e8cSAntti Palosaari 192c0decac1SMauro Carvalho Chehab strscpy(board_info.type, type, I2C_NAME_SIZE); 1933b2a5e8cSAntti Palosaari 1943b2a5e8cSAntti Palosaari /* find first free client */ 1953b2a5e8cSAntti Palosaari for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) { 1963b2a5e8cSAntti Palosaari if (state->i2c_client[num] == NULL) 1973b2a5e8cSAntti Palosaari break; 1983b2a5e8cSAntti Palosaari } 1993b2a5e8cSAntti Palosaari 2002b987ea7SAntti Palosaari dev_dbg(&intf->dev, "num=%d\n", num); 2013b2a5e8cSAntti Palosaari 2023b2a5e8cSAntti Palosaari if (num == AF9035_I2C_CLIENT_MAX) { 2032b987ea7SAntti Palosaari dev_err(&intf->dev, "I2C client out of index\n"); 2043b2a5e8cSAntti Palosaari ret = -ENODEV; 2053b2a5e8cSAntti Palosaari goto err; 2063b2a5e8cSAntti Palosaari } 2073b2a5e8cSAntti Palosaari 208a1ecf3c4SKees Cook request_module("%s", board_info.type); 2093b2a5e8cSAntti Palosaari 2103b2a5e8cSAntti Palosaari /* register I2C device */ 2117930196aSWolfram Sang client = i2c_new_client_device(adapter, &board_info); 2127930196aSWolfram Sang if (!i2c_client_has_driver(client)) { 2133b2a5e8cSAntti Palosaari ret = -ENODEV; 2143b2a5e8cSAntti Palosaari goto err; 2153b2a5e8cSAntti Palosaari } 2163b2a5e8cSAntti Palosaari 2173b2a5e8cSAntti Palosaari /* increase I2C driver usage count */ 2183b2a5e8cSAntti Palosaari if (!try_module_get(client->dev.driver->owner)) { 2193b2a5e8cSAntti Palosaari i2c_unregister_device(client); 2203b2a5e8cSAntti Palosaari ret = -ENODEV; 2213b2a5e8cSAntti Palosaari goto err; 2223b2a5e8cSAntti Palosaari } 2233b2a5e8cSAntti Palosaari 2243b2a5e8cSAntti Palosaari state->i2c_client[num] = client; 2253b2a5e8cSAntti Palosaari return 0; 2263b2a5e8cSAntti Palosaari err: 2272b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 2283b2a5e8cSAntti Palosaari return ret; 2293b2a5e8cSAntti Palosaari } 2303b2a5e8cSAntti Palosaari 2313b2a5e8cSAntti Palosaari static void af9035_del_i2c_dev(struct dvb_usb_device *d) 2323b2a5e8cSAntti Palosaari { 2333b2a5e8cSAntti Palosaari int num; 2343b2a5e8cSAntti Palosaari struct state *state = d_to_priv(d); 2352b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 2363b2a5e8cSAntti Palosaari struct i2c_client *client; 2373b2a5e8cSAntti Palosaari 2383b2a5e8cSAntti Palosaari /* find last used client */ 2393b2a5e8cSAntti Palosaari num = AF9035_I2C_CLIENT_MAX; 2403b2a5e8cSAntti Palosaari while (num--) { 2413b2a5e8cSAntti Palosaari if (state->i2c_client[num] != NULL) 2423b2a5e8cSAntti Palosaari break; 2433b2a5e8cSAntti Palosaari } 2443b2a5e8cSAntti Palosaari 2452b987ea7SAntti Palosaari dev_dbg(&intf->dev, "num=%d\n", num); 2463b2a5e8cSAntti Palosaari 2473b2a5e8cSAntti Palosaari if (num == -1) { 2482b987ea7SAntti Palosaari dev_err(&intf->dev, "I2C client out of index\n"); 2493b2a5e8cSAntti Palosaari goto err; 2503b2a5e8cSAntti Palosaari } 2513b2a5e8cSAntti Palosaari 2523b2a5e8cSAntti Palosaari client = state->i2c_client[num]; 2533b2a5e8cSAntti Palosaari 2543b2a5e8cSAntti Palosaari /* decrease I2C driver usage count */ 2553b2a5e8cSAntti Palosaari module_put(client->dev.driver->owner); 2563b2a5e8cSAntti Palosaari 2573b2a5e8cSAntti Palosaari /* unregister I2C device */ 2583b2a5e8cSAntti Palosaari i2c_unregister_device(client); 2593b2a5e8cSAntti Palosaari 2603b2a5e8cSAntti Palosaari state->i2c_client[num] = NULL; 2613b2a5e8cSAntti Palosaari return; 2623b2a5e8cSAntti Palosaari err: 2632b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed\n"); 2643b2a5e8cSAntti Palosaari } 2653b2a5e8cSAntti Palosaari 266786baecfSMauro Carvalho Chehab static int af9035_i2c_master_xfer(struct i2c_adapter *adap, 267786baecfSMauro Carvalho Chehab struct i2c_msg msg[], int num) 268786baecfSMauro Carvalho Chehab { 269786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 270786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 271786baecfSMauro Carvalho Chehab int ret; 272786baecfSMauro Carvalho Chehab 273786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 274786baecfSMauro Carvalho Chehab return -EAGAIN; 275786baecfSMauro Carvalho Chehab 276786baecfSMauro Carvalho Chehab /* 2775b556084SOlli Salonen * AF9035 I2C sub header is 5 bytes long. Meaning of those bytes are: 278786baecfSMauro Carvalho Chehab * 0: data len 279786baecfSMauro Carvalho Chehab * 1: I2C addr << 1 280786baecfSMauro Carvalho Chehab * 2: reg addr len 281786baecfSMauro Carvalho Chehab * byte 3 and 4 can be used as reg addr 282786baecfSMauro Carvalho Chehab * 3: reg addr MSB 283786baecfSMauro Carvalho Chehab * used when reg addr len is set to 2 284786baecfSMauro Carvalho Chehab * 4: reg addr LSB 285786baecfSMauro Carvalho Chehab * used when reg addr len is set to 1 or 2 286786baecfSMauro Carvalho Chehab * 287786baecfSMauro Carvalho Chehab * For the simplify we do not use register addr at all. 288786baecfSMauro Carvalho Chehab * NOTE: As a firmware knows tuner type there is very small possibility 289786baecfSMauro Carvalho Chehab * there could be some tuner I2C hacks done by firmware and this may 290786baecfSMauro Carvalho Chehab * lead problems if firmware expects those bytes are used. 291f5b00a76SAntti Palosaari * 292f5b00a76SAntti Palosaari * TODO: Here is few hacks. AF9035 chip integrates AF9033 demodulator. 293f5b00a76SAntti Palosaari * IT9135 chip integrates AF9033 demodulator and RF tuner. For dual 294f5b00a76SAntti Palosaari * tuner devices, there is also external AF9033 demodulator connected 295f5b00a76SAntti Palosaari * via external I2C bus. All AF9033 demod I2C traffic, both single and 296f5b00a76SAntti Palosaari * dual tuner configuration, is covered by firmware - actual USB IO 297f5b00a76SAntti Palosaari * looks just like a memory access. 298f5b00a76SAntti Palosaari * In case of IT913x chip, there is own tuner driver. It is implemented 299f5b00a76SAntti Palosaari * currently as a I2C driver, even tuner IP block is likely build 300f5b00a76SAntti Palosaari * directly into the demodulator memory space and there is no own I2C 301f5b00a76SAntti Palosaari * bus. I2C subsystem does not allow register multiple devices to same 302f5b00a76SAntti Palosaari * bus, having same slave address. Due to that we reuse demod address, 303f5b00a76SAntti Palosaari * shifted by one bit, on that case. 3045b556084SOlli Salonen * 3055b556084SOlli Salonen * For IT930x we use a different command and the sub header is 3065b556084SOlli Salonen * different as well: 3075b556084SOlli Salonen * 0: data len 3085b556084SOlli Salonen * 1: I2C bus (0x03 seems to be only value used) 3095b556084SOlli Salonen * 2: I2C addr << 1 310786baecfSMauro Carvalho Chehab */ 311ee36381eSAntti Palosaari #define AF9035_IS_I2C_XFER_WRITE_READ(_msg, _num) \ 312ee36381eSAntti Palosaari (_num == 2 && !(_msg[0].flags & I2C_M_RD) && (_msg[1].flags & I2C_M_RD)) 313ee36381eSAntti Palosaari #define AF9035_IS_I2C_XFER_WRITE(_msg, _num) \ 314ee36381eSAntti Palosaari (_num == 1 && !(_msg[0].flags & I2C_M_RD)) 315ee36381eSAntti Palosaari #define AF9035_IS_I2C_XFER_READ(_msg, _num) \ 316ee36381eSAntti Palosaari (_num == 1 && (_msg[0].flags & I2C_M_RD)) 317ee36381eSAntti Palosaari 318ee36381eSAntti Palosaari if (AF9035_IS_I2C_XFER_WRITE_READ(msg, num)) { 319786baecfSMauro Carvalho Chehab if (msg[0].len > 40 || msg[1].len > 40) { 320786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 321786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 322a781edd1SAntti Palosaari } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || 32335ef193bSAntti Palosaari (msg[0].addr == state->af9033_i2c_addr[1])) { 324bf97b637SAntti Palosaari /* demod access via firmware interface */ 325786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 326786baecfSMauro Carvalho Chehab msg[0].buf[2]; 327bf97b637SAntti Palosaari 32835ef193bSAntti Palosaari if (msg[0].addr == state->af9033_i2c_addr[1]) 3299805992fSJose Alberto Reguero reg |= 0x100000; 330bf97b637SAntti Palosaari 331786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &msg[1].buf[0], 332786baecfSMauro Carvalho Chehab msg[1].len); 3331882f59fSAlessandro Radicati } else if (state->no_read) { 3341882f59fSAlessandro Radicati memset(msg[1].buf, 0, msg[1].len); 3351882f59fSAlessandro Radicati ret = 0; 336786baecfSMauro Carvalho Chehab } else { 337ee36381eSAntti Palosaari /* I2C write + read */ 3387760e148SMauro Carvalho Chehab u8 buf[MAX_XFER_SIZE]; 3399323297dSAntti Palosaari struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len, 340786baecfSMauro Carvalho Chehab buf, msg[1].len, msg[1].buf }; 3417760e148SMauro Carvalho Chehab 3425b556084SOlli Salonen if (state->chip_type == 0x9306) { 3435b556084SOlli Salonen req.cmd = CMD_GENERIC_I2C_RD; 3445b556084SOlli Salonen req.wlen = 3 + msg[0].len; 3455b556084SOlli Salonen } 3469805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 3475b556084SOlli Salonen 348786baecfSMauro Carvalho Chehab buf[0] = msg[1].len; 3495b556084SOlli Salonen if (state->chip_type == 0x9306) { 3505b556084SOlli Salonen buf[1] = 0x03; /* I2C bus */ 3515b556084SOlli Salonen buf[2] = msg[0].addr << 1; 3525b556084SOlli Salonen memcpy(&buf[3], msg[0].buf, msg[0].len); 3535b556084SOlli Salonen } else { 354bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 355786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 356786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 35757f1c053SAlessandro Radicati 35857f1c053SAlessandro Radicati /* Keep prev behavior for write req len > 2*/ 35957f1c053SAlessandro Radicati if (msg[0].len > 2) { 36057f1c053SAlessandro Radicati buf[2] = 0x00; /* reg addr len */ 361786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 36257f1c053SAlessandro Radicati 36357f1c053SAlessandro Radicati /* Use reg addr fields if write req len <= 2 */ 36457f1c053SAlessandro Radicati } else { 36557f1c053SAlessandro Radicati req.wlen = 5; 36657f1c053SAlessandro Radicati buf[2] = msg[0].len; 36757f1c053SAlessandro Radicati if (msg[0].len == 2) { 36857f1c053SAlessandro Radicati buf[3] = msg[0].buf[0]; 36957f1c053SAlessandro Radicati buf[4] = msg[0].buf[1]; 37057f1c053SAlessandro Radicati } else if (msg[0].len == 1) { 37157f1c053SAlessandro Radicati buf[4] = msg[0].buf[0]; 37257f1c053SAlessandro Radicati } 37357f1c053SAlessandro Radicati } 3745b556084SOlli Salonen } 375786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 376786baecfSMauro Carvalho Chehab } 377ee36381eSAntti Palosaari } else if (AF9035_IS_I2C_XFER_WRITE(msg, num)) { 378786baecfSMauro Carvalho Chehab if (msg[0].len > 40) { 379786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 380786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 381a781edd1SAntti Palosaari } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || 38235ef193bSAntti Palosaari (msg[0].addr == state->af9033_i2c_addr[1])) { 383bf97b637SAntti Palosaari /* demod access via firmware interface */ 384786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 385786baecfSMauro Carvalho Chehab msg[0].buf[2]; 386bf97b637SAntti Palosaari 38735ef193bSAntti Palosaari if (msg[0].addr == state->af9033_i2c_addr[1]) 3889805992fSJose Alberto Reguero reg |= 0x100000; 389bf97b637SAntti Palosaari 390312f73b6SJozef Balga ret = (msg[0].len >= 3) ? af9035_wr_regs(d, reg, 391312f73b6SJozef Balga &msg[0].buf[3], 392312f73b6SJozef Balga msg[0].len - 3) 393312f73b6SJozef Balga : -EOPNOTSUPP; 394786baecfSMauro Carvalho Chehab } else { 395ee36381eSAntti Palosaari /* I2C write */ 3967760e148SMauro Carvalho Chehab u8 buf[MAX_XFER_SIZE]; 3979323297dSAntti Palosaari struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len, 3989323297dSAntti Palosaari buf, 0, NULL }; 3997760e148SMauro Carvalho Chehab 4005b556084SOlli Salonen if (state->chip_type == 0x9306) { 4015b556084SOlli Salonen req.cmd = CMD_GENERIC_I2C_WR; 4025b556084SOlli Salonen req.wlen = 3 + msg[0].len; 4035b556084SOlli Salonen } 4045b556084SOlli Salonen 4059805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 406786baecfSMauro Carvalho Chehab buf[0] = msg[0].len; 4075b556084SOlli Salonen if (state->chip_type == 0x9306) { 4085b556084SOlli Salonen buf[1] = 0x03; /* I2C bus */ 4095b556084SOlli Salonen buf[2] = msg[0].addr << 1; 4105b556084SOlli Salonen memcpy(&buf[3], msg[0].buf, msg[0].len); 4115b556084SOlli Salonen } else { 412bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 413786baecfSMauro Carvalho Chehab buf[2] = 0x00; /* reg addr len */ 414786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 415786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 416786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 4175b556084SOlli Salonen } 418786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 419786baecfSMauro Carvalho Chehab } 420ee36381eSAntti Palosaari } else if (AF9035_IS_I2C_XFER_READ(msg, num)) { 4213b98c347SAntti Palosaari if (msg[0].len > 40) { 4223b98c347SAntti Palosaari /* TODO: correct limits > 40 */ 4233b98c347SAntti Palosaari ret = -EOPNOTSUPP; 4241882f59fSAlessandro Radicati } else if (state->no_read) { 4251882f59fSAlessandro Radicati memset(msg[0].buf, 0, msg[0].len); 4261882f59fSAlessandro Radicati ret = 0; 4273b98c347SAntti Palosaari } else { 428ee36381eSAntti Palosaari /* I2C read */ 4293b98c347SAntti Palosaari u8 buf[5]; 4303b98c347SAntti Palosaari struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), 4313b98c347SAntti Palosaari buf, msg[0].len, msg[0].buf }; 4325b556084SOlli Salonen 4335b556084SOlli Salonen if (state->chip_type == 0x9306) { 4345b556084SOlli Salonen req.cmd = CMD_GENERIC_I2C_RD; 4355b556084SOlli Salonen req.wlen = 3; 4365b556084SOlli Salonen } 4373b98c347SAntti Palosaari req.mbox |= ((msg[0].addr & 0x80) >> 3); 4383b98c347SAntti Palosaari buf[0] = msg[0].len; 4395b556084SOlli Salonen if (state->chip_type == 0x9306) { 4405b556084SOlli Salonen buf[1] = 0x03; /* I2C bus */ 4415b556084SOlli Salonen buf[2] = msg[0].addr << 1; 4425b556084SOlli Salonen } else { 4433b98c347SAntti Palosaari buf[1] = msg[0].addr << 1; 4443b98c347SAntti Palosaari buf[2] = 0x00; /* reg addr len */ 4453b98c347SAntti Palosaari buf[3] = 0x00; /* reg addr MSB */ 4463b98c347SAntti Palosaari buf[4] = 0x00; /* reg addr LSB */ 4475b556084SOlli Salonen } 4483b98c347SAntti Palosaari ret = af9035_ctrl_msg(d, &req); 4493b98c347SAntti Palosaari } 450786baecfSMauro Carvalho Chehab } else { 451786baecfSMauro Carvalho Chehab /* 4523b98c347SAntti Palosaari * We support only three kind of I2C transactions: 453ee36381eSAntti Palosaari * 1) 1 x write + 1 x read (repeated start) 454786baecfSMauro Carvalho Chehab * 2) 1 x write 4553b98c347SAntti Palosaari * 3) 1 x read 456786baecfSMauro Carvalho Chehab */ 457786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 458786baecfSMauro Carvalho Chehab } 459786baecfSMauro Carvalho Chehab 460786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 461786baecfSMauro Carvalho Chehab 462786baecfSMauro Carvalho Chehab if (ret < 0) 463786baecfSMauro Carvalho Chehab return ret; 464786baecfSMauro Carvalho Chehab else 465786baecfSMauro Carvalho Chehab return num; 466786baecfSMauro Carvalho Chehab } 467786baecfSMauro Carvalho Chehab 468786baecfSMauro Carvalho Chehab static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) 469786baecfSMauro Carvalho Chehab { 470786baecfSMauro Carvalho Chehab return I2C_FUNC_I2C; 471786baecfSMauro Carvalho Chehab } 472786baecfSMauro Carvalho Chehab 473786baecfSMauro Carvalho Chehab static struct i2c_algorithm af9035_i2c_algo = { 474786baecfSMauro Carvalho Chehab .master_xfer = af9035_i2c_master_xfer, 475786baecfSMauro Carvalho Chehab .functionality = af9035_i2c_functionality, 476786baecfSMauro Carvalho Chehab }; 477786baecfSMauro Carvalho Chehab 478786baecfSMauro Carvalho Chehab static int af9035_identify_state(struct dvb_usb_device *d, const char **name) 479786baecfSMauro Carvalho Chehab { 48074c1883aSAntti Palosaari struct state *state = d_to_priv(d); 4812b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 48209bfd96cSAntti Palosaari int ret, i, ts_mode_invalid; 48309bfd96cSAntti Palosaari unsigned int utmp, eeprom_addr; 4849e422f64SStefan Pöschel u8 tmp; 485786baecfSMauro Carvalho Chehab u8 wbuf[1] = { 1 }; 486786baecfSMauro Carvalho Chehab u8 rbuf[4]; 487786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, 488786baecfSMauro Carvalho Chehab sizeof(rbuf), rbuf }; 489786baecfSMauro Carvalho Chehab 49074c1883aSAntti Palosaari ret = af9035_rd_regs(d, 0x1222, rbuf, 3); 49174c1883aSAntti Palosaari if (ret < 0) 49274c1883aSAntti Palosaari goto err; 49374c1883aSAntti Palosaari 49474c1883aSAntti Palosaari state->chip_version = rbuf[0]; 49574c1883aSAntti Palosaari state->chip_type = rbuf[2] << 8 | rbuf[1] << 0; 49674c1883aSAntti Palosaari 49774c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x384f, &state->prechip_version); 49874c1883aSAntti Palosaari if (ret < 0) 49974c1883aSAntti Palosaari goto err; 50074c1883aSAntti Palosaari 5012b987ea7SAntti Palosaari dev_info(&intf->dev, "prechip_version=%02x chip_version=%02x chip_type=%04x\n", 5022b987ea7SAntti Palosaari state->prechip_version, state->chip_version, state->chip_type); 50374c1883aSAntti Palosaari 50474c1883aSAntti Palosaari if (state->chip_type == 0x9135) { 50509bfd96cSAntti Palosaari if (state->chip_version == 0x02) { 50674c1883aSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V2; 50709bfd96cSAntti Palosaari utmp = 0x00461d; 50874c1883aSAntti Palosaari } else { 50909bfd96cSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V1; 51009bfd96cSAntti Palosaari utmp = 0x00461b; 51174c1883aSAntti Palosaari } 51274c1883aSAntti Palosaari 51309bfd96cSAntti Palosaari /* Check if eeprom exists */ 51409bfd96cSAntti Palosaari ret = af9035_rd_reg(d, utmp, &tmp); 5159e422f64SStefan Pöschel if (ret < 0) 5169e422f64SStefan Pöschel goto err; 5179e422f64SStefan Pöschel 51809bfd96cSAntti Palosaari if (tmp == 0x00) { 51909bfd96cSAntti Palosaari dev_dbg(&intf->dev, "no eeprom\n"); 52009bfd96cSAntti Palosaari state->no_eeprom = true; 52109bfd96cSAntti Palosaari goto check_firmware_status; 52209bfd96cSAntti Palosaari } 52309bfd96cSAntti Palosaari 52409bfd96cSAntti Palosaari eeprom_addr = EEPROM_BASE_IT9135; 52509bfd96cSAntti Palosaari } else if (state->chip_type == 0x9306) { 52609bfd96cSAntti Palosaari *name = AF9035_FIRMWARE_IT9303; 52709bfd96cSAntti Palosaari state->no_eeprom = true; 52809bfd96cSAntti Palosaari goto check_firmware_status; 52909bfd96cSAntti Palosaari } else { 53009bfd96cSAntti Palosaari *name = AF9035_FIRMWARE_AF9035; 53109bfd96cSAntti Palosaari eeprom_addr = EEPROM_BASE_AF9035; 53209bfd96cSAntti Palosaari } 53309bfd96cSAntti Palosaari 53409bfd96cSAntti Palosaari /* Read and store eeprom */ 53509bfd96cSAntti Palosaari for (i = 0; i < 256; i += 32) { 53609bfd96cSAntti Palosaari ret = af9035_rd_regs(d, eeprom_addr + i, &state->eeprom[i], 32); 53709bfd96cSAntti Palosaari if (ret < 0) 53809bfd96cSAntti Palosaari goto err; 53909bfd96cSAntti Palosaari } 54009bfd96cSAntti Palosaari 54109bfd96cSAntti Palosaari dev_dbg(&intf->dev, "eeprom dump:\n"); 54209bfd96cSAntti Palosaari for (i = 0; i < 256; i += 16) 54309bfd96cSAntti Palosaari dev_dbg(&intf->dev, "%*ph\n", 16, &state->eeprom[i]); 54409bfd96cSAntti Palosaari 54509bfd96cSAntti Palosaari /* check for dual tuner mode */ 54609bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_TS_MODE]; 5479e422f64SStefan Pöschel ts_mode_invalid = 0; 5489e422f64SStefan Pöschel switch (tmp) { 5499e422f64SStefan Pöschel case 0: 5509e422f64SStefan Pöschel break; 5519e422f64SStefan Pöschel case 1: 5529e422f64SStefan Pöschel case 3: 5539e422f64SStefan Pöschel state->dual_mode = true; 5549e422f64SStefan Pöschel break; 5559e422f64SStefan Pöschel case 5: 5569e422f64SStefan Pöschel if (state->chip_type != 0x9135 && state->chip_type != 0x9306) 5579e422f64SStefan Pöschel state->dual_mode = true; /* AF9035 */ 5589e422f64SStefan Pöschel else 5599e422f64SStefan Pöschel ts_mode_invalid = 1; 5609e422f64SStefan Pöschel break; 5619e422f64SStefan Pöschel default: 5629e422f64SStefan Pöschel ts_mode_invalid = 1; 5639e422f64SStefan Pöschel } 5649e422f64SStefan Pöschel 5659e422f64SStefan Pöschel dev_dbg(&intf->dev, "ts mode=%d dual mode=%d\n", tmp, state->dual_mode); 5669e422f64SStefan Pöschel 5679e422f64SStefan Pöschel if (ts_mode_invalid) 5689e422f64SStefan Pöschel dev_info(&intf->dev, "ts mode=%d not supported, defaulting to single tuner mode!", tmp); 5699e422f64SStefan Pöschel 57009bfd96cSAntti Palosaari check_firmware_status: 571786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 572786baecfSMauro Carvalho Chehab if (ret < 0) 573786baecfSMauro Carvalho Chehab goto err; 574786baecfSMauro Carvalho Chehab 5752b987ea7SAntti Palosaari dev_dbg(&intf->dev, "reply=%*ph\n", 4, rbuf); 576786baecfSMauro Carvalho Chehab if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) 577786baecfSMauro Carvalho Chehab ret = WARM; 578786baecfSMauro Carvalho Chehab else 579786baecfSMauro Carvalho Chehab ret = COLD; 580786baecfSMauro Carvalho Chehab 581786baecfSMauro Carvalho Chehab return ret; 582786baecfSMauro Carvalho Chehab 583786baecfSMauro Carvalho Chehab err: 5842b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 585786baecfSMauro Carvalho Chehab 586786baecfSMauro Carvalho Chehab return ret; 587786baecfSMauro Carvalho Chehab } 588786baecfSMauro Carvalho Chehab 5898229da50SAntti Palosaari static int af9035_download_firmware_old(struct dvb_usb_device *d, 590786baecfSMauro Carvalho Chehab const struct firmware *fw) 591786baecfSMauro Carvalho Chehab { 5922b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 593786baecfSMauro Carvalho Chehab int ret, i, j, len; 594786baecfSMauro Carvalho Chehab u8 wbuf[1]; 595786baecfSMauro Carvalho Chehab struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 596786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; 597df8f1be1SAntti Palosaari u8 hdr_core; 598786baecfSMauro Carvalho Chehab u16 hdr_addr, hdr_data_len, hdr_checksum; 599786baecfSMauro Carvalho Chehab #define MAX_DATA 58 600786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 601786baecfSMauro Carvalho Chehab 602786baecfSMauro Carvalho Chehab /* 603786baecfSMauro Carvalho Chehab * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! 604786baecfSMauro Carvalho Chehab * 605786baecfSMauro Carvalho Chehab * byte 0: MCS 51 core 606786baecfSMauro Carvalho Chehab * There are two inside the AF9035 (1=Link and 2=OFDM) with separate 607786baecfSMauro Carvalho Chehab * address spaces 608786baecfSMauro Carvalho Chehab * byte 1-2: Big endian destination address 609786baecfSMauro Carvalho Chehab * byte 3-4: Big endian number of data bytes following the header 610786baecfSMauro Carvalho Chehab * byte 5-6: Big endian header checksum, apparently ignored by the chip 611786baecfSMauro Carvalho Chehab * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) 612786baecfSMauro Carvalho Chehab */ 613786baecfSMauro Carvalho Chehab 614786baecfSMauro Carvalho Chehab for (i = fw->size; i > HDR_SIZE;) { 615786baecfSMauro Carvalho Chehab hdr_core = fw->data[fw->size - i + 0]; 616786baecfSMauro Carvalho Chehab hdr_addr = fw->data[fw->size - i + 1] << 8; 617786baecfSMauro Carvalho Chehab hdr_addr |= fw->data[fw->size - i + 2] << 0; 618786baecfSMauro Carvalho Chehab hdr_data_len = fw->data[fw->size - i + 3] << 8; 619786baecfSMauro Carvalho Chehab hdr_data_len |= fw->data[fw->size - i + 4] << 0; 620786baecfSMauro Carvalho Chehab hdr_checksum = fw->data[fw->size - i + 5] << 8; 621786baecfSMauro Carvalho Chehab hdr_checksum |= fw->data[fw->size - i + 6] << 0; 622786baecfSMauro Carvalho Chehab 6232b987ea7SAntti Palosaari dev_dbg(&intf->dev, "core=%d addr=%04x data_len=%d checksum=%04x\n", 6242b987ea7SAntti Palosaari hdr_core, hdr_addr, hdr_data_len, hdr_checksum); 625786baecfSMauro Carvalho Chehab 626786baecfSMauro Carvalho Chehab if (((hdr_core != 1) && (hdr_core != 2)) || 627786baecfSMauro Carvalho Chehab (hdr_data_len > i)) { 6282b987ea7SAntti Palosaari dev_dbg(&intf->dev, "bad firmware\n"); 629786baecfSMauro Carvalho Chehab break; 630786baecfSMauro Carvalho Chehab } 631786baecfSMauro Carvalho Chehab 632786baecfSMauro Carvalho Chehab /* download begin packet */ 633786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_BEGIN; 634786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 635786baecfSMauro Carvalho Chehab if (ret < 0) 636786baecfSMauro Carvalho Chehab goto err; 637786baecfSMauro Carvalho Chehab 638786baecfSMauro Carvalho Chehab /* download firmware packet(s) */ 639786baecfSMauro Carvalho Chehab for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { 640786baecfSMauro Carvalho Chehab len = j; 641786baecfSMauro Carvalho Chehab if (len > MAX_DATA) 642786baecfSMauro Carvalho Chehab len = MAX_DATA; 643786baecfSMauro Carvalho Chehab req_fw_dl.wlen = len; 644786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + 645786baecfSMauro Carvalho Chehab HDR_SIZE + hdr_data_len - j]; 646786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 647786baecfSMauro Carvalho Chehab if (ret < 0) 648786baecfSMauro Carvalho Chehab goto err; 649786baecfSMauro Carvalho Chehab } 650786baecfSMauro Carvalho Chehab 651786baecfSMauro Carvalho Chehab /* download end packet */ 652786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_END; 653786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 654786baecfSMauro Carvalho Chehab if (ret < 0) 655786baecfSMauro Carvalho Chehab goto err; 656786baecfSMauro Carvalho Chehab 657786baecfSMauro Carvalho Chehab i -= hdr_data_len + HDR_SIZE; 658786baecfSMauro Carvalho Chehab 6592b987ea7SAntti Palosaari dev_dbg(&intf->dev, "data uploaded=%zu\n", fw->size - i); 660786baecfSMauro Carvalho Chehab } 661786baecfSMauro Carvalho Chehab 662ff4e3fe8SAntti Palosaari /* print warn if firmware is bad, continue and see what happens */ 663ff4e3fe8SAntti Palosaari if (i) 6642b987ea7SAntti Palosaari dev_warn(&intf->dev, "bad firmware\n"); 665ff4e3fe8SAntti Palosaari 666786baecfSMauro Carvalho Chehab return 0; 667786baecfSMauro Carvalho Chehab 668786baecfSMauro Carvalho Chehab err: 6692b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 670786baecfSMauro Carvalho Chehab 671786baecfSMauro Carvalho Chehab return ret; 672786baecfSMauro Carvalho Chehab } 673786baecfSMauro Carvalho Chehab 6748229da50SAntti Palosaari static int af9035_download_firmware_new(struct dvb_usb_device *d, 675786baecfSMauro Carvalho Chehab const struct firmware *fw) 676786baecfSMauro Carvalho Chehab { 6772b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 678786baecfSMauro Carvalho Chehab int ret, i, i_prev; 679786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; 680786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 681786baecfSMauro Carvalho Chehab 682786baecfSMauro Carvalho Chehab /* 683786baecfSMauro Carvalho Chehab * There seems to be following firmware header. Meaning of bytes 0-3 684786baecfSMauro Carvalho Chehab * is unknown. 685786baecfSMauro Carvalho Chehab * 686786baecfSMauro Carvalho Chehab * 0: 3 687786baecfSMauro Carvalho Chehab * 1: 0, 1 688786baecfSMauro Carvalho Chehab * 2: 0 689786baecfSMauro Carvalho Chehab * 3: 1, 2, 3 690786baecfSMauro Carvalho Chehab * 4: addr MSB 691786baecfSMauro Carvalho Chehab * 5: addr LSB 692786baecfSMauro Carvalho Chehab * 6: count of data bytes ? 693786baecfSMauro Carvalho Chehab */ 694786baecfSMauro Carvalho Chehab for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { 695786baecfSMauro Carvalho Chehab if (i == fw->size || 696786baecfSMauro Carvalho Chehab (fw->data[i + 0] == 0x03 && 697786baecfSMauro Carvalho Chehab (fw->data[i + 1] == 0x00 || 698786baecfSMauro Carvalho Chehab fw->data[i + 1] == 0x01) && 699786baecfSMauro Carvalho Chehab fw->data[i + 2] == 0x00)) { 700786baecfSMauro Carvalho Chehab req_fw_dl.wlen = i - i_prev; 701786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; 702786baecfSMauro Carvalho Chehab i_prev = i; 703786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 704786baecfSMauro Carvalho Chehab if (ret < 0) 705786baecfSMauro Carvalho Chehab goto err; 706786baecfSMauro Carvalho Chehab 7072b987ea7SAntti Palosaari dev_dbg(&intf->dev, "data uploaded=%d\n", i); 708786baecfSMauro Carvalho Chehab } 709786baecfSMauro Carvalho Chehab } 710786baecfSMauro Carvalho Chehab 711df8f1be1SAntti Palosaari return 0; 712df8f1be1SAntti Palosaari 713df8f1be1SAntti Palosaari err: 7142b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 715df8f1be1SAntti Palosaari 716df8f1be1SAntti Palosaari return ret; 717df8f1be1SAntti Palosaari } 718df8f1be1SAntti Palosaari 719df8f1be1SAntti Palosaari static int af9035_download_firmware(struct dvb_usb_device *d, 720df8f1be1SAntti Palosaari const struct firmware *fw) 721df8f1be1SAntti Palosaari { 7222b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 723df8f1be1SAntti Palosaari struct state *state = d_to_priv(d); 724df8f1be1SAntti Palosaari int ret; 725df8f1be1SAntti Palosaari u8 wbuf[1]; 726df8f1be1SAntti Palosaari u8 rbuf[4]; 727df8f1be1SAntti Palosaari u8 tmp; 728df8f1be1SAntti Palosaari struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 729df8f1be1SAntti Palosaari struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; 730c10989a2SAntti Palosaari 7312b987ea7SAntti Palosaari dev_dbg(&intf->dev, "\n"); 732df8f1be1SAntti Palosaari 733df8f1be1SAntti Palosaari /* 734df8f1be1SAntti Palosaari * In case of dual tuner configuration we need to do some extra 735df8f1be1SAntti Palosaari * initialization in order to download firmware to slave demod too, 736df8f1be1SAntti Palosaari * which is done by master demod. 737df8f1be1SAntti Palosaari * Master feeds also clock and controls power via GPIO. 738df8f1be1SAntti Palosaari */ 7399e422f64SStefan Pöschel if (state->dual_mode) { 740df8f1be1SAntti Palosaari /* configure gpioh1, reset & power slave demod */ 741df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); 742df8f1be1SAntti Palosaari if (ret < 0) 743df8f1be1SAntti Palosaari goto err; 744df8f1be1SAntti Palosaari 745df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01); 746df8f1be1SAntti Palosaari if (ret < 0) 747df8f1be1SAntti Palosaari goto err; 748df8f1be1SAntti Palosaari 749df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01); 750df8f1be1SAntti Palosaari if (ret < 0) 751df8f1be1SAntti Palosaari goto err; 752df8f1be1SAntti Palosaari 753df8f1be1SAntti Palosaari usleep_range(10000, 50000); 754df8f1be1SAntti Palosaari 755df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01); 756df8f1be1SAntti Palosaari if (ret < 0) 757df8f1be1SAntti Palosaari goto err; 758df8f1be1SAntti Palosaari 759df8f1be1SAntti Palosaari /* tell the slave I2C address */ 76009bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; 761df8f1be1SAntti Palosaari 762a71e479cSAntti Palosaari /* Use default I2C address if eeprom has no address set */ 763a1310ff4SMalcolm Priestley if (!tmp) 764a71e479cSAntti Palosaari tmp = 0x1d << 1; /* 8-bit format used by chip */ 765a1310ff4SMalcolm Priestley 7665b556084SOlli Salonen if ((state->chip_type == 0x9135) || 7675b556084SOlli Salonen (state->chip_type == 0x9306)) { 768df8f1be1SAntti Palosaari ret = af9035_wr_reg(d, 0x004bfb, tmp); 769df8f1be1SAntti Palosaari if (ret < 0) 770df8f1be1SAntti Palosaari goto err; 771df8f1be1SAntti Palosaari } else { 772df8f1be1SAntti Palosaari ret = af9035_wr_reg(d, 0x00417f, tmp); 773df8f1be1SAntti Palosaari if (ret < 0) 774df8f1be1SAntti Palosaari goto err; 775df8f1be1SAntti Palosaari 776df8f1be1SAntti Palosaari /* enable clock out */ 777df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); 778df8f1be1SAntti Palosaari if (ret < 0) 779df8f1be1SAntti Palosaari goto err; 780df8f1be1SAntti Palosaari } 781df8f1be1SAntti Palosaari } 782df8f1be1SAntti Palosaari 7838229da50SAntti Palosaari if (fw->data[0] == 0x01) 7848229da50SAntti Palosaari ret = af9035_download_firmware_old(d, fw); 785df8f1be1SAntti Palosaari else 7868229da50SAntti Palosaari ret = af9035_download_firmware_new(d, fw); 787df8f1be1SAntti Palosaari if (ret < 0) 788df8f1be1SAntti Palosaari goto err; 789df8f1be1SAntti Palosaari 790786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 791786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 792786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 793786baecfSMauro Carvalho Chehab if (ret < 0) 794786baecfSMauro Carvalho Chehab goto err; 795786baecfSMauro Carvalho Chehab 796786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 797786baecfSMauro Carvalho Chehab wbuf[0] = 1; 798786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 799786baecfSMauro Carvalho Chehab if (ret < 0) 800786baecfSMauro Carvalho Chehab goto err; 801786baecfSMauro Carvalho Chehab 802786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 8032b987ea7SAntti Palosaari dev_err(&intf->dev, "firmware did not run\n"); 804786baecfSMauro Carvalho Chehab ret = -ENODEV; 805786baecfSMauro Carvalho Chehab goto err; 806786baecfSMauro Carvalho Chehab } 807786baecfSMauro Carvalho Chehab 8082b987ea7SAntti Palosaari dev_info(&intf->dev, "firmware version=%d.%d.%d.%d", 8092b987ea7SAntti Palosaari rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 810786baecfSMauro Carvalho Chehab 811786baecfSMauro Carvalho Chehab return 0; 812786baecfSMauro Carvalho Chehab 813786baecfSMauro Carvalho Chehab err: 8142b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 815786baecfSMauro Carvalho Chehab 816786baecfSMauro Carvalho Chehab return ret; 817786baecfSMauro Carvalho Chehab } 818786baecfSMauro Carvalho Chehab 8199ea3681dSAntti Palosaari static int af9035_read_config(struct dvb_usb_device *d) 820786baecfSMauro Carvalho Chehab { 8212b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 822786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 8239ea3681dSAntti Palosaari int ret, i; 824786baecfSMauro Carvalho Chehab u8 tmp; 82509bfd96cSAntti Palosaari u16 tmp16; 826786baecfSMauro Carvalho Chehab 827a71e479cSAntti Palosaari /* Demod I2C address */ 828a71e479cSAntti Palosaari state->af9033_i2c_addr[0] = 0x1c; 829a71e479cSAntti Palosaari state->af9033_i2c_addr[1] = 0x1d; 8300d94d6a0SAntti Palosaari state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 831df8f1be1SAntti Palosaari state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 832ab56ad6aSAntti Palosaari state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; 833ab56ad6aSAntti Palosaari state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; 834c51f3b7fSJose Alberto Reguero state->it930x_addresses = 0; 835bf97b637SAntti Palosaari 8369ea3681dSAntti Palosaari if (state->chip_type == 0x9135) { 83715ba8202SAntti Palosaari /* feed clock for integrated RF tuner */ 83815ba8202SAntti Palosaari state->af9033_config[0].dyn0_clk = true; 83915ba8202SAntti Palosaari state->af9033_config[1].dyn0_clk = true; 84015ba8202SAntti Palosaari 841bc3c9e10SAntti Palosaari if (state->chip_version == 0x02) { 842bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; 843df8f1be1SAntti Palosaari state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60; 844bc3c9e10SAntti Palosaari } else { 845bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; 846df8f1be1SAntti Palosaari state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38; 847bc3c9e10SAntti Palosaari } 848bc3c9e10SAntti Palosaari 84909bfd96cSAntti Palosaari if (state->no_eeprom) { 85009bfd96cSAntti Palosaari /* Remote controller to NEC polling by default */ 85109bfd96cSAntti Palosaari state->ir_mode = 0x05; 85209bfd96cSAntti Palosaari state->ir_type = 0x00; 8539ea3681dSAntti Palosaari 8549ea3681dSAntti Palosaari goto skip_eeprom; 8559ea3681dSAntti Palosaari } 8565b556084SOlli Salonen } else if (state->chip_type == 0x9306) { 8575b556084SOlli Salonen /* 8585b556084SOlli Salonen * IT930x is an USB bridge, only single demod-single tuner 8595b556084SOlli Salonen * configurations seen so far. 8605b556084SOlli Salonen */ 861c51f3b7fSJose Alberto Reguero if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) && 862c51f3b7fSJose Alberto Reguero (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_AVERMEDIA_TD310)) { 863c51f3b7fSJose Alberto Reguero state->it930x_addresses = 1; 864c51f3b7fSJose Alberto Reguero } 8655b556084SOlli Salonen return 0; 8669ea3681dSAntti Palosaari } 8679ea3681dSAntti Palosaari 86809bfd96cSAntti Palosaari /* Remote controller */ 86909bfd96cSAntti Palosaari state->ir_mode = state->eeprom[EEPROM_IR_MODE]; 87009bfd96cSAntti Palosaari state->ir_type = state->eeprom[EEPROM_IR_TYPE]; 8715b556084SOlli Salonen 8729805992fSJose Alberto Reguero if (state->dual_mode) { 873a71e479cSAntti Palosaari /* Read 2nd demodulator I2C address. 8-bit format on eeprom */ 87409bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; 87514992f01SAntti Palosaari if (tmp) 876a71e479cSAntti Palosaari state->af9033_i2c_addr[1] = tmp >> 1; 87714992f01SAntti Palosaari 878a71e479cSAntti Palosaari dev_dbg(&intf->dev, "2nd demod I2C addr=%02x\n", 879a71e479cSAntti Palosaari state->af9033_i2c_addr[1]); 8809805992fSJose Alberto Reguero } 8819805992fSJose Alberto Reguero 882786baecfSMauro Carvalho Chehab for (i = 0; i < state->dual_mode + 1; i++) { 88309bfd96cSAntti Palosaari unsigned int eeprom_offset = 0; 884786baecfSMauro Carvalho Chehab 88509bfd96cSAntti Palosaari /* tuner */ 88609bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_1_TUNER_ID + eeprom_offset]; 8872b987ea7SAntti Palosaari dev_dbg(&intf->dev, "[%d]tuner=%02x\n", i, tmp); 8881cbbf90dSAntti Palosaari 8891cbbf90dSAntti Palosaari /* tuner sanity check */ 8901cbbf90dSAntti Palosaari if (state->chip_type == 0x9135) { 8911cbbf90dSAntti Palosaari if (state->chip_version == 0x02) { 8921cbbf90dSAntti Palosaari /* IT9135 BX (v2) */ 8931cbbf90dSAntti Palosaari switch (tmp) { 8941cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_60: 8951cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_61: 8961cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_62: 8971cbbf90dSAntti Palosaari state->af9033_config[i].tuner = tmp; 8981cbbf90dSAntti Palosaari break; 8991cbbf90dSAntti Palosaari } 9001cbbf90dSAntti Palosaari } else { 9011cbbf90dSAntti Palosaari /* IT9135 AX (v1) */ 9021cbbf90dSAntti Palosaari switch (tmp) { 9031cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_38: 9041cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_51: 9051cbbf90dSAntti Palosaari case AF9033_TUNER_IT9135_52: 9061cbbf90dSAntti Palosaari state->af9033_config[i].tuner = tmp; 9071cbbf90dSAntti Palosaari break; 9081cbbf90dSAntti Palosaari } 9091cbbf90dSAntti Palosaari } 9101cbbf90dSAntti Palosaari } else { 9111cbbf90dSAntti Palosaari /* AF9035 */ 9121cbbf90dSAntti Palosaari state->af9033_config[i].tuner = tmp; 9131cbbf90dSAntti Palosaari } 9141cbbf90dSAntti Palosaari 9151cbbf90dSAntti Palosaari if (state->af9033_config[i].tuner != tmp) { 9162b987ea7SAntti Palosaari dev_info(&intf->dev, "[%d] overriding tuner from %02x to %02x\n", 9172b987ea7SAntti Palosaari i, tmp, state->af9033_config[i].tuner); 9181cbbf90dSAntti Palosaari } 9199ea3681dSAntti Palosaari 9209ea3681dSAntti Palosaari switch (state->af9033_config[i].tuner) { 921786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 922786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 923786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 924786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 925d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 9267e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 927786baecfSMauro Carvalho Chehab state->af9033_config[i].spec_inv = 1; 928786baecfSMauro Carvalho Chehab break; 9299ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_38: 9309ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_51: 9319ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_52: 9329ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_60: 9339ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_61: 9349ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_62: 9359ea3681dSAntti Palosaari break; 936786baecfSMauro Carvalho Chehab default: 9372b987ea7SAntti Palosaari dev_warn(&intf->dev, "tuner id=%02x not supported, please report!", 9382b987ea7SAntti Palosaari tmp); 939c2c1b415SPeter Senna Tschudin } 940786baecfSMauro Carvalho Chehab 941bf97b637SAntti Palosaari /* disable dual mode if driver does not support it */ 942bf97b637SAntti Palosaari if (i == 1) 943df8f1be1SAntti Palosaari switch (state->af9033_config[i].tuner) { 9440bb3d8acSAntti Palosaari case AF9033_TUNER_FC0012: 945df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_38: 946df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_51: 947df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_52: 948df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_60: 949df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_61: 950df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_62: 95178c7bc4bSJose Alberto Reguero case AF9033_TUNER_MXL5007T: 9520bb3d8acSAntti Palosaari break; 953bf97b637SAntti Palosaari default: 954bf97b637SAntti Palosaari state->dual_mode = false; 9552b987ea7SAntti Palosaari dev_info(&intf->dev, "driver does not support 2nd tuner and will disable it"); 956bf97b637SAntti Palosaari } 957bf97b637SAntti Palosaari 958786baecfSMauro Carvalho Chehab /* tuner IF frequency */ 95909bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_1_IF_L + eeprom_offset]; 96009bfd96cSAntti Palosaari tmp16 = tmp << 0; 96109bfd96cSAntti Palosaari tmp = state->eeprom[EEPROM_1_IF_H + eeprom_offset]; 962786baecfSMauro Carvalho Chehab tmp16 |= tmp << 8; 9632b987ea7SAntti Palosaari dev_dbg(&intf->dev, "[%d]IF=%d\n", i, tmp16); 964786baecfSMauro Carvalho Chehab 96509bfd96cSAntti Palosaari eeprom_offset += 0x10; /* shift for the 2nd tuner params */ 966786baecfSMauro Carvalho Chehab } 967786baecfSMauro Carvalho Chehab 9689ea3681dSAntti Palosaari skip_eeprom: 969786baecfSMauro Carvalho Chehab /* get demod clock */ 970786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, 0x00d800, &tmp); 971786baecfSMauro Carvalho Chehab if (ret < 0) 972786baecfSMauro Carvalho Chehab goto err; 973786baecfSMauro Carvalho Chehab 974786baecfSMauro Carvalho Chehab tmp = (tmp >> 0) & 0x0f; 975786baecfSMauro Carvalho Chehab 9769ea3681dSAntti Palosaari for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) { 97774c1883aSAntti Palosaari if (state->chip_type == 0x9135) 9789ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_it9135[tmp]; 97974c1883aSAntti Palosaari else 9809ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_af9035[tmp]; 9819ea3681dSAntti Palosaari } 9829ea3681dSAntti Palosaari 9831882f59fSAlessandro Radicati state->no_read = false; 9841882f59fSAlessandro Radicati /* Some MXL5007T devices cannot properly handle tuner I2C read ops. */ 9851882f59fSAlessandro Radicati if (state->af9033_config[0].tuner == AF9033_TUNER_MXL5007T && 9861882f59fSAlessandro Radicati le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) 9871882f59fSAlessandro Radicati 9881882f59fSAlessandro Radicati switch (le16_to_cpu(d->udev->descriptor.idProduct)) { 9891882f59fSAlessandro Radicati case USB_PID_AVERMEDIA_A867: 9901882f59fSAlessandro Radicati case USB_PID_AVERMEDIA_TWINSTAR: 9912b987ea7SAntti Palosaari dev_info(&intf->dev, 9922b987ea7SAntti Palosaari "Device may have issues with I2C read operations. Enabling fix.\n"); 9931882f59fSAlessandro Radicati state->no_read = true; 9941882f59fSAlessandro Radicati break; 9951882f59fSAlessandro Radicati } 9961882f59fSAlessandro Radicati 9979ea3681dSAntti Palosaari return 0; 9989ea3681dSAntti Palosaari 9999ea3681dSAntti Palosaari err: 10002b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 10019ea3681dSAntti Palosaari 10029ea3681dSAntti Palosaari return ret; 100374c1883aSAntti Palosaari } 100474c1883aSAntti Palosaari 100551639be3SAntti Palosaari static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, 100651639be3SAntti Palosaari int cmd, int arg) 100751639be3SAntti Palosaari { 10082b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 100951639be3SAntti Palosaari int ret; 101051639be3SAntti Palosaari u8 val; 101151639be3SAntti Palosaari 10122b987ea7SAntti Palosaari dev_dbg(&intf->dev, "cmd=%d arg=%d\n", cmd, arg); 101351639be3SAntti Palosaari 101451639be3SAntti Palosaari /* 101551639be3SAntti Palosaari * CEN always enabled by hardware wiring 101651639be3SAntti Palosaari * RESETN GPIOT3 101751639be3SAntti Palosaari * RXEN GPIOT2 101851639be3SAntti Palosaari */ 101951639be3SAntti Palosaari 102051639be3SAntti Palosaari switch (cmd) { 102151639be3SAntti Palosaari case TUA9001_CMD_RESETN: 102251639be3SAntti Palosaari if (arg) 102351639be3SAntti Palosaari val = 0x00; 102451639be3SAntti Palosaari else 102551639be3SAntti Palosaari val = 0x01; 102651639be3SAntti Palosaari 102751639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); 102851639be3SAntti Palosaari if (ret < 0) 102951639be3SAntti Palosaari goto err; 103051639be3SAntti Palosaari break; 103151639be3SAntti Palosaari case TUA9001_CMD_RXEN: 103251639be3SAntti Palosaari if (arg) 103351639be3SAntti Palosaari val = 0x01; 103451639be3SAntti Palosaari else 103551639be3SAntti Palosaari val = 0x00; 103651639be3SAntti Palosaari 103751639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); 103851639be3SAntti Palosaari if (ret < 0) 103951639be3SAntti Palosaari goto err; 104051639be3SAntti Palosaari break; 104151639be3SAntti Palosaari } 104251639be3SAntti Palosaari 104351639be3SAntti Palosaari return 0; 104451639be3SAntti Palosaari 104551639be3SAntti Palosaari err: 10462b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 104751639be3SAntti Palosaari 104851639be3SAntti Palosaari return ret; 104951639be3SAntti Palosaari } 105051639be3SAntti Palosaari 105151639be3SAntti Palosaari 1052786baecfSMauro Carvalho Chehab static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, 1053786baecfSMauro Carvalho Chehab int cmd, int arg) 1054786baecfSMauro Carvalho Chehab { 10552b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1056786baecfSMauro Carvalho Chehab int ret; 1057786baecfSMauro Carvalho Chehab 1058786baecfSMauro Carvalho Chehab switch (cmd) { 1059786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_POWER: 1060786baecfSMauro Carvalho Chehab /* Tuner enable */ 1061786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); 1062786baecfSMauro Carvalho Chehab if (ret < 0) 1063786baecfSMauro Carvalho Chehab goto err; 1064786baecfSMauro Carvalho Chehab 1065786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); 1066786baecfSMauro Carvalho Chehab if (ret < 0) 1067786baecfSMauro Carvalho Chehab goto err; 1068786baecfSMauro Carvalho Chehab 1069786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); 1070786baecfSMauro Carvalho Chehab if (ret < 0) 1071786baecfSMauro Carvalho Chehab goto err; 1072786baecfSMauro Carvalho Chehab 1073786baecfSMauro Carvalho Chehab /* LED */ 1074786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); 1075786baecfSMauro Carvalho Chehab if (ret < 0) 1076786baecfSMauro Carvalho Chehab goto err; 1077786baecfSMauro Carvalho Chehab 1078786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); 1079786baecfSMauro Carvalho Chehab if (ret < 0) 1080786baecfSMauro Carvalho Chehab goto err; 1081786baecfSMauro Carvalho Chehab 1082786baecfSMauro Carvalho Chehab usleep_range(10000, 50000); 1083786baecfSMauro Carvalho Chehab break; 1084786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_RESET: 1085786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e9, 1); 1086786baecfSMauro Carvalho Chehab if (ret < 0) 1087786baecfSMauro Carvalho Chehab goto err; 1088786baecfSMauro Carvalho Chehab 1089786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e8, 1); 1090786baecfSMauro Carvalho Chehab if (ret < 0) 1091786baecfSMauro Carvalho Chehab goto err; 1092786baecfSMauro Carvalho Chehab 1093786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 1); 1094786baecfSMauro Carvalho Chehab if (ret < 0) 1095786baecfSMauro Carvalho Chehab goto err; 1096786baecfSMauro Carvalho Chehab 1097786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 1098786baecfSMauro Carvalho Chehab 1099786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 0); 1100786baecfSMauro Carvalho Chehab if (ret < 0) 1101786baecfSMauro Carvalho Chehab goto err; 1102786baecfSMauro Carvalho Chehab 1103786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 1104786baecfSMauro Carvalho Chehab break; 1105786baecfSMauro Carvalho Chehab default: 1106786baecfSMauro Carvalho Chehab ret = -EINVAL; 1107786baecfSMauro Carvalho Chehab goto err; 1108786baecfSMauro Carvalho Chehab } 1109786baecfSMauro Carvalho Chehab 1110786baecfSMauro Carvalho Chehab return 0; 1111786baecfSMauro Carvalho Chehab 1112786baecfSMauro Carvalho Chehab err: 11132b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 1114786baecfSMauro Carvalho Chehab 1115786baecfSMauro Carvalho Chehab return ret; 1116786baecfSMauro Carvalho Chehab } 1117786baecfSMauro Carvalho Chehab 1118786baecfSMauro Carvalho Chehab static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) 1119786baecfSMauro Carvalho Chehab { 1120786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 1121786baecfSMauro Carvalho Chehab 1122786baecfSMauro Carvalho Chehab switch (state->af9033_config[0].tuner) { 1123786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 1124786baecfSMauro Carvalho Chehab return af9035_fc0011_tuner_callback(d, cmd, arg); 112551639be3SAntti Palosaari case AF9033_TUNER_TUA9001: 112651639be3SAntti Palosaari return af9035_tua9001_tuner_callback(d, cmd, arg); 1127786baecfSMauro Carvalho Chehab default: 1128786baecfSMauro Carvalho Chehab break; 1129786baecfSMauro Carvalho Chehab } 1130786baecfSMauro Carvalho Chehab 11311835af10SAntti Palosaari return 0; 1132786baecfSMauro Carvalho Chehab } 1133786baecfSMauro Carvalho Chehab 1134786baecfSMauro Carvalho Chehab static int af9035_frontend_callback(void *adapter_priv, int component, 1135786baecfSMauro Carvalho Chehab int cmd, int arg) 1136786baecfSMauro Carvalho Chehab { 1137786baecfSMauro Carvalho Chehab struct i2c_adapter *adap = adapter_priv; 1138786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 11392b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1140786baecfSMauro Carvalho Chehab 11412b987ea7SAntti Palosaari dev_dbg(&intf->dev, "component=%d cmd=%d arg=%d\n", 11422b987ea7SAntti Palosaari component, cmd, arg); 11431835af10SAntti Palosaari 1144786baecfSMauro Carvalho Chehab switch (component) { 1145786baecfSMauro Carvalho Chehab case DVB_FRONTEND_COMPONENT_TUNER: 1146786baecfSMauro Carvalho Chehab return af9035_tuner_callback(d, cmd, arg); 1147786baecfSMauro Carvalho Chehab default: 1148786baecfSMauro Carvalho Chehab break; 1149786baecfSMauro Carvalho Chehab } 1150786baecfSMauro Carvalho Chehab 11511835af10SAntti Palosaari return 0; 1152786baecfSMauro Carvalho Chehab } 1153786baecfSMauro Carvalho Chehab 11549805992fSJose Alberto Reguero static int af9035_get_adapter_count(struct dvb_usb_device *d) 11559805992fSJose Alberto Reguero { 11569805992fSJose Alberto Reguero struct state *state = d_to_priv(d); 1157c10989a2SAntti Palosaari 11589805992fSJose Alberto Reguero return state->dual_mode + 1; 11599805992fSJose Alberto Reguero } 11609805992fSJose Alberto Reguero 1161786baecfSMauro Carvalho Chehab static int af9035_frontend_attach(struct dvb_usb_adapter *adap) 1162786baecfSMauro Carvalho Chehab { 1163786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1164786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 11652b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1166786baecfSMauro Carvalho Chehab int ret; 1167c10989a2SAntti Palosaari 11682b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 1169786baecfSMauro Carvalho Chehab 1170786baecfSMauro Carvalho Chehab if (!state->af9033_config[adap->id].tuner) { 1171786baecfSMauro Carvalho Chehab /* unsupported tuner */ 1172786baecfSMauro Carvalho Chehab ret = -ENODEV; 1173786baecfSMauro Carvalho Chehab goto err; 1174786baecfSMauro Carvalho Chehab } 1175786baecfSMauro Carvalho Chehab 1176f5b00a76SAntti Palosaari state->af9033_config[adap->id].fe = &adap->fe[0]; 1177f5b00a76SAntti Palosaari state->af9033_config[adap->id].ops = &state->ops; 1178a781edd1SAntti Palosaari ret = af9035_add_i2c_dev(d, "af9033", state->af9033_i2c_addr[adap->id], 11795dcf5bf6SOlli Salonen &state->af9033_config[adap->id], &d->i2c_adap); 1180f5b00a76SAntti Palosaari if (ret) 1181f5b00a76SAntti Palosaari goto err; 1182f5b00a76SAntti Palosaari 1183786baecfSMauro Carvalho Chehab if (adap->fe[0] == NULL) { 1184786baecfSMauro Carvalho Chehab ret = -ENODEV; 1185786baecfSMauro Carvalho Chehab goto err; 1186786baecfSMauro Carvalho Chehab } 1187786baecfSMauro Carvalho Chehab 1188786baecfSMauro Carvalho Chehab /* disable I2C-gate */ 1189786baecfSMauro Carvalho Chehab adap->fe[0]->ops.i2c_gate_ctrl = NULL; 1190786baecfSMauro Carvalho Chehab adap->fe[0]->callback = af9035_frontend_callback; 1191786baecfSMauro Carvalho Chehab 1192786baecfSMauro Carvalho Chehab return 0; 1193786baecfSMauro Carvalho Chehab 1194786baecfSMauro Carvalho Chehab err: 11952b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 1196786baecfSMauro Carvalho Chehab 1197786baecfSMauro Carvalho Chehab return ret; 1198786baecfSMauro Carvalho Chehab } 1199786baecfSMauro Carvalho Chehab 1200d7f9e850SMauro Carvalho Chehab /* 1201d7f9e850SMauro Carvalho Chehab * The I2C speed register is calculated with: 1202d7f9e850SMauro Carvalho Chehab * I2C speed register = (1000000000 / (24.4 * 16 * I2C_speed)) 1203d7f9e850SMauro Carvalho Chehab * 1204d7f9e850SMauro Carvalho Chehab * The default speed register for it930x is 7, with means a 1205d7f9e850SMauro Carvalho Chehab * speed of ~366 kbps 1206d7f9e850SMauro Carvalho Chehab */ 1207d7f9e850SMauro Carvalho Chehab #define I2C_SPEED_366K 7 1208d7f9e850SMauro Carvalho Chehab 12095b556084SOlli Salonen static int it930x_frontend_attach(struct dvb_usb_adapter *adap) 12105b556084SOlli Salonen { 12115b556084SOlli Salonen struct state *state = adap_to_priv(adap); 12125b556084SOlli Salonen struct dvb_usb_device *d = adap_to_d(adap); 12132b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 12145b556084SOlli Salonen int ret; 12155b556084SOlli Salonen struct si2168_config si2168_config; 12165b556084SOlli Salonen struct i2c_adapter *adapter; 12175b556084SOlli Salonen 12182b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 12195b556084SOlli Salonen 1220d7f9e850SMauro Carvalho Chehab /* I2C master bus 2 clock speed 366k */ 1221d7f9e850SMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00f6a7, I2C_SPEED_366K); 12221cb11bfaSAndreas Kemnade if (ret < 0) 12231cb11bfaSAndreas Kemnade goto err; 12241cb11bfaSAndreas Kemnade 1225d7f9e850SMauro Carvalho Chehab /* I2C master bus 1,3 clock speed 366k */ 1226d7f9e850SMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00f103, I2C_SPEED_366K); 12271cb11bfaSAndreas Kemnade if (ret < 0) 12281cb11bfaSAndreas Kemnade goto err; 12291cb11bfaSAndreas Kemnade 12301cb11bfaSAndreas Kemnade /* set gpio11 low */ 12311cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8d4, 0x01, 0x01); 12321cb11bfaSAndreas Kemnade if (ret < 0) 12331cb11bfaSAndreas Kemnade goto err; 12341cb11bfaSAndreas Kemnade 12351cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8d5, 0x01, 0x01); 12361cb11bfaSAndreas Kemnade if (ret < 0) 12371cb11bfaSAndreas Kemnade goto err; 12381cb11bfaSAndreas Kemnade 12391cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8d3, 0x01, 0x01); 12401cb11bfaSAndreas Kemnade if (ret < 0) 12411cb11bfaSAndreas Kemnade goto err; 12421cb11bfaSAndreas Kemnade 12431cb11bfaSAndreas Kemnade /* Tuner enable using gpiot2_en, gpiot2_on and gpiot2_o (reset) */ 12441cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8b8, 0x01, 0x01); 12451cb11bfaSAndreas Kemnade if (ret < 0) 12461cb11bfaSAndreas Kemnade goto err; 12471cb11bfaSAndreas Kemnade 12481cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8b9, 0x01, 0x01); 12491cb11bfaSAndreas Kemnade if (ret < 0) 12501cb11bfaSAndreas Kemnade goto err; 12511cb11bfaSAndreas Kemnade 12521cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8b7, 0x00, 0x01); 12531cb11bfaSAndreas Kemnade if (ret < 0) 12541cb11bfaSAndreas Kemnade goto err; 12551cb11bfaSAndreas Kemnade 12561cb11bfaSAndreas Kemnade msleep(200); 12571cb11bfaSAndreas Kemnade 12581cb11bfaSAndreas Kemnade ret = af9035_wr_reg_mask(d, 0xd8b7, 0x01, 0x01); 12591cb11bfaSAndreas Kemnade if (ret < 0) 12601cb11bfaSAndreas Kemnade goto err; 12611cb11bfaSAndreas Kemnade 1262251a5c4eSOlli Salonen memset(&si2168_config, 0, sizeof(si2168_config)); 12635b556084SOlli Salonen si2168_config.i2c_adapter = &adapter; 12645b556084SOlli Salonen si2168_config.fe = &adap->fe[0]; 12655b556084SOlli Salonen si2168_config.ts_mode = SI2168_TS_SERIAL; 12665b556084SOlli Salonen 12675b556084SOlli Salonen state->af9033_config[adap->id].fe = &adap->fe[0]; 12685b556084SOlli Salonen state->af9033_config[adap->id].ops = &state->ops; 1269c51f3b7fSJose Alberto Reguero ret = af9035_add_i2c_dev(d, "si2168", 1270c51f3b7fSJose Alberto Reguero it930x_addresses_table[state->it930x_addresses].frontend_i2c_addr, 1271c51f3b7fSJose Alberto Reguero &si2168_config, &d->i2c_adap); 12725b556084SOlli Salonen if (ret) 12735b556084SOlli Salonen goto err; 12745b556084SOlli Salonen 12755b556084SOlli Salonen if (adap->fe[0] == NULL) { 12765b556084SOlli Salonen ret = -ENODEV; 12775b556084SOlli Salonen goto err; 12785b556084SOlli Salonen } 12795b556084SOlli Salonen state->i2c_adapter_demod = adapter; 12805b556084SOlli Salonen 12815b556084SOlli Salonen return 0; 12825b556084SOlli Salonen 12835b556084SOlli Salonen err: 12842b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 12855b556084SOlli Salonen 12865b556084SOlli Salonen return ret; 12875b556084SOlli Salonen } 12885b556084SOlli Salonen 1289d4d6a34dSAntti Palosaari static int af9035_frontend_detach(struct dvb_usb_adapter *adap) 1290d4d6a34dSAntti Palosaari { 1291d4d6a34dSAntti Palosaari struct state *state = adap_to_priv(adap); 1292d4d6a34dSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 12932b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1294d4d6a34dSAntti Palosaari 12952b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 1296d4d6a34dSAntti Palosaari 1297d4d6a34dSAntti Palosaari if (adap->id == 1) { 129835ef193bSAntti Palosaari if (state->i2c_client[1]) 1299d4d6a34dSAntti Palosaari af9035_del_i2c_dev(d); 1300d4d6a34dSAntti Palosaari } else if (adap->id == 0) { 1301d4d6a34dSAntti Palosaari if (state->i2c_client[0]) 1302d4d6a34dSAntti Palosaari af9035_del_i2c_dev(d); 1303d4d6a34dSAntti Palosaari } 1304d4d6a34dSAntti Palosaari 1305d4d6a34dSAntti Palosaari return 0; 1306d4d6a34dSAntti Palosaari } 1307d4d6a34dSAntti Palosaari 1308786baecfSMauro Carvalho Chehab static const struct fc0011_config af9035_fc0011_config = { 1309786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 1310786baecfSMauro Carvalho Chehab }; 1311786baecfSMauro Carvalho Chehab 13129805992fSJose Alberto Reguero static struct mxl5007t_config af9035_mxl5007t_config[] = { 13139805992fSJose Alberto Reguero { 1314786baecfSMauro Carvalho Chehab .xtal_freq_hz = MxL_XTAL_24_MHZ, 1315786baecfSMauro Carvalho Chehab .if_freq_hz = MxL_IF_4_57_MHZ, 1316786baecfSMauro Carvalho Chehab .invert_if = 0, 1317786baecfSMauro Carvalho Chehab .loop_thru_enable = 0, 1318786baecfSMauro Carvalho Chehab .clk_out_enable = 0, 1319786baecfSMauro Carvalho Chehab .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 13209805992fSJose Alberto Reguero }, { 13219805992fSJose Alberto Reguero .xtal_freq_hz = MxL_XTAL_24_MHZ, 13229805992fSJose Alberto Reguero .if_freq_hz = MxL_IF_4_57_MHZ, 13239805992fSJose Alberto Reguero .invert_if = 0, 13249805992fSJose Alberto Reguero .loop_thru_enable = 1, 13259805992fSJose Alberto Reguero .clk_out_enable = 1, 13269805992fSJose Alberto Reguero .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 13279805992fSJose Alberto Reguero } 1328786baecfSMauro Carvalho Chehab }; 1329786baecfSMauro Carvalho Chehab 1330786baecfSMauro Carvalho Chehab static struct tda18218_config af9035_tda18218_config = { 1331786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 1332786baecfSMauro Carvalho Chehab .i2c_wr_max = 21, 1333786baecfSMauro Carvalho Chehab }; 1334786baecfSMauro Carvalho Chehab 13350bb3d8acSAntti Palosaari static const struct fc0012_config af9035_fc0012_config[] = { 13360bb3d8acSAntti Palosaari { 1337ad3a758bSAntti Palosaari .i2c_address = 0x63, 1338ad3a758bSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 13393a984772SAntti Palosaari .dual_master = true, 13400bb3d8acSAntti Palosaari .loop_through = true, 13410bb3d8acSAntti Palosaari .clock_out = true, 13420bb3d8acSAntti Palosaari }, { 13430bb3d8acSAntti Palosaari .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ 13440bb3d8acSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 13453a984772SAntti Palosaari .dual_master = true, 13460bb3d8acSAntti Palosaari } 1347ad3a758bSAntti Palosaari }; 1348ad3a758bSAntti Palosaari 1349786baecfSMauro Carvalho Chehab static int af9035_tuner_attach(struct dvb_usb_adapter *adap) 1350786baecfSMauro Carvalho Chehab { 1351786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1352786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 13532b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1354786baecfSMauro Carvalho Chehab int ret; 1355786baecfSMauro Carvalho Chehab struct dvb_frontend *fe; 13560bb3d8acSAntti Palosaari struct i2c_msg msg[1]; 1357bf97b637SAntti Palosaari u8 tuner_addr; 1358c10989a2SAntti Palosaari 13592b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 1360df8f1be1SAntti Palosaari 1361bf97b637SAntti Palosaari /* 1362bf97b637SAntti Palosaari * XXX: Hack used in that function: we abuse unused I2C address bit [7] 1363bf97b637SAntti Palosaari * to carry info about used I2C bus for dual tuner configuration. 1364bf97b637SAntti Palosaari */ 1365786baecfSMauro Carvalho Chehab 1366786baecfSMauro Carvalho Chehab switch (state->af9033_config[adap->id].tuner) { 1367b6c5fe70SAntti Palosaari case AF9033_TUNER_TUA9001: { 1368b6c5fe70SAntti Palosaari struct tua9001_platform_data tua9001_pdata = { 1369b6c5fe70SAntti Palosaari .dvb_frontend = adap->fe[0], 1370b6c5fe70SAntti Palosaari }; 1371b6c5fe70SAntti Palosaari 1372b6c5fe70SAntti Palosaari /* 1373b6c5fe70SAntti Palosaari * AF9035 gpiot3 = TUA9001 RESETN 1374b6c5fe70SAntti Palosaari * AF9035 gpiot2 = TUA9001 RXEN 1375b6c5fe70SAntti Palosaari */ 1376786baecfSMauro Carvalho Chehab 1377786baecfSMauro Carvalho Chehab /* configure gpiot2 and gpiot2 as output */ 1378786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); 1379786baecfSMauro Carvalho Chehab if (ret < 0) 1380786baecfSMauro Carvalho Chehab goto err; 1381786baecfSMauro Carvalho Chehab 1382786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); 1383786baecfSMauro Carvalho Chehab if (ret < 0) 1384786baecfSMauro Carvalho Chehab goto err; 1385786baecfSMauro Carvalho Chehab 1386786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); 1387786baecfSMauro Carvalho Chehab if (ret < 0) 1388786baecfSMauro Carvalho Chehab goto err; 1389786baecfSMauro Carvalho Chehab 1390786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); 1391786baecfSMauro Carvalho Chehab if (ret < 0) 1392786baecfSMauro Carvalho Chehab goto err; 1393786baecfSMauro Carvalho Chehab 1394786baecfSMauro Carvalho Chehab /* attach tuner */ 1395b6c5fe70SAntti Palosaari ret = af9035_add_i2c_dev(d, "tua9001", 0x60, &tua9001_pdata, 1396b6c5fe70SAntti Palosaari &d->i2c_adap); 1397b6c5fe70SAntti Palosaari if (ret) 1398b6c5fe70SAntti Palosaari goto err; 1399b6c5fe70SAntti Palosaari 1400b6c5fe70SAntti Palosaari fe = adap->fe[0]; 1401786baecfSMauro Carvalho Chehab break; 1402b6c5fe70SAntti Palosaari } 1403786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 1404786baecfSMauro Carvalho Chehab fe = dvb_attach(fc0011_attach, adap->fe[0], 1405786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_fc0011_config); 1406786baecfSMauro Carvalho Chehab break; 1407786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 14089805992fSJose Alberto Reguero if (adap->id == 0) { 1409786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e0, 1); 1410786baecfSMauro Carvalho Chehab if (ret < 0) 1411786baecfSMauro Carvalho Chehab goto err; 1412bf97b637SAntti Palosaari 1413786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e1, 1); 1414786baecfSMauro Carvalho Chehab if (ret < 0) 1415786baecfSMauro Carvalho Chehab goto err; 1416bf97b637SAntti Palosaari 1417786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 0); 1418786baecfSMauro Carvalho Chehab if (ret < 0) 1419786baecfSMauro Carvalho Chehab goto err; 1420786baecfSMauro Carvalho Chehab 1421786baecfSMauro Carvalho Chehab msleep(30); 1422786baecfSMauro Carvalho Chehab 1423786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 1); 1424786baecfSMauro Carvalho Chehab if (ret < 0) 1425786baecfSMauro Carvalho Chehab goto err; 1426786baecfSMauro Carvalho Chehab 1427786baecfSMauro Carvalho Chehab msleep(300); 1428786baecfSMauro Carvalho Chehab 1429786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c0, 1); 1430786baecfSMauro Carvalho Chehab if (ret < 0) 1431786baecfSMauro Carvalho Chehab goto err; 1432bf97b637SAntti Palosaari 1433786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c1, 1); 1434786baecfSMauro Carvalho Chehab if (ret < 0) 1435786baecfSMauro Carvalho Chehab goto err; 1436bf97b637SAntti Palosaari 1437786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8bf, 0); 1438786baecfSMauro Carvalho Chehab if (ret < 0) 1439786baecfSMauro Carvalho Chehab goto err; 1440bf97b637SAntti Palosaari 1441786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b4, 1); 1442786baecfSMauro Carvalho Chehab if (ret < 0) 1443786baecfSMauro Carvalho Chehab goto err; 1444bf97b637SAntti Palosaari 1445786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b5, 1); 1446786baecfSMauro Carvalho Chehab if (ret < 0) 1447786baecfSMauro Carvalho Chehab goto err; 1448bf97b637SAntti Palosaari 1449786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b3, 1); 1450786baecfSMauro Carvalho Chehab if (ret < 0) 1451786baecfSMauro Carvalho Chehab goto err; 1452bf97b637SAntti Palosaari 1453bf97b637SAntti Palosaari tuner_addr = 0x60; 1454bf97b637SAntti Palosaari } else { 1455bf97b637SAntti Palosaari tuner_addr = 0x60 | 0x80; /* I2C bus hack */ 14569805992fSJose Alberto Reguero } 1457786baecfSMauro Carvalho Chehab 1458786baecfSMauro Carvalho Chehab /* attach tuner */ 1459bf97b637SAntti Palosaari fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, 1460bf97b637SAntti Palosaari tuner_addr, &af9035_mxl5007t_config[adap->id]); 1461786baecfSMauro Carvalho Chehab break; 1462786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 1463786baecfSMauro Carvalho Chehab /* attach tuner */ 1464786baecfSMauro Carvalho Chehab fe = dvb_attach(tda18218_attach, adap->fe[0], 1465786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tda18218_config); 1466786baecfSMauro Carvalho Chehab break; 14677a893ba9SAntti Palosaari case AF9033_TUNER_FC2580: { 14687a893ba9SAntti Palosaari struct fc2580_platform_data fc2580_pdata = { 14697a893ba9SAntti Palosaari .dvb_frontend = adap->fe[0], 14707a893ba9SAntti Palosaari }; 14717a893ba9SAntti Palosaari 1472d67ceb33SOliver Schinagl /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ 1473d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 1474d67ceb33SOliver Schinagl if (ret < 0) 1475d67ceb33SOliver Schinagl goto err; 1476d67ceb33SOliver Schinagl 1477d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 1478d67ceb33SOliver Schinagl if (ret < 0) 1479d67ceb33SOliver Schinagl goto err; 1480d67ceb33SOliver Schinagl 1481d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 1482d67ceb33SOliver Schinagl if (ret < 0) 1483d67ceb33SOliver Schinagl goto err; 1484d67ceb33SOliver Schinagl 1485d67ceb33SOliver Schinagl usleep_range(10000, 50000); 1486d67ceb33SOliver Schinagl /* attach tuner */ 14877a893ba9SAntti Palosaari ret = af9035_add_i2c_dev(d, "fc2580", 0x56, &fc2580_pdata, 14887a893ba9SAntti Palosaari &d->i2c_adap); 14897a893ba9SAntti Palosaari if (ret) 14907a893ba9SAntti Palosaari goto err; 14917a893ba9SAntti Palosaari 14927a893ba9SAntti Palosaari fe = adap->fe[0]; 1493d67ceb33SOliver Schinagl break; 14947a893ba9SAntti Palosaari } 14957e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 14967e0bc296SAntti Palosaari /* 14977e0bc296SAntti Palosaari * AF9035 gpiot2 = FC0012 enable 14987e0bc296SAntti Palosaari * XXX: there seems to be something on gpioh8 too, but on my 14997e0bc296SAntti Palosaari * my test I didn't find any difference. 15007e0bc296SAntti Palosaari */ 15017e0bc296SAntti Palosaari 15020bb3d8acSAntti Palosaari if (adap->id == 0) { 15037e0bc296SAntti Palosaari /* configure gpiot2 as output and high */ 15047e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 15057e0bc296SAntti Palosaari if (ret < 0) 15067e0bc296SAntti Palosaari goto err; 15077e0bc296SAntti Palosaari 15087e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 15097e0bc296SAntti Palosaari if (ret < 0) 15107e0bc296SAntti Palosaari goto err; 15117e0bc296SAntti Palosaari 15127e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 15137e0bc296SAntti Palosaari if (ret < 0) 15147e0bc296SAntti Palosaari goto err; 15150bb3d8acSAntti Palosaari } else { 15160bb3d8acSAntti Palosaari /* 15170bb3d8acSAntti Palosaari * FIXME: That belongs for the FC0012 driver. 15180bb3d8acSAntti Palosaari * Write 02 to FC0012 master tuner register 0d directly 15190bb3d8acSAntti Palosaari * in order to make slave tuner working. 15200bb3d8acSAntti Palosaari */ 15210bb3d8acSAntti Palosaari msg[0].addr = 0x63; 15220bb3d8acSAntti Palosaari msg[0].flags = 0; 15230bb3d8acSAntti Palosaari msg[0].len = 2; 15240bb3d8acSAntti Palosaari msg[0].buf = "\x0d\x02"; 15250bb3d8acSAntti Palosaari ret = i2c_transfer(&d->i2c_adap, msg, 1); 15260bb3d8acSAntti Palosaari if (ret < 0) 15270bb3d8acSAntti Palosaari goto err; 15280bb3d8acSAntti Palosaari } 15297e0bc296SAntti Palosaari 15307e0bc296SAntti Palosaari usleep_range(10000, 50000); 15317e0bc296SAntti Palosaari 1532ad3a758bSAntti Palosaari fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, 15330bb3d8acSAntti Palosaari &af9035_fc0012_config[adap->id]); 15347e0bc296SAntti Palosaari break; 1535ac77fb0fSAntti Palosaari case AF9033_TUNER_IT9135_38: 153674c1883aSAntti Palosaari case AF9033_TUNER_IT9135_51: 153774c1883aSAntti Palosaari case AF9033_TUNER_IT9135_52: 153874c1883aSAntti Palosaari case AF9033_TUNER_IT9135_60: 153974c1883aSAntti Palosaari case AF9033_TUNER_IT9135_61: 154074c1883aSAntti Palosaari case AF9033_TUNER_IT9135_62: 15413b2a5e8cSAntti Palosaari { 154235ef193bSAntti Palosaari struct platform_device *pdev; 15438efb34b2SAntti Palosaari const char *name; 154435ef193bSAntti Palosaari struct it913x_platform_data it913x_pdata = { 154535ef193bSAntti Palosaari .regmap = state->af9033_config[adap->id].regmap, 15463b2a5e8cSAntti Palosaari .fe = adap->fe[0], 15473b2a5e8cSAntti Palosaari }; 15483b2a5e8cSAntti Palosaari 154935ef193bSAntti Palosaari switch (state->af9033_config[adap->id].tuner) { 155035ef193bSAntti Palosaari case AF9033_TUNER_IT9135_38: 155135ef193bSAntti Palosaari case AF9033_TUNER_IT9135_51: 155235ef193bSAntti Palosaari case AF9033_TUNER_IT9135_52: 15538efb34b2SAntti Palosaari name = "it9133ax-tuner"; 155435ef193bSAntti Palosaari break; 155535ef193bSAntti Palosaari case AF9033_TUNER_IT9135_60: 155635ef193bSAntti Palosaari case AF9033_TUNER_IT9135_61: 155735ef193bSAntti Palosaari case AF9033_TUNER_IT9135_62: 15588efb34b2SAntti Palosaari name = "it9133bx-tuner"; 155935ef193bSAntti Palosaari break; 156035ef193bSAntti Palosaari default: 156135ef193bSAntti Palosaari ret = -ENODEV; 156235ef193bSAntti Palosaari goto err; 156335ef193bSAntti Palosaari } 156435ef193bSAntti Palosaari 1565676c350fSAntti Palosaari if (state->dual_mode) { 1566676c350fSAntti Palosaari if (adap->id == 0) 156735ef193bSAntti Palosaari it913x_pdata.role = IT913X_ROLE_DUAL_MASTER; 1568676c350fSAntti Palosaari else 156935ef193bSAntti Palosaari it913x_pdata.role = IT913X_ROLE_DUAL_SLAVE; 157035ef193bSAntti Palosaari } else { 157135ef193bSAntti Palosaari it913x_pdata.role = IT913X_ROLE_SINGLE; 1572676c350fSAntti Palosaari } 1573676c350fSAntti Palosaari 157435ef193bSAntti Palosaari request_module("%s", "it913x"); 15758efb34b2SAntti Palosaari pdev = platform_device_register_data(&d->intf->dev, name, 157635ef193bSAntti Palosaari PLATFORM_DEVID_AUTO, 157735ef193bSAntti Palosaari &it913x_pdata, 157835ef193bSAntti Palosaari sizeof(it913x_pdata)); 157935ef193bSAntti Palosaari if (IS_ERR(pdev) || !pdev->dev.driver) { 158035ef193bSAntti Palosaari ret = -ENODEV; 15813b2a5e8cSAntti Palosaari goto err; 158235ef193bSAntti Palosaari } 158335ef193bSAntti Palosaari if (!try_module_get(pdev->dev.driver->owner)) { 158435ef193bSAntti Palosaari platform_device_unregister(pdev); 158535ef193bSAntti Palosaari ret = -ENODEV; 158635ef193bSAntti Palosaari goto err; 158735ef193bSAntti Palosaari } 15883b2a5e8cSAntti Palosaari 158935ef193bSAntti Palosaari state->platform_device_tuner[adap->id] = pdev; 15903b2a5e8cSAntti Palosaari fe = adap->fe[0]; 1591ac77fb0fSAntti Palosaari break; 15923b2a5e8cSAntti Palosaari } 1593786baecfSMauro Carvalho Chehab default: 1594786baecfSMauro Carvalho Chehab fe = NULL; 1595786baecfSMauro Carvalho Chehab } 1596786baecfSMauro Carvalho Chehab 1597786baecfSMauro Carvalho Chehab if (fe == NULL) { 1598786baecfSMauro Carvalho Chehab ret = -ENODEV; 1599786baecfSMauro Carvalho Chehab goto err; 1600786baecfSMauro Carvalho Chehab } 1601786baecfSMauro Carvalho Chehab 1602786baecfSMauro Carvalho Chehab return 0; 1603786baecfSMauro Carvalho Chehab 1604786baecfSMauro Carvalho Chehab err: 16052b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 1606786baecfSMauro Carvalho Chehab 1607786baecfSMauro Carvalho Chehab return ret; 1608786baecfSMauro Carvalho Chehab } 1609786baecfSMauro Carvalho Chehab 16105b556084SOlli Salonen static int it930x_tuner_attach(struct dvb_usb_adapter *adap) 16115b556084SOlli Salonen { 16125b556084SOlli Salonen struct state *state = adap_to_priv(adap); 16135b556084SOlli Salonen struct dvb_usb_device *d = adap_to_d(adap); 16142b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 16155b556084SOlli Salonen int ret; 16165b556084SOlli Salonen struct si2157_config si2157_config; 16175b556084SOlli Salonen 16182b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 16195b556084SOlli Salonen 16205b556084SOlli Salonen memset(&si2157_config, 0, sizeof(si2157_config)); 16215b556084SOlli Salonen si2157_config.fe = adap->fe[0]; 16226bf05f75SGon Solo 16236bf05f75SGon Solo /* 1624c0e0d313STomasz Maciej Nowak * HACK: The Logilink VG0022A and TerraTec TC2 Stick have 1625c0e0d313STomasz Maciej Nowak * a bug: when the si2157 firmware that came with the device 1626c0e0d313STomasz Maciej Nowak * is replaced by a new one, the I2C transfers to the tuner 1627c0e0d313STomasz Maciej Nowak * will return just 0xff. 16286bf05f75SGon Solo * 16296bf05f75SGon Solo * Probably, the vendor firmware has some patch specifically 16306bf05f75SGon Solo * designed for this device. So, we can't replace by the 16316bf05f75SGon Solo * generic firmware. The right solution would be to extract 16326bf05f75SGon Solo * the si2157 firmware from the original driver and ask the 16336bf05f75SGon Solo * driver to load the specifically designed firmware, but, 16346bf05f75SGon Solo * while we don't have that, the next best solution is to just 16356bf05f75SGon Solo * keep the original firmware at the device. 16366bf05f75SGon Solo */ 1637c0e0d313STomasz Maciej Nowak if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_DEXATEK && 1638c0e0d313STomasz Maciej Nowak le16_to_cpu(d->udev->descriptor.idProduct) == 0x0100) || 1639c0e0d313STomasz Maciej Nowak (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_TERRATEC && 1640c0e0d313STomasz Maciej Nowak le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_TERRATEC_CINERGY_TC2_STICK)) 16416bf05f75SGon Solo si2157_config.dont_load_firmware = true; 16426bf05f75SGon Solo 1643c51f3b7fSJose Alberto Reguero si2157_config.if_port = it930x_addresses_table[state->it930x_addresses].tuner_if_port; 1644c51f3b7fSJose Alberto Reguero ret = af9035_add_i2c_dev(d, "si2157", 1645c51f3b7fSJose Alberto Reguero it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr, 16465b556084SOlli Salonen &si2157_config, state->i2c_adapter_demod); 16475b556084SOlli Salonen if (ret) 16485b556084SOlli Salonen goto err; 16495b556084SOlli Salonen 16505b556084SOlli Salonen return 0; 16515b556084SOlli Salonen 16525b556084SOlli Salonen err: 16532b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 16545b556084SOlli Salonen 16555b556084SOlli Salonen return ret; 16565b556084SOlli Salonen } 16575b556084SOlli Salonen 16585b556084SOlli Salonen 16595b556084SOlli Salonen static int it930x_tuner_detach(struct dvb_usb_adapter *adap) 16605b556084SOlli Salonen { 16615b556084SOlli Salonen struct state *state = adap_to_priv(adap); 16625b556084SOlli Salonen struct dvb_usb_device *d = adap_to_d(adap); 16632b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 16645b556084SOlli Salonen 16652b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 16665b556084SOlli Salonen 16675b556084SOlli Salonen if (adap->id == 1) { 16685b556084SOlli Salonen if (state->i2c_client[3]) 16695b556084SOlli Salonen af9035_del_i2c_dev(d); 16705b556084SOlli Salonen } else if (adap->id == 0) { 16715b556084SOlli Salonen if (state->i2c_client[1]) 16725b556084SOlli Salonen af9035_del_i2c_dev(d); 16735b556084SOlli Salonen } 16745b556084SOlli Salonen 16755b556084SOlli Salonen return 0; 16765b556084SOlli Salonen } 16775b556084SOlli Salonen 16785b556084SOlli Salonen 1679d4d6a34dSAntti Palosaari static int af9035_tuner_detach(struct dvb_usb_adapter *adap) 1680d4d6a34dSAntti Palosaari { 1681d4d6a34dSAntti Palosaari struct state *state = adap_to_priv(adap); 1682d4d6a34dSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 16832b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1684d4d6a34dSAntti Palosaari 16852b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); 1686d4d6a34dSAntti Palosaari 1687d4d6a34dSAntti Palosaari switch (state->af9033_config[adap->id].tuner) { 1688b6c5fe70SAntti Palosaari case AF9033_TUNER_TUA9001: 16897a893ba9SAntti Palosaari case AF9033_TUNER_FC2580: 1690d4d6a34dSAntti Palosaari if (adap->id == 1) { 1691d4d6a34dSAntti Palosaari if (state->i2c_client[3]) 1692d4d6a34dSAntti Palosaari af9035_del_i2c_dev(d); 1693d4d6a34dSAntti Palosaari } else if (adap->id == 0) { 1694d4d6a34dSAntti Palosaari if (state->i2c_client[1]) 1695d4d6a34dSAntti Palosaari af9035_del_i2c_dev(d); 1696d4d6a34dSAntti Palosaari } 169735ef193bSAntti Palosaari break; 169835ef193bSAntti Palosaari case AF9033_TUNER_IT9135_38: 169935ef193bSAntti Palosaari case AF9033_TUNER_IT9135_51: 170035ef193bSAntti Palosaari case AF9033_TUNER_IT9135_52: 170135ef193bSAntti Palosaari case AF9033_TUNER_IT9135_60: 170235ef193bSAntti Palosaari case AF9033_TUNER_IT9135_61: 170335ef193bSAntti Palosaari case AF9033_TUNER_IT9135_62: 170435ef193bSAntti Palosaari { 170535ef193bSAntti Palosaari struct platform_device *pdev; 170635ef193bSAntti Palosaari 170735ef193bSAntti Palosaari pdev = state->platform_device_tuner[adap->id]; 170835ef193bSAntti Palosaari if (pdev) { 170935ef193bSAntti Palosaari module_put(pdev->dev.driver->owner); 171035ef193bSAntti Palosaari platform_device_unregister(pdev); 171135ef193bSAntti Palosaari } 171235ef193bSAntti Palosaari break; 171335ef193bSAntti Palosaari } 1714d4d6a34dSAntti Palosaari } 1715d4d6a34dSAntti Palosaari 1716d4d6a34dSAntti Palosaari return 0; 1717d4d6a34dSAntti Palosaari } 1718d4d6a34dSAntti Palosaari 1719786baecfSMauro Carvalho Chehab static int af9035_init(struct dvb_usb_device *d) 1720786baecfSMauro Carvalho Chehab { 1721786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 17222b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1723786baecfSMauro Carvalho Chehab int ret, i; 1724bada342eSAntti Palosaari u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; 1725bada342eSAntti Palosaari u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 1726786baecfSMauro Carvalho Chehab struct reg_val_mask tab[] = { 1727786baecfSMauro Carvalho Chehab { 0x80f99d, 0x01, 0x01 }, 1728786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x01, 0x01 }, 1729786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x20 }, 1730786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x40 }, 1731786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x20 }, 1732786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x40 }, 1733786baecfSMauro Carvalho Chehab { 0x00dd11, 0x20, 0x20 }, 1734786baecfSMauro Carvalho Chehab { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 1735786baecfSMauro Carvalho Chehab { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 1736786baecfSMauro Carvalho Chehab { 0x00dd0c, packet_size, 0xff}, 1737786baecfSMauro Carvalho Chehab { 0x00dd11, state->dual_mode << 6, 0x40 }, 1738786baecfSMauro Carvalho Chehab { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 1739786baecfSMauro Carvalho Chehab { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 1740786baecfSMauro Carvalho Chehab { 0x00dd0d, packet_size, 0xff }, 17419805992fSJose Alberto Reguero { 0x80f9a3, state->dual_mode, 0x01 }, 17429805992fSJose Alberto Reguero { 0x80f9cd, state->dual_mode, 0x01 }, 1743786baecfSMauro Carvalho Chehab { 0x80f99d, 0x00, 0x01 }, 1744786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x00, 0x01 }, 1745786baecfSMauro Carvalho Chehab }; 1746786baecfSMauro Carvalho Chehab 17472b987ea7SAntti Palosaari dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n", 17482b987ea7SAntti Palosaari d->udev->speed, frame_size, packet_size); 1749786baecfSMauro Carvalho Chehab 1750786baecfSMauro Carvalho Chehab /* init endpoints */ 1751786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 1752786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, 1753786baecfSMauro Carvalho Chehab tab[i].mask); 1754786baecfSMauro Carvalho Chehab if (ret < 0) 1755786baecfSMauro Carvalho Chehab goto err; 1756786baecfSMauro Carvalho Chehab } 1757786baecfSMauro Carvalho Chehab 1758786baecfSMauro Carvalho Chehab return 0; 1759786baecfSMauro Carvalho Chehab 1760786baecfSMauro Carvalho Chehab err: 17612b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 1762786baecfSMauro Carvalho Chehab 1763786baecfSMauro Carvalho Chehab return ret; 1764786baecfSMauro Carvalho Chehab } 1765786baecfSMauro Carvalho Chehab 17665b556084SOlli Salonen static int it930x_init(struct dvb_usb_device *d) 17675b556084SOlli Salonen { 17685b556084SOlli Salonen struct state *state = d_to_priv(d); 17692b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 17705b556084SOlli Salonen int ret, i; 17715b556084SOlli Salonen u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 816) * 188 / 4; 17725b556084SOlli Salonen u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 17735b556084SOlli Salonen struct reg_val_mask tab[] = { 17745b556084SOlli Salonen { 0x00da1a, 0x00, 0x01 }, /* ignore_sync_byte */ 17755b556084SOlli Salonen { 0x00f41f, 0x04, 0x04 }, /* dvbt_inten */ 17765b556084SOlli Salonen { 0x00da10, 0x00, 0x01 }, /* mpeg_full_speed */ 17775b556084SOlli Salonen { 0x00f41a, 0x01, 0x01 }, /* dvbt_en */ 17785b556084SOlli Salonen { 0x00da1d, 0x01, 0x01 }, /* mp2_sw_rst, reset EP4 */ 17795b556084SOlli Salonen { 0x00dd11, 0x00, 0x20 }, /* ep4_tx_en, disable EP4 */ 17805b556084SOlli Salonen { 0x00dd13, 0x00, 0x20 }, /* ep4_tx_nak, disable EP4 NAK */ 17815b556084SOlli Salonen { 0x00dd11, 0x20, 0x20 }, /* ep4_tx_en, enable EP4 */ 17825b556084SOlli Salonen { 0x00dd11, 0x00, 0x40 }, /* ep5_tx_en, disable EP5 */ 17835b556084SOlli Salonen { 0x00dd13, 0x00, 0x40 }, /* ep5_tx_nak, disable EP5 NAK */ 17845b556084SOlli Salonen { 0x00dd11, state->dual_mode << 6, 0x40 }, /* enable EP5 */ 17855b556084SOlli Salonen { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 17865b556084SOlli Salonen { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 17875b556084SOlli Salonen { 0x00dd0c, packet_size, 0xff}, 17885b556084SOlli Salonen { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 17895b556084SOlli Salonen { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 17905b556084SOlli Salonen { 0x00dd0d, packet_size, 0xff }, 17915b556084SOlli Salonen { 0x00da1d, 0x00, 0x01 }, /* mp2_sw_rst, disable */ 17925b556084SOlli Salonen { 0x00d833, 0x01, 0xff }, /* slew rate ctrl: slew rate boosts */ 17935b556084SOlli Salonen { 0x00d830, 0x00, 0xff }, /* Bit 0 of output driving control */ 17945b556084SOlli Salonen { 0x00d831, 0x01, 0xff }, /* Bit 1 of output driving control */ 17955b556084SOlli Salonen { 0x00d832, 0x00, 0xff }, /* Bit 2 of output driving control */ 17965b556084SOlli Salonen 17975b556084SOlli Salonen /* suspend gpio1 for TS-C */ 17985b556084SOlli Salonen { 0x00d8b0, 0x01, 0xff }, /* gpio1 */ 17995b556084SOlli Salonen { 0x00d8b1, 0x01, 0xff }, /* gpio1 */ 18005b556084SOlli Salonen { 0x00d8af, 0x00, 0xff }, /* gpio1 */ 18015b556084SOlli Salonen 18025b556084SOlli Salonen /* suspend gpio7 for TS-D */ 18035b556084SOlli Salonen { 0x00d8c4, 0x01, 0xff }, /* gpio7 */ 18045b556084SOlli Salonen { 0x00d8c5, 0x01, 0xff }, /* gpio7 */ 18055b556084SOlli Salonen { 0x00d8c3, 0x00, 0xff }, /* gpio7 */ 18065b556084SOlli Salonen 18075b556084SOlli Salonen /* suspend gpio13 for TS-B */ 18085b556084SOlli Salonen { 0x00d8dc, 0x01, 0xff }, /* gpio13 */ 18095b556084SOlli Salonen { 0x00d8dd, 0x01, 0xff }, /* gpio13 */ 18105b556084SOlli Salonen { 0x00d8db, 0x00, 0xff }, /* gpio13 */ 18115b556084SOlli Salonen 18125b556084SOlli Salonen /* suspend gpio14 for TS-E */ 18135b556084SOlli Salonen { 0x00d8e4, 0x01, 0xff }, /* gpio14 */ 18145b556084SOlli Salonen { 0x00d8e5, 0x01, 0xff }, /* gpio14 */ 18155b556084SOlli Salonen { 0x00d8e3, 0x00, 0xff }, /* gpio14 */ 18165b556084SOlli Salonen 18175b556084SOlli Salonen /* suspend gpio15 for TS-A */ 18185b556084SOlli Salonen { 0x00d8e8, 0x01, 0xff }, /* gpio15 */ 18195b556084SOlli Salonen { 0x00d8e9, 0x01, 0xff }, /* gpio15 */ 18205b556084SOlli Salonen { 0x00d8e7, 0x00, 0xff }, /* gpio15 */ 18215b556084SOlli Salonen 18225b556084SOlli Salonen { 0x00da58, 0x00, 0x01 }, /* ts_in_src, serial */ 18235b556084SOlli Salonen { 0x00da73, 0x01, 0xff }, /* ts0_aggre_mode */ 18245b556084SOlli Salonen { 0x00da78, 0x47, 0xff }, /* ts0_sync_byte */ 18255b556084SOlli Salonen { 0x00da4c, 0x01, 0xff }, /* ts0_en */ 18265b556084SOlli Salonen { 0x00da5a, 0x1f, 0xff }, /* ts_fail_ignore */ 18275b556084SOlli Salonen }; 18285b556084SOlli Salonen 18292b987ea7SAntti Palosaari dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n", 18302b987ea7SAntti Palosaari d->udev->speed, frame_size, packet_size); 18315b556084SOlli Salonen 18325b556084SOlli Salonen /* init endpoints */ 18335b556084SOlli Salonen for (i = 0; i < ARRAY_SIZE(tab); i++) { 18345b556084SOlli Salonen ret = af9035_wr_reg_mask(d, tab[i].reg, 18355b556084SOlli Salonen tab[i].val, tab[i].mask); 18365b556084SOlli Salonen 18375b556084SOlli Salonen if (ret < 0) 18385b556084SOlli Salonen goto err; 18395b556084SOlli Salonen } 18405b556084SOlli Salonen 18415b556084SOlli Salonen return 0; 18425b556084SOlli Salonen err: 18432b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 18445b556084SOlli Salonen 18455b556084SOlli Salonen return ret; 18465b556084SOlli Salonen } 18475b556084SOlli Salonen 18485b556084SOlli Salonen 184937b44a0fSAntti Palosaari #if IS_ENABLED(CONFIG_RC_CORE) 1850786baecfSMauro Carvalho Chehab static int af9035_rc_query(struct dvb_usb_device *d) 1851786baecfSMauro Carvalho Chehab { 18522b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1853786baecfSMauro Carvalho Chehab int ret; 18546d741bfeSSean Young enum rc_proto proto; 185575cd5886SAntti Palosaari u32 key; 185675cd5886SAntti Palosaari u8 buf[4]; 185775cd5886SAntti Palosaari struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf }; 1858786baecfSMauro Carvalho Chehab 1859786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 18601bfd5294SAntti Palosaari if (ret == 1) 18611bfd5294SAntti Palosaari return 0; 18621bfd5294SAntti Palosaari else if (ret < 0) 1863786baecfSMauro Carvalho Chehab goto err; 1864786baecfSMauro Carvalho Chehab 186575cd5886SAntti Palosaari if ((buf[2] + buf[3]) == 0xff) { 186675cd5886SAntti Palosaari if ((buf[0] + buf[1]) == 0xff) { 186775cd5886SAntti Palosaari /* NEC standard 16bit */ 1868120703f9SDavid Härdeman key = RC_SCANCODE_NEC(buf[0], buf[2]); 18696d741bfeSSean Young proto = RC_PROTO_NEC; 1870786baecfSMauro Carvalho Chehab } else { 187175cd5886SAntti Palosaari /* NEC extended 24bit */ 1872120703f9SDavid Härdeman key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]); 18736d741bfeSSean Young proto = RC_PROTO_NECX; 1874786baecfSMauro Carvalho Chehab } 1875786baecfSMauro Carvalho Chehab } else { 187675cd5886SAntti Palosaari /* NEC full code 32bit */ 1877120703f9SDavid Härdeman key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 | 1878120703f9SDavid Härdeman buf[2] << 8 | buf[3]); 18796d741bfeSSean Young proto = RC_PROTO_NEC32; 1880786baecfSMauro Carvalho Chehab } 1881786baecfSMauro Carvalho Chehab 18822b987ea7SAntti Palosaari dev_dbg(&intf->dev, "%*ph\n", 4, buf); 188375cd5886SAntti Palosaari 18842ceeca04SSean Young rc_keydown(d->rc_dev, proto, key, 0); 1885786baecfSMauro Carvalho Chehab 1886786baecfSMauro Carvalho Chehab return 0; 18871bfd5294SAntti Palosaari 18881bfd5294SAntti Palosaari err: 18892b987ea7SAntti Palosaari dev_dbg(&intf->dev, "failed=%d\n", ret); 18901bfd5294SAntti Palosaari 18911bfd5294SAntti Palosaari return ret; 1892786baecfSMauro Carvalho Chehab } 1893786baecfSMauro Carvalho Chehab 1894786baecfSMauro Carvalho Chehab static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 1895786baecfSMauro Carvalho Chehab { 189674c1883aSAntti Palosaari struct state *state = d_to_priv(d); 18972b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1898786baecfSMauro Carvalho Chehab 189909bfd96cSAntti Palosaari dev_dbg(&intf->dev, "ir_mode=%02x ir_type=%02x\n", 190009bfd96cSAntti Palosaari state->ir_mode, state->ir_type); 1901786baecfSMauro Carvalho Chehab 1902786baecfSMauro Carvalho Chehab /* don't activate rc if in HID mode or if not available */ 190309bfd96cSAntti Palosaari if (state->ir_mode == 0x05) { 190409bfd96cSAntti Palosaari switch (state->ir_type) { 1905786baecfSMauro Carvalho Chehab case 0: /* NEC */ 1906786baecfSMauro Carvalho Chehab default: 19076d741bfeSSean Young rc->allowed_protos = RC_PROTO_BIT_NEC | 19086d741bfeSSean Young RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32; 1909786baecfSMauro Carvalho Chehab break; 1910786baecfSMauro Carvalho Chehab case 1: /* RC6 */ 19116d741bfeSSean Young rc->allowed_protos = RC_PROTO_BIT_RC6_MCE; 1912786baecfSMauro Carvalho Chehab break; 1913786baecfSMauro Carvalho Chehab } 1914786baecfSMauro Carvalho Chehab 1915786baecfSMauro Carvalho Chehab rc->query = af9035_rc_query; 1916786baecfSMauro Carvalho Chehab rc->interval = 500; 1917786baecfSMauro Carvalho Chehab 1918786baecfSMauro Carvalho Chehab /* load empty to enable rc */ 1919786baecfSMauro Carvalho Chehab if (!rc->map_name) 1920786baecfSMauro Carvalho Chehab rc->map_name = RC_MAP_EMPTY; 1921786baecfSMauro Carvalho Chehab } 1922786baecfSMauro Carvalho Chehab 1923786baecfSMauro Carvalho Chehab return 0; 1924786baecfSMauro Carvalho Chehab } 1925eed5670aSAntti Palosaari #else 1926eed5670aSAntti Palosaari #define af9035_get_rc_config NULL 1927eed5670aSAntti Palosaari #endif 1928786baecfSMauro Carvalho Chehab 1929bada342eSAntti Palosaari static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, 1930bada342eSAntti Palosaari struct usb_data_stream_properties *stream) 1931bada342eSAntti Palosaari { 1932bada342eSAntti Palosaari struct dvb_usb_device *d = fe_to_d(fe); 19332b987ea7SAntti Palosaari struct usb_interface *intf = d->intf; 1934c10989a2SAntti Palosaari 19352b987ea7SAntti Palosaari dev_dbg(&intf->dev, "adap=%d\n", fe_to_adap(fe)->id); 1936bada342eSAntti Palosaari 1937bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 1938bada342eSAntti Palosaari stream->u.bulk.buffersize = 5 * 188; 1939bada342eSAntti Palosaari 1940bada342eSAntti Palosaari return 0; 1941bada342eSAntti Palosaari } 1942bada342eSAntti Palosaari 1943bada342eSAntti Palosaari static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) 1944bada342eSAntti Palosaari { 1945ed97a6feSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1946ed97a6feSMauro Carvalho Chehab 1947ed97a6feSMauro Carvalho Chehab return state->ops.pid_filter_ctrl(adap->fe[0], onoff); 1948bada342eSAntti Palosaari } 1949bada342eSAntti Palosaari 1950bada342eSAntti Palosaari static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, 1951bada342eSAntti Palosaari int onoff) 1952bada342eSAntti Palosaari { 1953ed97a6feSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1954ed97a6feSMauro Carvalho Chehab 1955ed97a6feSMauro Carvalho Chehab return state->ops.pid_filter(adap->fe[0], index, pid, onoff); 1956bada342eSAntti Palosaari } 1957bada342eSAntti Palosaari 1958b799b810SAntti Palosaari static int af9035_probe(struct usb_interface *intf, 1959b799b810SAntti Palosaari const struct usb_device_id *id) 1960b799b810SAntti Palosaari { 1961b799b810SAntti Palosaari struct usb_device *udev = interface_to_usbdev(intf); 1962b799b810SAntti Palosaari char manufacturer[sizeof("Afatech")]; 1963b799b810SAntti Palosaari 1964b799b810SAntti Palosaari memset(manufacturer, 0, sizeof(manufacturer)); 1965b799b810SAntti Palosaari usb_string(udev, udev->descriptor.iManufacturer, 1966b799b810SAntti Palosaari manufacturer, sizeof(manufacturer)); 1967b799b810SAntti Palosaari /* 1968b799b810SAntti Palosaari * There is two devices having same ID but different chipset. One uses 1969b799b810SAntti Palosaari * AF9015 and the other IT9135 chipset. Only difference seen on lsusb 1970b799b810SAntti Palosaari * is iManufacturer string. 1971b799b810SAntti Palosaari * 1972b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1973b799b810SAntti Palosaari * idProduct 0x0099 1974b799b810SAntti Palosaari * bcdDevice 2.00 1975b799b810SAntti Palosaari * iManufacturer 1 Afatech 1976b799b810SAntti Palosaari * iProduct 2 DVB-T 2 1977b799b810SAntti Palosaari * 1978b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1979b799b810SAntti Palosaari * idProduct 0x0099 1980b799b810SAntti Palosaari * bcdDevice 2.00 1981b799b810SAntti Palosaari * iManufacturer 1 ITE Technologies, Inc. 1982b799b810SAntti Palosaari * iProduct 2 DVB-T TV Stick 1983b799b810SAntti Palosaari */ 1984b799b810SAntti Palosaari if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && 1985b799b810SAntti Palosaari (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { 1986b799b810SAntti Palosaari if (!strcmp("Afatech", manufacturer)) { 19872b987ea7SAntti Palosaari dev_dbg(&udev->dev, "rejecting device\n"); 1988b799b810SAntti Palosaari return -ENODEV; 1989b799b810SAntti Palosaari } 1990b799b810SAntti Palosaari } 1991b799b810SAntti Palosaari 1992b799b810SAntti Palosaari return dvb_usbv2_probe(intf, id); 1993b799b810SAntti Palosaari } 1994b799b810SAntti Palosaari 1995786baecfSMauro Carvalho Chehab /* interface 0 is used by DVB-T receiver and 1996786baecfSMauro Carvalho Chehab interface 1 is for remote controller (HID) */ 1997786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties af9035_props = { 1998786baecfSMauro Carvalho Chehab .driver_name = KBUILD_MODNAME, 1999786baecfSMauro Carvalho Chehab .owner = THIS_MODULE, 2000786baecfSMauro Carvalho Chehab .adapter_nr = adapter_nr, 2001786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct state), 2002786baecfSMauro Carvalho Chehab 2003786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x02, 2004786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint_response = 0x81, 2005786baecfSMauro Carvalho Chehab 2006786baecfSMauro Carvalho Chehab .identify_state = af9035_identify_state, 2007786baecfSMauro Carvalho Chehab .download_firmware = af9035_download_firmware, 2008786baecfSMauro Carvalho Chehab 2009786baecfSMauro Carvalho Chehab .i2c_algo = &af9035_i2c_algo, 2010786baecfSMauro Carvalho Chehab .read_config = af9035_read_config, 2011786baecfSMauro Carvalho Chehab .frontend_attach = af9035_frontend_attach, 2012d4d6a34dSAntti Palosaari .frontend_detach = af9035_frontend_detach, 2013786baecfSMauro Carvalho Chehab .tuner_attach = af9035_tuner_attach, 2014d4d6a34dSAntti Palosaari .tuner_detach = af9035_tuner_detach, 2015786baecfSMauro Carvalho Chehab .init = af9035_init, 2016786baecfSMauro Carvalho Chehab .get_rc_config = af9035_get_rc_config, 2017bada342eSAntti Palosaari .get_stream_config = af9035_get_stream_config, 2018786baecfSMauro Carvalho Chehab 20199805992fSJose Alberto Reguero .get_adapter_count = af9035_get_adapter_count, 2020786baecfSMauro Carvalho Chehab .adapter = { 2021786baecfSMauro Carvalho Chehab { 2022bada342eSAntti Palosaari .caps = DVB_USB_ADAP_HAS_PID_FILTER | 2023bada342eSAntti Palosaari DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 2024bada342eSAntti Palosaari 2025bada342eSAntti Palosaari .pid_filter_count = 32, 2026bada342eSAntti Palosaari .pid_filter_ctrl = af9035_pid_filter_ctrl, 2027bada342eSAntti Palosaari .pid_filter = af9035_pid_filter, 2028bada342eSAntti Palosaari 2029786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), 2030786baecfSMauro Carvalho Chehab }, { 2031b24c2b4fSAntti Palosaari .caps = DVB_USB_ADAP_HAS_PID_FILTER | 2032b24c2b4fSAntti Palosaari DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 2033b24c2b4fSAntti Palosaari 2034b24c2b4fSAntti Palosaari .pid_filter_count = 32, 2035b24c2b4fSAntti Palosaari .pid_filter_ctrl = af9035_pid_filter_ctrl, 2036b24c2b4fSAntti Palosaari .pid_filter = af9035_pid_filter, 2037b24c2b4fSAntti Palosaari 2038786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), 2039786baecfSMauro Carvalho Chehab }, 2040786baecfSMauro Carvalho Chehab }, 2041786baecfSMauro Carvalho Chehab }; 2042786baecfSMauro Carvalho Chehab 20435b556084SOlli Salonen static const struct dvb_usb_device_properties it930x_props = { 20445b556084SOlli Salonen .driver_name = KBUILD_MODNAME, 20455b556084SOlli Salonen .owner = THIS_MODULE, 20465b556084SOlli Salonen .adapter_nr = adapter_nr, 20475b556084SOlli Salonen .size_of_priv = sizeof(struct state), 20485b556084SOlli Salonen 20495b556084SOlli Salonen .generic_bulk_ctrl_endpoint = 0x02, 20505b556084SOlli Salonen .generic_bulk_ctrl_endpoint_response = 0x81, 20515b556084SOlli Salonen 20525b556084SOlli Salonen .identify_state = af9035_identify_state, 20535b556084SOlli Salonen .download_firmware = af9035_download_firmware, 20545b556084SOlli Salonen 20555b556084SOlli Salonen .i2c_algo = &af9035_i2c_algo, 20565b556084SOlli Salonen .read_config = af9035_read_config, 20575b556084SOlli Salonen .frontend_attach = it930x_frontend_attach, 20585b556084SOlli Salonen .frontend_detach = af9035_frontend_detach, 20595b556084SOlli Salonen .tuner_attach = it930x_tuner_attach, 20605b556084SOlli Salonen .tuner_detach = it930x_tuner_detach, 20615b556084SOlli Salonen .init = it930x_init, 20625b556084SOlli Salonen .get_stream_config = af9035_get_stream_config, 20635b556084SOlli Salonen 20645b556084SOlli Salonen .get_adapter_count = af9035_get_adapter_count, 20655b556084SOlli Salonen .adapter = { 20665b556084SOlli Salonen { 20675b556084SOlli Salonen .stream = DVB_USB_STREAM_BULK(0x84, 4, 816 * 188), 20685b556084SOlli Salonen }, { 20695b556084SOlli Salonen .stream = DVB_USB_STREAM_BULK(0x85, 4, 816 * 188), 20705b556084SOlli Salonen }, 20715b556084SOlli Salonen }, 20725b556084SOlli Salonen }; 20735b556084SOlli Salonen 2074786baecfSMauro Carvalho Chehab static const struct usb_device_id af9035_id_table[] = { 2075bc3c9e10SAntti Palosaari /* AF9035 devices */ 2076786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, 2077786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 2078786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, 2079786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 2080786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, 2081786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 2082786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, 2083786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 2084786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, 2085786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 2086786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, 2087786baecfSMauro Carvalho Chehab &af9035_props, "TerraTec Cinergy T Stick", NULL) }, 2088786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, 2089786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 2090786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, 2091786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 2092786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, 2093786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 2094786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, 2095786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 2096786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, 2097786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, 2098d67ceb33SOliver Schinagl { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, 2099d67ceb33SOliver Schinagl &af9035_props, "Asus U3100Mini Plus", NULL) }, 2100d9b7595bSFabrizio Gazzato { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, 2101d9b7595bSFabrizio Gazzato &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, 2102baf06b51SAntti Palosaari { DVB_USB_DEVICE(USB_VID_AVERMEDIA, 0x0337, 2103baf06b51SAntti Palosaari &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 210437e78568SCIJOML CIJOMLovic { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_EVOLVEO_XTRATV_STICK, 210537e78568SCIJOML CIJOMLovic &af9035_props, "EVOLVEO XtraTV stick", NULL) }, 2106b3f02270SAntti Palosaari 2107bc3c9e10SAntti Palosaari /* IT9135 devices */ 21087a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, 21097a541ce0SMalcolm Priestley &af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) }, 21107a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, 21117a541ce0SMalcolm Priestley &af9035_props, "ITE 9135(9005) Generic", RC_MAP_IT913X_V2) }, 21127a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, 21137a541ce0SMalcolm Priestley &af9035_props, "ITE 9135(9006) Generic", RC_MAP_IT913X_V1) }, 21147a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835, 21157a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(1835)", RC_MAP_IT913X_V2) }, 21167a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835, 21177a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(2835)", RC_MAP_IT913X_V2) }, 21187a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835, 21197a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(3835)", RC_MAP_IT913X_V2) }, 21207a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, 21217a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, 2122b8ebfafcSPhilippe Valembois { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD110, 2123b8ebfafcSPhilippe Valembois &af9035_props, "Avermedia AverTV Volar HD 2 (TD110)", RC_MAP_AVERMEDIA_RM_KS) }, 21247a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335, 21257a541ce0SMalcolm Priestley &af9035_props, "Avermedia H335", RC_MAP_IT913X_V2) }, 212637973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, 212737973e01SMalcolm Priestley &af9035_props, "Kworld UB499-2T T09", RC_MAP_IT913X_V1) }, 212837973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, 212937973e01SMalcolm Priestley &af9035_props, "Sveon STV22 Dual DVB-T HDTV", 213037973e01SMalcolm Priestley RC_MAP_IT913X_V1) }, 213137973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, 213237973e01SMalcolm Priestley &af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2", 213337973e01SMalcolm Priestley RC_MAP_IT913X_V1) }, 2134b5e0733fSNuno Henriques { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T1, 2135b5e0733fSNuno Henriques &af9035_props, "TerraTec T1", RC_MAP_IT913X_V1) }, 2136b799b810SAntti Palosaari /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ 2137b799b810SAntti Palosaari { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, 2138c10989a2SAntti Palosaari &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", 2139c10989a2SAntti Palosaari NULL) }, 21400c413d10SAntti Palosaari { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, 21410c413d10SAntti Palosaari &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, 2142261cb200SAntti Palosaari { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, 2143261cb200SAntti Palosaari &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, 2144a04646c0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E, 21455c114a4fSAntti Palosaari &af9035_props, "PCTV AndroiDTV (78e)", RC_MAP_IT913X_V1) }, 2146a04646c0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E, 21475c114a4fSAntti Palosaari &af9035_props, "PCTV microStick (79e)", RC_MAP_IT913X_V2) }, 2148b3f02270SAntti Palosaari 2149b3f02270SAntti Palosaari /* IT930x devices */ 2150b3f02270SAntti Palosaari { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303, 2151b3f02270SAntti Palosaari &it930x_props, "ITE 9303 Generic", NULL) }, 2152c51f3b7fSJose Alberto Reguero { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD310, 2153c51f3b7fSJose Alberto Reguero &it930x_props, "AVerMedia TD310 DVB-T2", NULL) }, 21546bf05f75SGon Solo { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x0100, 21556bf05f75SGon Solo &it930x_props, "Logilink VG0022A", NULL) }, 2156c0e0d313STomasz Maciej Nowak { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_TC2_STICK, 2157c0e0d313STomasz Maciej Nowak &it930x_props, "TerraTec Cinergy TC2 Stick", NULL) }, 2158786baecfSMauro Carvalho Chehab { } 2159786baecfSMauro Carvalho Chehab }; 2160786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, af9035_id_table); 2161786baecfSMauro Carvalho Chehab 2162786baecfSMauro Carvalho Chehab static struct usb_driver af9035_usb_driver = { 2163786baecfSMauro Carvalho Chehab .name = KBUILD_MODNAME, 2164786baecfSMauro Carvalho Chehab .id_table = af9035_id_table, 2165b799b810SAntti Palosaari .probe = af9035_probe, 2166786baecfSMauro Carvalho Chehab .disconnect = dvb_usbv2_disconnect, 2167786baecfSMauro Carvalho Chehab .suspend = dvb_usbv2_suspend, 2168786baecfSMauro Carvalho Chehab .resume = dvb_usbv2_resume, 216904966aa8SAntti Palosaari .reset_resume = dvb_usbv2_reset_resume, 2170786baecfSMauro Carvalho Chehab .no_dynamic_id = 1, 2171786baecfSMauro Carvalho Chehab .soft_unbind = 1, 2172786baecfSMauro Carvalho Chehab }; 2173786baecfSMauro Carvalho Chehab 2174786baecfSMauro Carvalho Chehab module_usb_driver(af9035_usb_driver); 2175786baecfSMauro Carvalho Chehab 2176786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 2177786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9035 driver"); 2178786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 21794395e4b7SAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); 218074c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); 218174c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); 21825b556084SOlli Salonen MODULE_FIRMWARE(AF9035_FIRMWARE_IT9303); 2183