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 247760e148SMauro Carvalho Chehab /* Max transfer size done by I2C transfer functions */ 257760e148SMauro Carvalho Chehab #define MAX_XFER_SIZE 64 267760e148SMauro Carvalho Chehab 27786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 28786baecfSMauro Carvalho Chehab 29786baecfSMauro Carvalho Chehab static u16 af9035_checksum(const u8 *buf, size_t len) 30786baecfSMauro Carvalho Chehab { 31786baecfSMauro Carvalho Chehab size_t i; 32786baecfSMauro Carvalho Chehab u16 checksum = 0; 33786baecfSMauro Carvalho Chehab 34786baecfSMauro Carvalho Chehab for (i = 1; i < len; i++) { 35786baecfSMauro Carvalho Chehab if (i % 2) 36786baecfSMauro Carvalho Chehab checksum += buf[i] << 8; 37786baecfSMauro Carvalho Chehab else 38786baecfSMauro Carvalho Chehab checksum += buf[i]; 39786baecfSMauro Carvalho Chehab } 40786baecfSMauro Carvalho Chehab checksum = ~checksum; 41786baecfSMauro Carvalho Chehab 42786baecfSMauro Carvalho Chehab return checksum; 43786baecfSMauro Carvalho Chehab } 44786baecfSMauro Carvalho Chehab 45786baecfSMauro Carvalho Chehab static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) 46786baecfSMauro Carvalho Chehab { 47786baecfSMauro Carvalho Chehab #define REQ_HDR_LEN 4 /* send header size */ 48786baecfSMauro Carvalho Chehab #define ACK_HDR_LEN 3 /* rece header size */ 49786baecfSMauro Carvalho Chehab #define CHECKSUM_LEN 2 50786baecfSMauro Carvalho Chehab #define USB_TIMEOUT 2000 51786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 52786baecfSMauro Carvalho Chehab int ret, wlen, rlen; 53786baecfSMauro Carvalho Chehab u16 checksum, tmp_checksum; 54786baecfSMauro Carvalho Chehab 553484d37aSAntti Palosaari mutex_lock(&d->usb_mutex); 563484d37aSAntti Palosaari 57786baecfSMauro Carvalho Chehab /* buffer overflow check */ 58786baecfSMauro Carvalho Chehab if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || 59786baecfSMauro Carvalho Chehab req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { 60119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", 61e8292e28SAntti Palosaari KBUILD_MODNAME, req->wlen, req->rlen); 623484d37aSAntti Palosaari ret = -EINVAL; 630170a39bSWei Yongjun goto exit; 64786baecfSMauro Carvalho Chehab } 65786baecfSMauro Carvalho Chehab 663484d37aSAntti Palosaari state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; 673484d37aSAntti Palosaari state->buf[1] = req->mbox; 683484d37aSAntti Palosaari state->buf[2] = req->cmd; 693484d37aSAntti Palosaari state->buf[3] = state->seq++; 703484d37aSAntti Palosaari memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen); 71786baecfSMauro Carvalho Chehab 72786baecfSMauro Carvalho Chehab wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; 73786baecfSMauro Carvalho Chehab rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; 74786baecfSMauro Carvalho Chehab 75786baecfSMauro Carvalho Chehab /* calc and add checksum */ 763484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, state->buf[0] - 1); 773484d37aSAntti Palosaari state->buf[state->buf[0] - 1] = (checksum >> 8); 783484d37aSAntti Palosaari state->buf[state->buf[0] - 0] = (checksum & 0xff); 79786baecfSMauro Carvalho Chehab 80786baecfSMauro Carvalho Chehab /* no ack for these packets */ 81786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 82786baecfSMauro Carvalho Chehab rlen = 0; 83786baecfSMauro Carvalho Chehab 843484d37aSAntti Palosaari ret = dvb_usbv2_generic_rw_locked(d, 853484d37aSAntti Palosaari state->buf, wlen, state->buf, rlen); 86786baecfSMauro Carvalho Chehab if (ret) 870170a39bSWei Yongjun goto exit; 88786baecfSMauro Carvalho Chehab 89786baecfSMauro Carvalho Chehab /* no ack for those packets */ 90786baecfSMauro Carvalho Chehab if (req->cmd == CMD_FW_DL) 91786baecfSMauro Carvalho Chehab goto exit; 92786baecfSMauro Carvalho Chehab 93786baecfSMauro Carvalho Chehab /* verify checksum */ 943484d37aSAntti Palosaari checksum = af9035_checksum(state->buf, rlen - 2); 953484d37aSAntti Palosaari tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; 96786baecfSMauro Carvalho Chehab if (tmp_checksum != checksum) { 97cb9114e9SAntti Palosaari dev_err(&d->udev->dev, 98cb9114e9SAntti Palosaari "%s: command=%02x checksum mismatch (%04x != %04x)\n", 99cb9114e9SAntti Palosaari KBUILD_MODNAME, req->cmd, tmp_checksum, 100cb9114e9SAntti Palosaari checksum); 101786baecfSMauro Carvalho Chehab ret = -EIO; 1020170a39bSWei Yongjun goto exit; 103786baecfSMauro Carvalho Chehab } 104786baecfSMauro Carvalho Chehab 105786baecfSMauro Carvalho Chehab /* check status */ 1063484d37aSAntti Palosaari if (state->buf[2]) { 1071bfd5294SAntti Palosaari /* fw returns status 1 when IR code was not received */ 1080170a39bSWei Yongjun if (req->cmd == CMD_IR_GET || state->buf[2] == 1) { 1090170a39bSWei Yongjun ret = 1; 1100170a39bSWei Yongjun goto exit; 1110170a39bSWei Yongjun } 1121bfd5294SAntti Palosaari 113119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n", 1143484d37aSAntti Palosaari __func__, req->cmd, state->buf[2]); 115786baecfSMauro Carvalho Chehab ret = -EIO; 1160170a39bSWei Yongjun goto exit; 117786baecfSMauro Carvalho Chehab } 118786baecfSMauro Carvalho Chehab 119786baecfSMauro Carvalho Chehab /* read request, copy returned data to return buf */ 120786baecfSMauro Carvalho Chehab if (req->rlen) 1213484d37aSAntti Palosaari memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen); 122786baecfSMauro Carvalho Chehab exit: 1233484d37aSAntti Palosaari mutex_unlock(&d->usb_mutex); 1240170a39bSWei Yongjun if (ret < 0) 125119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 126786baecfSMauro Carvalho Chehab return ret; 127786baecfSMauro Carvalho Chehab } 128786baecfSMauro Carvalho Chehab 129786baecfSMauro Carvalho Chehab /* write multiple registers */ 130786baecfSMauro Carvalho Chehab static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 131786baecfSMauro Carvalho Chehab { 1327760e148SMauro Carvalho Chehab u8 wbuf[MAX_XFER_SIZE]; 133786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 1349323297dSAntti Palosaari struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL }; 135786baecfSMauro Carvalho Chehab 1367760e148SMauro Carvalho Chehab if (6 + len > sizeof(wbuf)) { 1377760e148SMauro Carvalho Chehab dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n", 1387760e148SMauro Carvalho Chehab KBUILD_MODNAME, len); 1397760e148SMauro Carvalho Chehab return -EOPNOTSUPP; 1407760e148SMauro Carvalho Chehab } 1417760e148SMauro Carvalho Chehab 142786baecfSMauro Carvalho Chehab wbuf[0] = len; 143786baecfSMauro Carvalho Chehab wbuf[1] = 2; 144786baecfSMauro Carvalho Chehab wbuf[2] = 0; 145786baecfSMauro Carvalho Chehab wbuf[3] = 0; 146786baecfSMauro Carvalho Chehab wbuf[4] = (reg >> 8) & 0xff; 147786baecfSMauro Carvalho Chehab wbuf[5] = (reg >> 0) & 0xff; 148786baecfSMauro Carvalho Chehab memcpy(&wbuf[6], val, len); 149786baecfSMauro Carvalho Chehab 150786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 151786baecfSMauro Carvalho Chehab } 152786baecfSMauro Carvalho Chehab 153786baecfSMauro Carvalho Chehab /* read multiple registers */ 154786baecfSMauro Carvalho Chehab static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) 155786baecfSMauro Carvalho Chehab { 156786baecfSMauro Carvalho Chehab u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; 157786baecfSMauro Carvalho Chehab u8 mbox = (reg >> 16) & 0xff; 158786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; 159786baecfSMauro Carvalho Chehab 160786baecfSMauro Carvalho Chehab return af9035_ctrl_msg(d, &req); 161786baecfSMauro Carvalho Chehab } 162786baecfSMauro Carvalho Chehab 163786baecfSMauro Carvalho Chehab /* write single register */ 164786baecfSMauro Carvalho Chehab static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) 165786baecfSMauro Carvalho Chehab { 166786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 167786baecfSMauro Carvalho Chehab } 168786baecfSMauro Carvalho Chehab 169786baecfSMauro Carvalho Chehab /* read single register */ 170786baecfSMauro Carvalho Chehab static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) 171786baecfSMauro Carvalho Chehab { 172786baecfSMauro Carvalho Chehab return af9035_rd_regs(d, reg, val, 1); 173786baecfSMauro Carvalho Chehab } 174786baecfSMauro Carvalho Chehab 175786baecfSMauro Carvalho Chehab /* write single register with mask */ 176786baecfSMauro Carvalho Chehab static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, 177786baecfSMauro Carvalho Chehab u8 mask) 178786baecfSMauro Carvalho Chehab { 179786baecfSMauro Carvalho Chehab int ret; 180786baecfSMauro Carvalho Chehab u8 tmp; 181786baecfSMauro Carvalho Chehab 182786baecfSMauro Carvalho Chehab /* no need for read if whole reg is written */ 183786baecfSMauro Carvalho Chehab if (mask != 0xff) { 184786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &tmp, 1); 185786baecfSMauro Carvalho Chehab if (ret) 186786baecfSMauro Carvalho Chehab return ret; 187786baecfSMauro Carvalho Chehab 188786baecfSMauro Carvalho Chehab val &= mask; 189786baecfSMauro Carvalho Chehab tmp &= ~mask; 190786baecfSMauro Carvalho Chehab val |= tmp; 191786baecfSMauro Carvalho Chehab } 192786baecfSMauro Carvalho Chehab 193786baecfSMauro Carvalho Chehab return af9035_wr_regs(d, reg, &val, 1); 194786baecfSMauro Carvalho Chehab } 195786baecfSMauro Carvalho Chehab 196786baecfSMauro Carvalho Chehab static int af9035_i2c_master_xfer(struct i2c_adapter *adap, 197786baecfSMauro Carvalho Chehab struct i2c_msg msg[], int num) 198786baecfSMauro Carvalho Chehab { 199786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 200786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 201786baecfSMauro Carvalho Chehab int ret; 202786baecfSMauro Carvalho Chehab 203786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 204786baecfSMauro Carvalho Chehab return -EAGAIN; 205786baecfSMauro Carvalho Chehab 206786baecfSMauro Carvalho Chehab /* 207786baecfSMauro Carvalho Chehab * I2C sub header is 5 bytes long. Meaning of those bytes are: 208786baecfSMauro Carvalho Chehab * 0: data len 209786baecfSMauro Carvalho Chehab * 1: I2C addr << 1 210786baecfSMauro Carvalho Chehab * 2: reg addr len 211786baecfSMauro Carvalho Chehab * byte 3 and 4 can be used as reg addr 212786baecfSMauro Carvalho Chehab * 3: reg addr MSB 213786baecfSMauro Carvalho Chehab * used when reg addr len is set to 2 214786baecfSMauro Carvalho Chehab * 4: reg addr LSB 215786baecfSMauro Carvalho Chehab * used when reg addr len is set to 1 or 2 216786baecfSMauro Carvalho Chehab * 217786baecfSMauro Carvalho Chehab * For the simplify we do not use register addr at all. 218786baecfSMauro Carvalho Chehab * NOTE: As a firmware knows tuner type there is very small possibility 219786baecfSMauro Carvalho Chehab * there could be some tuner I2C hacks done by firmware and this may 220786baecfSMauro Carvalho Chehab * lead problems if firmware expects those bytes are used. 221786baecfSMauro Carvalho Chehab */ 222786baecfSMauro Carvalho Chehab if (num == 2 && !(msg[0].flags & I2C_M_RD) && 223786baecfSMauro Carvalho Chehab (msg[1].flags & I2C_M_RD)) { 224786baecfSMauro Carvalho Chehab if (msg[0].len > 40 || msg[1].len > 40) { 225786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 226786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 2279805992fSJose Alberto Reguero } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || 2289805992fSJose Alberto Reguero (msg[0].addr == state->af9033_config[1].i2c_addr)) { 229bf97b637SAntti Palosaari /* demod access via firmware interface */ 230786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 231786baecfSMauro Carvalho Chehab msg[0].buf[2]; 232bf97b637SAntti Palosaari 233bf97b637SAntti Palosaari if (msg[0].addr == state->af9033_config[1].i2c_addr) 2349805992fSJose Alberto Reguero reg |= 0x100000; 235bf97b637SAntti Palosaari 236786baecfSMauro Carvalho Chehab ret = af9035_rd_regs(d, reg, &msg[1].buf[0], 237786baecfSMauro Carvalho Chehab msg[1].len); 238786baecfSMauro Carvalho Chehab } else { 239786baecfSMauro Carvalho Chehab /* I2C */ 2407760e148SMauro Carvalho Chehab u8 buf[MAX_XFER_SIZE]; 2419323297dSAntti Palosaari struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len, 242786baecfSMauro Carvalho Chehab buf, msg[1].len, msg[1].buf }; 2437760e148SMauro Carvalho Chehab 2447760e148SMauro Carvalho Chehab if (5 + msg[0].len > sizeof(buf)) { 2457760e148SMauro Carvalho Chehab dev_warn(&d->udev->dev, 2467760e148SMauro Carvalho Chehab "%s: i2c xfer: len=%d is too big!\n", 2477760e148SMauro Carvalho Chehab KBUILD_MODNAME, msg[0].len); 2483189ef02SDan Carpenter ret = -EOPNOTSUPP; 2493189ef02SDan Carpenter goto unlock; 2507760e148SMauro Carvalho Chehab } 2519805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 252786baecfSMauro Carvalho Chehab buf[0] = msg[1].len; 253bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 254786baecfSMauro Carvalho Chehab buf[2] = 0x00; /* reg addr len */ 255786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 256786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 257786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 258786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 259786baecfSMauro Carvalho Chehab } 260786baecfSMauro Carvalho Chehab } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { 261786baecfSMauro Carvalho Chehab if (msg[0].len > 40) { 262786baecfSMauro Carvalho Chehab /* TODO: correct limits > 40 */ 263786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 2649805992fSJose Alberto Reguero } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || 2659805992fSJose Alberto Reguero (msg[0].addr == state->af9033_config[1].i2c_addr)) { 266bf97b637SAntti Palosaari /* demod access via firmware interface */ 267786baecfSMauro Carvalho Chehab u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | 268786baecfSMauro Carvalho Chehab msg[0].buf[2]; 269bf97b637SAntti Palosaari 270bf97b637SAntti Palosaari if (msg[0].addr == state->af9033_config[1].i2c_addr) 2719805992fSJose Alberto Reguero reg |= 0x100000; 272bf97b637SAntti Palosaari 273786baecfSMauro Carvalho Chehab ret = af9035_wr_regs(d, reg, &msg[0].buf[3], 274786baecfSMauro Carvalho Chehab msg[0].len - 3); 275786baecfSMauro Carvalho Chehab } else { 276786baecfSMauro Carvalho Chehab /* I2C */ 2777760e148SMauro Carvalho Chehab u8 buf[MAX_XFER_SIZE]; 2789323297dSAntti Palosaari struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len, 2799323297dSAntti Palosaari buf, 0, NULL }; 2807760e148SMauro Carvalho Chehab 2817760e148SMauro Carvalho Chehab if (5 + msg[0].len > sizeof(buf)) { 2827760e148SMauro Carvalho Chehab dev_warn(&d->udev->dev, 2837760e148SMauro Carvalho Chehab "%s: i2c xfer: len=%d is too big!\n", 2847760e148SMauro Carvalho Chehab KBUILD_MODNAME, msg[0].len); 2853189ef02SDan Carpenter ret = -EOPNOTSUPP; 2863189ef02SDan Carpenter goto unlock; 2877760e148SMauro Carvalho Chehab } 2889805992fSJose Alberto Reguero req.mbox |= ((msg[0].addr & 0x80) >> 3); 289786baecfSMauro Carvalho Chehab buf[0] = msg[0].len; 290bf97b637SAntti Palosaari buf[1] = msg[0].addr << 1; 291786baecfSMauro Carvalho Chehab buf[2] = 0x00; /* reg addr len */ 292786baecfSMauro Carvalho Chehab buf[3] = 0x00; /* reg addr MSB */ 293786baecfSMauro Carvalho Chehab buf[4] = 0x00; /* reg addr LSB */ 294786baecfSMauro Carvalho Chehab memcpy(&buf[5], msg[0].buf, msg[0].len); 295786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 296786baecfSMauro Carvalho Chehab } 2973b98c347SAntti Palosaari } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { 2983b98c347SAntti Palosaari if (msg[0].len > 40) { 2993b98c347SAntti Palosaari /* TODO: correct limits > 40 */ 3003b98c347SAntti Palosaari ret = -EOPNOTSUPP; 3013b98c347SAntti Palosaari } else { 3023b98c347SAntti Palosaari /* I2C */ 3033b98c347SAntti Palosaari u8 buf[5]; 3043b98c347SAntti Palosaari struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), 3053b98c347SAntti Palosaari buf, msg[0].len, msg[0].buf }; 3063b98c347SAntti Palosaari req.mbox |= ((msg[0].addr & 0x80) >> 3); 3073b98c347SAntti Palosaari buf[0] = msg[0].len; 3083b98c347SAntti Palosaari buf[1] = msg[0].addr << 1; 3093b98c347SAntti Palosaari buf[2] = 0x00; /* reg addr len */ 3103b98c347SAntti Palosaari buf[3] = 0x00; /* reg addr MSB */ 3113b98c347SAntti Palosaari buf[4] = 0x00; /* reg addr LSB */ 3123b98c347SAntti Palosaari ret = af9035_ctrl_msg(d, &req); 3133b98c347SAntti Palosaari } 314786baecfSMauro Carvalho Chehab } else { 315786baecfSMauro Carvalho Chehab /* 3163b98c347SAntti Palosaari * We support only three kind of I2C transactions: 3173b98c347SAntti Palosaari * 1) 1 x read + 1 x write (repeated start) 318786baecfSMauro Carvalho Chehab * 2) 1 x write 3193b98c347SAntti Palosaari * 3) 1 x read 320786baecfSMauro Carvalho Chehab */ 321786baecfSMauro Carvalho Chehab ret = -EOPNOTSUPP; 322786baecfSMauro Carvalho Chehab } 323786baecfSMauro Carvalho Chehab 3243189ef02SDan Carpenter unlock: 325786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 326786baecfSMauro Carvalho Chehab 327786baecfSMauro Carvalho Chehab if (ret < 0) 328786baecfSMauro Carvalho Chehab return ret; 329786baecfSMauro Carvalho Chehab else 330786baecfSMauro Carvalho Chehab return num; 331786baecfSMauro Carvalho Chehab } 332786baecfSMauro Carvalho Chehab 333786baecfSMauro Carvalho Chehab static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) 334786baecfSMauro Carvalho Chehab { 335786baecfSMauro Carvalho Chehab return I2C_FUNC_I2C; 336786baecfSMauro Carvalho Chehab } 337786baecfSMauro Carvalho Chehab 338786baecfSMauro Carvalho Chehab static struct i2c_algorithm af9035_i2c_algo = { 339786baecfSMauro Carvalho Chehab .master_xfer = af9035_i2c_master_xfer, 340786baecfSMauro Carvalho Chehab .functionality = af9035_i2c_functionality, 341786baecfSMauro Carvalho Chehab }; 342786baecfSMauro Carvalho Chehab 343786baecfSMauro Carvalho Chehab static int af9035_identify_state(struct dvb_usb_device *d, const char **name) 344786baecfSMauro Carvalho Chehab { 34574c1883aSAntti Palosaari struct state *state = d_to_priv(d); 346786baecfSMauro Carvalho Chehab int ret; 347786baecfSMauro Carvalho Chehab u8 wbuf[1] = { 1 }; 348786baecfSMauro Carvalho Chehab u8 rbuf[4]; 349786baecfSMauro Carvalho Chehab struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, 350786baecfSMauro Carvalho Chehab sizeof(rbuf), rbuf }; 351786baecfSMauro Carvalho Chehab 35274c1883aSAntti Palosaari ret = af9035_rd_regs(d, 0x1222, rbuf, 3); 35374c1883aSAntti Palosaari if (ret < 0) 35474c1883aSAntti Palosaari goto err; 35574c1883aSAntti Palosaari 35674c1883aSAntti Palosaari state->chip_version = rbuf[0]; 35774c1883aSAntti Palosaari state->chip_type = rbuf[2] << 8 | rbuf[1] << 0; 35874c1883aSAntti Palosaari 35974c1883aSAntti Palosaari ret = af9035_rd_reg(d, 0x384f, &state->prechip_version); 36074c1883aSAntti Palosaari if (ret < 0) 36174c1883aSAntti Palosaari goto err; 36274c1883aSAntti Palosaari 36374c1883aSAntti Palosaari dev_info(&d->udev->dev, 36474c1883aSAntti Palosaari "%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n", 365e8292e28SAntti Palosaari KBUILD_MODNAME, state->prechip_version, 366e8292e28SAntti Palosaari state->chip_version, state->chip_type); 36774c1883aSAntti Palosaari 36874c1883aSAntti Palosaari if (state->chip_type == 0x9135) { 369bc3c9e10SAntti Palosaari if (state->chip_version == 0x02) 37074c1883aSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V2; 37174c1883aSAntti Palosaari else 37274c1883aSAntti Palosaari *name = AF9035_FIRMWARE_IT9135_V1; 373df8f1be1SAntti Palosaari state->eeprom_addr = EEPROM_BASE_IT9135; 37474c1883aSAntti Palosaari } else { 37574c1883aSAntti Palosaari *name = AF9035_FIRMWARE_AF9035; 376df8f1be1SAntti Palosaari state->eeprom_addr = EEPROM_BASE_AF9035; 37774c1883aSAntti Palosaari } 37874c1883aSAntti Palosaari 379786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 380786baecfSMauro Carvalho Chehab if (ret < 0) 381786baecfSMauro Carvalho Chehab goto err; 382786baecfSMauro Carvalho Chehab 383119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: reply=%*ph\n", __func__, 4, rbuf); 384786baecfSMauro Carvalho Chehab if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) 385786baecfSMauro Carvalho Chehab ret = WARM; 386786baecfSMauro Carvalho Chehab else 387786baecfSMauro Carvalho Chehab ret = COLD; 388786baecfSMauro Carvalho Chehab 389786baecfSMauro Carvalho Chehab return ret; 390786baecfSMauro Carvalho Chehab 391786baecfSMauro Carvalho Chehab err: 392119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 393786baecfSMauro Carvalho Chehab 394786baecfSMauro Carvalho Chehab return ret; 395786baecfSMauro Carvalho Chehab } 396786baecfSMauro Carvalho Chehab 3978229da50SAntti Palosaari static int af9035_download_firmware_old(struct dvb_usb_device *d, 398786baecfSMauro Carvalho Chehab const struct firmware *fw) 399786baecfSMauro Carvalho Chehab { 400786baecfSMauro Carvalho Chehab int ret, i, j, len; 401786baecfSMauro Carvalho Chehab u8 wbuf[1]; 402786baecfSMauro Carvalho Chehab struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 403786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; 404df8f1be1SAntti Palosaari u8 hdr_core; 405786baecfSMauro Carvalho Chehab u16 hdr_addr, hdr_data_len, hdr_checksum; 406786baecfSMauro Carvalho Chehab #define MAX_DATA 58 407786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 408786baecfSMauro Carvalho Chehab 409786baecfSMauro Carvalho Chehab /* 410786baecfSMauro Carvalho Chehab * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! 411786baecfSMauro Carvalho Chehab * 412786baecfSMauro Carvalho Chehab * byte 0: MCS 51 core 413786baecfSMauro Carvalho Chehab * There are two inside the AF9035 (1=Link and 2=OFDM) with separate 414786baecfSMauro Carvalho Chehab * address spaces 415786baecfSMauro Carvalho Chehab * byte 1-2: Big endian destination address 416786baecfSMauro Carvalho Chehab * byte 3-4: Big endian number of data bytes following the header 417786baecfSMauro Carvalho Chehab * byte 5-6: Big endian header checksum, apparently ignored by the chip 418786baecfSMauro Carvalho Chehab * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) 419786baecfSMauro Carvalho Chehab */ 420786baecfSMauro Carvalho Chehab 421786baecfSMauro Carvalho Chehab for (i = fw->size; i > HDR_SIZE;) { 422786baecfSMauro Carvalho Chehab hdr_core = fw->data[fw->size - i + 0]; 423786baecfSMauro Carvalho Chehab hdr_addr = fw->data[fw->size - i + 1] << 8; 424786baecfSMauro Carvalho Chehab hdr_addr |= fw->data[fw->size - i + 2] << 0; 425786baecfSMauro Carvalho Chehab hdr_data_len = fw->data[fw->size - i + 3] << 8; 426786baecfSMauro Carvalho Chehab hdr_data_len |= fw->data[fw->size - i + 4] << 0; 427786baecfSMauro Carvalho Chehab hdr_checksum = fw->data[fw->size - i + 5] << 8; 428786baecfSMauro Carvalho Chehab hdr_checksum |= fw->data[fw->size - i + 6] << 0; 429786baecfSMauro Carvalho Chehab 430cb9114e9SAntti Palosaari dev_dbg(&d->udev->dev, 431cb9114e9SAntti Palosaari "%s: core=%d addr=%04x data_len=%d checksum=%04x\n", 432cb9114e9SAntti Palosaari __func__, hdr_core, hdr_addr, hdr_data_len, 433cb9114e9SAntti Palosaari hdr_checksum); 434786baecfSMauro Carvalho Chehab 435786baecfSMauro Carvalho Chehab if (((hdr_core != 1) && (hdr_core != 2)) || 436786baecfSMauro Carvalho Chehab (hdr_data_len > i)) { 437119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: bad firmware\n", __func__); 438786baecfSMauro Carvalho Chehab break; 439786baecfSMauro Carvalho Chehab } 440786baecfSMauro Carvalho Chehab 441786baecfSMauro Carvalho Chehab /* download begin packet */ 442786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_BEGIN; 443786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 444786baecfSMauro Carvalho Chehab if (ret < 0) 445786baecfSMauro Carvalho Chehab goto err; 446786baecfSMauro Carvalho Chehab 447786baecfSMauro Carvalho Chehab /* download firmware packet(s) */ 448786baecfSMauro Carvalho Chehab for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { 449786baecfSMauro Carvalho Chehab len = j; 450786baecfSMauro Carvalho Chehab if (len > MAX_DATA) 451786baecfSMauro Carvalho Chehab len = MAX_DATA; 452786baecfSMauro Carvalho Chehab req_fw_dl.wlen = len; 453786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + 454786baecfSMauro Carvalho Chehab HDR_SIZE + hdr_data_len - j]; 455786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 456786baecfSMauro Carvalho Chehab if (ret < 0) 457786baecfSMauro Carvalho Chehab goto err; 458786baecfSMauro Carvalho Chehab } 459786baecfSMauro Carvalho Chehab 460786baecfSMauro Carvalho Chehab /* download end packet */ 461786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_DL_END; 462786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 463786baecfSMauro Carvalho Chehab if (ret < 0) 464786baecfSMauro Carvalho Chehab goto err; 465786baecfSMauro Carvalho Chehab 466786baecfSMauro Carvalho Chehab i -= hdr_data_len + HDR_SIZE; 467786baecfSMauro Carvalho Chehab 468119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%zu\n", 469119f7a8cSAntti Palosaari __func__, fw->size - i); 470786baecfSMauro Carvalho Chehab } 471786baecfSMauro Carvalho Chehab 472ff4e3fe8SAntti Palosaari /* print warn if firmware is bad, continue and see what happens */ 473ff4e3fe8SAntti Palosaari if (i) 474ff4e3fe8SAntti Palosaari dev_warn(&d->udev->dev, "%s: bad firmware\n", KBUILD_MODNAME); 475ff4e3fe8SAntti Palosaari 476786baecfSMauro Carvalho Chehab return 0; 477786baecfSMauro Carvalho Chehab 478786baecfSMauro Carvalho Chehab err: 479119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 480786baecfSMauro Carvalho Chehab 481786baecfSMauro Carvalho Chehab return ret; 482786baecfSMauro Carvalho Chehab } 483786baecfSMauro Carvalho Chehab 4848229da50SAntti Palosaari static int af9035_download_firmware_new(struct dvb_usb_device *d, 485786baecfSMauro Carvalho Chehab const struct firmware *fw) 486786baecfSMauro Carvalho Chehab { 487786baecfSMauro Carvalho Chehab int ret, i, i_prev; 488786baecfSMauro Carvalho Chehab struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; 489786baecfSMauro Carvalho Chehab #define HDR_SIZE 7 490786baecfSMauro Carvalho Chehab 491786baecfSMauro Carvalho Chehab /* 492786baecfSMauro Carvalho Chehab * There seems to be following firmware header. Meaning of bytes 0-3 493786baecfSMauro Carvalho Chehab * is unknown. 494786baecfSMauro Carvalho Chehab * 495786baecfSMauro Carvalho Chehab * 0: 3 496786baecfSMauro Carvalho Chehab * 1: 0, 1 497786baecfSMauro Carvalho Chehab * 2: 0 498786baecfSMauro Carvalho Chehab * 3: 1, 2, 3 499786baecfSMauro Carvalho Chehab * 4: addr MSB 500786baecfSMauro Carvalho Chehab * 5: addr LSB 501786baecfSMauro Carvalho Chehab * 6: count of data bytes ? 502786baecfSMauro Carvalho Chehab */ 503786baecfSMauro Carvalho Chehab for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { 504786baecfSMauro Carvalho Chehab if (i == fw->size || 505786baecfSMauro Carvalho Chehab (fw->data[i + 0] == 0x03 && 506786baecfSMauro Carvalho Chehab (fw->data[i + 1] == 0x00 || 507786baecfSMauro Carvalho Chehab fw->data[i + 1] == 0x01) && 508786baecfSMauro Carvalho Chehab fw->data[i + 2] == 0x00)) { 509786baecfSMauro Carvalho Chehab req_fw_dl.wlen = i - i_prev; 510786baecfSMauro Carvalho Chehab req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; 511786baecfSMauro Carvalho Chehab i_prev = i; 512786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_dl); 513786baecfSMauro Carvalho Chehab if (ret < 0) 514786baecfSMauro Carvalho Chehab goto err; 515786baecfSMauro Carvalho Chehab 516119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: data uploaded=%d\n", 517119f7a8cSAntti Palosaari __func__, i); 518786baecfSMauro Carvalho Chehab } 519786baecfSMauro Carvalho Chehab } 520786baecfSMauro Carvalho Chehab 521df8f1be1SAntti Palosaari return 0; 522df8f1be1SAntti Palosaari 523df8f1be1SAntti Palosaari err: 524df8f1be1SAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 525df8f1be1SAntti Palosaari 526df8f1be1SAntti Palosaari return ret; 527df8f1be1SAntti Palosaari } 528df8f1be1SAntti Palosaari 529df8f1be1SAntti Palosaari static int af9035_download_firmware(struct dvb_usb_device *d, 530df8f1be1SAntti Palosaari const struct firmware *fw) 531df8f1be1SAntti Palosaari { 532df8f1be1SAntti Palosaari struct state *state = d_to_priv(d); 533df8f1be1SAntti Palosaari int ret; 534df8f1be1SAntti Palosaari u8 wbuf[1]; 535df8f1be1SAntti Palosaari u8 rbuf[4]; 536df8f1be1SAntti Palosaari u8 tmp; 537df8f1be1SAntti Palosaari struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; 538df8f1be1SAntti Palosaari struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; 539df8f1be1SAntti Palosaari dev_dbg(&d->udev->dev, "%s:\n", __func__); 540df8f1be1SAntti Palosaari 541df8f1be1SAntti Palosaari /* 542df8f1be1SAntti Palosaari * In case of dual tuner configuration we need to do some extra 543df8f1be1SAntti Palosaari * initialization in order to download firmware to slave demod too, 544df8f1be1SAntti Palosaari * which is done by master demod. 545df8f1be1SAntti Palosaari * Master feeds also clock and controls power via GPIO. 546df8f1be1SAntti Palosaari */ 547d716ef46SAntti Palosaari ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); 548df8f1be1SAntti Palosaari if (ret < 0) 549df8f1be1SAntti Palosaari goto err; 550df8f1be1SAntti Palosaari 551d716ef46SAntti Palosaari if (tmp == 1 || tmp == 3) { 552df8f1be1SAntti Palosaari /* configure gpioh1, reset & power slave demod */ 553df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); 554df8f1be1SAntti Palosaari if (ret < 0) 555df8f1be1SAntti Palosaari goto err; 556df8f1be1SAntti Palosaari 557df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01); 558df8f1be1SAntti Palosaari if (ret < 0) 559df8f1be1SAntti Palosaari goto err; 560df8f1be1SAntti Palosaari 561df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01); 562df8f1be1SAntti Palosaari if (ret < 0) 563df8f1be1SAntti Palosaari goto err; 564df8f1be1SAntti Palosaari 565df8f1be1SAntti Palosaari usleep_range(10000, 50000); 566df8f1be1SAntti Palosaari 567df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01); 568df8f1be1SAntti Palosaari if (ret < 0) 569df8f1be1SAntti Palosaari goto err; 570df8f1be1SAntti Palosaari 571df8f1be1SAntti Palosaari /* tell the slave I2C address */ 572df8f1be1SAntti Palosaari ret = af9035_rd_reg(d, 573df8f1be1SAntti Palosaari state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR, 574df8f1be1SAntti Palosaari &tmp); 575df8f1be1SAntti Palosaari if (ret < 0) 576df8f1be1SAntti Palosaari goto err; 577df8f1be1SAntti Palosaari 57814992f01SAntti Palosaari /* use default I2C address if eeprom has no address set */ 579a1310ff4SMalcolm Priestley if (!tmp) 580a1310ff4SMalcolm Priestley tmp = 0x3a; 581a1310ff4SMalcolm Priestley 58214992f01SAntti Palosaari if (state->chip_type == 0x9135) { 583df8f1be1SAntti Palosaari ret = af9035_wr_reg(d, 0x004bfb, tmp); 584df8f1be1SAntti Palosaari if (ret < 0) 585df8f1be1SAntti Palosaari goto err; 586df8f1be1SAntti Palosaari } else { 587df8f1be1SAntti Palosaari ret = af9035_wr_reg(d, 0x00417f, tmp); 588df8f1be1SAntti Palosaari if (ret < 0) 589df8f1be1SAntti Palosaari goto err; 590df8f1be1SAntti Palosaari 591df8f1be1SAntti Palosaari /* enable clock out */ 592df8f1be1SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); 593df8f1be1SAntti Palosaari if (ret < 0) 594df8f1be1SAntti Palosaari goto err; 595df8f1be1SAntti Palosaari } 596df8f1be1SAntti Palosaari } 597df8f1be1SAntti Palosaari 5988229da50SAntti Palosaari if (fw->data[0] == 0x01) 5998229da50SAntti Palosaari ret = af9035_download_firmware_old(d, fw); 600df8f1be1SAntti Palosaari else 6018229da50SAntti Palosaari ret = af9035_download_firmware_new(d, fw); 602df8f1be1SAntti Palosaari if (ret < 0) 603df8f1be1SAntti Palosaari goto err; 604df8f1be1SAntti Palosaari 605786baecfSMauro Carvalho Chehab /* firmware loaded, request boot */ 606786baecfSMauro Carvalho Chehab req.cmd = CMD_FW_BOOT; 607786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 608786baecfSMauro Carvalho Chehab if (ret < 0) 609786baecfSMauro Carvalho Chehab goto err; 610786baecfSMauro Carvalho Chehab 611786baecfSMauro Carvalho Chehab /* ensure firmware starts */ 612786baecfSMauro Carvalho Chehab wbuf[0] = 1; 613786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req_fw_ver); 614786baecfSMauro Carvalho Chehab if (ret < 0) 615786baecfSMauro Carvalho Chehab goto err; 616786baecfSMauro Carvalho Chehab 617786baecfSMauro Carvalho Chehab if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { 618119f7a8cSAntti Palosaari dev_err(&d->udev->dev, "%s: firmware did not run\n", 619119f7a8cSAntti Palosaari KBUILD_MODNAME); 620786baecfSMauro Carvalho Chehab ret = -ENODEV; 621786baecfSMauro Carvalho Chehab goto err; 622786baecfSMauro Carvalho Chehab } 623786baecfSMauro Carvalho Chehab 624119f7a8cSAntti Palosaari dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", 625119f7a8cSAntti Palosaari KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); 626786baecfSMauro Carvalho Chehab 627786baecfSMauro Carvalho Chehab return 0; 628786baecfSMauro Carvalho Chehab 629786baecfSMauro Carvalho Chehab err: 630119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 631786baecfSMauro Carvalho Chehab 632786baecfSMauro Carvalho Chehab return ret; 633786baecfSMauro Carvalho Chehab } 634786baecfSMauro Carvalho Chehab 6359ea3681dSAntti Palosaari static int af9035_read_config(struct dvb_usb_device *d) 636786baecfSMauro Carvalho Chehab { 637786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 6389ea3681dSAntti Palosaari int ret, i; 639786baecfSMauro Carvalho Chehab u8 tmp; 6409ea3681dSAntti Palosaari u16 tmp16, addr; 641786baecfSMauro Carvalho Chehab 642bf97b637SAntti Palosaari /* demod I2C "address" */ 643bf97b637SAntti Palosaari state->af9033_config[0].i2c_addr = 0x38; 64414992f01SAntti Palosaari state->af9033_config[1].i2c_addr = 0x3a; 6450d94d6a0SAntti Palosaari state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 646df8f1be1SAntti Palosaari state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; 647ab56ad6aSAntti Palosaari state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; 648ab56ad6aSAntti Palosaari state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; 649bf97b637SAntti Palosaari 6509ea3681dSAntti Palosaari /* eeprom memory mapped location */ 6519ea3681dSAntti Palosaari if (state->chip_type == 0x9135) { 652bc3c9e10SAntti Palosaari if (state->chip_version == 0x02) { 653bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; 654df8f1be1SAntti Palosaari state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60; 655bc3c9e10SAntti Palosaari tmp16 = 0x00461d; 656bc3c9e10SAntti Palosaari } else { 657bc3c9e10SAntti Palosaari state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; 658df8f1be1SAntti Palosaari state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38; 659bc3c9e10SAntti Palosaari tmp16 = 0x00461b; 660bc3c9e10SAntti Palosaari } 661bc3c9e10SAntti Palosaari 6629ea3681dSAntti Palosaari /* check if eeprom exists */ 663bc3c9e10SAntti Palosaari ret = af9035_rd_reg(d, tmp16, &tmp); 6649ea3681dSAntti Palosaari if (ret < 0) 6659ea3681dSAntti Palosaari goto err; 6669ea3681dSAntti Palosaari 667431a6d4aSAntti Palosaari if (tmp == 0x00) { 668bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: no eeprom\n", __func__); 6699ea3681dSAntti Palosaari goto skip_eeprom; 6709ea3681dSAntti Palosaari } 6719ea3681dSAntti Palosaari } 6729ea3681dSAntti Palosaari 673786baecfSMauro Carvalho Chehab /* check if there is dual tuners */ 674d716ef46SAntti Palosaari ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); 675786baecfSMauro Carvalho Chehab if (ret < 0) 676786baecfSMauro Carvalho Chehab goto err; 677786baecfSMauro Carvalho Chehab 678d716ef46SAntti Palosaari if (tmp == 1 || tmp == 3) 679d716ef46SAntti Palosaari state->dual_mode = true; 680d716ef46SAntti Palosaari 681d716ef46SAntti Palosaari dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, 682d716ef46SAntti Palosaari tmp, state->dual_mode); 683786baecfSMauro Carvalho Chehab 6849805992fSJose Alberto Reguero if (state->dual_mode) { 6859805992fSJose Alberto Reguero /* read 2nd demodulator I2C address */ 686431a6d4aSAntti Palosaari ret = af9035_rd_reg(d, 687431a6d4aSAntti Palosaari state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR, 688431a6d4aSAntti Palosaari &tmp); 6899805992fSJose Alberto Reguero if (ret < 0) 6909805992fSJose Alberto Reguero goto err; 691bf97b637SAntti Palosaari 69214992f01SAntti Palosaari if (tmp) 6939805992fSJose Alberto Reguero state->af9033_config[1].i2c_addr = tmp; 69414992f01SAntti Palosaari 695bf97b637SAntti Palosaari dev_dbg(&d->udev->dev, "%s: 2nd demod I2C addr=%02x\n", 696bf97b637SAntti Palosaari __func__, tmp); 6979805992fSJose Alberto Reguero } 6989805992fSJose Alberto Reguero 699431a6d4aSAntti Palosaari addr = state->eeprom_addr; 700431a6d4aSAntti Palosaari 701786baecfSMauro Carvalho Chehab for (i = 0; i < state->dual_mode + 1; i++) { 702786baecfSMauro Carvalho Chehab /* tuner */ 7039ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_TUNER_ID, &tmp); 704786baecfSMauro Carvalho Chehab if (ret < 0) 705786baecfSMauro Carvalho Chehab goto err; 706786baecfSMauro Carvalho Chehab 707bc3c9e10SAntti Palosaari if (tmp == 0x00) 708bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, 709bc3c9e10SAntti Palosaari "%s: [%d]tuner not set, using default\n", 710bc3c9e10SAntti Palosaari __func__, i); 711bc3c9e10SAntti Palosaari else 712786baecfSMauro Carvalho Chehab state->af9033_config[i].tuner = tmp; 713786baecfSMauro Carvalho Chehab 714bc3c9e10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", 715bc3c9e10SAntti Palosaari __func__, i, state->af9033_config[i].tuner); 7169ea3681dSAntti Palosaari 7179ea3681dSAntti Palosaari switch (state->af9033_config[i].tuner) { 718786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 719786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 720786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 721786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 722d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 7237e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 724786baecfSMauro Carvalho Chehab state->af9033_config[i].spec_inv = 1; 725786baecfSMauro Carvalho Chehab break; 7269ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_38: 7279ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_51: 7289ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_52: 7299ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_60: 7309ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_61: 7319ea3681dSAntti Palosaari case AF9033_TUNER_IT9135_62: 7329ea3681dSAntti Palosaari break; 733786baecfSMauro Carvalho Chehab default: 7349ea3681dSAntti Palosaari dev_warn(&d->udev->dev, 7359ea3681dSAntti Palosaari "%s: tuner id=%02x not supported, please report!", 736119f7a8cSAntti Palosaari KBUILD_MODNAME, tmp); 737c2c1b415SPeter Senna Tschudin } 738786baecfSMauro Carvalho Chehab 739bf97b637SAntti Palosaari /* disable dual mode if driver does not support it */ 740bf97b637SAntti Palosaari if (i == 1) 741df8f1be1SAntti Palosaari switch (state->af9033_config[i].tuner) { 7420bb3d8acSAntti Palosaari case AF9033_TUNER_FC0012: 743df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_38: 744df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_51: 745df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_52: 746df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_60: 747df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_61: 748df8f1be1SAntti Palosaari case AF9033_TUNER_IT9135_62: 74978c7bc4bSJose Alberto Reguero case AF9033_TUNER_MXL5007T: 7500bb3d8acSAntti Palosaari break; 751bf97b637SAntti Palosaari default: 752bf97b637SAntti Palosaari state->dual_mode = false; 7539ea3681dSAntti Palosaari dev_info(&d->udev->dev, 7549ea3681dSAntti Palosaari "%s: driver does not support 2nd tuner and will disable it", 7559ea3681dSAntti Palosaari KBUILD_MODNAME); 756bf97b637SAntti Palosaari } 757bf97b637SAntti Palosaari 758786baecfSMauro Carvalho Chehab /* tuner IF frequency */ 7599ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_IF_L, &tmp); 760786baecfSMauro Carvalho Chehab if (ret < 0) 761786baecfSMauro Carvalho Chehab goto err; 762786baecfSMauro Carvalho Chehab 763786baecfSMauro Carvalho Chehab tmp16 = tmp; 764786baecfSMauro Carvalho Chehab 7659ea3681dSAntti Palosaari ret = af9035_rd_reg(d, addr + EEPROM_1_IF_H, &tmp); 766786baecfSMauro Carvalho Chehab if (ret < 0) 767786baecfSMauro Carvalho Chehab goto err; 768786baecfSMauro Carvalho Chehab 769786baecfSMauro Carvalho Chehab tmp16 |= tmp << 8; 770786baecfSMauro Carvalho Chehab 771119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16); 772786baecfSMauro Carvalho Chehab 7739ea3681dSAntti Palosaari addr += 0x10; /* shift for the 2nd tuner params */ 774786baecfSMauro Carvalho Chehab } 775786baecfSMauro Carvalho Chehab 7769ea3681dSAntti Palosaari skip_eeprom: 777786baecfSMauro Carvalho Chehab /* get demod clock */ 778786baecfSMauro Carvalho Chehab ret = af9035_rd_reg(d, 0x00d800, &tmp); 779786baecfSMauro Carvalho Chehab if (ret < 0) 780786baecfSMauro Carvalho Chehab goto err; 781786baecfSMauro Carvalho Chehab 782786baecfSMauro Carvalho Chehab tmp = (tmp >> 0) & 0x0f; 783786baecfSMauro Carvalho Chehab 7849ea3681dSAntti Palosaari for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) { 78574c1883aSAntti Palosaari if (state->chip_type == 0x9135) 7869ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_it9135[tmp]; 78774c1883aSAntti Palosaari else 7889ea3681dSAntti Palosaari state->af9033_config[i].clock = clock_lut_af9035[tmp]; 7899ea3681dSAntti Palosaari } 7909ea3681dSAntti Palosaari 7919ea3681dSAntti Palosaari return 0; 7929ea3681dSAntti Palosaari 7939ea3681dSAntti Palosaari err: 7949ea3681dSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 7959ea3681dSAntti Palosaari 7969ea3681dSAntti Palosaari return ret; 79774c1883aSAntti Palosaari } 79874c1883aSAntti Palosaari 79951639be3SAntti Palosaari static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, 80051639be3SAntti Palosaari int cmd, int arg) 80151639be3SAntti Palosaari { 80251639be3SAntti Palosaari int ret; 80351639be3SAntti Palosaari u8 val; 80451639be3SAntti Palosaari 80551639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); 80651639be3SAntti Palosaari 80751639be3SAntti Palosaari /* 80851639be3SAntti Palosaari * CEN always enabled by hardware wiring 80951639be3SAntti Palosaari * RESETN GPIOT3 81051639be3SAntti Palosaari * RXEN GPIOT2 81151639be3SAntti Palosaari */ 81251639be3SAntti Palosaari 81351639be3SAntti Palosaari switch (cmd) { 81451639be3SAntti Palosaari case TUA9001_CMD_RESETN: 81551639be3SAntti Palosaari if (arg) 81651639be3SAntti Palosaari val = 0x00; 81751639be3SAntti Palosaari else 81851639be3SAntti Palosaari val = 0x01; 81951639be3SAntti Palosaari 82051639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); 82151639be3SAntti Palosaari if (ret < 0) 82251639be3SAntti Palosaari goto err; 82351639be3SAntti Palosaari break; 82451639be3SAntti Palosaari case TUA9001_CMD_RXEN: 82551639be3SAntti Palosaari if (arg) 82651639be3SAntti Palosaari val = 0x01; 82751639be3SAntti Palosaari else 82851639be3SAntti Palosaari val = 0x00; 82951639be3SAntti Palosaari 83051639be3SAntti Palosaari ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); 83151639be3SAntti Palosaari if (ret < 0) 83251639be3SAntti Palosaari goto err; 83351639be3SAntti Palosaari break; 83451639be3SAntti Palosaari } 83551639be3SAntti Palosaari 83651639be3SAntti Palosaari return 0; 83751639be3SAntti Palosaari 83851639be3SAntti Palosaari err: 83951639be3SAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 84051639be3SAntti Palosaari 84151639be3SAntti Palosaari return ret; 84251639be3SAntti Palosaari } 84351639be3SAntti Palosaari 84451639be3SAntti Palosaari 845786baecfSMauro Carvalho Chehab static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, 846786baecfSMauro Carvalho Chehab int cmd, int arg) 847786baecfSMauro Carvalho Chehab { 848786baecfSMauro Carvalho Chehab int ret; 849786baecfSMauro Carvalho Chehab 850786baecfSMauro Carvalho Chehab switch (cmd) { 851786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_POWER: 852786baecfSMauro Carvalho Chehab /* Tuner enable */ 853786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); 854786baecfSMauro Carvalho Chehab if (ret < 0) 855786baecfSMauro Carvalho Chehab goto err; 856786baecfSMauro Carvalho Chehab 857786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); 858786baecfSMauro Carvalho Chehab if (ret < 0) 859786baecfSMauro Carvalho Chehab goto err; 860786baecfSMauro Carvalho Chehab 861786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); 862786baecfSMauro Carvalho Chehab if (ret < 0) 863786baecfSMauro Carvalho Chehab goto err; 864786baecfSMauro Carvalho Chehab 865786baecfSMauro Carvalho Chehab /* LED */ 866786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); 867786baecfSMauro Carvalho Chehab if (ret < 0) 868786baecfSMauro Carvalho Chehab goto err; 869786baecfSMauro Carvalho Chehab 870786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); 871786baecfSMauro Carvalho Chehab if (ret < 0) 872786baecfSMauro Carvalho Chehab goto err; 873786baecfSMauro Carvalho Chehab 874786baecfSMauro Carvalho Chehab usleep_range(10000, 50000); 875786baecfSMauro Carvalho Chehab break; 876786baecfSMauro Carvalho Chehab case FC0011_FE_CALLBACK_RESET: 877786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e9, 1); 878786baecfSMauro Carvalho Chehab if (ret < 0) 879786baecfSMauro Carvalho Chehab goto err; 880786baecfSMauro Carvalho Chehab 881786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e8, 1); 882786baecfSMauro Carvalho Chehab if (ret < 0) 883786baecfSMauro Carvalho Chehab goto err; 884786baecfSMauro Carvalho Chehab 885786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 1); 886786baecfSMauro Carvalho Chehab if (ret < 0) 887786baecfSMauro Carvalho Chehab goto err; 888786baecfSMauro Carvalho Chehab 889786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 890786baecfSMauro Carvalho Chehab 891786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0xd8e7, 0); 892786baecfSMauro Carvalho Chehab if (ret < 0) 893786baecfSMauro Carvalho Chehab goto err; 894786baecfSMauro Carvalho Chehab 895786baecfSMauro Carvalho Chehab usleep_range(10000, 20000); 896786baecfSMauro Carvalho Chehab break; 897786baecfSMauro Carvalho Chehab default: 898786baecfSMauro Carvalho Chehab ret = -EINVAL; 899786baecfSMauro Carvalho Chehab goto err; 900786baecfSMauro Carvalho Chehab } 901786baecfSMauro Carvalho Chehab 902786baecfSMauro Carvalho Chehab return 0; 903786baecfSMauro Carvalho Chehab 904786baecfSMauro Carvalho Chehab err: 905119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 906786baecfSMauro Carvalho Chehab 907786baecfSMauro Carvalho Chehab return ret; 908786baecfSMauro Carvalho Chehab } 909786baecfSMauro Carvalho Chehab 910786baecfSMauro Carvalho Chehab static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) 911786baecfSMauro Carvalho Chehab { 912786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 913786baecfSMauro Carvalho Chehab 914786baecfSMauro Carvalho Chehab switch (state->af9033_config[0].tuner) { 915786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 916786baecfSMauro Carvalho Chehab return af9035_fc0011_tuner_callback(d, cmd, arg); 91751639be3SAntti Palosaari case AF9033_TUNER_TUA9001: 91851639be3SAntti Palosaari return af9035_tua9001_tuner_callback(d, cmd, arg); 919786baecfSMauro Carvalho Chehab default: 920786baecfSMauro Carvalho Chehab break; 921786baecfSMauro Carvalho Chehab } 922786baecfSMauro Carvalho Chehab 9231835af10SAntti Palosaari return 0; 924786baecfSMauro Carvalho Chehab } 925786baecfSMauro Carvalho Chehab 926786baecfSMauro Carvalho Chehab static int af9035_frontend_callback(void *adapter_priv, int component, 927786baecfSMauro Carvalho Chehab int cmd, int arg) 928786baecfSMauro Carvalho Chehab { 929786baecfSMauro Carvalho Chehab struct i2c_adapter *adap = adapter_priv; 930786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 931786baecfSMauro Carvalho Chehab 9321835af10SAntti Palosaari dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", 9331835af10SAntti Palosaari __func__, component, cmd, arg); 9341835af10SAntti Palosaari 935786baecfSMauro Carvalho Chehab switch (component) { 936786baecfSMauro Carvalho Chehab case DVB_FRONTEND_COMPONENT_TUNER: 937786baecfSMauro Carvalho Chehab return af9035_tuner_callback(d, cmd, arg); 938786baecfSMauro Carvalho Chehab default: 939786baecfSMauro Carvalho Chehab break; 940786baecfSMauro Carvalho Chehab } 941786baecfSMauro Carvalho Chehab 9421835af10SAntti Palosaari return 0; 943786baecfSMauro Carvalho Chehab } 944786baecfSMauro Carvalho Chehab 9459805992fSJose Alberto Reguero static int af9035_get_adapter_count(struct dvb_usb_device *d) 9469805992fSJose Alberto Reguero { 9479805992fSJose Alberto Reguero struct state *state = d_to_priv(d); 948bada342eSAntti Palosaari 949bada342eSAntti Palosaari /* disable 2nd adapter as we don't have PID filters implemented */ 950bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 951bada342eSAntti Palosaari return 1; 952bada342eSAntti Palosaari else 9539805992fSJose Alberto Reguero return state->dual_mode + 1; 9549805992fSJose Alberto Reguero } 9559805992fSJose Alberto Reguero 956786baecfSMauro Carvalho Chehab static int af9035_frontend_attach(struct dvb_usb_adapter *adap) 957786baecfSMauro Carvalho Chehab { 958786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 959786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 960786baecfSMauro Carvalho Chehab int ret; 961df8f1be1SAntti Palosaari dev_dbg(&d->udev->dev, "%s:\n", __func__); 962786baecfSMauro Carvalho Chehab 963786baecfSMauro Carvalho Chehab if (!state->af9033_config[adap->id].tuner) { 964786baecfSMauro Carvalho Chehab /* unsupported tuner */ 965786baecfSMauro Carvalho Chehab ret = -ENODEV; 966786baecfSMauro Carvalho Chehab goto err; 967786baecfSMauro Carvalho Chehab } 968786baecfSMauro Carvalho Chehab 969786baecfSMauro Carvalho Chehab /* attach demodulator */ 970bf97b637SAntti Palosaari adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], 971bf97b637SAntti Palosaari &d->i2c_adap); 972786baecfSMauro Carvalho Chehab if (adap->fe[0] == NULL) { 973786baecfSMauro Carvalho Chehab ret = -ENODEV; 974786baecfSMauro Carvalho Chehab goto err; 975786baecfSMauro Carvalho Chehab } 976786baecfSMauro Carvalho Chehab 977786baecfSMauro Carvalho Chehab /* disable I2C-gate */ 978786baecfSMauro Carvalho Chehab adap->fe[0]->ops.i2c_gate_ctrl = NULL; 979786baecfSMauro Carvalho Chehab adap->fe[0]->callback = af9035_frontend_callback; 980786baecfSMauro Carvalho Chehab 981786baecfSMauro Carvalho Chehab return 0; 982786baecfSMauro Carvalho Chehab 983786baecfSMauro Carvalho Chehab err: 984119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 985786baecfSMauro Carvalho Chehab 986786baecfSMauro Carvalho Chehab return ret; 987786baecfSMauro Carvalho Chehab } 988786baecfSMauro Carvalho Chehab 989786baecfSMauro Carvalho Chehab static struct tua9001_config af9035_tua9001_config = { 990786baecfSMauro Carvalho Chehab .i2c_addr = 0x60, 991786baecfSMauro Carvalho Chehab }; 992786baecfSMauro Carvalho Chehab 993786baecfSMauro Carvalho Chehab static const struct fc0011_config af9035_fc0011_config = { 994786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 995786baecfSMauro Carvalho Chehab }; 996786baecfSMauro Carvalho Chehab 9979805992fSJose Alberto Reguero static struct mxl5007t_config af9035_mxl5007t_config[] = { 9989805992fSJose Alberto Reguero { 999786baecfSMauro Carvalho Chehab .xtal_freq_hz = MxL_XTAL_24_MHZ, 1000786baecfSMauro Carvalho Chehab .if_freq_hz = MxL_IF_4_57_MHZ, 1001786baecfSMauro Carvalho Chehab .invert_if = 0, 1002786baecfSMauro Carvalho Chehab .loop_thru_enable = 0, 1003786baecfSMauro Carvalho Chehab .clk_out_enable = 0, 1004786baecfSMauro Carvalho Chehab .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 10059805992fSJose Alberto Reguero }, { 10069805992fSJose Alberto Reguero .xtal_freq_hz = MxL_XTAL_24_MHZ, 10079805992fSJose Alberto Reguero .if_freq_hz = MxL_IF_4_57_MHZ, 10089805992fSJose Alberto Reguero .invert_if = 0, 10099805992fSJose Alberto Reguero .loop_thru_enable = 1, 10109805992fSJose Alberto Reguero .clk_out_enable = 1, 10119805992fSJose Alberto Reguero .clk_out_amp = MxL_CLKOUT_AMP_0_94V, 10129805992fSJose Alberto Reguero } 1013786baecfSMauro Carvalho Chehab }; 1014786baecfSMauro Carvalho Chehab 1015786baecfSMauro Carvalho Chehab static struct tda18218_config af9035_tda18218_config = { 1016786baecfSMauro Carvalho Chehab .i2c_address = 0x60, 1017786baecfSMauro Carvalho Chehab .i2c_wr_max = 21, 1018786baecfSMauro Carvalho Chehab }; 1019786baecfSMauro Carvalho Chehab 1020d67ceb33SOliver Schinagl static const struct fc2580_config af9035_fc2580_config = { 1021d67ceb33SOliver Schinagl .i2c_addr = 0x56, 1022d67ceb33SOliver Schinagl .clock = 16384000, 1023d67ceb33SOliver Schinagl }; 1024d67ceb33SOliver Schinagl 10250bb3d8acSAntti Palosaari static const struct fc0012_config af9035_fc0012_config[] = { 10260bb3d8acSAntti Palosaari { 1027ad3a758bSAntti Palosaari .i2c_address = 0x63, 1028ad3a758bSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 10293a984772SAntti Palosaari .dual_master = true, 10300bb3d8acSAntti Palosaari .loop_through = true, 10310bb3d8acSAntti Palosaari .clock_out = true, 10320bb3d8acSAntti Palosaari }, { 10330bb3d8acSAntti Palosaari .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ 10340bb3d8acSAntti Palosaari .xtal_freq = FC_XTAL_36_MHZ, 10353a984772SAntti Palosaari .dual_master = true, 10360bb3d8acSAntti Palosaari } 1037ad3a758bSAntti Palosaari }; 1038ad3a758bSAntti Palosaari 1039786baecfSMauro Carvalho Chehab static int af9035_tuner_attach(struct dvb_usb_adapter *adap) 1040786baecfSMauro Carvalho Chehab { 1041786baecfSMauro Carvalho Chehab struct state *state = adap_to_priv(adap); 1042786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = adap_to_d(adap); 1043786baecfSMauro Carvalho Chehab int ret; 1044786baecfSMauro Carvalho Chehab struct dvb_frontend *fe; 10450bb3d8acSAntti Palosaari struct i2c_msg msg[1]; 1046bf97b637SAntti Palosaari u8 tuner_addr; 1047df8f1be1SAntti Palosaari dev_dbg(&d->udev->dev, "%s:\n", __func__); 1048df8f1be1SAntti Palosaari 1049bf97b637SAntti Palosaari /* 1050bf97b637SAntti Palosaari * XXX: Hack used in that function: we abuse unused I2C address bit [7] 1051bf97b637SAntti Palosaari * to carry info about used I2C bus for dual tuner configuration. 1052bf97b637SAntti Palosaari */ 1053786baecfSMauro Carvalho Chehab 1054786baecfSMauro Carvalho Chehab switch (state->af9033_config[adap->id].tuner) { 1055786baecfSMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 1056786baecfSMauro Carvalho Chehab /* AF9035 gpiot3 = TUA9001 RESETN 1057786baecfSMauro Carvalho Chehab AF9035 gpiot2 = TUA9001 RXEN */ 1058786baecfSMauro Carvalho Chehab 1059786baecfSMauro Carvalho Chehab /* configure gpiot2 and gpiot2 as output */ 1060786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); 1061786baecfSMauro Carvalho Chehab if (ret < 0) 1062786baecfSMauro Carvalho Chehab goto err; 1063786baecfSMauro Carvalho Chehab 1064786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); 1065786baecfSMauro Carvalho Chehab if (ret < 0) 1066786baecfSMauro Carvalho Chehab goto err; 1067786baecfSMauro Carvalho Chehab 1068786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); 1069786baecfSMauro Carvalho Chehab if (ret < 0) 1070786baecfSMauro Carvalho Chehab goto err; 1071786baecfSMauro Carvalho Chehab 1072786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); 1073786baecfSMauro Carvalho Chehab if (ret < 0) 1074786baecfSMauro Carvalho Chehab goto err; 1075786baecfSMauro Carvalho Chehab 1076786baecfSMauro Carvalho Chehab /* attach tuner */ 1077786baecfSMauro Carvalho Chehab fe = dvb_attach(tua9001_attach, adap->fe[0], 1078786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tua9001_config); 1079786baecfSMauro Carvalho Chehab break; 1080786baecfSMauro Carvalho Chehab case AF9033_TUNER_FC0011: 1081786baecfSMauro Carvalho Chehab fe = dvb_attach(fc0011_attach, adap->fe[0], 1082786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_fc0011_config); 1083786baecfSMauro Carvalho Chehab break; 1084786baecfSMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 10859805992fSJose Alberto Reguero if (adap->id == 0) { 1086786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e0, 1); 1087786baecfSMauro Carvalho Chehab if (ret < 0) 1088786baecfSMauro Carvalho Chehab goto err; 1089bf97b637SAntti Palosaari 1090786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8e1, 1); 1091786baecfSMauro Carvalho Chehab if (ret < 0) 1092786baecfSMauro Carvalho Chehab goto err; 1093bf97b637SAntti Palosaari 1094786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 0); 1095786baecfSMauro Carvalho Chehab if (ret < 0) 1096786baecfSMauro Carvalho Chehab goto err; 1097786baecfSMauro Carvalho Chehab 1098786baecfSMauro Carvalho Chehab msleep(30); 1099786baecfSMauro Carvalho Chehab 1100786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8df, 1); 1101786baecfSMauro Carvalho Chehab if (ret < 0) 1102786baecfSMauro Carvalho Chehab goto err; 1103786baecfSMauro Carvalho Chehab 1104786baecfSMauro Carvalho Chehab msleep(300); 1105786baecfSMauro Carvalho Chehab 1106786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c0, 1); 1107786baecfSMauro Carvalho Chehab if (ret < 0) 1108786baecfSMauro Carvalho Chehab goto err; 1109bf97b637SAntti Palosaari 1110786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8c1, 1); 1111786baecfSMauro Carvalho Chehab if (ret < 0) 1112786baecfSMauro Carvalho Chehab goto err; 1113bf97b637SAntti Palosaari 1114786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8bf, 0); 1115786baecfSMauro Carvalho Chehab if (ret < 0) 1116786baecfSMauro Carvalho Chehab goto err; 1117bf97b637SAntti Palosaari 1118786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b4, 1); 1119786baecfSMauro Carvalho Chehab if (ret < 0) 1120786baecfSMauro Carvalho Chehab goto err; 1121bf97b637SAntti Palosaari 1122786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b5, 1); 1123786baecfSMauro Carvalho Chehab if (ret < 0) 1124786baecfSMauro Carvalho Chehab goto err; 1125bf97b637SAntti Palosaari 1126786baecfSMauro Carvalho Chehab ret = af9035_wr_reg(d, 0x00d8b3, 1); 1127786baecfSMauro Carvalho Chehab if (ret < 0) 1128786baecfSMauro Carvalho Chehab goto err; 1129bf97b637SAntti Palosaari 1130bf97b637SAntti Palosaari tuner_addr = 0x60; 1131bf97b637SAntti Palosaari } else { 1132bf97b637SAntti Palosaari tuner_addr = 0x60 | 0x80; /* I2C bus hack */ 11339805992fSJose Alberto Reguero } 1134786baecfSMauro Carvalho Chehab 1135786baecfSMauro Carvalho Chehab /* attach tuner */ 1136bf97b637SAntti Palosaari fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, 1137bf97b637SAntti Palosaari tuner_addr, &af9035_mxl5007t_config[adap->id]); 1138786baecfSMauro Carvalho Chehab break; 1139786baecfSMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 1140786baecfSMauro Carvalho Chehab /* attach tuner */ 1141786baecfSMauro Carvalho Chehab fe = dvb_attach(tda18218_attach, adap->fe[0], 1142786baecfSMauro Carvalho Chehab &d->i2c_adap, &af9035_tda18218_config); 1143786baecfSMauro Carvalho Chehab break; 1144d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 1145d67ceb33SOliver Schinagl /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ 1146d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 1147d67ceb33SOliver Schinagl if (ret < 0) 1148d67ceb33SOliver Schinagl goto err; 1149d67ceb33SOliver Schinagl 1150d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 1151d67ceb33SOliver Schinagl if (ret < 0) 1152d67ceb33SOliver Schinagl goto err; 1153d67ceb33SOliver Schinagl 1154d67ceb33SOliver Schinagl ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 1155d67ceb33SOliver Schinagl if (ret < 0) 1156d67ceb33SOliver Schinagl goto err; 1157d67ceb33SOliver Schinagl 1158d67ceb33SOliver Schinagl usleep_range(10000, 50000); 1159d67ceb33SOliver Schinagl /* attach tuner */ 1160d67ceb33SOliver Schinagl fe = dvb_attach(fc2580_attach, adap->fe[0], 1161d67ceb33SOliver Schinagl &d->i2c_adap, &af9035_fc2580_config); 1162d67ceb33SOliver Schinagl break; 11637e0bc296SAntti Palosaari case AF9033_TUNER_FC0012: 11647e0bc296SAntti Palosaari /* 11657e0bc296SAntti Palosaari * AF9035 gpiot2 = FC0012 enable 11667e0bc296SAntti Palosaari * XXX: there seems to be something on gpioh8 too, but on my 11677e0bc296SAntti Palosaari * my test I didn't find any difference. 11687e0bc296SAntti Palosaari */ 11697e0bc296SAntti Palosaari 11700bb3d8acSAntti Palosaari if (adap->id == 0) { 11717e0bc296SAntti Palosaari /* configure gpiot2 as output and high */ 11727e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); 11737e0bc296SAntti Palosaari if (ret < 0) 11747e0bc296SAntti Palosaari goto err; 11757e0bc296SAntti Palosaari 11767e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); 11777e0bc296SAntti Palosaari if (ret < 0) 11787e0bc296SAntti Palosaari goto err; 11797e0bc296SAntti Palosaari 11807e0bc296SAntti Palosaari ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); 11817e0bc296SAntti Palosaari if (ret < 0) 11827e0bc296SAntti Palosaari goto err; 11830bb3d8acSAntti Palosaari } else { 11840bb3d8acSAntti Palosaari /* 11850bb3d8acSAntti Palosaari * FIXME: That belongs for the FC0012 driver. 11860bb3d8acSAntti Palosaari * Write 02 to FC0012 master tuner register 0d directly 11870bb3d8acSAntti Palosaari * in order to make slave tuner working. 11880bb3d8acSAntti Palosaari */ 11890bb3d8acSAntti Palosaari msg[0].addr = 0x63; 11900bb3d8acSAntti Palosaari msg[0].flags = 0; 11910bb3d8acSAntti Palosaari msg[0].len = 2; 11920bb3d8acSAntti Palosaari msg[0].buf = "\x0d\x02"; 11930bb3d8acSAntti Palosaari ret = i2c_transfer(&d->i2c_adap, msg, 1); 11940bb3d8acSAntti Palosaari if (ret < 0) 11950bb3d8acSAntti Palosaari goto err; 11960bb3d8acSAntti Palosaari } 11977e0bc296SAntti Palosaari 11987e0bc296SAntti Palosaari usleep_range(10000, 50000); 11997e0bc296SAntti Palosaari 1200ad3a758bSAntti Palosaari fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, 12010bb3d8acSAntti Palosaari &af9035_fc0012_config[adap->id]); 12027e0bc296SAntti Palosaari break; 1203ac77fb0fSAntti Palosaari case AF9033_TUNER_IT9135_38: 120474c1883aSAntti Palosaari case AF9033_TUNER_IT9135_51: 120574c1883aSAntti Palosaari case AF9033_TUNER_IT9135_52: 120674c1883aSAntti Palosaari case AF9033_TUNER_IT9135_60: 120774c1883aSAntti Palosaari case AF9033_TUNER_IT9135_61: 120874c1883aSAntti Palosaari case AF9033_TUNER_IT9135_62: 1209df8f1be1SAntti Palosaari /* attach tuner */ 1210df8f1be1SAntti Palosaari fe = dvb_attach(it913x_attach, adap->fe[0], &d->i2c_adap, 1211df8f1be1SAntti Palosaari state->af9033_config[adap->id].i2c_addr, 121244af747fSAntti Palosaari state->af9033_config[0].tuner); 1213ac77fb0fSAntti Palosaari break; 1214786baecfSMauro Carvalho Chehab default: 1215786baecfSMauro Carvalho Chehab fe = NULL; 1216786baecfSMauro Carvalho Chehab } 1217786baecfSMauro Carvalho Chehab 1218786baecfSMauro Carvalho Chehab if (fe == NULL) { 1219786baecfSMauro Carvalho Chehab ret = -ENODEV; 1220786baecfSMauro Carvalho Chehab goto err; 1221786baecfSMauro Carvalho Chehab } 1222786baecfSMauro Carvalho Chehab 1223786baecfSMauro Carvalho Chehab return 0; 1224786baecfSMauro Carvalho Chehab 1225786baecfSMauro Carvalho Chehab err: 1226119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1227786baecfSMauro Carvalho Chehab 1228786baecfSMauro Carvalho Chehab return ret; 1229786baecfSMauro Carvalho Chehab } 1230786baecfSMauro Carvalho Chehab 1231786baecfSMauro Carvalho Chehab static int af9035_init(struct dvb_usb_device *d) 1232786baecfSMauro Carvalho Chehab { 1233786baecfSMauro Carvalho Chehab struct state *state = d_to_priv(d); 1234786baecfSMauro Carvalho Chehab int ret, i; 1235bada342eSAntti Palosaari u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; 1236bada342eSAntti Palosaari u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; 1237786baecfSMauro Carvalho Chehab struct reg_val_mask tab[] = { 1238786baecfSMauro Carvalho Chehab { 0x80f99d, 0x01, 0x01 }, 1239786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x01, 0x01 }, 1240786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x20 }, 1241786baecfSMauro Carvalho Chehab { 0x00dd11, 0x00, 0x40 }, 1242786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x20 }, 1243786baecfSMauro Carvalho Chehab { 0x00dd13, 0x00, 0x40 }, 1244786baecfSMauro Carvalho Chehab { 0x00dd11, 0x20, 0x20 }, 1245786baecfSMauro Carvalho Chehab { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, 1246786baecfSMauro Carvalho Chehab { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, 1247786baecfSMauro Carvalho Chehab { 0x00dd0c, packet_size, 0xff}, 1248786baecfSMauro Carvalho Chehab { 0x00dd11, state->dual_mode << 6, 0x40 }, 1249786baecfSMauro Carvalho Chehab { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, 1250786baecfSMauro Carvalho Chehab { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, 1251786baecfSMauro Carvalho Chehab { 0x00dd0d, packet_size, 0xff }, 12529805992fSJose Alberto Reguero { 0x80f9a3, state->dual_mode, 0x01 }, 12539805992fSJose Alberto Reguero { 0x80f9cd, state->dual_mode, 0x01 }, 1254786baecfSMauro Carvalho Chehab { 0x80f99d, 0x00, 0x01 }, 1255786baecfSMauro Carvalho Chehab { 0x80f9a4, 0x00, 0x01 }, 1256786baecfSMauro Carvalho Chehab }; 1257786baecfSMauro Carvalho Chehab 1258cb9114e9SAntti Palosaari dev_dbg(&d->udev->dev, 1259cb9114e9SAntti Palosaari "%s: USB speed=%d frame_size=%04x packet_size=%02x\n", 1260cb9114e9SAntti Palosaari __func__, d->udev->speed, frame_size, packet_size); 1261786baecfSMauro Carvalho Chehab 1262786baecfSMauro Carvalho Chehab /* init endpoints */ 1263786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 1264786baecfSMauro Carvalho Chehab ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, 1265786baecfSMauro Carvalho Chehab tab[i].mask); 1266786baecfSMauro Carvalho Chehab if (ret < 0) 1267786baecfSMauro Carvalho Chehab goto err; 1268786baecfSMauro Carvalho Chehab } 1269786baecfSMauro Carvalho Chehab 1270786baecfSMauro Carvalho Chehab return 0; 1271786baecfSMauro Carvalho Chehab 1272786baecfSMauro Carvalho Chehab err: 1273119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1274786baecfSMauro Carvalho Chehab 1275786baecfSMauro Carvalho Chehab return ret; 1276786baecfSMauro Carvalho Chehab } 1277786baecfSMauro Carvalho Chehab 127837b44a0fSAntti Palosaari #if IS_ENABLED(CONFIG_RC_CORE) 1279786baecfSMauro Carvalho Chehab static int af9035_rc_query(struct dvb_usb_device *d) 1280786baecfSMauro Carvalho Chehab { 1281786baecfSMauro Carvalho Chehab int ret; 128275cd5886SAntti Palosaari u32 key; 128375cd5886SAntti Palosaari u8 buf[4]; 128475cd5886SAntti Palosaari struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf }; 1285786baecfSMauro Carvalho Chehab 1286786baecfSMauro Carvalho Chehab ret = af9035_ctrl_msg(d, &req); 12871bfd5294SAntti Palosaari if (ret == 1) 12881bfd5294SAntti Palosaari return 0; 12891bfd5294SAntti Palosaari else if (ret < 0) 1290786baecfSMauro Carvalho Chehab goto err; 1291786baecfSMauro Carvalho Chehab 129275cd5886SAntti Palosaari if ((buf[2] + buf[3]) == 0xff) { 129375cd5886SAntti Palosaari if ((buf[0] + buf[1]) == 0xff) { 129475cd5886SAntti Palosaari /* NEC standard 16bit */ 129575cd5886SAntti Palosaari key = buf[0] << 8 | buf[2]; 1296786baecfSMauro Carvalho Chehab } else { 129775cd5886SAntti Palosaari /* NEC extended 24bit */ 129875cd5886SAntti Palosaari key = buf[0] << 16 | buf[1] << 8 | buf[2]; 1299786baecfSMauro Carvalho Chehab } 1300786baecfSMauro Carvalho Chehab } else { 130175cd5886SAntti Palosaari /* NEC full code 32bit */ 130275cd5886SAntti Palosaari key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; 1303786baecfSMauro Carvalho Chehab } 1304786baecfSMauro Carvalho Chehab 130575cd5886SAntti Palosaari dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf); 130675cd5886SAntti Palosaari 1307786baecfSMauro Carvalho Chehab rc_keydown(d->rc_dev, key, 0); 1308786baecfSMauro Carvalho Chehab 1309786baecfSMauro Carvalho Chehab return 0; 13101bfd5294SAntti Palosaari 13111bfd5294SAntti Palosaari err: 13121bfd5294SAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 13131bfd5294SAntti Palosaari 13141bfd5294SAntti Palosaari return ret; 1315786baecfSMauro Carvalho Chehab } 1316786baecfSMauro Carvalho Chehab 1317786baecfSMauro Carvalho Chehab static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) 1318786baecfSMauro Carvalho Chehab { 131974c1883aSAntti Palosaari struct state *state = d_to_priv(d); 1320786baecfSMauro Carvalho Chehab int ret; 1321786baecfSMauro Carvalho Chehab u8 tmp; 1322786baecfSMauro Carvalho Chehab 1323431a6d4aSAntti Palosaari ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_MODE, &tmp); 1324786baecfSMauro Carvalho Chehab if (ret < 0) 1325786baecfSMauro Carvalho Chehab goto err; 1326786baecfSMauro Carvalho Chehab 1327119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_mode=%02x\n", __func__, tmp); 1328786baecfSMauro Carvalho Chehab 1329786baecfSMauro Carvalho Chehab /* don't activate rc if in HID mode or if not available */ 1330786baecfSMauro Carvalho Chehab if (tmp == 5) { 1331431a6d4aSAntti Palosaari ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_TYPE, 13329ea3681dSAntti Palosaari &tmp); 1333786baecfSMauro Carvalho Chehab if (ret < 0) 1334786baecfSMauro Carvalho Chehab goto err; 1335786baecfSMauro Carvalho Chehab 1336119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: ir_type=%02x\n", __func__, tmp); 1337786baecfSMauro Carvalho Chehab 1338786baecfSMauro Carvalho Chehab switch (tmp) { 1339786baecfSMauro Carvalho Chehab case 0: /* NEC */ 1340786baecfSMauro Carvalho Chehab default: 1341c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_NEC; 1342786baecfSMauro Carvalho Chehab break; 1343786baecfSMauro Carvalho Chehab case 1: /* RC6 */ 1344c003ab1bSDavid Härdeman rc->allowed_protos = RC_BIT_RC6_MCE; 1345786baecfSMauro Carvalho Chehab break; 1346786baecfSMauro Carvalho Chehab } 1347786baecfSMauro Carvalho Chehab 1348786baecfSMauro Carvalho Chehab rc->query = af9035_rc_query; 1349786baecfSMauro Carvalho Chehab rc->interval = 500; 1350786baecfSMauro Carvalho Chehab 1351786baecfSMauro Carvalho Chehab /* load empty to enable rc */ 1352786baecfSMauro Carvalho Chehab if (!rc->map_name) 1353786baecfSMauro Carvalho Chehab rc->map_name = RC_MAP_EMPTY; 1354786baecfSMauro Carvalho Chehab } 1355786baecfSMauro Carvalho Chehab 1356786baecfSMauro Carvalho Chehab return 0; 1357786baecfSMauro Carvalho Chehab 1358786baecfSMauro Carvalho Chehab err: 1359119f7a8cSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1360786baecfSMauro Carvalho Chehab 1361786baecfSMauro Carvalho Chehab return ret; 1362786baecfSMauro Carvalho Chehab } 1363eed5670aSAntti Palosaari #else 1364eed5670aSAntti Palosaari #define af9035_get_rc_config NULL 1365eed5670aSAntti Palosaari #endif 1366786baecfSMauro Carvalho Chehab 1367bada342eSAntti Palosaari static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, 1368bada342eSAntti Palosaari struct usb_data_stream_properties *stream) 1369bada342eSAntti Palosaari { 1370bada342eSAntti Palosaari struct dvb_usb_device *d = fe_to_d(fe); 1371bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); 1372bada342eSAntti Palosaari 1373bada342eSAntti Palosaari if (d->udev->speed == USB_SPEED_FULL) 1374bada342eSAntti Palosaari stream->u.bulk.buffersize = 5 * 188; 1375bada342eSAntti Palosaari 1376bada342eSAntti Palosaari return 0; 1377bada342eSAntti Palosaari } 1378bada342eSAntti Palosaari 1379bada342eSAntti Palosaari /* 1380bada342eSAntti Palosaari * FIXME: PID filter is property of demodulator and should be moved to the 1381bada342eSAntti Palosaari * correct driver. Also we support only adapter #0 PID filter and will 1382bada342eSAntti Palosaari * disable adapter #1 if USB1.1 is used. 1383bada342eSAntti Palosaari */ 1384bada342eSAntti Palosaari static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) 1385bada342eSAntti Palosaari { 1386bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1387bada342eSAntti Palosaari int ret; 1388bada342eSAntti Palosaari 1389bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); 1390bada342eSAntti Palosaari 1391bada342eSAntti Palosaari ret = af9035_wr_reg_mask(d, 0x80f993, onoff, 0x01); 1392bada342eSAntti Palosaari if (ret < 0) 1393bada342eSAntti Palosaari goto err; 1394bada342eSAntti Palosaari 1395bada342eSAntti Palosaari return 0; 1396bada342eSAntti Palosaari 1397bada342eSAntti Palosaari err: 1398bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1399bada342eSAntti Palosaari 1400bada342eSAntti Palosaari return ret; 1401bada342eSAntti Palosaari } 1402bada342eSAntti Palosaari 1403bada342eSAntti Palosaari static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, 1404bada342eSAntti Palosaari int onoff) 1405bada342eSAntti Palosaari { 1406bada342eSAntti Palosaari struct dvb_usb_device *d = adap_to_d(adap); 1407bada342eSAntti Palosaari int ret; 1408bada342eSAntti Palosaari u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 1409bada342eSAntti Palosaari 1410bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", 1411bada342eSAntti Palosaari __func__, index, pid, onoff); 1412bada342eSAntti Palosaari 1413bada342eSAntti Palosaari ret = af9035_wr_regs(d, 0x80f996, wbuf, 2); 1414bada342eSAntti Palosaari if (ret < 0) 1415bada342eSAntti Palosaari goto err; 1416bada342eSAntti Palosaari 1417bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f994, onoff); 1418bada342eSAntti Palosaari if (ret < 0) 1419bada342eSAntti Palosaari goto err; 1420bada342eSAntti Palosaari 1421bada342eSAntti Palosaari ret = af9035_wr_reg(d, 0x80f995, index); 1422bada342eSAntti Palosaari if (ret < 0) 1423bada342eSAntti Palosaari goto err; 1424bada342eSAntti Palosaari 1425bada342eSAntti Palosaari return 0; 1426bada342eSAntti Palosaari 1427bada342eSAntti Palosaari err: 1428bada342eSAntti Palosaari dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 1429bada342eSAntti Palosaari 1430bada342eSAntti Palosaari return ret; 1431bada342eSAntti Palosaari } 1432bada342eSAntti Palosaari 1433b799b810SAntti Palosaari static int af9035_probe(struct usb_interface *intf, 1434b799b810SAntti Palosaari const struct usb_device_id *id) 1435b799b810SAntti Palosaari { 1436b799b810SAntti Palosaari struct usb_device *udev = interface_to_usbdev(intf); 1437b799b810SAntti Palosaari char manufacturer[sizeof("Afatech")]; 1438b799b810SAntti Palosaari 1439b799b810SAntti Palosaari memset(manufacturer, 0, sizeof(manufacturer)); 1440b799b810SAntti Palosaari usb_string(udev, udev->descriptor.iManufacturer, 1441b799b810SAntti Palosaari manufacturer, sizeof(manufacturer)); 1442b799b810SAntti Palosaari /* 1443b799b810SAntti Palosaari * There is two devices having same ID but different chipset. One uses 1444b799b810SAntti Palosaari * AF9015 and the other IT9135 chipset. Only difference seen on lsusb 1445b799b810SAntti Palosaari * is iManufacturer string. 1446b799b810SAntti Palosaari * 1447b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1448b799b810SAntti Palosaari * idProduct 0x0099 1449b799b810SAntti Palosaari * bcdDevice 2.00 1450b799b810SAntti Palosaari * iManufacturer 1 Afatech 1451b799b810SAntti Palosaari * iProduct 2 DVB-T 2 1452b799b810SAntti Palosaari * 1453b799b810SAntti Palosaari * idVendor 0x0ccd TerraTec Electronic GmbH 1454b799b810SAntti Palosaari * idProduct 0x0099 1455b799b810SAntti Palosaari * bcdDevice 2.00 1456b799b810SAntti Palosaari * iManufacturer 1 ITE Technologies, Inc. 1457b799b810SAntti Palosaari * iProduct 2 DVB-T TV Stick 1458b799b810SAntti Palosaari */ 1459b799b810SAntti Palosaari if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && 1460b799b810SAntti Palosaari (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { 1461b799b810SAntti Palosaari if (!strcmp("Afatech", manufacturer)) { 1462b799b810SAntti Palosaari dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); 1463b799b810SAntti Palosaari return -ENODEV; 1464b799b810SAntti Palosaari } 1465b799b810SAntti Palosaari } 1466b799b810SAntti Palosaari 1467b799b810SAntti Palosaari return dvb_usbv2_probe(intf, id); 1468b799b810SAntti Palosaari } 1469b799b810SAntti Palosaari 1470786baecfSMauro Carvalho Chehab /* interface 0 is used by DVB-T receiver and 1471786baecfSMauro Carvalho Chehab interface 1 is for remote controller (HID) */ 1472786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties af9035_props = { 1473786baecfSMauro Carvalho Chehab .driver_name = KBUILD_MODNAME, 1474786baecfSMauro Carvalho Chehab .owner = THIS_MODULE, 1475786baecfSMauro Carvalho Chehab .adapter_nr = adapter_nr, 1476786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct state), 1477786baecfSMauro Carvalho Chehab 1478786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x02, 1479786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint_response = 0x81, 1480786baecfSMauro Carvalho Chehab 1481786baecfSMauro Carvalho Chehab .identify_state = af9035_identify_state, 1482786baecfSMauro Carvalho Chehab .download_firmware = af9035_download_firmware, 1483786baecfSMauro Carvalho Chehab 1484786baecfSMauro Carvalho Chehab .i2c_algo = &af9035_i2c_algo, 1485786baecfSMauro Carvalho Chehab .read_config = af9035_read_config, 1486786baecfSMauro Carvalho Chehab .frontend_attach = af9035_frontend_attach, 1487786baecfSMauro Carvalho Chehab .tuner_attach = af9035_tuner_attach, 1488786baecfSMauro Carvalho Chehab .init = af9035_init, 1489786baecfSMauro Carvalho Chehab .get_rc_config = af9035_get_rc_config, 1490bada342eSAntti Palosaari .get_stream_config = af9035_get_stream_config, 1491786baecfSMauro Carvalho Chehab 14929805992fSJose Alberto Reguero .get_adapter_count = af9035_get_adapter_count, 1493786baecfSMauro Carvalho Chehab .adapter = { 1494786baecfSMauro Carvalho Chehab { 1495bada342eSAntti Palosaari .caps = DVB_USB_ADAP_HAS_PID_FILTER | 1496bada342eSAntti Palosaari DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 1497bada342eSAntti Palosaari 1498bada342eSAntti Palosaari .pid_filter_count = 32, 1499bada342eSAntti Palosaari .pid_filter_ctrl = af9035_pid_filter_ctrl, 1500bada342eSAntti Palosaari .pid_filter = af9035_pid_filter, 1501bada342eSAntti Palosaari 1502786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), 1503786baecfSMauro Carvalho Chehab }, { 1504786baecfSMauro Carvalho Chehab .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), 1505786baecfSMauro Carvalho Chehab }, 1506786baecfSMauro Carvalho Chehab }, 1507786baecfSMauro Carvalho Chehab }; 1508786baecfSMauro Carvalho Chehab 1509786baecfSMauro Carvalho Chehab static const struct usb_device_id af9035_id_table[] = { 1510bc3c9e10SAntti Palosaari /* AF9035 devices */ 1511786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, 1512786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1513786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, 1514786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1515786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, 1516786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1517786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, 1518786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1519786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, 1520786baecfSMauro Carvalho Chehab &af9035_props, "Afatech AF9035 reference design", NULL) }, 1521786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, 1522786baecfSMauro Carvalho Chehab &af9035_props, "TerraTec Cinergy T Stick", NULL) }, 1523786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, 1524786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1525786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, 1526786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, 1527786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, 1528786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1529786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, 1530786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, 1531786baecfSMauro Carvalho Chehab { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, 1532786baecfSMauro Carvalho Chehab &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, 1533d67ceb33SOliver Schinagl { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, 1534d67ceb33SOliver Schinagl &af9035_props, "Asus U3100Mini Plus", NULL) }, 1535d9b7595bSFabrizio Gazzato { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, 1536d9b7595bSFabrizio Gazzato &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, 1537bc3c9e10SAntti Palosaari /* IT9135 devices */ 15387a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, 15397a541ce0SMalcolm Priestley &af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) }, 15407a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, 15417a541ce0SMalcolm Priestley &af9035_props, "ITE 9135(9005) Generic", RC_MAP_IT913X_V2) }, 15427a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, 15437a541ce0SMalcolm Priestley &af9035_props, "ITE 9135(9006) Generic", RC_MAP_IT913X_V1) }, 15447a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835, 15457a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(1835)", RC_MAP_IT913X_V2) }, 15467a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835, 15477a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(2835)", RC_MAP_IT913X_V2) }, 15487a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835, 15497a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(3835)", RC_MAP_IT913X_V2) }, 15507a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, 15517a541ce0SMalcolm Priestley &af9035_props, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, 15527a541ce0SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335, 15537a541ce0SMalcolm Priestley &af9035_props, "Avermedia H335", RC_MAP_IT913X_V2) }, 155437973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, 155537973e01SMalcolm Priestley &af9035_props, "Kworld UB499-2T T09", RC_MAP_IT913X_V1) }, 155637973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, 155737973e01SMalcolm Priestley &af9035_props, "Sveon STV22 Dual DVB-T HDTV", 155837973e01SMalcolm Priestley RC_MAP_IT913X_V1) }, 155937973e01SMalcolm Priestley { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, 156037973e01SMalcolm Priestley &af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2", 156137973e01SMalcolm Priestley RC_MAP_IT913X_V1) }, 1562b799b810SAntti Palosaari /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ 1563b799b810SAntti Palosaari { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, 1564b799b810SAntti Palosaari &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, 15650c413d10SAntti Palosaari { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, 15660c413d10SAntti Palosaari &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, 1567261cb200SAntti Palosaari { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, 1568261cb200SAntti Palosaari &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, 1569786baecfSMauro Carvalho Chehab { } 1570786baecfSMauro Carvalho Chehab }; 1571786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, af9035_id_table); 1572786baecfSMauro Carvalho Chehab 1573786baecfSMauro Carvalho Chehab static struct usb_driver af9035_usb_driver = { 1574786baecfSMauro Carvalho Chehab .name = KBUILD_MODNAME, 1575786baecfSMauro Carvalho Chehab .id_table = af9035_id_table, 1576b799b810SAntti Palosaari .probe = af9035_probe, 1577786baecfSMauro Carvalho Chehab .disconnect = dvb_usbv2_disconnect, 1578786baecfSMauro Carvalho Chehab .suspend = dvb_usbv2_suspend, 1579786baecfSMauro Carvalho Chehab .resume = dvb_usbv2_resume, 158004966aa8SAntti Palosaari .reset_resume = dvb_usbv2_reset_resume, 1581786baecfSMauro Carvalho Chehab .no_dynamic_id = 1, 1582786baecfSMauro Carvalho Chehab .soft_unbind = 1, 1583786baecfSMauro Carvalho Chehab }; 1584786baecfSMauro Carvalho Chehab 1585786baecfSMauro Carvalho Chehab module_usb_driver(af9035_usb_driver); 1586786baecfSMauro Carvalho Chehab 1587786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 1588786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9035 driver"); 1589786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 15904395e4b7SAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); 159174c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); 159274c1883aSAntti Palosaari MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); 1593