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