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) { 319bc3c9e10SAntti Palosaari if (state->chip_version == 0x02) 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 */ 3659ea3681dSAntti Palosaari ret = af9035_rd_reg(d, EEPROM_BASE_AF9035 + 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 */ 3909ea3681dSAntti Palosaari ret = af9035_rd_reg(d, 3919ea3681dSAntti Palosaari EEPROM_BASE_AF9035 + EEPROM_2ND_DEMOD_ADDR, 3929ea3681dSAntti Palosaari &tmp); 393bf97b637SAntti Palosaari if (ret < 0) 394bf97b637SAntti Palosaari goto err; 395bf97b637SAntti Palosaari 396bf97b637SAntti Palosaari ret = af9035_wr_reg(d, 0x00417f, tmp); 397bf97b637SAntti Palosaari if (ret < 0) 398bf97b637SAntti Palosaari goto err; 399bf97b637SAntti Palosaari 400bf97b637SAntti Palosaari /* enable clock out */ 401bf97b637SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); 402bf97b637SAntti Palosaari if (ret < 0) 403bf97b637SAntti Palosaari goto err; 404bf97b637SAntti Palosaari } 405bf97b637SAntti Palosaari 406bf97b637SAntti Palosaari /* 407786baecfSMauro Carvalho Chehab * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! 408786baecfSMauro Carvalho Chehab * 409786baecfSMauro Carvalho Chehab * byte 0: MCS 51 core 410786baecfSMauro Carvalho Chehab * There are two inside the AF9035 (1=Link and 2=OFDM) with separate 411786baecfSMauro Carvalho Chehab * address spaces 412786baecfSMauro Carvalho Chehab * byte 1-2: Big endian destination address 413786baecfSMauro Carvalho Chehab * byte 3-4: Big endian number of data bytes following the header 414786baecfSMauro Carvalho Chehab * byte 5-6: Big endian header checksum, apparently ignored by the chip 415786baecfSMauro Carvalho Chehab * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) 416786baecfSMauro Carvalho Chehab */ 417786baecfSMauro Carvalho Chehab 418786baecfSMauro Carvalho Chehab for (i = fw->size; i > HDR_SIZE;) { 419786baecfSMauro Carvalho Chehab hdr_core = fw->data[fw->size - i + 0]; 420786baecfSMauro Carvalho Chehab hdr_addr = fw->data[fw->size - i + 1] << 8; 421786baecfSMauro Carvalho Chehab hdr_addr |= fw->data[fw->size - i + 2] << 0; 422786baecfSMauro Carvalho Chehab hdr_data_len = fw->data[fw->size - i + 3] << 8; 423786baecfSMauro Carvalho Chehab hdr_data_len |= fw->data[fw->size - i + 4] << 0; 424786baecfSMauro Carvalho Chehab hdr_checksum = fw->data[fw->size - i + 5] << 8; 425786baecfSMauro Carvalho Chehab hdr_checksum |= fw->data[fw->size - i + 6] << 0; 426786baecfSMauro Carvalho Chehab 427119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ 428119f7a8cSAntti Palosaari "checksum=%04x\n", __func__, hdr_core, hdr_addr, 429119f7a8cSAntti Palosaari hdr_data_len, hdr_checksum); 430786baecfSMauro Carvalho Chehab 431786baecfSMauro Carvalho Chehab if (((hdr_core != 1) && (hdr_core != 2)) || 432786baecfSMauro Carvalho Chehab (hdr_data_len > i)) { 433119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: bad firmware\n", __func__); 434786baecfSMauro Carvalho Chehab break; 435786baecfSMauro Carvalho Chehab } 436786baecfSMauro Carvalho Chehab 437786baecfSMauro Carvalho Chehab /* download begin packet */ 438786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_BEGIN; 439786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 440786baecfSMauro Carvalho Chehab if (ret < 0) 441786baecfSMauro Carvalho Chehab goto err; 442786baecfSMauro Carvalho Chehab 443786baecfSMauro Carvalho Chehab /* download firmware packet(s) */ 444786baecfSMauro Carvalho Chehab for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { 445786baecfSMauro Carvalho Chehab len = j; 446786baecfSMauro Carvalho Chehab if (len > MAX_DATA) 447786baecfSMauro Carvalho Chehab len = MAX_DATA; 448786baecfSMauro Carvalho Chehab req_fw_dl.wlen = len; 449786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + 450786baecfSMauro Carvalho Chehab HDR_SIZE + hdr_data_len - j]; 451786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 452786baecfSMauro Carvalho Chehab if (ret < 0) 453786baecfSMauro Carvalho Chehab goto err; 454786baecfSMauro Carvalho Chehab } 455786baecfSMauro Carvalho Chehab 456786baecfSMauro Carvalho Chehab /* download end packet */ 457786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_END; 458786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 459786baecfSMauro Carvalho Chehab if (ret < 0) 460786baecfSMauro Carvalho Chehab goto err; 461786baecfSMauro Carvalho Chehab 462786baecfSMauro Carvalho Chehab i -= hdr_data_len + HDR_SIZE; 463786baecfSMauro Carvalho Chehab 464119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%zu\n", 465119f7a8cSAntti Palosaari __func__, fw->size - i); 466786baecfSMauro Carvalho Chehab } 467786baecfSMauro Carvalho Chehab 468ff4e3fe8SAntti Palosaari /* print warn if firmware is bad, continue and see what happens */ 469ff4e3fe8SAntti Palosaari if (i) 470ff4e3fe8SAntti Palosaari dev_warn(&d->udev->dev, "%s: bad firmware\n", KBUILD_MODNAME); 471ff4e3fe8SAntti Palosaari 472786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 473786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 474786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 475786baecfSMauro Carvalho Chehab if (ret < 0) 476786baecfSMauro Carvalho Chehab goto err; 477786baecfSMauro Carvalho Chehab 478786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 479786baecfSMauro Carvalho Chehab wbuf[0] = 1; 480786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 481786baecfSMauro Carvalho Chehab if (ret < 0) 482786baecfSMauro Carvalho Chehab goto err; 483786baecfSMauro Carvalho Chehab 484786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 485119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: firmware did not run\n", 486119f7a8cSAntti Palosaari KBUILD_MODNAME); 487786baecfSMauro Carvalho Chehab ret = -ENODEV; 488786baecfSMauro Carvalho Chehab goto err; 489786baecfSMauro Carvalho Chehab } 490786baecfSMauro Carvalho Chehab 491119f7a8cSAntti Palosaari dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", 492119f7a8cSAntti Palosaari KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 493786baecfSMauro Carvalho Chehab 494786baecfSMauro Carvalho Chehab return 0; 495786baecfSMauro Carvalho Chehab 496786baecfSMauro Carvalho Chehab err: 497119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 498786baecfSMauro Carvalho Chehab 499786baecfSMauro Carvalho Chehab return ret; 500786baecfSMauro Carvalho Chehab } 501786baecfSMauro Carvalho Chehab 502786baecfSMauro Carvalho Chehab static int af9035_download_firmware_it9135(struct dvb_usb_device *d, 503786baecfSMauro Carvalho Chehab const struct firmware *fw) 504786baecfSMauro Carvalho Chehab { 505786baecfSMauro Carvalho Chehab int ret, i, i_prev; 506786baecfSMauro Carvalho Chehab u8 wbuf[1]; 507786baecfSMauro Carvalho Chehab u8 rbuf[4]; 508786baecfSMauro Carvalho Chehab struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 509786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; 510786baecfSMauro Carvalho Chehab struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; 511786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 512786baecfSMauro Carvalho Chehab 513786baecfSMauro Carvalho Chehab /* 514786baecfSMauro Carvalho Chehab * There seems to be following firmware header. Meaning of bytes 0-3 515786baecfSMauro Carvalho Chehab * is unknown. 516786baecfSMauro Carvalho Chehab * 517786baecfSMauro Carvalho Chehab * 0: 3 518786baecfSMauro Carvalho Chehab * 1: 0, 1 519786baecfSMauro Carvalho Chehab * 2: 0 520786baecfSMauro Carvalho Chehab * 3: 1, 2, 3 521786baecfSMauro Carvalho Chehab * 4: addr MSB 522786baecfSMauro Carvalho Chehab * 5: addr LSB 523786baecfSMauro Carvalho Chehab * 6: count of data bytes ? 524786baecfSMauro Carvalho Chehab */ 525786baecfSMauro Carvalho Chehab 526786baecfSMauro Carvalho Chehab for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { 527786baecfSMauro Carvalho Chehab if (i == fw->size || 528786baecfSMauro Carvalho Chehab (fw->data[i + 0] == 0x03 && 529786baecfSMauro Carvalho Chehab (fw->data[i + 1] == 0x00 || 530786baecfSMauro Carvalho Chehab fw->data[i + 1] == 0x01) && 531786baecfSMauro Carvalho Chehab fw->data[i + 2] == 0x00)) { 532786baecfSMauro Carvalho Chehab req_fw_dl.wlen = i - i_prev; 533786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; 534786baecfSMauro Carvalho Chehab i_prev = i; 535786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 536786baecfSMauro Carvalho Chehab if (ret < 0) 537786baecfSMauro Carvalho Chehab goto err; 538786baecfSMauro Carvalho Chehab 539119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%d\n", 540119f7a8cSAntti Palosaari __func__, i); 541786baecfSMauro Carvalho Chehab } 542786baecfSMauro Carvalho Chehab } 543786baecfSMauro Carvalho Chehab 544786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 545786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 546786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 547786baecfSMauro Carvalho Chehab if (ret < 0) 548786baecfSMauro Carvalho Chehab goto err; 549786baecfSMauro Carvalho Chehab 550786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 551786baecfSMauro Carvalho Chehab wbuf[0] = 1; 552786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 553786baecfSMauro Carvalho Chehab if (ret < 0) 554786baecfSMauro Carvalho Chehab goto err; 555786baecfSMauro Carvalho Chehab 556786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 557119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: firmware did not run\n", 558119f7a8cSAntti Palosaari KBUILD_MODNAME); 559786baecfSMauro Carvalho Chehab ret = -ENODEV; 560786baecfSMauro Carvalho Chehab goto err; 561786baecfSMauro Carvalho Chehab } 562786baecfSMauro Carvalho Chehab 563119f7a8cSAntti Palosaari dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", 564119f7a8cSAntti Palosaari KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 565786baecfSMauro Carvalho Chehab 566786baecfSMauro Carvalho Chehab return 0; 567786baecfSMauro Carvalho Chehab 568786baecfSMauro Carvalho Chehab err: 569119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 570786baecfSMauro Carvalho Chehab 571786baecfSMauro Carvalho Chehab return ret; 572786baecfSMauro Carvalho Chehab } 573786baecfSMauro Carvalho Chehab 57474c1883aSAntti Palosaari static int af9035_download_firmware(struct dvb_usb_device *d, 57574c1883aSAntti Palosaari const struct firmware *fw) 57674c1883aSAntti Palosaari { 57774c1883aSAntti Palosaari struct state *state = d_to_priv(d); 57874c1883aSAntti Palosaari 57974c1883aSAntti Palosaari if (state->chip_type == 0x9135) 58074c1883aSAntti Palosaari return af9035_download_firmware_it9135(d, fw); 58174c1883aSAntti Palosaari else 58274c1883aSAntti Palosaari return af9035_download_firmware_af9035(d, fw); 58374c1883aSAntti Palosaari } 58474c1883aSAntti Palosaari 5859ea3681dSAntti Palosaari static int af9035_read_config(struct dvb_usb_device *d) 586786baecfSMauro Carvalho Chehab { 587786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 5889ea3681dSAntti Palosaari int ret, i; 589786baecfSMauro Carvalho Chehab u8 tmp; 5909ea3681dSAntti Palosaari u16 tmp16, addr; 591786baecfSMauro Carvalho Chehab 592bf97b637SAntti Palosaari /* demod I2C "address" */ 593bf97b637SAntti Palosaari state->af9033_config[0].i2c_addr = 0x38; 5940d94d6a0SAntti Palosaari state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 595bf97b637SAntti Palosaari 5969ea3681dSAntti Palosaari /* eeprom memory mapped location */ 5979ea3681dSAntti Palosaari if (state->chip_type == 0x9135) { 598bc3c9e10SAntti Palosaari if (state->chip_version == 0x02) { 599bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; 600bc3c9e10SAntti Palosaari tmp16 = 0x00461d; 601bc3c9e10SAntti Palosaari } else { 602bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; 603bc3c9e10SAntti Palosaari tmp16 = 0x00461b; 604bc3c9e10SAntti Palosaari } 605bc3c9e10SAntti Palosaari 6069ea3681dSAntti Palosaari /* check if eeprom exists */ 607bc3c9e10SAntti Palosaari ret = af9035_rd_reg(d, tmp16, &tmp); 6089ea3681dSAntti Palosaari if (ret < 0) 6099ea3681dSAntti Palosaari goto err; 6109ea3681dSAntti Palosaari 6119ea3681dSAntti Palosaari if (tmp) { 6129ea3681dSAntti Palosaari addr = EEPROM_BASE_IT9135; 6139ea3681dSAntti Palosaari } else { 614bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: no eeprom\n", __func__); 6159ea3681dSAntti Palosaari goto skip_eeprom; 6169ea3681dSAntti Palosaari } 6179ea3681dSAntti Palosaari } else { 6189ea3681dSAntti Palosaari addr = EEPROM_BASE_AF9035; 6199ea3681dSAntti Palosaari } 6209ea3681dSAntti Palosaari 621786baecfSMauro Carvalho Chehab /* check if there is dual tuners */ 6229ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_DUAL_MODE, &tmp); 623786baecfSMauro Carvalho Chehab if (ret < 0) 624786baecfSMauro Carvalho Chehab goto err; 625786baecfSMauro Carvalho Chehab 626786baecfSMauro Carvalho Chehab state->dual_mode = tmp; 627bf97b637SAntti Palosaari dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", __func__, 628bf97b637SAntti Palosaari state->dual_mode); 629786baecfSMauro Carvalho Chehab 6309805992fSJose Alberto Reguero if (state->dual_mode) { 6319805992fSJose Alberto Reguero /* read 2nd demodulator I2C address */ 6329ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_2ND_DEMOD_ADDR, &tmp); 6339805992fSJose Alberto Reguero if (ret < 0) 6349805992fSJose Alberto Reguero goto err; 635bf97b637SAntti Palosaari 6369805992fSJose Alberto Reguero state->af9033_config[1].i2c_addr = tmp; 637bf97b637SAntti Palosaari dev_dbg(&d->udev->dev, "%s: 2nd demod I2C addr=%02x\n", 638bf97b637SAntti Palosaari __func__, tmp); 6399805992fSJose Alberto Reguero } 6409805992fSJose Alberto Reguero 641786baecfSMauro Carvalho Chehab for (i = 0; i < state->dual_mode + 1; i++) { 642786baecfSMauro Carvalho Chehab /* tuner */ 6439ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_TUNER_ID, &tmp); 644786baecfSMauro Carvalho Chehab if (ret < 0) 645786baecfSMauro Carvalho Chehab goto err; 646786baecfSMauro Carvalho Chehab 647bc3c9e10SAntti Palosaari if (tmp == 0x00) 648bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, 649bc3c9e10SAntti Palosaari "%s: [%d]tuner not set, using default\n", 650bc3c9e10SAntti Palosaari __func__, i); 651bc3c9e10SAntti Palosaari else 652786baecfSMauro Carvalho Chehab state->af9033_config[i].tuner = tmp; 653786baecfSMauro Carvalho Chehab 654bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", 655bc3c9e10SAntti Palosaari __func__, i, state->af9033_config[i].tuner); 6569ea3681dSAntti Palosaari 6579ea3681dSAntti Palosaari switch (state->af9033_config[i].tuner) { 658786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 659786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 660786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 661786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 662d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 6637e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 664786baecfSMauro Carvalho Chehab state->af9033_config[i].spec_inv = 1; 665786baecfSMauro Carvalho Chehab break; 6669ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_38: 6679ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_51: 6689ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_52: 6699ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_60: 6709ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_61: 6719ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_62: 6729ea3681dSAntti Palosaari break; 673786baecfSMauro Carvalho Chehab default: 6749ea3681dSAntti Palosaari dev_warn(&d->udev->dev, 6759ea3681dSAntti Palosaari "%s: tuner id=%02x not supported, please report!", 676119f7a8cSAntti Palosaari KBUILD_MODNAME, tmp); 677c2c1b415SPeter Senna Tschudin } 678786baecfSMauro Carvalho Chehab 679bf97b637SAntti Palosaari /* disable dual mode if driver does not support it */ 680bf97b637SAntti Palosaari if (i == 1) 681bf97b637SAntti Palosaari switch (tmp) { 6820bb3d8acSAntti Palosaari case AF9033_TUNER_FC0012: 6830bb3d8acSAntti Palosaari break; 684bf97b637SAntti Palosaari default: 685bf97b637SAntti Palosaari state->dual_mode = false; 6869ea3681dSAntti Palosaari dev_info(&d->udev->dev, 6879ea3681dSAntti Palosaari "%s: driver does not support 2nd tuner and will disable it", 6889ea3681dSAntti Palosaari KBUILD_MODNAME); 689bf97b637SAntti Palosaari } 690bf97b637SAntti Palosaari 691786baecfSMauro Carvalho Chehab /* tuner IF frequency */ 6929ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_IF_L, &tmp); 693786baecfSMauro Carvalho Chehab if (ret < 0) 694786baecfSMauro Carvalho Chehab goto err; 695786baecfSMauro Carvalho Chehab 696786baecfSMauro Carvalho Chehab tmp16 = tmp; 697786baecfSMauro Carvalho Chehab 6989ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_IF_H, &tmp); 699786baecfSMauro Carvalho Chehab if (ret < 0) 700786baecfSMauro Carvalho Chehab goto err; 701786baecfSMauro Carvalho Chehab 702786baecfSMauro Carvalho Chehab tmp16 |= tmp << 8; 703786baecfSMauro Carvalho Chehab 704119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16); 705786baecfSMauro Carvalho Chehab 7069ea3681dSAntti Palosaari addr += 0x10; /* shift for the 2nd tuner params */ 707786baecfSMauro Carvalho Chehab } 708786baecfSMauro Carvalho Chehab 7099ea3681dSAntti Palosaari skip_eeprom: 710786baecfSMauro Carvalho Chehab /* get demod clock */ 711786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, 0x00d800, &tmp); 712786baecfSMauro Carvalho Chehab if (ret < 0) 713786baecfSMauro Carvalho Chehab goto err; 714786baecfSMauro Carvalho Chehab 715786baecfSMauro Carvalho Chehab tmp = (tmp >> 0) & 0x0f; 716786baecfSMauro Carvalho Chehab 7179ea3681dSAntti Palosaari for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) { 71874c1883aSAntti Palosaari if (state->chip_type == 0x9135) 7199ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_it9135[tmp]; 72074c1883aSAntti Palosaari else 7219ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_af9035[tmp]; 7229ea3681dSAntti Palosaari } 7239ea3681dSAntti Palosaari 7249ea3681dSAntti Palosaari return 0; 7259ea3681dSAntti Palosaari 7269ea3681dSAntti Palosaari err: 7279ea3681dSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 7289ea3681dSAntti Palosaari 7299ea3681dSAntti Palosaari return ret; 73074c1883aSAntti Palosaari } 73174c1883aSAntti Palosaari 73251639be3SAntti Palosaari static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, 73351639be3SAntti Palosaari int cmd, int arg) 73451639be3SAntti Palosaari { 73551639be3SAntti Palosaari int ret; 73651639be3SAntti Palosaari u8 val; 73751639be3SAntti Palosaari 73851639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); 73951639be3SAntti Palosaari 74051639be3SAntti Palosaari /* 74151639be3SAntti Palosaari * CEN always enabled by hardware wiring 74251639be3SAntti Palosaari * RESETN GPIOT3 74351639be3SAntti Palosaari * RXEN GPIOT2 74451639be3SAntti Palosaari */ 74551639be3SAntti Palosaari 74651639be3SAntti Palosaari switch (cmd) { 74751639be3SAntti Palosaari case TUA9001_CMD_RESETN: 74851639be3SAntti Palosaari if (arg) 74951639be3SAntti Palosaari val = 0x00; 75051639be3SAntti Palosaari else 75151639be3SAntti Palosaari val = 0x01; 75251639be3SAntti Palosaari 75351639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); 75451639be3SAntti Palosaari if (ret < 0) 75551639be3SAntti Palosaari goto err; 75651639be3SAntti Palosaari break; 75751639be3SAntti Palosaari case TUA9001_CMD_RXEN: 75851639be3SAntti Palosaari if (arg) 75951639be3SAntti Palosaari val = 0x01; 76051639be3SAntti Palosaari else 76151639be3SAntti Palosaari val = 0x00; 76251639be3SAntti Palosaari 76351639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); 76451639be3SAntti Palosaari if (ret < 0) 76551639be3SAntti Palosaari goto err; 76651639be3SAntti Palosaari break; 76751639be3SAntti Palosaari } 76851639be3SAntti Palosaari 76951639be3SAntti Palosaari return 0; 77051639be3SAntti Palosaari 77151639be3SAntti Palosaari err: 77251639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 77351639be3SAntti Palosaari 77451639be3SAntti Palosaari return ret; 77551639be3SAntti Palosaari } 77651639be3SAntti Palosaari 77751639be3SAntti Palosaari 778786baecfSMauro Carvalho Chehab static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, 779786baecfSMauro Carvalho Chehab int cmd, int arg) 780786baecfSMauro Carvalho Chehab { 781786baecfSMauro Carvalho Chehab int ret; 782786baecfSMauro Carvalho Chehab 783786baecfSMauro Carvalho Chehab switch (cmd) { 784786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_POWER: 785786baecfSMauro Carvalho Chehab /* Tuner enable */ 786786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); 787786baecfSMauro Carvalho Chehab if (ret < 0) 788786baecfSMauro Carvalho Chehab goto err; 789786baecfSMauro Carvalho Chehab 790786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); 791786baecfSMauro Carvalho Chehab if (ret < 0) 792786baecfSMauro Carvalho Chehab goto err; 793786baecfSMauro Carvalho Chehab 794786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); 795786baecfSMauro Carvalho Chehab if (ret < 0) 796786baecfSMauro Carvalho Chehab goto err; 797786baecfSMauro Carvalho Chehab 798786baecfSMauro Carvalho Chehab /* LED */ 799786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); 800786baecfSMauro Carvalho Chehab if (ret < 0) 801786baecfSMauro Carvalho Chehab goto err; 802786baecfSMauro Carvalho Chehab 803786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); 804786baecfSMauro Carvalho Chehab if (ret < 0) 805786baecfSMauro Carvalho Chehab goto err; 806786baecfSMauro Carvalho Chehab 807786baecfSMauro Carvalho Chehab usleep_range(10000, 50000); 808786baecfSMauro Carvalho Chehab break; 809786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_RESET: 810786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e9, 1); 811786baecfSMauro Carvalho Chehab if (ret < 0) 812786baecfSMauro Carvalho Chehab goto err; 813786baecfSMauro Carvalho Chehab 814786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e8, 1); 815786baecfSMauro Carvalho Chehab if (ret < 0) 816786baecfSMauro Carvalho Chehab goto err; 817786baecfSMauro Carvalho Chehab 818786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 1); 819786baecfSMauro Carvalho Chehab if (ret < 0) 820786baecfSMauro Carvalho Chehab goto err; 821786baecfSMauro Carvalho Chehab 822786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 823786baecfSMauro Carvalho Chehab 824786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 0); 825786baecfSMauro Carvalho Chehab if (ret < 0) 826786baecfSMauro Carvalho Chehab goto err; 827786baecfSMauro Carvalho Chehab 828786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 829786baecfSMauro Carvalho Chehab break; 830786baecfSMauro Carvalho Chehab default: 831786baecfSMauro Carvalho Chehab ret = -EINVAL; 832786baecfSMauro Carvalho Chehab goto err; 833786baecfSMauro Carvalho Chehab } 834786baecfSMauro Carvalho Chehab 835786baecfSMauro Carvalho Chehab return 0; 836786baecfSMauro Carvalho Chehab 837786baecfSMauro Carvalho Chehab err: 838119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 839786baecfSMauro Carvalho Chehab 840786baecfSMauro Carvalho Chehab return ret; 841786baecfSMauro Carvalho Chehab } 842786baecfSMauro Carvalho Chehab 843786baecfSMauro Carvalho Chehab static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) 844786baecfSMauro Carvalho Chehab { 845786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 846786baecfSMauro Carvalho Chehab 847786baecfSMauro Carvalho Chehab switch (state->af9033_config[0].tuner) { 848786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 849786baecfSMauro Carvalho Chehab return af9035_fc0011_tuner_callback(d, cmd, arg); 85051639be3SAntti Palosaari case AF9033_TUNER_TUA9001: 85151639be3SAntti Palosaari return af9035_tua9001_tuner_callback(d, cmd, arg); 852786baecfSMauro Carvalho Chehab default: 853786baecfSMauro Carvalho Chehab break; 854786baecfSMauro Carvalho Chehab } 855786baecfSMauro Carvalho Chehab 8561835af10SAntti Palosaari return 0; 857786baecfSMauro Carvalho Chehab } 858786baecfSMauro Carvalho Chehab 859786baecfSMauro Carvalho Chehab static int af9035_frontend_callback(void *adapter_priv, int component, 860786baecfSMauro Carvalho Chehab int cmd, int arg) 861786baecfSMauro Carvalho Chehab { 862786baecfSMauro Carvalho Chehab struct i2c_adapter *adap = adapter_priv; 863786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 864786baecfSMauro Carvalho Chehab 8651835af10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", 8661835af10SAntti Palosaari __func__, component, cmd, arg); 8671835af10SAntti Palosaari 868786baecfSMauro Carvalho Chehab switch (component) { 869786baecfSMauro Carvalho Chehab case DVB_FRONTEND_COMPONENT_TUNER: 870786baecfSMauro Carvalho Chehab return af9035_tuner_callback(d, cmd, arg); 871786baecfSMauro Carvalho Chehab default: 872786baecfSMauro Carvalho Chehab break; 873786baecfSMauro Carvalho Chehab } 874786baecfSMauro Carvalho Chehab 8751835af10SAntti Palosaari return 0; 876786baecfSMauro Carvalho Chehab } 877786baecfSMauro Carvalho Chehab 8789805992fSJose Alberto Reguero static int af9035_get_adapter_count(struct dvb_usb_device *d) 8799805992fSJose Alberto Reguero { 8809805992fSJose Alberto Reguero struct state *state = d_to_priv(d); 881bada342eSAntti Palosaari 882bada342eSAntti Palosaari /* disable 2nd adapter as we don't have PID filters implemented */ 883bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 884bada342eSAntti Palosaari return 1; 885bada342eSAntti Palosaari else 8869805992fSJose Alberto Reguero return state->dual_mode + 1; 8879805992fSJose Alberto Reguero } 8889805992fSJose Alberto Reguero 889786baecfSMauro Carvalho Chehab static int af9035_frontend_attach(struct dvb_usb_adapter *adap) 890786baecfSMauro Carvalho Chehab { 891786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 892786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 893786baecfSMauro Carvalho Chehab int ret; 894786baecfSMauro Carvalho Chehab 895786baecfSMauro Carvalho Chehab if (!state->af9033_config[adap->id].tuner) { 896786baecfSMauro Carvalho Chehab /* unsupported tuner */ 897786baecfSMauro Carvalho Chehab ret = -ENODEV; 898786baecfSMauro Carvalho Chehab goto err; 899786baecfSMauro Carvalho Chehab } 900786baecfSMauro Carvalho Chehab 901786baecfSMauro Carvalho Chehab if (adap->id == 0) { 902786baecfSMauro Carvalho Chehab state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; 903786baecfSMauro Carvalho Chehab state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; 904786baecfSMauro Carvalho Chehab 905786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00417f, 906786baecfSMauro Carvalho Chehab state->af9033_config[1].i2c_addr); 907786baecfSMauro Carvalho Chehab if (ret < 0) 908786baecfSMauro Carvalho Chehab goto err; 909786baecfSMauro Carvalho Chehab 910bf97b637SAntti Palosaari ret = af9035_wr_reg(d, 0x00d81a, state->dual_mode); 911786baecfSMauro Carvalho Chehab if (ret < 0) 912786baecfSMauro Carvalho Chehab goto err; 913786baecfSMauro Carvalho Chehab } 914786baecfSMauro Carvalho Chehab 915786baecfSMauro Carvalho Chehab /* attach demodulator */ 916bf97b637SAntti Palosaari adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], 917bf97b637SAntti Palosaari &d->i2c_adap); 918786baecfSMauro Carvalho Chehab if (adap->fe[0] == NULL) { 919786baecfSMauro Carvalho Chehab ret = -ENODEV; 920786baecfSMauro Carvalho Chehab goto err; 921786baecfSMauro Carvalho Chehab } 922786baecfSMauro Carvalho Chehab 923786baecfSMauro Carvalho Chehab /* disable I2C-gate */ 924786baecfSMauro Carvalho Chehab adap->fe[0]->ops.i2c_gate_ctrl = NULL; 925786baecfSMauro Carvalho Chehab adap->fe[0]->callback = af9035_frontend_callback; 926786baecfSMauro Carvalho Chehab 927786baecfSMauro Carvalho Chehab return 0; 928786baecfSMauro Carvalho Chehab 929786baecfSMauro Carvalho Chehab err: 930119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 931786baecfSMauro Carvalho Chehab 932786baecfSMauro Carvalho Chehab return ret; 933786baecfSMauro Carvalho Chehab } 934786baecfSMauro Carvalho Chehab 935786baecfSMauro Carvalho Chehab static struct tua9001_config af9035_tua9001_config = { 936786baecfSMauro Carvalho Chehab .i2c_addr = 0x60, 937786baecfSMauro Carvalho Chehab }; 938786baecfSMauro Carvalho Chehab 939786baecfSMauro Carvalho Chehab static const struct fc0011_config af9035_fc0011_config = { 940786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 941786baecfSMauro Carvalho Chehab }; 942786baecfSMauro Carvalho Chehab 9439805992fSJose Alberto Reguero static struct mxl5007t_config af9035_mxl5007t_config[] = { 9449805992fSJose Alberto Reguero { 945786baecfSMauro Carvalho Chehab .xtal_freq_hz = MxL_XTAL_24_MHZ, 946786baecfSMauro Carvalho Chehab .if_freq_hz = MxL_IF_4_57_MHZ, 947786baecfSMauro Carvalho Chehab .invert_if = 0, 948786baecfSMauro Carvalho Chehab .loop_thru_enable = 0, 949786baecfSMauro Carvalho Chehab .clk_out_enable = 0, 950786baecfSMauro Carvalho Chehab .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 9519805992fSJose Alberto Reguero }, { 9529805992fSJose Alberto Reguero .xtal_freq_hz = MxL_XTAL_24_MHZ, 9539805992fSJose Alberto Reguero .if_freq_hz = MxL_IF_4_57_MHZ, 9549805992fSJose Alberto Reguero .invert_if = 0, 9559805992fSJose Alberto Reguero .loop_thru_enable = 1, 9569805992fSJose Alberto Reguero .clk_out_enable = 1, 9579805992fSJose Alberto Reguero .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 9589805992fSJose Alberto Reguero } 959786baecfSMauro Carvalho Chehab }; 960786baecfSMauro Carvalho Chehab 961786baecfSMauro Carvalho Chehab static struct tda18218_config af9035_tda18218_config = { 962786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 963786baecfSMauro Carvalho Chehab .i2c_wr_max = 21, 964786baecfSMauro Carvalho Chehab }; 965786baecfSMauro Carvalho Chehab 966d67ceb33SOliver Schinagl static const struct fc2580_config af9035_fc2580_config = { 967d67ceb33SOliver Schinagl .i2c_addr = 0x56, 968d67ceb33SOliver Schinagl .clock = 16384000, 969d67ceb33SOliver Schinagl }; 970d67ceb33SOliver Schinagl 9710bb3d8acSAntti Palosaari static const struct fc0012_config af9035_fc0012_config[] = { 9720bb3d8acSAntti Palosaari { 973ad3a758bSAntti Palosaari .i2c_address = 0x63, 974ad3a758bSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 9753a984772SAntti Palosaari .dual_master = true, 9760bb3d8acSAntti Palosaari .loop_through = true, 9770bb3d8acSAntti Palosaari .clock_out = true, 9780bb3d8acSAntti Palosaari }, { 9790bb3d8acSAntti Palosaari .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ 9800bb3d8acSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 9813a984772SAntti Palosaari .dual_master = true, 9820bb3d8acSAntti Palosaari } 983ad3a758bSAntti Palosaari }; 984ad3a758bSAntti Palosaari 985ac77fb0fSAntti Palosaari static struct ite_config af9035_it913x_config = { 986bc3c9e10SAntti Palosaari .chip_ver = 0x02, 987ac77fb0fSAntti Palosaari .chip_type = 0x9135, 988ac77fb0fSAntti Palosaari .firmware = 0x00000000, 989ac77fb0fSAntti Palosaari .firmware_ver = 1, 990ac77fb0fSAntti Palosaari .adc_x2 = 1, 991bc3c9e10SAntti Palosaari .tuner_id_0 = 0x00, 992ac77fb0fSAntti Palosaari .tuner_id_1 = 0x00, 993ac77fb0fSAntti Palosaari .dual_mode = 0x00, 994ac77fb0fSAntti Palosaari .adf = 0x00, 995ac77fb0fSAntti Palosaari /* option to read SIGNAL_LEVEL */ 996ac77fb0fSAntti Palosaari .read_slevel = 0, 997ac77fb0fSAntti Palosaari }; 998ac77fb0fSAntti Palosaari 999786baecfSMauro Carvalho Chehab static int af9035_tuner_attach(struct dvb_usb_adapter *adap) 1000786baecfSMauro Carvalho Chehab { 1001786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1002786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 1003786baecfSMauro Carvalho Chehab int ret; 1004786baecfSMauro Carvalho Chehab struct dvb_frontend *fe; 10050bb3d8acSAntti Palosaari struct i2c_msg msg[1]; 1006bf97b637SAntti Palosaari u8 tuner_addr; 1007bf97b637SAntti Palosaari /* 1008bf97b637SAntti Palosaari * XXX: Hack used in that function: we abuse unused I2C address bit [7] 1009bf97b637SAntti Palosaari * to carry info about used I2C bus for dual tuner configuration. 1010bf97b637SAntti Palosaari */ 1011786baecfSMauro Carvalho Chehab 1012786baecfSMauro Carvalho Chehab switch (state->af9033_config[adap->id].tuner) { 1013786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 1014786baecfSMauro Carvalho Chehab /* AF9035 gpiot3 = TUA9001 RESETN 1015786baecfSMauro Carvalho Chehab AF9035 gpiot2 = TUA9001 RXEN */ 1016786baecfSMauro Carvalho Chehab 1017786baecfSMauro Carvalho Chehab /* configure gpiot2 and gpiot2 as output */ 1018786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); 1019786baecfSMauro Carvalho Chehab if (ret < 0) 1020786baecfSMauro Carvalho Chehab goto err; 1021786baecfSMauro Carvalho Chehab 1022786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); 1023786baecfSMauro Carvalho Chehab if (ret < 0) 1024786baecfSMauro Carvalho Chehab goto err; 1025786baecfSMauro Carvalho Chehab 1026786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); 1027786baecfSMauro Carvalho Chehab if (ret < 0) 1028786baecfSMauro Carvalho Chehab goto err; 1029786baecfSMauro Carvalho Chehab 1030786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); 1031786baecfSMauro Carvalho Chehab if (ret < 0) 1032786baecfSMauro Carvalho Chehab goto err; 1033786baecfSMauro Carvalho Chehab 1034786baecfSMauro Carvalho Chehab /* attach tuner */ 1035786baecfSMauro Carvalho Chehab fe = dvb_attach(tua9001_attach, adap->fe[0], 1036786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tua9001_config); 1037786baecfSMauro Carvalho Chehab break; 1038786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 1039786baecfSMauro Carvalho Chehab fe = dvb_attach(fc0011_attach, adap->fe[0], 1040786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_fc0011_config); 1041786baecfSMauro Carvalho Chehab break; 1042786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 10439805992fSJose Alberto Reguero if (adap->id == 0) { 1044786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e0, 1); 1045786baecfSMauro Carvalho Chehab if (ret < 0) 1046786baecfSMauro Carvalho Chehab goto err; 1047bf97b637SAntti Palosaari 1048786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e1, 1); 1049786baecfSMauro Carvalho Chehab if (ret < 0) 1050786baecfSMauro Carvalho Chehab goto err; 1051bf97b637SAntti Palosaari 1052786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 0); 1053786baecfSMauro Carvalho Chehab if (ret < 0) 1054786baecfSMauro Carvalho Chehab goto err; 1055786baecfSMauro Carvalho Chehab 1056786baecfSMauro Carvalho Chehab msleep(30); 1057786baecfSMauro Carvalho Chehab 1058786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 1); 1059786baecfSMauro Carvalho Chehab if (ret < 0) 1060786baecfSMauro Carvalho Chehab goto err; 1061786baecfSMauro Carvalho Chehab 1062786baecfSMauro Carvalho Chehab msleep(300); 1063786baecfSMauro Carvalho Chehab 1064786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c0, 1); 1065786baecfSMauro Carvalho Chehab if (ret < 0) 1066786baecfSMauro Carvalho Chehab goto err; 1067bf97b637SAntti Palosaari 1068786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c1, 1); 1069786baecfSMauro Carvalho Chehab if (ret < 0) 1070786baecfSMauro Carvalho Chehab goto err; 1071bf97b637SAntti Palosaari 1072786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8bf, 0); 1073786baecfSMauro Carvalho Chehab if (ret < 0) 1074786baecfSMauro Carvalho Chehab goto err; 1075bf97b637SAntti Palosaari 1076786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b4, 1); 1077786baecfSMauro Carvalho Chehab if (ret < 0) 1078786baecfSMauro Carvalho Chehab goto err; 1079bf97b637SAntti Palosaari 1080786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b5, 1); 1081786baecfSMauro Carvalho Chehab if (ret < 0) 1082786baecfSMauro Carvalho Chehab goto err; 1083bf97b637SAntti Palosaari 1084786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b3, 1); 1085786baecfSMauro Carvalho Chehab if (ret < 0) 1086786baecfSMauro Carvalho Chehab goto err; 1087bf97b637SAntti Palosaari 1088bf97b637SAntti Palosaari tuner_addr = 0x60; 1089bf97b637SAntti Palosaari } else { 1090bf97b637SAntti Palosaari tuner_addr = 0x60 | 0x80; /* I2C bus hack */ 10919805992fSJose Alberto Reguero } 1092786baecfSMauro Carvalho Chehab 1093786baecfSMauro Carvalho Chehab /* attach tuner */ 1094bf97b637SAntti Palosaari fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, 1095bf97b637SAntti Palosaari tuner_addr, &af9035_mxl5007t_config[adap->id]); 1096786baecfSMauro Carvalho Chehab break; 1097786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 1098786baecfSMauro Carvalho Chehab /* attach tuner */ 1099786baecfSMauro Carvalho Chehab fe = dvb_attach(tda18218_attach, adap->fe[0], 1100786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tda18218_config); 1101786baecfSMauro Carvalho Chehab break; 1102d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 1103d67ceb33SOliver Schinagl /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ 1104d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 1105d67ceb33SOliver Schinagl if (ret < 0) 1106d67ceb33SOliver Schinagl goto err; 1107d67ceb33SOliver Schinagl 1108d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 1109d67ceb33SOliver Schinagl if (ret < 0) 1110d67ceb33SOliver Schinagl goto err; 1111d67ceb33SOliver Schinagl 1112d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 1113d67ceb33SOliver Schinagl if (ret < 0) 1114d67ceb33SOliver Schinagl goto err; 1115d67ceb33SOliver Schinagl 1116d67ceb33SOliver Schinagl usleep_range(10000, 50000); 1117d67ceb33SOliver Schinagl /* attach tuner */ 1118d67ceb33SOliver Schinagl fe = dvb_attach(fc2580_attach, adap->fe[0], 1119d67ceb33SOliver Schinagl &d->i2c_adap, &af9035_fc2580_config); 1120d67ceb33SOliver Schinagl break; 11217e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 11227e0bc296SAntti Palosaari /* 11237e0bc296SAntti Palosaari * AF9035 gpiot2 = FC0012 enable 11247e0bc296SAntti Palosaari * XXX: there seems to be something on gpioh8 too, but on my 11257e0bc296SAntti Palosaari * my test I didn't find any difference. 11267e0bc296SAntti Palosaari */ 11277e0bc296SAntti Palosaari 11280bb3d8acSAntti Palosaari if (adap->id == 0) { 11297e0bc296SAntti Palosaari /* configure gpiot2 as output and high */ 11307e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 11317e0bc296SAntti Palosaari if (ret < 0) 11327e0bc296SAntti Palosaari goto err; 11337e0bc296SAntti Palosaari 11347e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 11357e0bc296SAntti Palosaari if (ret < 0) 11367e0bc296SAntti Palosaari goto err; 11377e0bc296SAntti Palosaari 11387e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 11397e0bc296SAntti Palosaari if (ret < 0) 11407e0bc296SAntti Palosaari goto err; 11410bb3d8acSAntti Palosaari } else { 11420bb3d8acSAntti Palosaari /* 11430bb3d8acSAntti Palosaari * FIXME: That belongs for the FC0012 driver. 11440bb3d8acSAntti Palosaari * Write 02 to FC0012 master tuner register 0d directly 11450bb3d8acSAntti Palosaari * in order to make slave tuner working. 11460bb3d8acSAntti Palosaari */ 11470bb3d8acSAntti Palosaari msg[0].addr = 0x63; 11480bb3d8acSAntti Palosaari msg[0].flags = 0; 11490bb3d8acSAntti Palosaari msg[0].len = 2; 11500bb3d8acSAntti Palosaari msg[0].buf = "\x0d\x02"; 11510bb3d8acSAntti Palosaari ret = i2c_transfer(&d->i2c_adap, msg, 1); 11520bb3d8acSAntti Palosaari if (ret < 0) 11530bb3d8acSAntti Palosaari goto err; 11540bb3d8acSAntti Palosaari } 11557e0bc296SAntti Palosaari 11567e0bc296SAntti Palosaari usleep_range(10000, 50000); 11577e0bc296SAntti Palosaari 1158ad3a758bSAntti Palosaari fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, 11590bb3d8acSAntti Palosaari &af9035_fc0012_config[adap->id]); 11607e0bc296SAntti Palosaari break; 1161ac77fb0fSAntti Palosaari case AF9033_TUNER_IT9135_38: 116274c1883aSAntti Palosaari case AF9033_TUNER_IT9135_51: 116374c1883aSAntti Palosaari case AF9033_TUNER_IT9135_52: 1164bc3c9e10SAntti Palosaari af9035_it913x_config.chip_ver = 0x01; 116574c1883aSAntti Palosaari case AF9033_TUNER_IT9135_60: 116674c1883aSAntti Palosaari case AF9033_TUNER_IT9135_61: 116774c1883aSAntti Palosaari case AF9033_TUNER_IT9135_62: 1168ac77fb0fSAntti Palosaari /* attach tuner */ 116974c1883aSAntti Palosaari af9035_it913x_config.tuner_id_0 = state->af9033_config[0].tuner; 1170ac77fb0fSAntti Palosaari fe = dvb_attach(it913x_attach, adap->fe[0], 1171ac77fb0fSAntti Palosaari &d->i2c_adap, 0x38, &af9035_it913x_config); 1172ac77fb0fSAntti Palosaari break; 1173786baecfSMauro Carvalho Chehab default: 1174786baecfSMauro Carvalho Chehab fe = NULL; 1175786baecfSMauro Carvalho Chehab } 1176786baecfSMauro Carvalho Chehab 1177786baecfSMauro Carvalho Chehab if (fe == NULL) { 1178786baecfSMauro Carvalho Chehab ret = -ENODEV; 1179786baecfSMauro Carvalho Chehab goto err; 1180786baecfSMauro Carvalho Chehab } 1181786baecfSMauro Carvalho Chehab 1182786baecfSMauro Carvalho Chehab return 0; 1183786baecfSMauro Carvalho Chehab 1184786baecfSMauro Carvalho Chehab err: 1185119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1186786baecfSMauro Carvalho Chehab 1187786baecfSMauro Carvalho Chehab return ret; 1188786baecfSMauro Carvalho Chehab } 1189786baecfSMauro Carvalho Chehab 1190786baecfSMauro Carvalho Chehab static int af9035_init(struct dvb_usb_device *d) 1191786baecfSMauro Carvalho Chehab { 1192786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 1193786baecfSMauro Carvalho Chehab int ret, i; 1194bada342eSAntti Palosaari u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; 1195bada342eSAntti Palosaari u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 1196786baecfSMauro Carvalho Chehab struct reg_val_mask tab[] = { 1197786baecfSMauro Carvalho Chehab { 0x80f99d, 0x01, 0x01 }, 1198786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x01, 0x01 }, 1199786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x20 }, 1200786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x40 }, 1201786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x20 }, 1202786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x40 }, 1203786baecfSMauro Carvalho Chehab { 0x00dd11, 0x20, 0x20 }, 1204786baecfSMauro Carvalho Chehab { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 1205786baecfSMauro Carvalho Chehab { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 1206786baecfSMauro Carvalho Chehab { 0x00dd0c, packet_size, 0xff}, 1207786baecfSMauro Carvalho Chehab { 0x00dd11, state->dual_mode << 6, 0x40 }, 1208786baecfSMauro Carvalho Chehab { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 1209786baecfSMauro Carvalho Chehab { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 1210786baecfSMauro Carvalho Chehab { 0x00dd0d, packet_size, 0xff }, 12119805992fSJose Alberto Reguero { 0x80f9a3, state->dual_mode, 0x01 }, 12129805992fSJose Alberto Reguero { 0x80f9cd, state->dual_mode, 0x01 }, 1213786baecfSMauro Carvalho Chehab { 0x80f99d, 0x00, 0x01 }, 1214786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x00, 0x01 }, 1215786baecfSMauro Carvalho Chehab }; 1216786baecfSMauro Carvalho Chehab 1217119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ 1218119f7a8cSAntti Palosaari "packet_size=%02x\n", __func__, 1219119f7a8cSAntti Palosaari d->udev->speed, frame_size, packet_size); 1220786baecfSMauro Carvalho Chehab 1221786baecfSMauro Carvalho Chehab /* init endpoints */ 1222786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 1223786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, 1224786baecfSMauro Carvalho Chehab tab[i].mask); 1225786baecfSMauro Carvalho Chehab if (ret < 0) 1226786baecfSMauro Carvalho Chehab goto err; 1227786baecfSMauro Carvalho Chehab } 1228786baecfSMauro Carvalho Chehab 1229786baecfSMauro Carvalho Chehab return 0; 1230786baecfSMauro Carvalho Chehab 1231786baecfSMauro Carvalho Chehab err: 1232119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1233786baecfSMauro Carvalho Chehab 1234786baecfSMauro Carvalho Chehab return ret; 1235786baecfSMauro Carvalho Chehab } 1236786baecfSMauro Carvalho Chehab 123737b44a0fSAntti Palosaari #if IS_ENABLED(CONFIG_RC_CORE) 1238786baecfSMauro Carvalho Chehab static int af9035_rc_query(struct dvb_usb_device *d) 1239786baecfSMauro Carvalho Chehab { 1240786baecfSMauro Carvalho Chehab unsigned int key; 1241786baecfSMauro Carvalho Chehab unsigned char b[4]; 1242786baecfSMauro Carvalho Chehab int ret; 1243786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; 1244786baecfSMauro Carvalho Chehab 1245786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 1246786baecfSMauro Carvalho Chehab if (ret < 0) 1247786baecfSMauro Carvalho Chehab goto err; 1248786baecfSMauro Carvalho Chehab 1249786baecfSMauro Carvalho Chehab if ((b[2] + b[3]) == 0xff) { 1250786baecfSMauro Carvalho Chehab if ((b[0] + b[1]) == 0xff) { 1251786baecfSMauro Carvalho Chehab /* NEC */ 1252786baecfSMauro Carvalho Chehab key = b[0] << 8 | b[2]; 1253786baecfSMauro Carvalho Chehab } else { 1254786baecfSMauro Carvalho Chehab /* ext. NEC */ 1255786baecfSMauro Carvalho Chehab key = b[0] << 16 | b[1] << 8 | b[2]; 1256786baecfSMauro Carvalho Chehab } 1257786baecfSMauro Carvalho Chehab } else { 1258786baecfSMauro Carvalho Chehab key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; 1259786baecfSMauro Carvalho Chehab } 1260786baecfSMauro Carvalho Chehab 1261786baecfSMauro Carvalho Chehab rc_keydown(d->rc_dev, key, 0); 1262786baecfSMauro Carvalho Chehab 1263786baecfSMauro Carvalho Chehab err: 1264786baecfSMauro Carvalho Chehab /* ignore errors */ 1265786baecfSMauro Carvalho Chehab return 0; 1266786baecfSMauro Carvalho Chehab } 1267786baecfSMauro Carvalho Chehab 1268786baecfSMauro Carvalho Chehab static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 1269786baecfSMauro Carvalho Chehab { 127074c1883aSAntti Palosaari struct state *state = d_to_priv(d); 1271786baecfSMauro Carvalho Chehab int ret; 1272786baecfSMauro Carvalho Chehab u8 tmp; 1273786baecfSMauro Carvalho Chehab 127474c1883aSAntti Palosaari /* TODO: IT9135 remote control support */ 127574c1883aSAntti Palosaari if (state->chip_type == 0x9135) 127674c1883aSAntti Palosaari return 0; 127774c1883aSAntti Palosaari 12789ea3681dSAntti Palosaari ret = af9035_rd_reg(d, EEPROM_BASE_AF9035 + EEPROM_IR_MODE, &tmp); 1279786baecfSMauro Carvalho Chehab if (ret < 0) 1280786baecfSMauro Carvalho Chehab goto err; 1281786baecfSMauro Carvalho Chehab 1282119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_mode=%02x\n", __func__, tmp); 1283786baecfSMauro Carvalho Chehab 1284786baecfSMauro Carvalho Chehab /* don't activate rc if in HID mode or if not available */ 1285786baecfSMauro Carvalho Chehab if (tmp == 5) { 12869ea3681dSAntti Palosaari ret = af9035_rd_reg(d, EEPROM_BASE_AF9035 + EEPROM_IR_TYPE, 12879ea3681dSAntti Palosaari &tmp); 1288786baecfSMauro Carvalho Chehab if (ret < 0) 1289786baecfSMauro Carvalho Chehab goto err; 1290786baecfSMauro Carvalho Chehab 1291119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_type=%02x\n", __func__, tmp); 1292786baecfSMauro Carvalho Chehab 1293786baecfSMauro Carvalho Chehab switch (tmp) { 1294786baecfSMauro Carvalho Chehab case 0: /* NEC */ 1295786baecfSMauro Carvalho Chehab default: 1296c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_NEC; 1297786baecfSMauro Carvalho Chehab break; 1298786baecfSMauro Carvalho Chehab case 1: /* RC6 */ 1299c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_RC6_MCE; 1300786baecfSMauro Carvalho Chehab break; 1301786baecfSMauro Carvalho Chehab } 1302786baecfSMauro Carvalho Chehab 1303786baecfSMauro Carvalho Chehab rc->query = af9035_rc_query; 1304786baecfSMauro Carvalho Chehab rc->interval = 500; 1305786baecfSMauro Carvalho Chehab 1306786baecfSMauro Carvalho Chehab /* load empty to enable rc */ 1307786baecfSMauro Carvalho Chehab if (!rc->map_name) 1308786baecfSMauro Carvalho Chehab rc->map_name = RC_MAP_EMPTY; 1309786baecfSMauro Carvalho Chehab } 1310786baecfSMauro Carvalho Chehab 1311786baecfSMauro Carvalho Chehab return 0; 1312786baecfSMauro Carvalho Chehab 1313786baecfSMauro Carvalho Chehab err: 1314119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1315786baecfSMauro Carvalho Chehab 1316786baecfSMauro Carvalho Chehab return ret; 1317786baecfSMauro Carvalho Chehab } 1318eed5670aSAntti Palosaari #else 1319eed5670aSAntti Palosaari #define af9035_get_rc_config NULL 1320eed5670aSAntti Palosaari #endif 1321786baecfSMauro Carvalho Chehab 1322bada342eSAntti Palosaari static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, 1323bada342eSAntti Palosaari struct usb_data_stream_properties *stream) 1324bada342eSAntti Palosaari { 1325bada342eSAntti Palosaari struct dvb_usb_device *d = fe_to_d(fe); 1326bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); 1327bada342eSAntti Palosaari 1328bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 1329bada342eSAntti Palosaari stream->u.bulk.buffersize = 5 * 188; 1330bada342eSAntti Palosaari 1331bada342eSAntti Palosaari return 0; 1332bada342eSAntti Palosaari } 1333bada342eSAntti Palosaari 1334bada342eSAntti Palosaari /* 1335bada342eSAntti Palosaari * FIXME: PID filter is property of demodulator and should be moved to the 1336bada342eSAntti Palosaari * correct driver. Also we support only adapter #0 PID filter and will 1337bada342eSAntti Palosaari * disable adapter #1 if USB1.1 is used. 1338bada342eSAntti Palosaari */ 1339bada342eSAntti Palosaari static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) 1340bada342eSAntti Palosaari { 1341bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1342bada342eSAntti Palosaari int ret; 1343bada342eSAntti Palosaari 1344bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); 1345bada342eSAntti Palosaari 1346bada342eSAntti Palosaari ret = af9035_wr_reg_mask(d, 0x80f993, onoff, 0x01); 1347bada342eSAntti Palosaari if (ret < 0) 1348bada342eSAntti Palosaari goto err; 1349bada342eSAntti Palosaari 1350bada342eSAntti Palosaari return 0; 1351bada342eSAntti Palosaari 1352bada342eSAntti Palosaari err: 1353bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1354bada342eSAntti Palosaari 1355bada342eSAntti Palosaari return ret; 1356bada342eSAntti Palosaari } 1357bada342eSAntti Palosaari 1358bada342eSAntti Palosaari static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, 1359bada342eSAntti Palosaari int onoff) 1360bada342eSAntti Palosaari { 1361bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1362bada342eSAntti Palosaari int ret; 1363bada342eSAntti Palosaari u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 1364bada342eSAntti Palosaari 1365bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", 1366bada342eSAntti Palosaari __func__, index, pid, onoff); 1367bada342eSAntti Palosaari 1368bada342eSAntti Palosaari ret = af9035_wr_regs(d, 0x80f996, wbuf, 2); 1369bada342eSAntti Palosaari if (ret < 0) 1370bada342eSAntti Palosaari goto err; 1371bada342eSAntti Palosaari 1372bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f994, onoff); 1373bada342eSAntti Palosaari if (ret < 0) 1374bada342eSAntti Palosaari goto err; 1375bada342eSAntti Palosaari 1376bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f995, index); 1377bada342eSAntti Palosaari if (ret < 0) 1378bada342eSAntti Palosaari goto err; 1379bada342eSAntti Palosaari 1380bada342eSAntti Palosaari return 0; 1381bada342eSAntti Palosaari 1382bada342eSAntti Palosaari err: 1383bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1384bada342eSAntti Palosaari 1385bada342eSAntti Palosaari return ret; 1386bada342eSAntti Palosaari } 1387bada342eSAntti Palosaari 1388b799b810SAntti Palosaari static int af9035_probe(struct usb_interface *intf, 1389b799b810SAntti Palosaari const struct usb_device_id *id) 1390b799b810SAntti Palosaari { 1391b799b810SAntti Palosaari struct usb_device *udev = interface_to_usbdev(intf); 1392b799b810SAntti Palosaari char manufacturer[sizeof("Afatech")]; 1393b799b810SAntti Palosaari 1394b799b810SAntti Palosaari memset(manufacturer, 0, sizeof(manufacturer)); 1395b799b810SAntti Palosaari usb_string(udev, udev->descriptor.iManufacturer, 1396b799b810SAntti Palosaari manufacturer, sizeof(manufacturer)); 1397b799b810SAntti Palosaari /* 1398b799b810SAntti Palosaari * There is two devices having same ID but different chipset. One uses 1399b799b810SAntti Palosaari * AF9015 and the other IT9135 chipset. Only difference seen on lsusb 1400b799b810SAntti Palosaari * is iManufacturer string. 1401b799b810SAntti Palosaari * 1402b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1403b799b810SAntti Palosaari * idProduct 0x0099 1404b799b810SAntti Palosaari * bcdDevice 2.00 1405b799b810SAntti Palosaari * iManufacturer 1 Afatech 1406b799b810SAntti Palosaari * iProduct 2 DVB-T 2 1407b799b810SAntti Palosaari * 1408b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1409b799b810SAntti Palosaari * idProduct 0x0099 1410b799b810SAntti Palosaari * bcdDevice 2.00 1411b799b810SAntti Palosaari * iManufacturer 1 ITE Technologies, Inc. 1412b799b810SAntti Palosaari * iProduct 2 DVB-T TV Stick 1413b799b810SAntti Palosaari */ 1414b799b810SAntti Palosaari if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && 1415b799b810SAntti Palosaari (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { 1416b799b810SAntti Palosaari if (!strcmp("Afatech", manufacturer)) { 1417b799b810SAntti Palosaari dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); 1418b799b810SAntti Palosaari return -ENODEV; 1419b799b810SAntti Palosaari } 1420b799b810SAntti Palosaari } 1421b799b810SAntti Palosaari 1422b799b810SAntti Palosaari return dvb_usbv2_probe(intf, id); 1423b799b810SAntti Palosaari } 1424b799b810SAntti Palosaari 1425786baecfSMauro Carvalho Chehab /* interface 0 is used by DVB-T receiver and 1426786baecfSMauro Carvalho Chehab interface 1 is for remote controller (HID) */ 1427786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties af9035_props = { 1428786baecfSMauro Carvalho Chehab .driver_name = KBUILD_MODNAME, 1429786baecfSMauro Carvalho Chehab .owner = THIS_MODULE, 1430786baecfSMauro Carvalho Chehab .adapter_nr = adapter_nr, 1431786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct state), 1432786baecfSMauro Carvalho Chehab 1433786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x02, 1434786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint_response = 0x81, 1435786baecfSMauro Carvalho Chehab 1436786baecfSMauro Carvalho Chehab .identify_state = af9035_identify_state, 1437786baecfSMauro Carvalho Chehab .download_firmware = af9035_download_firmware, 1438786baecfSMauro Carvalho Chehab 1439786baecfSMauro Carvalho Chehab .i2c_algo = &af9035_i2c_algo, 1440786baecfSMauro Carvalho Chehab .read_config = af9035_read_config, 1441786baecfSMauro Carvalho Chehab .frontend_attach = af9035_frontend_attach, 1442786baecfSMauro Carvalho Chehab .tuner_attach = af9035_tuner_attach, 1443786baecfSMauro Carvalho Chehab .init = af9035_init, 1444786baecfSMauro Carvalho Chehab .get_rc_config = af9035_get_rc_config, 1445bada342eSAntti Palosaari .get_stream_config = af9035_get_stream_config, 1446786baecfSMauro Carvalho Chehab 14479805992fSJose Alberto Reguero .get_adapter_count = af9035_get_adapter_count, 1448786baecfSMauro Carvalho Chehab .adapter = { 1449786baecfSMauro Carvalho Chehab { 1450bada342eSAntti Palosaari .caps = DVB_USB_ADAP_HAS_PID_FILTER | 1451bada342eSAntti Palosaari DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 1452bada342eSAntti Palosaari 1453bada342eSAntti Palosaari .pid_filter_count = 32, 1454bada342eSAntti Palosaari .pid_filter_ctrl = af9035_pid_filter_ctrl, 1455bada342eSAntti Palosaari .pid_filter = af9035_pid_filter, 1456bada342eSAntti Palosaari 1457786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), 1458786baecfSMauro Carvalho Chehab }, { 1459786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), 1460786baecfSMauro Carvalho Chehab }, 1461786baecfSMauro Carvalho Chehab }, 1462786baecfSMauro Carvalho Chehab }; 1463786baecfSMauro Carvalho Chehab 1464786baecfSMauro Carvalho Chehab static const struct usb_device_id af9035_id_table[] = { 1465bc3c9e10SAntti Palosaari /* AF9035 devices */ 1466786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, 1467786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1468786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, 1469786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1470786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, 1471786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1472786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, 1473786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1474786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, 1475786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1476786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, 1477786baecfSMauro Carvalho Chehab &af9035_props, "TerraTec Cinergy T Stick", NULL) }, 1478786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, 1479786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1480786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, 1481786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1482786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, 1483786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1484786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, 1485786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1486786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, 1487786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, 1488d67ceb33SOliver Schinagl { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, 1489d67ceb33SOliver Schinagl &af9035_props, "Asus U3100Mini Plus", NULL) }, 1490d9b7595bSFabrizio Gazzato { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, 1491d9b7595bSFabrizio Gazzato &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, 1492bc3c9e10SAntti Palosaari /* IT9135 devices */ 1493bc3c9e10SAntti Palosaari #if 0 1494bc3c9e10SAntti Palosaari { DVB_USB_DEVICE(0x048d, 0x9135, 1495bc3c9e10SAntti Palosaari &af9035_props, "IT9135 reference design", NULL) }, 1496bc3c9e10SAntti Palosaari { DVB_USB_DEVICE(0x048d, 0x9006, 1497bc3c9e10SAntti Palosaari &af9035_props, "IT9135 reference design", NULL) }, 1498bc3c9e10SAntti Palosaari #endif 1499b799b810SAntti Palosaari /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ 1500b799b810SAntti Palosaari { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, 1501b799b810SAntti Palosaari &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, 1502786baecfSMauro Carvalho Chehab { } 1503786baecfSMauro Carvalho Chehab }; 1504786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, af9035_id_table); 1505786baecfSMauro Carvalho Chehab 1506786baecfSMauro Carvalho Chehab static struct usb_driver af9035_usb_driver = { 1507786baecfSMauro Carvalho Chehab .name = KBUILD_MODNAME, 1508786baecfSMauro Carvalho Chehab .id_table = af9035_id_table, 1509b799b810SAntti Palosaari .probe = af9035_probe, 1510786baecfSMauro Carvalho Chehab .disconnect = dvb_usbv2_disconnect, 1511786baecfSMauro Carvalho Chehab .suspend = dvb_usbv2_suspend, 1512786baecfSMauro Carvalho Chehab .resume = dvb_usbv2_resume, 151304966aa8SAntti Palosaari .reset_resume = dvb_usbv2_reset_resume, 1514786baecfSMauro Carvalho Chehab .no_dynamic_id = 1, 1515786baecfSMauro Carvalho Chehab .soft_unbind = 1, 1516786baecfSMauro Carvalho Chehab }; 1517786baecfSMauro Carvalho Chehab 1518786baecfSMauro Carvalho Chehab module_usb_driver(af9035_usb_driver); 1519786baecfSMauro Carvalho Chehab 1520786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 1521786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9035 driver"); 1522786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 15234395e4b7SAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); 152474c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); 152574c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); 1526