1786baecfSMauro Carvalho Chehab /* 2786baecfSMauro Carvalho Chehab * Afatech AF9035 DVB USB driver 3786baecfSMauro Carvalho Chehab * 4786baecfSMauro Carvalho Chehab * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 5786baecfSMauro Carvalho Chehab * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 6786baecfSMauro Carvalho Chehab * 7786baecfSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 8786baecfSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 9786baecfSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 10786baecfSMauro Carvalho Chehab * (at your option) any later version. 11786baecfSMauro Carvalho Chehab * 12786baecfSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 13786baecfSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 14786baecfSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15786baecfSMauro Carvalho Chehab * GNU General Public License for more details. 16786baecfSMauro Carvalho Chehab * 17786baecfSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License along 18786baecfSMauro Carvalho Chehab * with this program; if not, write to the Free Software Foundation, Inc., 19786baecfSMauro Carvalho Chehab * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20786baecfSMauro Carvalho Chehab */ 21786baecfSMauro Carvalho Chehab 22786baecfSMauro Carvalho Chehab #include "af9035.h" 23786baecfSMauro Carvalho Chehab 24786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 25786baecfSMauro Carvalho Chehab 26786baecfSMauro Carvalho Chehab static u16 af9035_checksum(const u8 *buf, size_t len) 27786baecfSMauro Carvalho Chehab { 28786baecfSMauro Carvalho Chehab size_t i; 29786baecfSMauro Carvalho Chehab u16 checksum = 0; 30786baecfSMauro Carvalho Chehab 31786baecfSMauro Carvalho Chehab for (i = 1; i < len; i++) { 32786baecfSMauro Carvalho Chehab if (i % 2) 33786baecfSMauro Carvalho Chehab checksum += buf[i] << 8; 34786baecfSMauro Carvalho Chehab else 35786baecfSMauro Carvalho Chehab checksum += buf[i]; 36786baecfSMauro Carvalho Chehab } 37786baecfSMauro Carvalho Chehab checksum = ~checksum; 38786baecfSMauro Carvalho Chehab 39786baecfSMauro Carvalho Chehab return checksum; 40786baecfSMauro Carvalho Chehab } 41786baecfSMauro Carvalho Chehab 42786baecfSMauro Carvalho Chehab static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) 43786baecfSMauro Carvalho Chehab { 44786baecfSMauro Carvalho Chehab #define REQ_HDR_LEN 4 /* send header size */ 45786baecfSMauro Carvalho Chehab #define ACK_HDR_LEN 3 /* rece header size */ 46786baecfSMauro Carvalho Chehab #define CHECKSUM_LEN 2 47786baecfSMauro Carvalho Chehab #define USB_TIMEOUT 2000 48786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 49786baecfSMauro Carvalho Chehab int ret, wlen, rlen; 50786baecfSMauro Carvalho Chehab u16 checksum, tmp_checksum; 51786baecfSMauro Carvalho Chehab 523484d37aSAntti Palosaari mutex_lock(&d->usb_mutex); 533484d37aSAntti Palosaari 54786baecfSMauro Carvalho Chehab /* buffer overflow check */ 55786baecfSMauro Carvalho Chehab if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || 56786baecfSMauro Carvalho Chehab req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { 57119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", 58119f7a8cSAntti Palosaari __func__, req->wlen, req->rlen); 593484d37aSAntti Palosaari ret = -EINVAL; 603484d37aSAntti Palosaari goto err; 61786baecfSMauro Carvalho Chehab } 62786baecfSMauro Carvalho Chehab 633484d37aSAntti Palosaari state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; 643484d37aSAntti Palosaari state->buf[1] = req->mbox; 653484d37aSAntti Palosaari state->buf[2] = req->cmd; 663484d37aSAntti Palosaari state->buf[3] = state->seq++; 673484d37aSAntti Palosaari memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen); 68786baecfSMauro Carvalho Chehab 69786baecfSMauro Carvalho Chehab wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; 70786baecfSMauro Carvalho Chehab rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; 71786baecfSMauro Carvalho Chehab 72786baecfSMauro Carvalho Chehab /* calc and add checksum */ 733484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, state->buf[0] - 1); 743484d37aSAntti Palosaari state->buf[state->buf[0] - 1] = (checksum >> 8); 753484d37aSAntti Palosaari state->buf[state->buf[0] - 0] = (checksum & 0xff); 76786baecfSMauro Carvalho Chehab 77786baecfSMauro Carvalho Chehab /* no ack for these packets */ 78786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 79786baecfSMauro Carvalho Chehab rlen = 0; 80786baecfSMauro Carvalho Chehab 813484d37aSAntti Palosaari ret = dvb_usbv2_generic_rw_locked(d, 823484d37aSAntti Palosaari state->buf, wlen, state->buf, rlen); 83786baecfSMauro Carvalho Chehab if (ret) 84786baecfSMauro Carvalho Chehab goto err; 85786baecfSMauro Carvalho Chehab 86786baecfSMauro Carvalho Chehab /* no ack for those packets */ 87786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 88786baecfSMauro Carvalho Chehab goto exit; 89786baecfSMauro Carvalho Chehab 90786baecfSMauro Carvalho Chehab /* verify checksum */ 913484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, rlen - 2); 923484d37aSAntti Palosaari tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; 93786baecfSMauro Carvalho Chehab if (tmp_checksum != checksum) { 94119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \ 95119f7a8cSAntti Palosaari "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd, 96119f7a8cSAntti Palosaari tmp_checksum, checksum); 97786baecfSMauro Carvalho Chehab ret = -EIO; 98786baecfSMauro Carvalho Chehab goto err; 99786baecfSMauro Carvalho Chehab } 100786baecfSMauro Carvalho Chehab 101786baecfSMauro Carvalho Chehab /* check status */ 1023484d37aSAntti Palosaari if (state->buf[2]) { 103119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n", 1043484d37aSAntti Palosaari __func__, req->cmd, state->buf[2]); 105786baecfSMauro Carvalho Chehab ret = -EIO; 106786baecfSMauro Carvalho Chehab goto err; 107786baecfSMauro Carvalho Chehab } 108786baecfSMauro Carvalho Chehab 109786baecfSMauro Carvalho Chehab /* read request, copy returned data to return buf */ 110786baecfSMauro Carvalho Chehab if (req->rlen) 1113484d37aSAntti Palosaari memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen); 112786baecfSMauro Carvalho Chehab exit: 113786baecfSMauro Carvalho Chehab err: 1143484d37aSAntti Palosaari mutex_unlock(&d->usb_mutex); 1153484d37aSAntti Palosaari if (ret) 116119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 117786baecfSMauro Carvalho Chehab return ret; 118786baecfSMauro Carvalho Chehab } 119786baecfSMauro Carvalho Chehab 120786baecfSMauro Carvalho Chehab /* write multiple registers */ 121786baecfSMauro Carvalho Chehab static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 122786baecfSMauro Carvalho Chehab { 123786baecfSMauro Carvalho Chehab u8 wbuf[6 + len]; 124786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 125786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; 126786baecfSMauro Carvalho Chehab 127786baecfSMauro Carvalho Chehab wbuf[0] = len; 128786baecfSMauro Carvalho Chehab wbuf[1] = 2; 129786baecfSMauro Carvalho Chehab wbuf[2] = 0; 130786baecfSMauro Carvalho Chehab wbuf[3] = 0; 131786baecfSMauro Carvalho Chehab wbuf[4] = (reg >> 8) & 0xff; 132786baecfSMauro Carvalho Chehab wbuf[5] = (reg >> 0) & 0xff; 133786baecfSMauro Carvalho Chehab memcpy(&wbuf[6], val, len); 134786baecfSMauro Carvalho Chehab 135786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 136786baecfSMauro Carvalho Chehab } 137786baecfSMauro Carvalho Chehab 138786baecfSMauro Carvalho Chehab /* read multiple registers */ 139786baecfSMauro Carvalho Chehab static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 140786baecfSMauro Carvalho Chehab { 141786baecfSMauro Carvalho Chehab u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; 142786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 143786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; 144786baecfSMauro Carvalho Chehab 145786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 146786baecfSMauro Carvalho Chehab } 147786baecfSMauro Carvalho Chehab 148786baecfSMauro Carvalho Chehab /* write single register */ 149786baecfSMauro Carvalho Chehab static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) 150786baecfSMauro Carvalho Chehab { 151786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 152786baecfSMauro Carvalho Chehab } 153786baecfSMauro Carvalho Chehab 154786baecfSMauro Carvalho Chehab /* read single register */ 155786baecfSMauro Carvalho Chehab static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) 156786baecfSMauro Carvalho Chehab { 157786baecfSMauro Carvalho Chehab return af9035_rd_regs(d, reg, val, 1); 158786baecfSMauro Carvalho Chehab } 159786baecfSMauro Carvalho Chehab 160786baecfSMauro Carvalho Chehab /* write single register with mask */ 161786baecfSMauro Carvalho Chehab static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, 162786baecfSMauro Carvalho Chehab u8 mask) 163786baecfSMauro Carvalho Chehab { 164786baecfSMauro Carvalho Chehab int ret; 165786baecfSMauro Carvalho Chehab u8 tmp; 166786baecfSMauro Carvalho Chehab 167786baecfSMauro Carvalho Chehab /* no need for read if whole reg is written */ 168786baecfSMauro Carvalho Chehab if (mask != 0xff) { 169786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &tmp, 1); 170786baecfSMauro Carvalho Chehab if (ret) 171786baecfSMauro Carvalho Chehab return ret; 172786baecfSMauro Carvalho Chehab 173786baecfSMauro Carvalho Chehab val &= mask; 174786baecfSMauro Carvalho Chehab tmp &= ~mask; 175786baecfSMauro Carvalho Chehab val |= tmp; 176786baecfSMauro Carvalho Chehab } 177786baecfSMauro Carvalho Chehab 178786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 179786baecfSMauro Carvalho Chehab } 180786baecfSMauro Carvalho Chehab 181786baecfSMauro Carvalho Chehab static int af9035_i2c_master_xfer(struct i2c_adapter *adap, 182786baecfSMauro Carvalho Chehab struct i2c_msg msg[], int num) 183786baecfSMauro Carvalho Chehab { 184786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 185786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 186786baecfSMauro Carvalho Chehab int ret; 187786baecfSMauro Carvalho Chehab 188786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 189786baecfSMauro Carvalho Chehab return -EAGAIN; 190786baecfSMauro Carvalho Chehab 191786baecfSMauro Carvalho Chehab /* 192786baecfSMauro Carvalho Chehab * I2C sub header is 5 bytes long. Meaning of those bytes are: 193786baecfSMauro Carvalho Chehab * 0: data len 194786baecfSMauro Carvalho Chehab * 1: I2C addr << 1 195786baecfSMauro Carvalho Chehab * 2: reg addr len 196786baecfSMauro Carvalho Chehab * byte 3 and 4 can be used as reg addr 197786baecfSMauro Carvalho Chehab * 3: reg addr MSB 198786baecfSMauro Carvalho Chehab * used when reg addr len is set to 2 199786baecfSMauro Carvalho Chehab * 4: reg addr LSB 200786baecfSMauro Carvalho Chehab * used when reg addr len is set to 1 or 2 201786baecfSMauro Carvalho Chehab * 202786baecfSMauro Carvalho Chehab * For the simplify we do not use register addr at all. 203786baecfSMauro Carvalho Chehab * NOTE: As a firmware knows tuner type there is very small possibility 204786baecfSMauro Carvalho Chehab * there could be some tuner I2C hacks done by firmware and this may 205786baecfSMauro Carvalho Chehab * lead problems if firmware expects those bytes are used. 206786baecfSMauro Carvalho Chehab */ 207786baecfSMauro Carvalho Chehab if (num == 2 && !(msg[0].flags & I2C_M_RD) && 208786baecfSMauro Carvalho Chehab (msg[1].flags & I2C_M_RD)) { 209786baecfSMauro Carvalho Chehab if (msg[0].len > 40 || msg[1].len > 40) { 210786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 211786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 2129805992fSJose Alberto Reguero } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || 2139805992fSJose Alberto Reguero (msg[0].addr == state->af9033_config[1].i2c_addr)) { 214bf97b637SAntti Palosaari /* demod access via firmware interface */ 215786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 216786baecfSMauro Carvalho Chehab msg[0].buf[2]; 217bf97b637SAntti Palosaari 218bf97b637SAntti Palosaari if (msg[0].addr == state->af9033_config[1].i2c_addr) 2199805992fSJose Alberto Reguero reg |= 0x100000; 220bf97b637SAntti Palosaari 221786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &msg[1].buf[0], 222786baecfSMauro Carvalho Chehab msg[1].len); 223786baecfSMauro Carvalho Chehab } else { 224786baecfSMauro Carvalho Chehab /* I2C */ 225786baecfSMauro Carvalho Chehab u8 buf[5 + msg[0].len]; 226786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), 227786baecfSMauro Carvalho Chehab buf, msg[1].len, msg[1].buf }; 2289805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 229786baecfSMauro Carvalho Chehab buf[0] = msg[1].len; 230bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 231786baecfSMauro Carvalho Chehab buf[2] = 0x00; /* reg addr len */ 232786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 233786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 234786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 235786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 236786baecfSMauro Carvalho Chehab } 237786baecfSMauro Carvalho Chehab } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { 238786baecfSMauro Carvalho Chehab if (msg[0].len > 40) { 239786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 240786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 2419805992fSJose Alberto Reguero } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || 2429805992fSJose Alberto Reguero (msg[0].addr == state->af9033_config[1].i2c_addr)) { 243bf97b637SAntti Palosaari /* demod access via firmware interface */ 244786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 245786baecfSMauro Carvalho Chehab msg[0].buf[2]; 246bf97b637SAntti Palosaari 247bf97b637SAntti Palosaari if (msg[0].addr == state->af9033_config[1].i2c_addr) 2489805992fSJose Alberto Reguero reg |= 0x100000; 249bf97b637SAntti Palosaari 250786baecfSMauro Carvalho Chehab ret = af9035_wr_regs(d, reg, &msg[0].buf[3], 251786baecfSMauro Carvalho Chehab msg[0].len - 3); 252786baecfSMauro Carvalho Chehab } else { 253786baecfSMauro Carvalho Chehab /* I2C */ 254786baecfSMauro Carvalho Chehab u8 buf[5 + msg[0].len]; 255786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, 256786baecfSMauro Carvalho Chehab 0, NULL }; 2579805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 258786baecfSMauro Carvalho Chehab buf[0] = msg[0].len; 259bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 260786baecfSMauro Carvalho Chehab buf[2] = 0x00; /* reg addr len */ 261786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 262786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 263786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 264786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 265786baecfSMauro Carvalho Chehab } 266786baecfSMauro Carvalho Chehab } else { 267786baecfSMauro Carvalho Chehab /* 268786baecfSMauro Carvalho Chehab * We support only two kind of I2C transactions: 269786baecfSMauro Carvalho Chehab * 1) 1 x read + 1 x write 270786baecfSMauro Carvalho Chehab * 2) 1 x write 271786baecfSMauro Carvalho Chehab */ 272786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 273786baecfSMauro Carvalho Chehab } 274786baecfSMauro Carvalho Chehab 275786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 276786baecfSMauro Carvalho Chehab 277786baecfSMauro Carvalho Chehab if (ret < 0) 278786baecfSMauro Carvalho Chehab return ret; 279786baecfSMauro Carvalho Chehab else 280786baecfSMauro Carvalho Chehab return num; 281786baecfSMauro Carvalho Chehab } 282786baecfSMauro Carvalho Chehab 283786baecfSMauro Carvalho Chehab static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) 284786baecfSMauro Carvalho Chehab { 285786baecfSMauro Carvalho Chehab return I2C_FUNC_I2C; 286786baecfSMauro Carvalho Chehab } 287786baecfSMauro Carvalho Chehab 288786baecfSMauro Carvalho Chehab static struct i2c_algorithm af9035_i2c_algo = { 289786baecfSMauro Carvalho Chehab .master_xfer = af9035_i2c_master_xfer, 290786baecfSMauro Carvalho Chehab .functionality = af9035_i2c_functionality, 291786baecfSMauro Carvalho Chehab }; 292786baecfSMauro Carvalho Chehab 293786baecfSMauro Carvalho Chehab static int af9035_identify_state(struct dvb_usb_device *d, const char **name) 294786baecfSMauro Carvalho Chehab { 29574c1883aSAntti Palosaari struct state *state = d_to_priv(d); 296786baecfSMauro Carvalho Chehab int ret; 297786baecfSMauro Carvalho Chehab u8 wbuf[1] = { 1 }; 298786baecfSMauro Carvalho Chehab u8 rbuf[4]; 299786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, 300786baecfSMauro Carvalho Chehab sizeof(rbuf), rbuf }; 301786baecfSMauro Carvalho Chehab 30274c1883aSAntti Palosaari ret = af9035_rd_regs(d, 0x1222, rbuf, 3); 30374c1883aSAntti Palosaari if (ret < 0) 30474c1883aSAntti Palosaari goto err; 30574c1883aSAntti Palosaari 30674c1883aSAntti Palosaari state->chip_version = rbuf[0]; 30774c1883aSAntti Palosaari state->chip_type = rbuf[2] << 8 | rbuf[1] << 0; 30874c1883aSAntti Palosaari 30974c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x384f, &state->prechip_version); 31074c1883aSAntti Palosaari if (ret < 0) 31174c1883aSAntti Palosaari goto err; 31274c1883aSAntti Palosaari 31374c1883aSAntti Palosaari dev_info(&d->udev->dev, 31474c1883aSAntti Palosaari "%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n", 31574c1883aSAntti Palosaari __func__, state->prechip_version, state->chip_version, 31674c1883aSAntti Palosaari state->chip_type); 31774c1883aSAntti Palosaari 31874c1883aSAntti Palosaari if (state->chip_type == 0x9135) { 31974c1883aSAntti Palosaari if (state->chip_version == 2) 32074c1883aSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V2; 32174c1883aSAntti Palosaari else 32274c1883aSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V1; 32374c1883aSAntti Palosaari } else { 32474c1883aSAntti Palosaari *name = AF9035_FIRMWARE_AF9035; 32574c1883aSAntti Palosaari } 32674c1883aSAntti Palosaari 327786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 328786baecfSMauro Carvalho Chehab if (ret < 0) 329786baecfSMauro Carvalho Chehab goto err; 330786baecfSMauro Carvalho Chehab 331119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: reply=%*ph\n", __func__, 4, rbuf); 332786baecfSMauro Carvalho Chehab if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) 333786baecfSMauro Carvalho Chehab ret = WARM; 334786baecfSMauro Carvalho Chehab else 335786baecfSMauro Carvalho Chehab ret = COLD; 336786baecfSMauro Carvalho Chehab 337786baecfSMauro Carvalho Chehab return ret; 338786baecfSMauro Carvalho Chehab 339786baecfSMauro Carvalho Chehab err: 340119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 341786baecfSMauro Carvalho Chehab 342786baecfSMauro Carvalho Chehab return ret; 343786baecfSMauro Carvalho Chehab } 344786baecfSMauro Carvalho Chehab 34574c1883aSAntti Palosaari static int af9035_download_firmware_af9035(struct dvb_usb_device *d, 346786baecfSMauro Carvalho Chehab const struct firmware *fw) 347786baecfSMauro Carvalho Chehab { 348786baecfSMauro Carvalho Chehab int ret, i, j, len; 349786baecfSMauro Carvalho Chehab u8 wbuf[1]; 350786baecfSMauro Carvalho Chehab u8 rbuf[4]; 351786baecfSMauro Carvalho Chehab struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 352786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; 353786baecfSMauro Carvalho Chehab struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; 354bf97b637SAntti Palosaari u8 hdr_core, tmp; 355786baecfSMauro Carvalho Chehab u16 hdr_addr, hdr_data_len, hdr_checksum; 356786baecfSMauro Carvalho Chehab #define MAX_DATA 58 357786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 358786baecfSMauro Carvalho Chehab 359786baecfSMauro Carvalho Chehab /* 360bf97b637SAntti Palosaari * In case of dual tuner configuration we need to do some extra 361bf97b637SAntti Palosaari * initialization in order to download firmware to slave demod too, 362bf97b637SAntti Palosaari * which is done by master demod. 363bf97b637SAntti Palosaari * Master feeds also clock and controls power via GPIO. 364bf97b637SAntti Palosaari */ 365bf97b637SAntti Palosaari ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); 366bf97b637SAntti Palosaari if (ret < 0) 367bf97b637SAntti Palosaari goto err; 368bf97b637SAntti Palosaari 369bf97b637SAntti Palosaari if (tmp) { 370bf97b637SAntti Palosaari /* configure gpioh1, reset & power slave demod */ 371bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); 372bf97b637SAntti Palosaari if (ret < 0) 373bf97b637SAntti Palosaari goto err; 374bf97b637SAntti Palosaari 375bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01); 376bf97b637SAntti Palosaari if (ret < 0) 377bf97b637SAntti Palosaari goto err; 378bf97b637SAntti Palosaari 379bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01); 380bf97b637SAntti Palosaari if (ret < 0) 381bf97b637SAntti Palosaari goto err; 382bf97b637SAntti Palosaari 383bf97b637SAntti Palosaari usleep_range(10000, 50000); 384bf97b637SAntti Palosaari 385bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01); 386bf97b637SAntti Palosaari if (ret < 0) 387bf97b637SAntti Palosaari goto err; 388bf97b637SAntti Palosaari 389bf97b637SAntti Palosaari /* tell the slave I2C address */ 390bf97b637SAntti Palosaari ret = af9035_rd_reg(d, EEPROM_2ND_DEMOD_ADDR, &tmp); 391bf97b637SAntti Palosaari if (ret < 0) 392bf97b637SAntti Palosaari goto err; 393bf97b637SAntti Palosaari 394bf97b637SAntti Palosaari ret = af9035_wr_reg(d, 0x00417f, tmp); 395bf97b637SAntti Palosaari if (ret < 0) 396bf97b637SAntti Palosaari goto err; 397bf97b637SAntti Palosaari 398bf97b637SAntti Palosaari /* enable clock out */ 399bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); 400bf97b637SAntti Palosaari if (ret < 0) 401bf97b637SAntti Palosaari goto err; 402bf97b637SAntti Palosaari } 403bf97b637SAntti Palosaari 404bf97b637SAntti Palosaari /* 405786baecfSMauro Carvalho Chehab * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! 406786baecfSMauro Carvalho Chehab * 407786baecfSMauro Carvalho Chehab * byte 0: MCS 51 core 408786baecfSMauro Carvalho Chehab * There are two inside the AF9035 (1=Link and 2=OFDM) with separate 409786baecfSMauro Carvalho Chehab * address spaces 410786baecfSMauro Carvalho Chehab * byte 1-2: Big endian destination address 411786baecfSMauro Carvalho Chehab * byte 3-4: Big endian number of data bytes following the header 412786baecfSMauro Carvalho Chehab * byte 5-6: Big endian header checksum, apparently ignored by the chip 413786baecfSMauro Carvalho Chehab * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) 414786baecfSMauro Carvalho Chehab */ 415786baecfSMauro Carvalho Chehab 416786baecfSMauro Carvalho Chehab for (i = fw->size; i > HDR_SIZE;) { 417786baecfSMauro Carvalho Chehab hdr_core = fw->data[fw->size - i + 0]; 418786baecfSMauro Carvalho Chehab hdr_addr = fw->data[fw->size - i + 1] << 8; 419786baecfSMauro Carvalho Chehab hdr_addr |= fw->data[fw->size - i + 2] << 0; 420786baecfSMauro Carvalho Chehab hdr_data_len = fw->data[fw->size - i + 3] << 8; 421786baecfSMauro Carvalho Chehab hdr_data_len |= fw->data[fw->size - i + 4] << 0; 422786baecfSMauro Carvalho Chehab hdr_checksum = fw->data[fw->size - i + 5] << 8; 423786baecfSMauro Carvalho Chehab hdr_checksum |= fw->data[fw->size - i + 6] << 0; 424786baecfSMauro Carvalho Chehab 425119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ 426119f7a8cSAntti Palosaari "checksum=%04x\n", __func__, hdr_core, hdr_addr, 427119f7a8cSAntti Palosaari hdr_data_len, hdr_checksum); 428786baecfSMauro Carvalho Chehab 429786baecfSMauro Carvalho Chehab if (((hdr_core != 1) && (hdr_core != 2)) || 430786baecfSMauro Carvalho Chehab (hdr_data_len > i)) { 431119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: bad firmware\n", __func__); 432786baecfSMauro Carvalho Chehab break; 433786baecfSMauro Carvalho Chehab } 434786baecfSMauro Carvalho Chehab 435786baecfSMauro Carvalho Chehab /* download begin packet */ 436786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_BEGIN; 437786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 438786baecfSMauro Carvalho Chehab if (ret < 0) 439786baecfSMauro Carvalho Chehab goto err; 440786baecfSMauro Carvalho Chehab 441786baecfSMauro Carvalho Chehab /* download firmware packet(s) */ 442786baecfSMauro Carvalho Chehab for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { 443786baecfSMauro Carvalho Chehab len = j; 444786baecfSMauro Carvalho Chehab if (len > MAX_DATA) 445786baecfSMauro Carvalho Chehab len = MAX_DATA; 446786baecfSMauro Carvalho Chehab req_fw_dl.wlen = len; 447786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + 448786baecfSMauro Carvalho Chehab HDR_SIZE + hdr_data_len - j]; 449786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 450786baecfSMauro Carvalho Chehab if (ret < 0) 451786baecfSMauro Carvalho Chehab goto err; 452786baecfSMauro Carvalho Chehab } 453786baecfSMauro Carvalho Chehab 454786baecfSMauro Carvalho Chehab /* download end packet */ 455786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_END; 456786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 457786baecfSMauro Carvalho Chehab if (ret < 0) 458786baecfSMauro Carvalho Chehab goto err; 459786baecfSMauro Carvalho Chehab 460786baecfSMauro Carvalho Chehab i -= hdr_data_len + HDR_SIZE; 461786baecfSMauro Carvalho Chehab 462119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%zu\n", 463119f7a8cSAntti Palosaari __func__, fw->size - i); 464786baecfSMauro Carvalho Chehab } 465786baecfSMauro Carvalho Chehab 466ff4e3fe8SAntti Palosaari /* print warn if firmware is bad, continue and see what happens */ 467ff4e3fe8SAntti Palosaari if (i) 468ff4e3fe8SAntti Palosaari dev_warn(&d->udev->dev, "%s: bad firmware\n", KBUILD_MODNAME); 469ff4e3fe8SAntti Palosaari 470786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 471786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 472786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 473786baecfSMauro Carvalho Chehab if (ret < 0) 474786baecfSMauro Carvalho Chehab goto err; 475786baecfSMauro Carvalho Chehab 476786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 477786baecfSMauro Carvalho Chehab wbuf[0] = 1; 478786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 479786baecfSMauro Carvalho Chehab if (ret < 0) 480786baecfSMauro Carvalho Chehab goto err; 481786baecfSMauro Carvalho Chehab 482786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 483119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: firmware did not run\n", 484119f7a8cSAntti Palosaari KBUILD_MODNAME); 485786baecfSMauro Carvalho Chehab ret = -ENODEV; 486786baecfSMauro Carvalho Chehab goto err; 487786baecfSMauro Carvalho Chehab } 488786baecfSMauro Carvalho Chehab 489119f7a8cSAntti Palosaari dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", 490119f7a8cSAntti Palosaari KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 491786baecfSMauro Carvalho Chehab 492786baecfSMauro Carvalho Chehab return 0; 493786baecfSMauro Carvalho Chehab 494786baecfSMauro Carvalho Chehab err: 495119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 496786baecfSMauro Carvalho Chehab 497786baecfSMauro Carvalho Chehab return ret; 498786baecfSMauro Carvalho Chehab } 499786baecfSMauro Carvalho Chehab 500786baecfSMauro Carvalho Chehab static int af9035_download_firmware_it9135(struct dvb_usb_device *d, 501786baecfSMauro Carvalho Chehab const struct firmware *fw) 502786baecfSMauro Carvalho Chehab { 503786baecfSMauro Carvalho Chehab int ret, i, i_prev; 504786baecfSMauro Carvalho Chehab u8 wbuf[1]; 505786baecfSMauro Carvalho Chehab u8 rbuf[4]; 506786baecfSMauro Carvalho Chehab struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 507786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; 508786baecfSMauro Carvalho Chehab struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; 509786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 510786baecfSMauro Carvalho Chehab 511786baecfSMauro Carvalho Chehab /* 512786baecfSMauro Carvalho Chehab * There seems to be following firmware header. Meaning of bytes 0-3 513786baecfSMauro Carvalho Chehab * is unknown. 514786baecfSMauro Carvalho Chehab * 515786baecfSMauro Carvalho Chehab * 0: 3 516786baecfSMauro Carvalho Chehab * 1: 0, 1 517786baecfSMauro Carvalho Chehab * 2: 0 518786baecfSMauro Carvalho Chehab * 3: 1, 2, 3 519786baecfSMauro Carvalho Chehab * 4: addr MSB 520786baecfSMauro Carvalho Chehab * 5: addr LSB 521786baecfSMauro Carvalho Chehab * 6: count of data bytes ? 522786baecfSMauro Carvalho Chehab */ 523786baecfSMauro Carvalho Chehab 524786baecfSMauro Carvalho Chehab for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { 525786baecfSMauro Carvalho Chehab if (i == fw->size || 526786baecfSMauro Carvalho Chehab (fw->data[i + 0] == 0x03 && 527786baecfSMauro Carvalho Chehab (fw->data[i + 1] == 0x00 || 528786baecfSMauro Carvalho Chehab fw->data[i + 1] == 0x01) && 529786baecfSMauro Carvalho Chehab fw->data[i + 2] == 0x00)) { 530786baecfSMauro Carvalho Chehab req_fw_dl.wlen = i - i_prev; 531786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; 532786baecfSMauro Carvalho Chehab i_prev = i; 533786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 534786baecfSMauro Carvalho Chehab if (ret < 0) 535786baecfSMauro Carvalho Chehab goto err; 536786baecfSMauro Carvalho Chehab 537119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%d\n", 538119f7a8cSAntti Palosaari __func__, i); 539786baecfSMauro Carvalho Chehab } 540786baecfSMauro Carvalho Chehab } 541786baecfSMauro Carvalho Chehab 542786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 543786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 544786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 545786baecfSMauro Carvalho Chehab if (ret < 0) 546786baecfSMauro Carvalho Chehab goto err; 547786baecfSMauro Carvalho Chehab 548786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 549786baecfSMauro Carvalho Chehab wbuf[0] = 1; 550786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 551786baecfSMauro Carvalho Chehab if (ret < 0) 552786baecfSMauro Carvalho Chehab goto err; 553786baecfSMauro Carvalho Chehab 554786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 555119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: firmware did not run\n", 556119f7a8cSAntti Palosaari KBUILD_MODNAME); 557786baecfSMauro Carvalho Chehab ret = -ENODEV; 558786baecfSMauro Carvalho Chehab goto err; 559786baecfSMauro Carvalho Chehab } 560786baecfSMauro Carvalho Chehab 561119f7a8cSAntti Palosaari dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", 562119f7a8cSAntti Palosaari KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 563786baecfSMauro Carvalho Chehab 564786baecfSMauro Carvalho Chehab return 0; 565786baecfSMauro Carvalho Chehab 566786baecfSMauro Carvalho Chehab err: 567119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 568786baecfSMauro Carvalho Chehab 569786baecfSMauro Carvalho Chehab return ret; 570786baecfSMauro Carvalho Chehab } 571786baecfSMauro Carvalho Chehab 57274c1883aSAntti Palosaari static int af9035_download_firmware(struct dvb_usb_device *d, 57374c1883aSAntti Palosaari const struct firmware *fw) 57474c1883aSAntti Palosaari { 57574c1883aSAntti Palosaari struct state *state = d_to_priv(d); 57674c1883aSAntti Palosaari 57774c1883aSAntti Palosaari if (state->chip_type == 0x9135) 57874c1883aSAntti Palosaari return af9035_download_firmware_it9135(d, fw); 57974c1883aSAntti Palosaari else 58074c1883aSAntti Palosaari return af9035_download_firmware_af9035(d, fw); 58174c1883aSAntti Palosaari } 58274c1883aSAntti Palosaari 58374c1883aSAntti Palosaari static int af9035_read_config_af9035(struct dvb_usb_device *d) 584786baecfSMauro Carvalho Chehab { 585786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 586786baecfSMauro Carvalho Chehab int ret, i, eeprom_shift = 0; 587786baecfSMauro Carvalho Chehab u8 tmp; 588786baecfSMauro Carvalho Chehab u16 tmp16; 589786baecfSMauro Carvalho Chehab 590bf97b637SAntti Palosaari /* demod I2C "address" */ 591bf97b637SAntti Palosaari state->af9033_config[0].i2c_addr = 0x38; 5920d94d6a0SAntti Palosaari state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 593bf97b637SAntti Palosaari 594786baecfSMauro Carvalho Chehab /* check if there is dual tuners */ 595786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); 596786baecfSMauro Carvalho Chehab if (ret < 0) 597786baecfSMauro Carvalho Chehab goto err; 598786baecfSMauro Carvalho Chehab 599786baecfSMauro Carvalho Chehab state->dual_mode = tmp; 600bf97b637SAntti Palosaari dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", __func__, 601bf97b637SAntti Palosaari state->dual_mode); 602786baecfSMauro Carvalho Chehab 6039805992fSJose Alberto Reguero if (state->dual_mode) { 6049805992fSJose Alberto Reguero /* read 2nd demodulator I2C address */ 605bf97b637SAntti Palosaari ret = af9035_rd_reg(d, EEPROM_2ND_DEMOD_ADDR, &tmp); 6069805992fSJose Alberto Reguero if (ret < 0) 6079805992fSJose Alberto Reguero goto err; 608bf97b637SAntti Palosaari 6099805992fSJose Alberto Reguero state->af9033_config[1].i2c_addr = tmp; 610bf97b637SAntti Palosaari dev_dbg(&d->udev->dev, "%s: 2nd demod I2C addr=%02x\n", 611bf97b637SAntti Palosaari __func__, tmp); 6129805992fSJose Alberto Reguero } 6139805992fSJose Alberto Reguero 614786baecfSMauro Carvalho Chehab for (i = 0; i < state->dual_mode + 1; i++) { 615786baecfSMauro Carvalho Chehab /* tuner */ 616786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); 617786baecfSMauro Carvalho Chehab if (ret < 0) 618786baecfSMauro Carvalho Chehab goto err; 619786baecfSMauro Carvalho Chehab 620786baecfSMauro Carvalho Chehab state->af9033_config[i].tuner = tmp; 621119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", 622119f7a8cSAntti Palosaari __func__, i, tmp); 623786baecfSMauro Carvalho Chehab 624786baecfSMauro Carvalho Chehab switch (tmp) { 625786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 626786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 627786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 628786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 629d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 6307e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 631786baecfSMauro Carvalho Chehab state->af9033_config[i].spec_inv = 1; 632786baecfSMauro Carvalho Chehab break; 633786baecfSMauro Carvalho Chehab default: 634119f7a8cSAntti Palosaari dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \ 635119f7a8cSAntti Palosaari "supported, please report!", 636119f7a8cSAntti Palosaari KBUILD_MODNAME, tmp); 637c2c1b415SPeter Senna Tschudin } 638786baecfSMauro Carvalho Chehab 639bf97b637SAntti Palosaari /* disable dual mode if driver does not support it */ 640bf97b637SAntti Palosaari if (i == 1) 641bf97b637SAntti Palosaari switch (tmp) { 6420bb3d8acSAntti Palosaari case AF9033_TUNER_FC0012: 6430bb3d8acSAntti Palosaari break; 644bf97b637SAntti Palosaari default: 645bf97b637SAntti Palosaari state->dual_mode = false; 646bf97b637SAntti Palosaari dev_info(&d->udev->dev, "%s: driver does not " \ 647bf97b637SAntti Palosaari "support 2nd tuner and will " \ 648bf97b637SAntti Palosaari "disable it", KBUILD_MODNAME); 649bf97b637SAntti Palosaari } 650bf97b637SAntti Palosaari 651786baecfSMauro Carvalho Chehab /* tuner IF frequency */ 652786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); 653786baecfSMauro Carvalho Chehab if (ret < 0) 654786baecfSMauro Carvalho Chehab goto err; 655786baecfSMauro Carvalho Chehab 656786baecfSMauro Carvalho Chehab tmp16 = tmp; 657786baecfSMauro Carvalho Chehab 658786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); 659786baecfSMauro Carvalho Chehab if (ret < 0) 660786baecfSMauro Carvalho Chehab goto err; 661786baecfSMauro Carvalho Chehab 662786baecfSMauro Carvalho Chehab tmp16 |= tmp << 8; 663786baecfSMauro Carvalho Chehab 664119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16); 665786baecfSMauro Carvalho Chehab 666786baecfSMauro Carvalho Chehab eeprom_shift = 0x10; /* shift for the 2nd tuner params */ 667786baecfSMauro Carvalho Chehab } 668786baecfSMauro Carvalho Chehab 669786baecfSMauro Carvalho Chehab /* get demod clock */ 670786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, 0x00d800, &tmp); 671786baecfSMauro Carvalho Chehab if (ret < 0) 672786baecfSMauro Carvalho Chehab goto err; 673786baecfSMauro Carvalho Chehab 674786baecfSMauro Carvalho Chehab tmp = (tmp >> 0) & 0x0f; 675786baecfSMauro Carvalho Chehab 676786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) 677786baecfSMauro Carvalho Chehab state->af9033_config[i].clock = clock_lut[tmp]; 678786baecfSMauro Carvalho Chehab 679786baecfSMauro Carvalho Chehab return 0; 680786baecfSMauro Carvalho Chehab 681786baecfSMauro Carvalho Chehab err: 682119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 683786baecfSMauro Carvalho Chehab 684786baecfSMauro Carvalho Chehab return ret; 685786baecfSMauro Carvalho Chehab } 686786baecfSMauro Carvalho Chehab 687786baecfSMauro Carvalho Chehab static int af9035_read_config_it9135(struct dvb_usb_device *d) 688786baecfSMauro Carvalho Chehab { 689786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 690786baecfSMauro Carvalho Chehab int ret, i; 691786baecfSMauro Carvalho Chehab u8 tmp; 692786baecfSMauro Carvalho Chehab 693ac77fb0fSAntti Palosaari /* demod I2C "address" */ 694ac77fb0fSAntti Palosaari state->af9033_config[0].i2c_addr = 0x38; 695ac77fb0fSAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; 696ac77fb0fSAntti Palosaari state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 697786baecfSMauro Carvalho Chehab state->dual_mode = false; 698786baecfSMauro Carvalho Chehab 69974c1883aSAntti Palosaari /* check if eeprom exists */ 70074c1883aSAntti Palosaari if (state->chip_version == 2) 70174c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x00461d, &tmp); 70274c1883aSAntti Palosaari else 70374c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x00461b, &tmp); 70474c1883aSAntti Palosaari if (ret < 0) 70574c1883aSAntti Palosaari goto err; 70674c1883aSAntti Palosaari 70774c1883aSAntti Palosaari if (tmp) { 70874c1883aSAntti Palosaari /* tuner */ 70974c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x0049d0, &tmp); 71074c1883aSAntti Palosaari if (ret < 0) 71174c1883aSAntti Palosaari goto err; 71274c1883aSAntti Palosaari 71374c1883aSAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", 71474c1883aSAntti Palosaari __func__, 0, tmp); 71574c1883aSAntti Palosaari 71674c1883aSAntti Palosaari if (tmp) 71774c1883aSAntti Palosaari state->af9033_config[0].tuner = tmp; 71874c1883aSAntti Palosaari } 71974c1883aSAntti Palosaari 720786baecfSMauro Carvalho Chehab /* get demod clock */ 721786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, 0x00d800, &tmp); 722786baecfSMauro Carvalho Chehab if (ret < 0) 723786baecfSMauro Carvalho Chehab goto err; 724786baecfSMauro Carvalho Chehab 725786baecfSMauro Carvalho Chehab tmp = (tmp >> 0) & 0x0f; 726786baecfSMauro Carvalho Chehab 727786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) 728786baecfSMauro Carvalho Chehab state->af9033_config[i].clock = clock_lut_it9135[tmp]; 729786baecfSMauro Carvalho Chehab 730786baecfSMauro Carvalho Chehab return 0; 731786baecfSMauro Carvalho Chehab 732786baecfSMauro Carvalho Chehab err: 733119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 734786baecfSMauro Carvalho Chehab 735786baecfSMauro Carvalho Chehab return ret; 736786baecfSMauro Carvalho Chehab } 737786baecfSMauro Carvalho Chehab 73874c1883aSAntti Palosaari static int af9035_read_config(struct dvb_usb_device *d) 73974c1883aSAntti Palosaari { 74074c1883aSAntti Palosaari struct state *state = d_to_priv(d); 74174c1883aSAntti Palosaari 74274c1883aSAntti Palosaari if (state->chip_type == 0x9135) 74374c1883aSAntti Palosaari return af9035_read_config_it9135(d); 74474c1883aSAntti Palosaari else 74574c1883aSAntti Palosaari return af9035_read_config_af9035(d); 74674c1883aSAntti Palosaari } 74774c1883aSAntti Palosaari 74851639be3SAntti Palosaari static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, 74951639be3SAntti Palosaari int cmd, int arg) 75051639be3SAntti Palosaari { 75151639be3SAntti Palosaari int ret; 75251639be3SAntti Palosaari u8 val; 75351639be3SAntti Palosaari 75451639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); 75551639be3SAntti Palosaari 75651639be3SAntti Palosaari /* 75751639be3SAntti Palosaari * CEN always enabled by hardware wiring 75851639be3SAntti Palosaari * RESETN GPIOT3 75951639be3SAntti Palosaari * RXEN GPIOT2 76051639be3SAntti Palosaari */ 76151639be3SAntti Palosaari 76251639be3SAntti Palosaari switch (cmd) { 76351639be3SAntti Palosaari case TUA9001_CMD_RESETN: 76451639be3SAntti Palosaari if (arg) 76551639be3SAntti Palosaari val = 0x00; 76651639be3SAntti Palosaari else 76751639be3SAntti Palosaari val = 0x01; 76851639be3SAntti Palosaari 76951639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); 77051639be3SAntti Palosaari if (ret < 0) 77151639be3SAntti Palosaari goto err; 77251639be3SAntti Palosaari break; 77351639be3SAntti Palosaari case TUA9001_CMD_RXEN: 77451639be3SAntti Palosaari if (arg) 77551639be3SAntti Palosaari val = 0x01; 77651639be3SAntti Palosaari else 77751639be3SAntti Palosaari val = 0x00; 77851639be3SAntti Palosaari 77951639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); 78051639be3SAntti Palosaari if (ret < 0) 78151639be3SAntti Palosaari goto err; 78251639be3SAntti Palosaari break; 78351639be3SAntti Palosaari } 78451639be3SAntti Palosaari 78551639be3SAntti Palosaari return 0; 78651639be3SAntti Palosaari 78751639be3SAntti Palosaari err: 78851639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 78951639be3SAntti Palosaari 79051639be3SAntti Palosaari return ret; 79151639be3SAntti Palosaari } 79251639be3SAntti Palosaari 79351639be3SAntti Palosaari 794786baecfSMauro Carvalho Chehab static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, 795786baecfSMauro Carvalho Chehab int cmd, int arg) 796786baecfSMauro Carvalho Chehab { 797786baecfSMauro Carvalho Chehab int ret; 798786baecfSMauro Carvalho Chehab 799786baecfSMauro Carvalho Chehab switch (cmd) { 800786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_POWER: 801786baecfSMauro Carvalho Chehab /* Tuner enable */ 802786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); 803786baecfSMauro Carvalho Chehab if (ret < 0) 804786baecfSMauro Carvalho Chehab goto err; 805786baecfSMauro Carvalho Chehab 806786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); 807786baecfSMauro Carvalho Chehab if (ret < 0) 808786baecfSMauro Carvalho Chehab goto err; 809786baecfSMauro Carvalho Chehab 810786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); 811786baecfSMauro Carvalho Chehab if (ret < 0) 812786baecfSMauro Carvalho Chehab goto err; 813786baecfSMauro Carvalho Chehab 814786baecfSMauro Carvalho Chehab /* LED */ 815786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); 816786baecfSMauro Carvalho Chehab if (ret < 0) 817786baecfSMauro Carvalho Chehab goto err; 818786baecfSMauro Carvalho Chehab 819786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); 820786baecfSMauro Carvalho Chehab if (ret < 0) 821786baecfSMauro Carvalho Chehab goto err; 822786baecfSMauro Carvalho Chehab 823786baecfSMauro Carvalho Chehab usleep_range(10000, 50000); 824786baecfSMauro Carvalho Chehab break; 825786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_RESET: 826786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e9, 1); 827786baecfSMauro Carvalho Chehab if (ret < 0) 828786baecfSMauro Carvalho Chehab goto err; 829786baecfSMauro Carvalho Chehab 830786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e8, 1); 831786baecfSMauro Carvalho Chehab if (ret < 0) 832786baecfSMauro Carvalho Chehab goto err; 833786baecfSMauro Carvalho Chehab 834786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 1); 835786baecfSMauro Carvalho Chehab if (ret < 0) 836786baecfSMauro Carvalho Chehab goto err; 837786baecfSMauro Carvalho Chehab 838786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 839786baecfSMauro Carvalho Chehab 840786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 0); 841786baecfSMauro Carvalho Chehab if (ret < 0) 842786baecfSMauro Carvalho Chehab goto err; 843786baecfSMauro Carvalho Chehab 844786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 845786baecfSMauro Carvalho Chehab break; 846786baecfSMauro Carvalho Chehab default: 847786baecfSMauro Carvalho Chehab ret = -EINVAL; 848786baecfSMauro Carvalho Chehab goto err; 849786baecfSMauro Carvalho Chehab } 850786baecfSMauro Carvalho Chehab 851786baecfSMauro Carvalho Chehab return 0; 852786baecfSMauro Carvalho Chehab 853786baecfSMauro Carvalho Chehab err: 854119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 855786baecfSMauro Carvalho Chehab 856786baecfSMauro Carvalho Chehab return ret; 857786baecfSMauro Carvalho Chehab } 858786baecfSMauro Carvalho Chehab 859786baecfSMauro Carvalho Chehab static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) 860786baecfSMauro Carvalho Chehab { 861786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 862786baecfSMauro Carvalho Chehab 863786baecfSMauro Carvalho Chehab switch (state->af9033_config[0].tuner) { 864786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 865786baecfSMauro Carvalho Chehab return af9035_fc0011_tuner_callback(d, cmd, arg); 86651639be3SAntti Palosaari case AF9033_TUNER_TUA9001: 86751639be3SAntti Palosaari return af9035_tua9001_tuner_callback(d, cmd, arg); 868786baecfSMauro Carvalho Chehab default: 869786baecfSMauro Carvalho Chehab break; 870786baecfSMauro Carvalho Chehab } 871786baecfSMauro Carvalho Chehab 8721835af10SAntti Palosaari return 0; 873786baecfSMauro Carvalho Chehab } 874786baecfSMauro Carvalho Chehab 875786baecfSMauro Carvalho Chehab static int af9035_frontend_callback(void *adapter_priv, int component, 876786baecfSMauro Carvalho Chehab int cmd, int arg) 877786baecfSMauro Carvalho Chehab { 878786baecfSMauro Carvalho Chehab struct i2c_adapter *adap = adapter_priv; 879786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 880786baecfSMauro Carvalho Chehab 8811835af10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", 8821835af10SAntti Palosaari __func__, component, cmd, arg); 8831835af10SAntti Palosaari 884786baecfSMauro Carvalho Chehab switch (component) { 885786baecfSMauro Carvalho Chehab case DVB_FRONTEND_COMPONENT_TUNER: 886786baecfSMauro Carvalho Chehab return af9035_tuner_callback(d, cmd, arg); 887786baecfSMauro Carvalho Chehab default: 888786baecfSMauro Carvalho Chehab break; 889786baecfSMauro Carvalho Chehab } 890786baecfSMauro Carvalho Chehab 8911835af10SAntti Palosaari return 0; 892786baecfSMauro Carvalho Chehab } 893786baecfSMauro Carvalho Chehab 8949805992fSJose Alberto Reguero static int af9035_get_adapter_count(struct dvb_usb_device *d) 8959805992fSJose Alberto Reguero { 8969805992fSJose Alberto Reguero struct state *state = d_to_priv(d); 897bada342eSAntti Palosaari 898bada342eSAntti Palosaari /* disable 2nd adapter as we don't have PID filters implemented */ 899bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 900bada342eSAntti Palosaari return 1; 901bada342eSAntti Palosaari else 9029805992fSJose Alberto Reguero return state->dual_mode + 1; 9039805992fSJose Alberto Reguero } 9049805992fSJose Alberto Reguero 905786baecfSMauro Carvalho Chehab static int af9035_frontend_attach(struct dvb_usb_adapter *adap) 906786baecfSMauro Carvalho Chehab { 907786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 908786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 909786baecfSMauro Carvalho Chehab int ret; 910786baecfSMauro Carvalho Chehab 911786baecfSMauro Carvalho Chehab if (!state->af9033_config[adap->id].tuner) { 912786baecfSMauro Carvalho Chehab /* unsupported tuner */ 913786baecfSMauro Carvalho Chehab ret = -ENODEV; 914786baecfSMauro Carvalho Chehab goto err; 915786baecfSMauro Carvalho Chehab } 916786baecfSMauro Carvalho Chehab 917786baecfSMauro Carvalho Chehab if (adap->id == 0) { 918786baecfSMauro Carvalho Chehab state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; 919786baecfSMauro Carvalho Chehab state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; 920786baecfSMauro Carvalho Chehab 921786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00417f, 922786baecfSMauro Carvalho Chehab state->af9033_config[1].i2c_addr); 923786baecfSMauro Carvalho Chehab if (ret < 0) 924786baecfSMauro Carvalho Chehab goto err; 925786baecfSMauro Carvalho Chehab 926bf97b637SAntti Palosaari ret = af9035_wr_reg(d, 0x00d81a, state->dual_mode); 927786baecfSMauro Carvalho Chehab if (ret < 0) 928786baecfSMauro Carvalho Chehab goto err; 929786baecfSMauro Carvalho Chehab } 930786baecfSMauro Carvalho Chehab 931786baecfSMauro Carvalho Chehab /* attach demodulator */ 932bf97b637SAntti Palosaari adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], 933bf97b637SAntti Palosaari &d->i2c_adap); 934786baecfSMauro Carvalho Chehab if (adap->fe[0] == NULL) { 935786baecfSMauro Carvalho Chehab ret = -ENODEV; 936786baecfSMauro Carvalho Chehab goto err; 937786baecfSMauro Carvalho Chehab } 938786baecfSMauro Carvalho Chehab 939786baecfSMauro Carvalho Chehab /* disable I2C-gate */ 940786baecfSMauro Carvalho Chehab adap->fe[0]->ops.i2c_gate_ctrl = NULL; 941786baecfSMauro Carvalho Chehab adap->fe[0]->callback = af9035_frontend_callback; 942786baecfSMauro Carvalho Chehab 943786baecfSMauro Carvalho Chehab return 0; 944786baecfSMauro Carvalho Chehab 945786baecfSMauro Carvalho Chehab err: 946119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 947786baecfSMauro Carvalho Chehab 948786baecfSMauro Carvalho Chehab return ret; 949786baecfSMauro Carvalho Chehab } 950786baecfSMauro Carvalho Chehab 951786baecfSMauro Carvalho Chehab static struct tua9001_config af9035_tua9001_config = { 952786baecfSMauro Carvalho Chehab .i2c_addr = 0x60, 953786baecfSMauro Carvalho Chehab }; 954786baecfSMauro Carvalho Chehab 955786baecfSMauro Carvalho Chehab static const struct fc0011_config af9035_fc0011_config = { 956786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 957786baecfSMauro Carvalho Chehab }; 958786baecfSMauro Carvalho Chehab 9599805992fSJose Alberto Reguero static struct mxl5007t_config af9035_mxl5007t_config[] = { 9609805992fSJose Alberto Reguero { 961786baecfSMauro Carvalho Chehab .xtal_freq_hz = MxL_XTAL_24_MHZ, 962786baecfSMauro Carvalho Chehab .if_freq_hz = MxL_IF_4_57_MHZ, 963786baecfSMauro Carvalho Chehab .invert_if = 0, 964786baecfSMauro Carvalho Chehab .loop_thru_enable = 0, 965786baecfSMauro Carvalho Chehab .clk_out_enable = 0, 966786baecfSMauro Carvalho Chehab .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 9679805992fSJose Alberto Reguero }, { 9689805992fSJose Alberto Reguero .xtal_freq_hz = MxL_XTAL_24_MHZ, 9699805992fSJose Alberto Reguero .if_freq_hz = MxL_IF_4_57_MHZ, 9709805992fSJose Alberto Reguero .invert_if = 0, 9719805992fSJose Alberto Reguero .loop_thru_enable = 1, 9729805992fSJose Alberto Reguero .clk_out_enable = 1, 9739805992fSJose Alberto Reguero .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 9749805992fSJose Alberto Reguero } 975786baecfSMauro Carvalho Chehab }; 976786baecfSMauro Carvalho Chehab 977786baecfSMauro Carvalho Chehab static struct tda18218_config af9035_tda18218_config = { 978786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 979786baecfSMauro Carvalho Chehab .i2c_wr_max = 21, 980786baecfSMauro Carvalho Chehab }; 981786baecfSMauro Carvalho Chehab 982d67ceb33SOliver Schinagl static const struct fc2580_config af9035_fc2580_config = { 983d67ceb33SOliver Schinagl .i2c_addr = 0x56, 984d67ceb33SOliver Schinagl .clock = 16384000, 985d67ceb33SOliver Schinagl }; 986d67ceb33SOliver Schinagl 9870bb3d8acSAntti Palosaari static const struct fc0012_config af9035_fc0012_config[] = { 9880bb3d8acSAntti Palosaari { 989ad3a758bSAntti Palosaari .i2c_address = 0x63, 990ad3a758bSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 9913a984772SAntti Palosaari .dual_master = true, 9920bb3d8acSAntti Palosaari .loop_through = true, 9930bb3d8acSAntti Palosaari .clock_out = true, 9940bb3d8acSAntti Palosaari }, { 9950bb3d8acSAntti Palosaari .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ 9960bb3d8acSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 9973a984772SAntti Palosaari .dual_master = true, 9980bb3d8acSAntti Palosaari } 999ad3a758bSAntti Palosaari }; 1000ad3a758bSAntti Palosaari 1001ac77fb0fSAntti Palosaari static struct ite_config af9035_it913x_config = { 1002ac77fb0fSAntti Palosaari .chip_ver = 0x01, 1003ac77fb0fSAntti Palosaari .chip_type = 0x9135, 1004ac77fb0fSAntti Palosaari .firmware = 0x00000000, 1005ac77fb0fSAntti Palosaari .firmware_ver = 1, 1006ac77fb0fSAntti Palosaari .adc_x2 = 1, 1007ac77fb0fSAntti Palosaari .tuner_id_0 = AF9033_TUNER_IT9135_38, 1008ac77fb0fSAntti Palosaari .tuner_id_1 = 0x00, 1009ac77fb0fSAntti Palosaari .dual_mode = 0x00, 1010ac77fb0fSAntti Palosaari .adf = 0x00, 1011ac77fb0fSAntti Palosaari /* option to read SIGNAL_LEVEL */ 1012ac77fb0fSAntti Palosaari .read_slevel = 0, 1013ac77fb0fSAntti Palosaari }; 1014ac77fb0fSAntti Palosaari 1015786baecfSMauro Carvalho Chehab static int af9035_tuner_attach(struct dvb_usb_adapter *adap) 1016786baecfSMauro Carvalho Chehab { 1017786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1018786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 1019786baecfSMauro Carvalho Chehab int ret; 1020786baecfSMauro Carvalho Chehab struct dvb_frontend *fe; 10210bb3d8acSAntti Palosaari struct i2c_msg msg[1]; 1022bf97b637SAntti Palosaari u8 tuner_addr; 1023bf97b637SAntti Palosaari /* 1024bf97b637SAntti Palosaari * XXX: Hack used in that function: we abuse unused I2C address bit [7] 1025bf97b637SAntti Palosaari * to carry info about used I2C bus for dual tuner configuration. 1026bf97b637SAntti Palosaari */ 1027786baecfSMauro Carvalho Chehab 1028786baecfSMauro Carvalho Chehab switch (state->af9033_config[adap->id].tuner) { 1029786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 1030786baecfSMauro Carvalho Chehab /* AF9035 gpiot3 = TUA9001 RESETN 1031786baecfSMauro Carvalho Chehab AF9035 gpiot2 = TUA9001 RXEN */ 1032786baecfSMauro Carvalho Chehab 1033786baecfSMauro Carvalho Chehab /* configure gpiot2 and gpiot2 as output */ 1034786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); 1035786baecfSMauro Carvalho Chehab if (ret < 0) 1036786baecfSMauro Carvalho Chehab goto err; 1037786baecfSMauro Carvalho Chehab 1038786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); 1039786baecfSMauro Carvalho Chehab if (ret < 0) 1040786baecfSMauro Carvalho Chehab goto err; 1041786baecfSMauro Carvalho Chehab 1042786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); 1043786baecfSMauro Carvalho Chehab if (ret < 0) 1044786baecfSMauro Carvalho Chehab goto err; 1045786baecfSMauro Carvalho Chehab 1046786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); 1047786baecfSMauro Carvalho Chehab if (ret < 0) 1048786baecfSMauro Carvalho Chehab goto err; 1049786baecfSMauro Carvalho Chehab 1050786baecfSMauro Carvalho Chehab /* attach tuner */ 1051786baecfSMauro Carvalho Chehab fe = dvb_attach(tua9001_attach, adap->fe[0], 1052786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tua9001_config); 1053786baecfSMauro Carvalho Chehab break; 1054786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 1055786baecfSMauro Carvalho Chehab fe = dvb_attach(fc0011_attach, adap->fe[0], 1056786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_fc0011_config); 1057786baecfSMauro Carvalho Chehab break; 1058786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 10599805992fSJose Alberto Reguero if (adap->id == 0) { 1060786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e0, 1); 1061786baecfSMauro Carvalho Chehab if (ret < 0) 1062786baecfSMauro Carvalho Chehab goto err; 1063bf97b637SAntti Palosaari 1064786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e1, 1); 1065786baecfSMauro Carvalho Chehab if (ret < 0) 1066786baecfSMauro Carvalho Chehab goto err; 1067bf97b637SAntti Palosaari 1068786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 0); 1069786baecfSMauro Carvalho Chehab if (ret < 0) 1070786baecfSMauro Carvalho Chehab goto err; 1071786baecfSMauro Carvalho Chehab 1072786baecfSMauro Carvalho Chehab msleep(30); 1073786baecfSMauro Carvalho Chehab 1074786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 1); 1075786baecfSMauro Carvalho Chehab if (ret < 0) 1076786baecfSMauro Carvalho Chehab goto err; 1077786baecfSMauro Carvalho Chehab 1078786baecfSMauro Carvalho Chehab msleep(300); 1079786baecfSMauro Carvalho Chehab 1080786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c0, 1); 1081786baecfSMauro Carvalho Chehab if (ret < 0) 1082786baecfSMauro Carvalho Chehab goto err; 1083bf97b637SAntti Palosaari 1084786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c1, 1); 1085786baecfSMauro Carvalho Chehab if (ret < 0) 1086786baecfSMauro Carvalho Chehab goto err; 1087bf97b637SAntti Palosaari 1088786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8bf, 0); 1089786baecfSMauro Carvalho Chehab if (ret < 0) 1090786baecfSMauro Carvalho Chehab goto err; 1091bf97b637SAntti Palosaari 1092786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b4, 1); 1093786baecfSMauro Carvalho Chehab if (ret < 0) 1094786baecfSMauro Carvalho Chehab goto err; 1095bf97b637SAntti Palosaari 1096786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b5, 1); 1097786baecfSMauro Carvalho Chehab if (ret < 0) 1098786baecfSMauro Carvalho Chehab goto err; 1099bf97b637SAntti Palosaari 1100786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b3, 1); 1101786baecfSMauro Carvalho Chehab if (ret < 0) 1102786baecfSMauro Carvalho Chehab goto err; 1103bf97b637SAntti Palosaari 1104bf97b637SAntti Palosaari tuner_addr = 0x60; 1105bf97b637SAntti Palosaari } else { 1106bf97b637SAntti Palosaari tuner_addr = 0x60 | 0x80; /* I2C bus hack */ 11079805992fSJose Alberto Reguero } 1108786baecfSMauro Carvalho Chehab 1109786baecfSMauro Carvalho Chehab /* attach tuner */ 1110bf97b637SAntti Palosaari fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, 1111bf97b637SAntti Palosaari tuner_addr, &af9035_mxl5007t_config[adap->id]); 1112786baecfSMauro Carvalho Chehab break; 1113786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 1114786baecfSMauro Carvalho Chehab /* attach tuner */ 1115786baecfSMauro Carvalho Chehab fe = dvb_attach(tda18218_attach, adap->fe[0], 1116786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tda18218_config); 1117786baecfSMauro Carvalho Chehab break; 1118d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 1119d67ceb33SOliver Schinagl /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ 1120d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 1121d67ceb33SOliver Schinagl if (ret < 0) 1122d67ceb33SOliver Schinagl goto err; 1123d67ceb33SOliver Schinagl 1124d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 1125d67ceb33SOliver Schinagl if (ret < 0) 1126d67ceb33SOliver Schinagl goto err; 1127d67ceb33SOliver Schinagl 1128d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 1129d67ceb33SOliver Schinagl if (ret < 0) 1130d67ceb33SOliver Schinagl goto err; 1131d67ceb33SOliver Schinagl 1132d67ceb33SOliver Schinagl usleep_range(10000, 50000); 1133d67ceb33SOliver Schinagl /* attach tuner */ 1134d67ceb33SOliver Schinagl fe = dvb_attach(fc2580_attach, adap->fe[0], 1135d67ceb33SOliver Schinagl &d->i2c_adap, &af9035_fc2580_config); 1136d67ceb33SOliver Schinagl break; 11377e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 11387e0bc296SAntti Palosaari /* 11397e0bc296SAntti Palosaari * AF9035 gpiot2 = FC0012 enable 11407e0bc296SAntti Palosaari * XXX: there seems to be something on gpioh8 too, but on my 11417e0bc296SAntti Palosaari * my test I didn't find any difference. 11427e0bc296SAntti Palosaari */ 11437e0bc296SAntti Palosaari 11440bb3d8acSAntti Palosaari if (adap->id == 0) { 11457e0bc296SAntti Palosaari /* configure gpiot2 as output and high */ 11467e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 11477e0bc296SAntti Palosaari if (ret < 0) 11487e0bc296SAntti Palosaari goto err; 11497e0bc296SAntti Palosaari 11507e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 11517e0bc296SAntti Palosaari if (ret < 0) 11527e0bc296SAntti Palosaari goto err; 11537e0bc296SAntti Palosaari 11547e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 11557e0bc296SAntti Palosaari if (ret < 0) 11567e0bc296SAntti Palosaari goto err; 11570bb3d8acSAntti Palosaari } else { 11580bb3d8acSAntti Palosaari /* 11590bb3d8acSAntti Palosaari * FIXME: That belongs for the FC0012 driver. 11600bb3d8acSAntti Palosaari * Write 02 to FC0012 master tuner register 0d directly 11610bb3d8acSAntti Palosaari * in order to make slave tuner working. 11620bb3d8acSAntti Palosaari */ 11630bb3d8acSAntti Palosaari msg[0].addr = 0x63; 11640bb3d8acSAntti Palosaari msg[0].flags = 0; 11650bb3d8acSAntti Palosaari msg[0].len = 2; 11660bb3d8acSAntti Palosaari msg[0].buf = "\x0d\x02"; 11670bb3d8acSAntti Palosaari ret = i2c_transfer(&d->i2c_adap, msg, 1); 11680bb3d8acSAntti Palosaari if (ret < 0) 11690bb3d8acSAntti Palosaari goto err; 11700bb3d8acSAntti Palosaari } 11717e0bc296SAntti Palosaari 11727e0bc296SAntti Palosaari usleep_range(10000, 50000); 11737e0bc296SAntti Palosaari 1174ad3a758bSAntti Palosaari fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, 11750bb3d8acSAntti Palosaari &af9035_fc0012_config[adap->id]); 11767e0bc296SAntti Palosaari break; 1177ac77fb0fSAntti Palosaari case AF9033_TUNER_IT9135_38: 117874c1883aSAntti Palosaari case AF9033_TUNER_IT9135_51: 117974c1883aSAntti Palosaari case AF9033_TUNER_IT9135_52: 118074c1883aSAntti Palosaari case AF9033_TUNER_IT9135_60: 118174c1883aSAntti Palosaari case AF9033_TUNER_IT9135_61: 118274c1883aSAntti Palosaari case AF9033_TUNER_IT9135_62: 1183ac77fb0fSAntti Palosaari /* attach tuner */ 118474c1883aSAntti Palosaari af9035_it913x_config.tuner_id_0 = state->af9033_config[0].tuner; 1185ac77fb0fSAntti Palosaari fe = dvb_attach(it913x_attach, adap->fe[0], 1186ac77fb0fSAntti Palosaari &d->i2c_adap, 0x38, &af9035_it913x_config); 1187ac77fb0fSAntti Palosaari break; 1188786baecfSMauro Carvalho Chehab default: 1189786baecfSMauro Carvalho Chehab fe = NULL; 1190786baecfSMauro Carvalho Chehab } 1191786baecfSMauro Carvalho Chehab 1192786baecfSMauro Carvalho Chehab if (fe == NULL) { 1193786baecfSMauro Carvalho Chehab ret = -ENODEV; 1194786baecfSMauro Carvalho Chehab goto err; 1195786baecfSMauro Carvalho Chehab } 1196786baecfSMauro Carvalho Chehab 1197786baecfSMauro Carvalho Chehab return 0; 1198786baecfSMauro Carvalho Chehab 1199786baecfSMauro Carvalho Chehab err: 1200119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1201786baecfSMauro Carvalho Chehab 1202786baecfSMauro Carvalho Chehab return ret; 1203786baecfSMauro Carvalho Chehab } 1204786baecfSMauro Carvalho Chehab 1205786baecfSMauro Carvalho Chehab static int af9035_init(struct dvb_usb_device *d) 1206786baecfSMauro Carvalho Chehab { 1207786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 1208786baecfSMauro Carvalho Chehab int ret, i; 1209bada342eSAntti Palosaari u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; 1210bada342eSAntti Palosaari u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 1211786baecfSMauro Carvalho Chehab struct reg_val_mask tab[] = { 1212786baecfSMauro Carvalho Chehab { 0x80f99d, 0x01, 0x01 }, 1213786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x01, 0x01 }, 1214786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x20 }, 1215786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x40 }, 1216786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x20 }, 1217786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x40 }, 1218786baecfSMauro Carvalho Chehab { 0x00dd11, 0x20, 0x20 }, 1219786baecfSMauro Carvalho Chehab { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 1220786baecfSMauro Carvalho Chehab { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 1221786baecfSMauro Carvalho Chehab { 0x00dd0c, packet_size, 0xff}, 1222786baecfSMauro Carvalho Chehab { 0x00dd11, state->dual_mode << 6, 0x40 }, 1223786baecfSMauro Carvalho Chehab { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 1224786baecfSMauro Carvalho Chehab { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 1225786baecfSMauro Carvalho Chehab { 0x00dd0d, packet_size, 0xff }, 12269805992fSJose Alberto Reguero { 0x80f9a3, state->dual_mode, 0x01 }, 12279805992fSJose Alberto Reguero { 0x80f9cd, state->dual_mode, 0x01 }, 1228786baecfSMauro Carvalho Chehab { 0x80f99d, 0x00, 0x01 }, 1229786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x00, 0x01 }, 1230786baecfSMauro Carvalho Chehab }; 1231786baecfSMauro Carvalho Chehab 1232119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ 1233119f7a8cSAntti Palosaari "packet_size=%02x\n", __func__, 1234119f7a8cSAntti Palosaari d->udev->speed, frame_size, packet_size); 1235786baecfSMauro Carvalho Chehab 1236786baecfSMauro Carvalho Chehab /* init endpoints */ 1237786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 1238786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, 1239786baecfSMauro Carvalho Chehab tab[i].mask); 1240786baecfSMauro Carvalho Chehab if (ret < 0) 1241786baecfSMauro Carvalho Chehab goto err; 1242786baecfSMauro Carvalho Chehab } 1243786baecfSMauro Carvalho Chehab 1244786baecfSMauro Carvalho Chehab return 0; 1245786baecfSMauro Carvalho Chehab 1246786baecfSMauro Carvalho Chehab err: 1247119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1248786baecfSMauro Carvalho Chehab 1249786baecfSMauro Carvalho Chehab return ret; 1250786baecfSMauro Carvalho Chehab } 1251786baecfSMauro Carvalho Chehab 125237b44a0fSAntti Palosaari #if IS_ENABLED(CONFIG_RC_CORE) 1253786baecfSMauro Carvalho Chehab static int af9035_rc_query(struct dvb_usb_device *d) 1254786baecfSMauro Carvalho Chehab { 1255786baecfSMauro Carvalho Chehab unsigned int key; 1256786baecfSMauro Carvalho Chehab unsigned char b[4]; 1257786baecfSMauro Carvalho Chehab int ret; 1258786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; 1259786baecfSMauro Carvalho Chehab 1260786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 1261786baecfSMauro Carvalho Chehab if (ret < 0) 1262786baecfSMauro Carvalho Chehab goto err; 1263786baecfSMauro Carvalho Chehab 1264786baecfSMauro Carvalho Chehab if ((b[2] + b[3]) == 0xff) { 1265786baecfSMauro Carvalho Chehab if ((b[0] + b[1]) == 0xff) { 1266786baecfSMauro Carvalho Chehab /* NEC */ 1267786baecfSMauro Carvalho Chehab key = b[0] << 8 | b[2]; 1268786baecfSMauro Carvalho Chehab } else { 1269786baecfSMauro Carvalho Chehab /* ext. NEC */ 1270786baecfSMauro Carvalho Chehab key = b[0] << 16 | b[1] << 8 | b[2]; 1271786baecfSMauro Carvalho Chehab } 1272786baecfSMauro Carvalho Chehab } else { 1273786baecfSMauro Carvalho Chehab key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; 1274786baecfSMauro Carvalho Chehab } 1275786baecfSMauro Carvalho Chehab 1276786baecfSMauro Carvalho Chehab rc_keydown(d->rc_dev, key, 0); 1277786baecfSMauro Carvalho Chehab 1278786baecfSMauro Carvalho Chehab err: 1279786baecfSMauro Carvalho Chehab /* ignore errors */ 1280786baecfSMauro Carvalho Chehab return 0; 1281786baecfSMauro Carvalho Chehab } 1282786baecfSMauro Carvalho Chehab 1283786baecfSMauro Carvalho Chehab static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 1284786baecfSMauro Carvalho Chehab { 128574c1883aSAntti Palosaari struct state *state = d_to_priv(d); 1286786baecfSMauro Carvalho Chehab int ret; 1287786baecfSMauro Carvalho Chehab u8 tmp; 1288786baecfSMauro Carvalho Chehab 128974c1883aSAntti Palosaari /* TODO: IT9135 remote control support */ 129074c1883aSAntti Palosaari if (state->chip_type == 0x9135) 129174c1883aSAntti Palosaari return 0; 129274c1883aSAntti Palosaari 1293786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp); 1294786baecfSMauro Carvalho Chehab if (ret < 0) 1295786baecfSMauro Carvalho Chehab goto err; 1296786baecfSMauro Carvalho Chehab 1297119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_mode=%02x\n", __func__, tmp); 1298786baecfSMauro Carvalho Chehab 1299786baecfSMauro Carvalho Chehab /* don't activate rc if in HID mode or if not available */ 1300786baecfSMauro Carvalho Chehab if (tmp == 5) { 1301786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp); 1302786baecfSMauro Carvalho Chehab if (ret < 0) 1303786baecfSMauro Carvalho Chehab goto err; 1304786baecfSMauro Carvalho Chehab 1305119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_type=%02x\n", __func__, tmp); 1306786baecfSMauro Carvalho Chehab 1307786baecfSMauro Carvalho Chehab switch (tmp) { 1308786baecfSMauro Carvalho Chehab case 0: /* NEC */ 1309786baecfSMauro Carvalho Chehab default: 1310c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_NEC; 1311786baecfSMauro Carvalho Chehab break; 1312786baecfSMauro Carvalho Chehab case 1: /* RC6 */ 1313c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_RC6_MCE; 1314786baecfSMauro Carvalho Chehab break; 1315786baecfSMauro Carvalho Chehab } 1316786baecfSMauro Carvalho Chehab 1317786baecfSMauro Carvalho Chehab rc->query = af9035_rc_query; 1318786baecfSMauro Carvalho Chehab rc->interval = 500; 1319786baecfSMauro Carvalho Chehab 1320786baecfSMauro Carvalho Chehab /* load empty to enable rc */ 1321786baecfSMauro Carvalho Chehab if (!rc->map_name) 1322786baecfSMauro Carvalho Chehab rc->map_name = RC_MAP_EMPTY; 1323786baecfSMauro Carvalho Chehab } 1324786baecfSMauro Carvalho Chehab 1325786baecfSMauro Carvalho Chehab return 0; 1326786baecfSMauro Carvalho Chehab 1327786baecfSMauro Carvalho Chehab err: 1328119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1329786baecfSMauro Carvalho Chehab 1330786baecfSMauro Carvalho Chehab return ret; 1331786baecfSMauro Carvalho Chehab } 1332eed5670aSAntti Palosaari #else 1333eed5670aSAntti Palosaari #define af9035_get_rc_config NULL 1334eed5670aSAntti Palosaari #endif 1335786baecfSMauro Carvalho Chehab 1336bada342eSAntti Palosaari static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, 1337bada342eSAntti Palosaari struct usb_data_stream_properties *stream) 1338bada342eSAntti Palosaari { 1339bada342eSAntti Palosaari struct dvb_usb_device *d = fe_to_d(fe); 1340bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); 1341bada342eSAntti Palosaari 1342bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 1343bada342eSAntti Palosaari stream->u.bulk.buffersize = 5 * 188; 1344bada342eSAntti Palosaari 1345bada342eSAntti Palosaari return 0; 1346bada342eSAntti Palosaari } 1347bada342eSAntti Palosaari 1348bada342eSAntti Palosaari /* 1349bada342eSAntti Palosaari * FIXME: PID filter is property of demodulator and should be moved to the 1350bada342eSAntti Palosaari * correct driver. Also we support only adapter #0 PID filter and will 1351bada342eSAntti Palosaari * disable adapter #1 if USB1.1 is used. 1352bada342eSAntti Palosaari */ 1353bada342eSAntti Palosaari static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) 1354bada342eSAntti Palosaari { 1355bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1356bada342eSAntti Palosaari int ret; 1357bada342eSAntti Palosaari 1358bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); 1359bada342eSAntti Palosaari 1360bada342eSAntti Palosaari ret = af9035_wr_reg_mask(d, 0x80f993, onoff, 0x01); 1361bada342eSAntti Palosaari if (ret < 0) 1362bada342eSAntti Palosaari goto err; 1363bada342eSAntti Palosaari 1364bada342eSAntti Palosaari return 0; 1365bada342eSAntti Palosaari 1366bada342eSAntti Palosaari err: 1367bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1368bada342eSAntti Palosaari 1369bada342eSAntti Palosaari return ret; 1370bada342eSAntti Palosaari } 1371bada342eSAntti Palosaari 1372bada342eSAntti Palosaari static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, 1373bada342eSAntti Palosaari int onoff) 1374bada342eSAntti Palosaari { 1375bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1376bada342eSAntti Palosaari int ret; 1377bada342eSAntti Palosaari u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 1378bada342eSAntti Palosaari 1379bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", 1380bada342eSAntti Palosaari __func__, index, pid, onoff); 1381bada342eSAntti Palosaari 1382bada342eSAntti Palosaari ret = af9035_wr_regs(d, 0x80f996, wbuf, 2); 1383bada342eSAntti Palosaari if (ret < 0) 1384bada342eSAntti Palosaari goto err; 1385bada342eSAntti Palosaari 1386bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f994, onoff); 1387bada342eSAntti Palosaari if (ret < 0) 1388bada342eSAntti Palosaari goto err; 1389bada342eSAntti Palosaari 1390bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f995, index); 1391bada342eSAntti Palosaari if (ret < 0) 1392bada342eSAntti Palosaari goto err; 1393bada342eSAntti Palosaari 1394bada342eSAntti Palosaari return 0; 1395bada342eSAntti Palosaari 1396bada342eSAntti Palosaari err: 1397bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1398bada342eSAntti Palosaari 1399bada342eSAntti Palosaari return ret; 1400bada342eSAntti Palosaari } 1401bada342eSAntti Palosaari 1402b799b810SAntti Palosaari static int af9035_probe(struct usb_interface *intf, 1403b799b810SAntti Palosaari const struct usb_device_id *id) 1404b799b810SAntti Palosaari { 1405b799b810SAntti Palosaari struct usb_device *udev = interface_to_usbdev(intf); 1406b799b810SAntti Palosaari char manufacturer[sizeof("Afatech")]; 1407b799b810SAntti Palosaari 1408b799b810SAntti Palosaari memset(manufacturer, 0, sizeof(manufacturer)); 1409b799b810SAntti Palosaari usb_string(udev, udev->descriptor.iManufacturer, 1410b799b810SAntti Palosaari manufacturer, sizeof(manufacturer)); 1411b799b810SAntti Palosaari /* 1412b799b810SAntti Palosaari * There is two devices having same ID but different chipset. One uses 1413b799b810SAntti Palosaari * AF9015 and the other IT9135 chipset. Only difference seen on lsusb 1414b799b810SAntti Palosaari * is iManufacturer string. 1415b799b810SAntti Palosaari * 1416b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1417b799b810SAntti Palosaari * idProduct 0x0099 1418b799b810SAntti Palosaari * bcdDevice 2.00 1419b799b810SAntti Palosaari * iManufacturer 1 Afatech 1420b799b810SAntti Palosaari * iProduct 2 DVB-T 2 1421b799b810SAntti Palosaari * 1422b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1423b799b810SAntti Palosaari * idProduct 0x0099 1424b799b810SAntti Palosaari * bcdDevice 2.00 1425b799b810SAntti Palosaari * iManufacturer 1 ITE Technologies, Inc. 1426b799b810SAntti Palosaari * iProduct 2 DVB-T TV Stick 1427b799b810SAntti Palosaari */ 1428b799b810SAntti Palosaari if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && 1429b799b810SAntti Palosaari (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { 1430b799b810SAntti Palosaari if (!strcmp("Afatech", manufacturer)) { 1431b799b810SAntti Palosaari dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); 1432b799b810SAntti Palosaari return -ENODEV; 1433b799b810SAntti Palosaari } 1434b799b810SAntti Palosaari } 1435b799b810SAntti Palosaari 1436b799b810SAntti Palosaari return dvb_usbv2_probe(intf, id); 1437b799b810SAntti Palosaari } 1438b799b810SAntti Palosaari 1439786baecfSMauro Carvalho Chehab /* interface 0 is used by DVB-T receiver and 1440786baecfSMauro Carvalho Chehab interface 1 is for remote controller (HID) */ 1441786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties af9035_props = { 1442786baecfSMauro Carvalho Chehab .driver_name = KBUILD_MODNAME, 1443786baecfSMauro Carvalho Chehab .owner = THIS_MODULE, 1444786baecfSMauro Carvalho Chehab .adapter_nr = adapter_nr, 1445786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct state), 1446786baecfSMauro Carvalho Chehab 1447786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x02, 1448786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint_response = 0x81, 1449786baecfSMauro Carvalho Chehab 1450786baecfSMauro Carvalho Chehab .identify_state = af9035_identify_state, 1451786baecfSMauro Carvalho Chehab .download_firmware = af9035_download_firmware, 1452786baecfSMauro Carvalho Chehab 1453786baecfSMauro Carvalho Chehab .i2c_algo = &af9035_i2c_algo, 1454786baecfSMauro Carvalho Chehab .read_config = af9035_read_config, 1455786baecfSMauro Carvalho Chehab .frontend_attach = af9035_frontend_attach, 1456786baecfSMauro Carvalho Chehab .tuner_attach = af9035_tuner_attach, 1457786baecfSMauro Carvalho Chehab .init = af9035_init, 1458786baecfSMauro Carvalho Chehab .get_rc_config = af9035_get_rc_config, 1459bada342eSAntti Palosaari .get_stream_config = af9035_get_stream_config, 1460786baecfSMauro Carvalho Chehab 14619805992fSJose Alberto Reguero .get_adapter_count = af9035_get_adapter_count, 1462786baecfSMauro Carvalho Chehab .adapter = { 1463786baecfSMauro Carvalho Chehab { 1464bada342eSAntti Palosaari .caps = DVB_USB_ADAP_HAS_PID_FILTER | 1465bada342eSAntti Palosaari DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 1466bada342eSAntti Palosaari 1467bada342eSAntti Palosaari .pid_filter_count = 32, 1468bada342eSAntti Palosaari .pid_filter_ctrl = af9035_pid_filter_ctrl, 1469bada342eSAntti Palosaari .pid_filter = af9035_pid_filter, 1470bada342eSAntti Palosaari 1471786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), 1472786baecfSMauro Carvalho Chehab }, { 1473786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), 1474786baecfSMauro Carvalho Chehab }, 1475786baecfSMauro Carvalho Chehab }, 1476786baecfSMauro Carvalho Chehab }; 1477786baecfSMauro Carvalho Chehab 1478786baecfSMauro Carvalho Chehab static const struct usb_device_id af9035_id_table[] = { 1479786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, 1480786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1481786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, 1482786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1483786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, 1484786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1485786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, 1486786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1487786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, 1488786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1489786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, 1490786baecfSMauro Carvalho Chehab &af9035_props, "TerraTec Cinergy T Stick", NULL) }, 1491786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, 1492786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1493786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, 1494786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1495786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, 1496786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1497786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, 1498786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1499786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, 1500786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, 1501d67ceb33SOliver Schinagl { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, 1502d67ceb33SOliver Schinagl &af9035_props, "Asus U3100Mini Plus", NULL) }, 1503d9b7595bSFabrizio Gazzato { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, 1504d9b7595bSFabrizio Gazzato &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, 1505b799b810SAntti Palosaari /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ 1506b799b810SAntti Palosaari { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, 1507b799b810SAntti Palosaari &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, 1508786baecfSMauro Carvalho Chehab { } 1509786baecfSMauro Carvalho Chehab }; 1510786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, af9035_id_table); 1511786baecfSMauro Carvalho Chehab 1512786baecfSMauro Carvalho Chehab static struct usb_driver af9035_usb_driver = { 1513786baecfSMauro Carvalho Chehab .name = KBUILD_MODNAME, 1514786baecfSMauro Carvalho Chehab .id_table = af9035_id_table, 1515b799b810SAntti Palosaari .probe = af9035_probe, 1516786baecfSMauro Carvalho Chehab .disconnect = dvb_usbv2_disconnect, 1517786baecfSMauro Carvalho Chehab .suspend = dvb_usbv2_suspend, 1518786baecfSMauro Carvalho Chehab .resume = dvb_usbv2_resume, 151904966aa8SAntti Palosaari .reset_resume = dvb_usbv2_reset_resume, 1520786baecfSMauro Carvalho Chehab .no_dynamic_id = 1, 1521786baecfSMauro Carvalho Chehab .soft_unbind = 1, 1522786baecfSMauro Carvalho Chehab }; 1523786baecfSMauro Carvalho Chehab 1524786baecfSMauro Carvalho Chehab module_usb_driver(af9035_usb_driver); 1525786baecfSMauro Carvalho Chehab 1526786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 1527786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9035 driver"); 1528786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 15294395e4b7SAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); 153074c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); 153174c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); 1532