1786baecfSMauro Carvalho Chehab /*
2786baecfSMauro Carvalho Chehab  * Afatech AF9035 DVB USB driver
3786baecfSMauro Carvalho Chehab  *
4786baecfSMauro Carvalho Chehab  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
5786baecfSMauro Carvalho Chehab  * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
6786baecfSMauro Carvalho Chehab  *
7786baecfSMauro Carvalho Chehab  *    This program is free software; you can redistribute it and/or modify
8786baecfSMauro Carvalho Chehab  *    it under the terms of the GNU General Public License as published by
9786baecfSMauro Carvalho Chehab  *    the Free Software Foundation; either version 2 of the License, or
10786baecfSMauro Carvalho Chehab  *    (at your option) any later version.
11786baecfSMauro Carvalho Chehab  *
12786baecfSMauro Carvalho Chehab  *    This program is distributed in the hope that it will be useful,
13786baecfSMauro Carvalho Chehab  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14786baecfSMauro Carvalho Chehab  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15786baecfSMauro Carvalho Chehab  *    GNU General Public License for more details.
16786baecfSMauro Carvalho Chehab  *
17786baecfSMauro Carvalho Chehab  *    You should have received a copy of the GNU General Public License along
18786baecfSMauro Carvalho Chehab  *    with this program; if not, write to the Free Software Foundation, Inc.,
19786baecfSMauro Carvalho Chehab  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20786baecfSMauro Carvalho Chehab  */
21786baecfSMauro Carvalho Chehab 
22786baecfSMauro Carvalho Chehab #include "af9035.h"
23786baecfSMauro Carvalho Chehab 
24786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
25786baecfSMauro Carvalho Chehab 
26786baecfSMauro Carvalho Chehab static u16 af9035_checksum(const u8 *buf, size_t len)
27786baecfSMauro Carvalho Chehab {
28786baecfSMauro Carvalho Chehab 	size_t i;
29786baecfSMauro Carvalho Chehab 	u16 checksum = 0;
30786baecfSMauro Carvalho Chehab 
31786baecfSMauro Carvalho Chehab 	for (i = 1; i < len; i++) {
32786baecfSMauro Carvalho Chehab 		if (i % 2)
33786baecfSMauro Carvalho Chehab 			checksum += buf[i] << 8;
34786baecfSMauro Carvalho Chehab 		else
35786baecfSMauro Carvalho Chehab 			checksum += buf[i];
36786baecfSMauro Carvalho Chehab 	}
37786baecfSMauro Carvalho Chehab 	checksum = ~checksum;
38786baecfSMauro Carvalho Chehab 
39786baecfSMauro Carvalho Chehab 	return checksum;
40786baecfSMauro Carvalho Chehab }
41786baecfSMauro Carvalho Chehab 
42786baecfSMauro Carvalho Chehab static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
43786baecfSMauro Carvalho Chehab {
44786baecfSMauro Carvalho Chehab #define BUF_LEN 64
45786baecfSMauro Carvalho Chehab #define REQ_HDR_LEN 4 /* send header size */
46786baecfSMauro Carvalho Chehab #define ACK_HDR_LEN 3 /* rece header size */
47786baecfSMauro Carvalho Chehab #define CHECKSUM_LEN 2
48786baecfSMauro Carvalho Chehab #define USB_TIMEOUT 2000
49786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
50786baecfSMauro Carvalho Chehab 	int ret, wlen, rlen;
51786baecfSMauro Carvalho Chehab 	u8 buf[BUF_LEN];
52786baecfSMauro Carvalho Chehab 	u16 checksum, tmp_checksum;
53786baecfSMauro Carvalho Chehab 
54786baecfSMauro Carvalho Chehab 	/* buffer overflow check */
55786baecfSMauro Carvalho Chehab 	if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
56786baecfSMauro Carvalho Chehab 		req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
57786baecfSMauro Carvalho Chehab 		pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__,
58786baecfSMauro Carvalho Chehab 				req->wlen, req->rlen);
59786baecfSMauro Carvalho Chehab 		return -EINVAL;
60786baecfSMauro Carvalho Chehab 	}
61786baecfSMauro Carvalho Chehab 
62786baecfSMauro Carvalho Chehab 	buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
63786baecfSMauro Carvalho Chehab 	buf[1] = req->mbox;
64786baecfSMauro Carvalho Chehab 	buf[2] = req->cmd;
65786baecfSMauro Carvalho Chehab 	buf[3] = state->seq++;
66786baecfSMauro Carvalho Chehab 	memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen);
67786baecfSMauro Carvalho Chehab 
68786baecfSMauro Carvalho Chehab 	wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN;
69786baecfSMauro Carvalho Chehab 	rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
70786baecfSMauro Carvalho Chehab 
71786baecfSMauro Carvalho Chehab 	/* calc and add checksum */
72786baecfSMauro Carvalho Chehab 	checksum = af9035_checksum(buf, buf[0] - 1);
73786baecfSMauro Carvalho Chehab 	buf[buf[0] - 1] = (checksum >> 8);
74786baecfSMauro Carvalho Chehab 	buf[buf[0] - 0] = (checksum & 0xff);
75786baecfSMauro Carvalho Chehab 
76786baecfSMauro Carvalho Chehab 	/* no ack for these packets */
77786baecfSMauro Carvalho Chehab 	if (req->cmd == CMD_FW_DL)
78786baecfSMauro Carvalho Chehab 		rlen = 0;
79786baecfSMauro Carvalho Chehab 
80786baecfSMauro Carvalho Chehab 	ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
81786baecfSMauro Carvalho Chehab 	if (ret)
82786baecfSMauro Carvalho Chehab 		goto err;
83786baecfSMauro Carvalho Chehab 
84786baecfSMauro Carvalho Chehab 	/* no ack for those packets */
85786baecfSMauro Carvalho Chehab 	if (req->cmd == CMD_FW_DL)
86786baecfSMauro Carvalho Chehab 		goto exit;
87786baecfSMauro Carvalho Chehab 
88786baecfSMauro Carvalho Chehab 	/* verify checksum */
89786baecfSMauro Carvalho Chehab 	checksum = af9035_checksum(buf, rlen - 2);
90786baecfSMauro Carvalho Chehab 	tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1];
91786baecfSMauro Carvalho Chehab 	if (tmp_checksum != checksum) {
92786baecfSMauro Carvalho Chehab 		pr_err("%s: command=%02x checksum mismatch (%04x != %04x)\n",
93786baecfSMauro Carvalho Chehab 				KBUILD_MODNAME, req->cmd, tmp_checksum,
94786baecfSMauro Carvalho Chehab 				checksum);
95786baecfSMauro Carvalho Chehab 		ret = -EIO;
96786baecfSMauro Carvalho Chehab 		goto err;
97786baecfSMauro Carvalho Chehab 	}
98786baecfSMauro Carvalho Chehab 
99786baecfSMauro Carvalho Chehab 	/* check status */
100786baecfSMauro Carvalho Chehab 	if (buf[2]) {
101786baecfSMauro Carvalho Chehab 		pr_debug("%s: command=%02x failed fw error=%d\n", __func__,
102786baecfSMauro Carvalho Chehab 				req->cmd, buf[2]);
103786baecfSMauro Carvalho Chehab 		ret = -EIO;
104786baecfSMauro Carvalho Chehab 		goto err;
105786baecfSMauro Carvalho Chehab 	}
106786baecfSMauro Carvalho Chehab 
107786baecfSMauro Carvalho Chehab 	/* read request, copy returned data to return buf */
108786baecfSMauro Carvalho Chehab 	if (req->rlen)
109786baecfSMauro Carvalho Chehab 		memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
110786baecfSMauro Carvalho Chehab 
111786baecfSMauro Carvalho Chehab exit:
112786baecfSMauro Carvalho Chehab 	return 0;
113786baecfSMauro Carvalho Chehab 
114786baecfSMauro Carvalho Chehab err:
115786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
116786baecfSMauro Carvalho Chehab 
117786baecfSMauro Carvalho Chehab 	return ret;
118786baecfSMauro Carvalho Chehab }
119786baecfSMauro Carvalho Chehab 
120786baecfSMauro Carvalho Chehab /* write multiple registers */
121786baecfSMauro Carvalho Chehab static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
122786baecfSMauro Carvalho Chehab {
123786baecfSMauro Carvalho Chehab 	u8 wbuf[6 + len];
124786baecfSMauro Carvalho Chehab 	u8 mbox = (reg >> 16) & 0xff;
125786baecfSMauro Carvalho Chehab 	struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
126786baecfSMauro Carvalho Chehab 
127786baecfSMauro Carvalho Chehab 	wbuf[0] = len;
128786baecfSMauro Carvalho Chehab 	wbuf[1] = 2;
129786baecfSMauro Carvalho Chehab 	wbuf[2] = 0;
130786baecfSMauro Carvalho Chehab 	wbuf[3] = 0;
131786baecfSMauro Carvalho Chehab 	wbuf[4] = (reg >> 8) & 0xff;
132786baecfSMauro Carvalho Chehab 	wbuf[5] = (reg >> 0) & 0xff;
133786baecfSMauro Carvalho Chehab 	memcpy(&wbuf[6], val, len);
134786baecfSMauro Carvalho Chehab 
135786baecfSMauro Carvalho Chehab 	return af9035_ctrl_msg(d, &req);
136786baecfSMauro Carvalho Chehab }
137786baecfSMauro Carvalho Chehab 
138786baecfSMauro Carvalho Chehab /* read multiple registers */
139786baecfSMauro Carvalho Chehab static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
140786baecfSMauro Carvalho Chehab {
141786baecfSMauro Carvalho Chehab 	u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff };
142786baecfSMauro Carvalho Chehab 	u8 mbox = (reg >> 16) & 0xff;
143786baecfSMauro Carvalho Chehab 	struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val };
144786baecfSMauro Carvalho Chehab 
145786baecfSMauro Carvalho Chehab 	return af9035_ctrl_msg(d, &req);
146786baecfSMauro Carvalho Chehab }
147786baecfSMauro Carvalho Chehab 
148786baecfSMauro Carvalho Chehab /* write single register */
149786baecfSMauro Carvalho Chehab static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val)
150786baecfSMauro Carvalho Chehab {
151786baecfSMauro Carvalho Chehab 	return af9035_wr_regs(d, reg, &val, 1);
152786baecfSMauro Carvalho Chehab }
153786baecfSMauro Carvalho Chehab 
154786baecfSMauro Carvalho Chehab /* read single register */
155786baecfSMauro Carvalho Chehab static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val)
156786baecfSMauro Carvalho Chehab {
157786baecfSMauro Carvalho Chehab 	return af9035_rd_regs(d, reg, val, 1);
158786baecfSMauro Carvalho Chehab }
159786baecfSMauro Carvalho Chehab 
160786baecfSMauro Carvalho Chehab /* write single register with mask */
161786baecfSMauro Carvalho Chehab static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
162786baecfSMauro Carvalho Chehab 		u8 mask)
163786baecfSMauro Carvalho Chehab {
164786baecfSMauro Carvalho Chehab 	int ret;
165786baecfSMauro Carvalho Chehab 	u8 tmp;
166786baecfSMauro Carvalho Chehab 
167786baecfSMauro Carvalho Chehab 	/* no need for read if whole reg is written */
168786baecfSMauro Carvalho Chehab 	if (mask != 0xff) {
169786baecfSMauro Carvalho Chehab 		ret = af9035_rd_regs(d, reg, &tmp, 1);
170786baecfSMauro Carvalho Chehab 		if (ret)
171786baecfSMauro Carvalho Chehab 			return ret;
172786baecfSMauro Carvalho Chehab 
173786baecfSMauro Carvalho Chehab 		val &= mask;
174786baecfSMauro Carvalho Chehab 		tmp &= ~mask;
175786baecfSMauro Carvalho Chehab 		val |= tmp;
176786baecfSMauro Carvalho Chehab 	}
177786baecfSMauro Carvalho Chehab 
178786baecfSMauro Carvalho Chehab 	return af9035_wr_regs(d, reg, &val, 1);
179786baecfSMauro Carvalho Chehab }
180786baecfSMauro Carvalho Chehab 
181786baecfSMauro Carvalho Chehab static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
182786baecfSMauro Carvalho Chehab 		struct i2c_msg msg[], int num)
183786baecfSMauro Carvalho Chehab {
184786baecfSMauro Carvalho Chehab 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
185786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
186786baecfSMauro Carvalho Chehab 	int ret;
187786baecfSMauro Carvalho Chehab 
188786baecfSMauro Carvalho Chehab 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
189786baecfSMauro Carvalho Chehab 		return -EAGAIN;
190786baecfSMauro Carvalho Chehab 
191786baecfSMauro Carvalho Chehab 	/*
192786baecfSMauro Carvalho Chehab 	 * I2C sub header is 5 bytes long. Meaning of those bytes are:
193786baecfSMauro Carvalho Chehab 	 * 0: data len
194786baecfSMauro Carvalho Chehab 	 * 1: I2C addr << 1
195786baecfSMauro Carvalho Chehab 	 * 2: reg addr len
196786baecfSMauro Carvalho Chehab 	 *    byte 3 and 4 can be used as reg addr
197786baecfSMauro Carvalho Chehab 	 * 3: reg addr MSB
198786baecfSMauro Carvalho Chehab 	 *    used when reg addr len is set to 2
199786baecfSMauro Carvalho Chehab 	 * 4: reg addr LSB
200786baecfSMauro Carvalho Chehab 	 *    used when reg addr len is set to 1 or 2
201786baecfSMauro Carvalho Chehab 	 *
202786baecfSMauro Carvalho Chehab 	 * For the simplify we do not use register addr at all.
203786baecfSMauro Carvalho Chehab 	 * NOTE: As a firmware knows tuner type there is very small possibility
204786baecfSMauro Carvalho Chehab 	 * there could be some tuner I2C hacks done by firmware and this may
205786baecfSMauro Carvalho Chehab 	 * lead problems if firmware expects those bytes are used.
206786baecfSMauro Carvalho Chehab 	 */
207786baecfSMauro Carvalho Chehab 	if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
208786baecfSMauro Carvalho Chehab 			(msg[1].flags & I2C_M_RD)) {
209786baecfSMauro Carvalho Chehab 		if (msg[0].len > 40 || msg[1].len > 40) {
210786baecfSMauro Carvalho Chehab 			/* TODO: correct limits > 40 */
211786baecfSMauro Carvalho Chehab 			ret = -EOPNOTSUPP;
212786baecfSMauro Carvalho Chehab 		} else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
213786baecfSMauro Carvalho Chehab 			/* integrated demod */
214786baecfSMauro Carvalho Chehab 			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
215786baecfSMauro Carvalho Chehab 					msg[0].buf[2];
216786baecfSMauro Carvalho Chehab 			ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
217786baecfSMauro Carvalho Chehab 					msg[1].len);
218786baecfSMauro Carvalho Chehab 		} else {
219786baecfSMauro Carvalho Chehab 			/* I2C */
220786baecfSMauro Carvalho Chehab 			u8 buf[5 + msg[0].len];
221786baecfSMauro Carvalho Chehab 			struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
222786baecfSMauro Carvalho Chehab 					buf, msg[1].len, msg[1].buf };
223786baecfSMauro Carvalho Chehab 			buf[0] = msg[1].len;
224786baecfSMauro Carvalho Chehab 			buf[1] = msg[0].addr << 1;
225786baecfSMauro Carvalho Chehab 			buf[2] = 0x00; /* reg addr len */
226786baecfSMauro Carvalho Chehab 			buf[3] = 0x00; /* reg addr MSB */
227786baecfSMauro Carvalho Chehab 			buf[4] = 0x00; /* reg addr LSB */
228786baecfSMauro Carvalho Chehab 			memcpy(&buf[5], msg[0].buf, msg[0].len);
229786baecfSMauro Carvalho Chehab 			ret = af9035_ctrl_msg(d, &req);
230786baecfSMauro Carvalho Chehab 		}
231786baecfSMauro Carvalho Chehab 	} else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
232786baecfSMauro Carvalho Chehab 		if (msg[0].len > 40) {
233786baecfSMauro Carvalho Chehab 			/* TODO: correct limits > 40 */
234786baecfSMauro Carvalho Chehab 			ret = -EOPNOTSUPP;
235786baecfSMauro Carvalho Chehab 		} else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
236786baecfSMauro Carvalho Chehab 			/* integrated demod */
237786baecfSMauro Carvalho Chehab 			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
238786baecfSMauro Carvalho Chehab 					msg[0].buf[2];
239786baecfSMauro Carvalho Chehab 			ret = af9035_wr_regs(d, reg, &msg[0].buf[3],
240786baecfSMauro Carvalho Chehab 					msg[0].len - 3);
241786baecfSMauro Carvalho Chehab 		} else {
242786baecfSMauro Carvalho Chehab 			/* I2C */
243786baecfSMauro Carvalho Chehab 			u8 buf[5 + msg[0].len];
244786baecfSMauro Carvalho Chehab 			struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
245786baecfSMauro Carvalho Chehab 					0, NULL };
246786baecfSMauro Carvalho Chehab 			buf[0] = msg[0].len;
247786baecfSMauro Carvalho Chehab 			buf[1] = msg[0].addr << 1;
248786baecfSMauro Carvalho Chehab 			buf[2] = 0x00; /* reg addr len */
249786baecfSMauro Carvalho Chehab 			buf[3] = 0x00; /* reg addr MSB */
250786baecfSMauro Carvalho Chehab 			buf[4] = 0x00; /* reg addr LSB */
251786baecfSMauro Carvalho Chehab 			memcpy(&buf[5], msg[0].buf, msg[0].len);
252786baecfSMauro Carvalho Chehab 			ret = af9035_ctrl_msg(d, &req);
253786baecfSMauro Carvalho Chehab 		}
254786baecfSMauro Carvalho Chehab 	} else {
255786baecfSMauro Carvalho Chehab 		/*
256786baecfSMauro Carvalho Chehab 		 * We support only two kind of I2C transactions:
257786baecfSMauro Carvalho Chehab 		 * 1) 1 x read + 1 x write
258786baecfSMauro Carvalho Chehab 		 * 2) 1 x write
259786baecfSMauro Carvalho Chehab 		 */
260786baecfSMauro Carvalho Chehab 		ret = -EOPNOTSUPP;
261786baecfSMauro Carvalho Chehab 	}
262786baecfSMauro Carvalho Chehab 
263786baecfSMauro Carvalho Chehab 	mutex_unlock(&d->i2c_mutex);
264786baecfSMauro Carvalho Chehab 
265786baecfSMauro Carvalho Chehab 	if (ret < 0)
266786baecfSMauro Carvalho Chehab 		return ret;
267786baecfSMauro Carvalho Chehab 	else
268786baecfSMauro Carvalho Chehab 		return num;
269786baecfSMauro Carvalho Chehab }
270786baecfSMauro Carvalho Chehab 
271786baecfSMauro Carvalho Chehab static u32 af9035_i2c_functionality(struct i2c_adapter *adapter)
272786baecfSMauro Carvalho Chehab {
273786baecfSMauro Carvalho Chehab 	return I2C_FUNC_I2C;
274786baecfSMauro Carvalho Chehab }
275786baecfSMauro Carvalho Chehab 
276786baecfSMauro Carvalho Chehab static struct i2c_algorithm af9035_i2c_algo = {
277786baecfSMauro Carvalho Chehab 	.master_xfer = af9035_i2c_master_xfer,
278786baecfSMauro Carvalho Chehab 	.functionality = af9035_i2c_functionality,
279786baecfSMauro Carvalho Chehab };
280786baecfSMauro Carvalho Chehab 
281786baecfSMauro Carvalho Chehab static int af9035_identify_state(struct dvb_usb_device *d, const char **name)
282786baecfSMauro Carvalho Chehab {
283786baecfSMauro Carvalho Chehab 	int ret;
284786baecfSMauro Carvalho Chehab 	u8 wbuf[1] = { 1 };
285786baecfSMauro Carvalho Chehab 	u8 rbuf[4];
286786baecfSMauro Carvalho Chehab 	struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
287786baecfSMauro Carvalho Chehab 			sizeof(rbuf), rbuf };
288786baecfSMauro Carvalho Chehab 
289786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req);
290786baecfSMauro Carvalho Chehab 	if (ret < 0)
291786baecfSMauro Carvalho Chehab 		goto err;
292786baecfSMauro Carvalho Chehab 
293786baecfSMauro Carvalho Chehab 	pr_debug("%s: reply=%*ph\n", __func__, 4, rbuf);
294786baecfSMauro Carvalho Chehab 	if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])
295786baecfSMauro Carvalho Chehab 		ret = WARM;
296786baecfSMauro Carvalho Chehab 	else
297786baecfSMauro Carvalho Chehab 		ret = COLD;
298786baecfSMauro Carvalho Chehab 
299786baecfSMauro Carvalho Chehab 	return ret;
300786baecfSMauro Carvalho Chehab 
301786baecfSMauro Carvalho Chehab err:
302786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
303786baecfSMauro Carvalho Chehab 
304786baecfSMauro Carvalho Chehab 	return ret;
305786baecfSMauro Carvalho Chehab }
306786baecfSMauro Carvalho Chehab 
307786baecfSMauro Carvalho Chehab static int af9035_download_firmware(struct dvb_usb_device *d,
308786baecfSMauro Carvalho Chehab 		const struct firmware *fw)
309786baecfSMauro Carvalho Chehab {
310786baecfSMauro Carvalho Chehab 	int ret, i, j, len;
311786baecfSMauro Carvalho Chehab 	u8 wbuf[1];
312786baecfSMauro Carvalho Chehab 	u8 rbuf[4];
313786baecfSMauro Carvalho Chehab 	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
314786baecfSMauro Carvalho Chehab 	struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL };
315786baecfSMauro Carvalho Chehab 	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
316786baecfSMauro Carvalho Chehab 	u8 hdr_core;
317786baecfSMauro Carvalho Chehab 	u16 hdr_addr, hdr_data_len, hdr_checksum;
318786baecfSMauro Carvalho Chehab 	#define MAX_DATA 58
319786baecfSMauro Carvalho Chehab 	#define HDR_SIZE 7
320786baecfSMauro Carvalho Chehab 
321786baecfSMauro Carvalho Chehab 	/*
322786baecfSMauro Carvalho Chehab 	 * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info!
323786baecfSMauro Carvalho Chehab 	 *
324786baecfSMauro Carvalho Chehab 	 * byte 0: MCS 51 core
325786baecfSMauro Carvalho Chehab 	 *  There are two inside the AF9035 (1=Link and 2=OFDM) with separate
326786baecfSMauro Carvalho Chehab 	 *  address spaces
327786baecfSMauro Carvalho Chehab 	 * byte 1-2: Big endian destination address
328786baecfSMauro Carvalho Chehab 	 * byte 3-4: Big endian number of data bytes following the header
329786baecfSMauro Carvalho Chehab 	 * byte 5-6: Big endian header checksum, apparently ignored by the chip
330786baecfSMauro Carvalho Chehab 	 *  Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256)
331786baecfSMauro Carvalho Chehab 	 */
332786baecfSMauro Carvalho Chehab 
333786baecfSMauro Carvalho Chehab 	for (i = fw->size; i > HDR_SIZE;) {
334786baecfSMauro Carvalho Chehab 		hdr_core = fw->data[fw->size - i + 0];
335786baecfSMauro Carvalho Chehab 		hdr_addr = fw->data[fw->size - i + 1] << 8;
336786baecfSMauro Carvalho Chehab 		hdr_addr |= fw->data[fw->size - i + 2] << 0;
337786baecfSMauro Carvalho Chehab 		hdr_data_len = fw->data[fw->size - i + 3] << 8;
338786baecfSMauro Carvalho Chehab 		hdr_data_len |= fw->data[fw->size - i + 4] << 0;
339786baecfSMauro Carvalho Chehab 		hdr_checksum = fw->data[fw->size - i + 5] << 8;
340786baecfSMauro Carvalho Chehab 		hdr_checksum |= fw->data[fw->size - i + 6] << 0;
341786baecfSMauro Carvalho Chehab 
342786baecfSMauro Carvalho Chehab 		pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n",
343786baecfSMauro Carvalho Chehab 				__func__, hdr_core, hdr_addr, hdr_data_len,
344786baecfSMauro Carvalho Chehab 				hdr_checksum);
345786baecfSMauro Carvalho Chehab 
346786baecfSMauro Carvalho Chehab 		if (((hdr_core != 1) && (hdr_core != 2)) ||
347786baecfSMauro Carvalho Chehab 				(hdr_data_len > i)) {
348786baecfSMauro Carvalho Chehab 			pr_debug("%s: bad firmware\n", __func__);
349786baecfSMauro Carvalho Chehab 			break;
350786baecfSMauro Carvalho Chehab 		}
351786baecfSMauro Carvalho Chehab 
352786baecfSMauro Carvalho Chehab 		/* download begin packet */
353786baecfSMauro Carvalho Chehab 		req.cmd = CMD_FW_DL_BEGIN;
354786baecfSMauro Carvalho Chehab 		ret = af9035_ctrl_msg(d, &req);
355786baecfSMauro Carvalho Chehab 		if (ret < 0)
356786baecfSMauro Carvalho Chehab 			goto err;
357786baecfSMauro Carvalho Chehab 
358786baecfSMauro Carvalho Chehab 		/* download firmware packet(s) */
359786baecfSMauro Carvalho Chehab 		for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) {
360786baecfSMauro Carvalho Chehab 			len = j;
361786baecfSMauro Carvalho Chehab 			if (len > MAX_DATA)
362786baecfSMauro Carvalho Chehab 				len = MAX_DATA;
363786baecfSMauro Carvalho Chehab 			req_fw_dl.wlen = len;
364786baecfSMauro Carvalho Chehab 			req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i +
365786baecfSMauro Carvalho Chehab 					HDR_SIZE + hdr_data_len - j];
366786baecfSMauro Carvalho Chehab 			ret = af9035_ctrl_msg(d, &req_fw_dl);
367786baecfSMauro Carvalho Chehab 			if (ret < 0)
368786baecfSMauro Carvalho Chehab 				goto err;
369786baecfSMauro Carvalho Chehab 		}
370786baecfSMauro Carvalho Chehab 
371786baecfSMauro Carvalho Chehab 		/* download end packet */
372786baecfSMauro Carvalho Chehab 		req.cmd = CMD_FW_DL_END;
373786baecfSMauro Carvalho Chehab 		ret = af9035_ctrl_msg(d, &req);
374786baecfSMauro Carvalho Chehab 		if (ret < 0)
375786baecfSMauro Carvalho Chehab 			goto err;
376786baecfSMauro Carvalho Chehab 
377786baecfSMauro Carvalho Chehab 		i -= hdr_data_len + HDR_SIZE;
378786baecfSMauro Carvalho Chehab 
379786baecfSMauro Carvalho Chehab 		pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i);
380786baecfSMauro Carvalho Chehab 	}
381786baecfSMauro Carvalho Chehab 
382786baecfSMauro Carvalho Chehab 	/* firmware loaded, request boot */
383786baecfSMauro Carvalho Chehab 	req.cmd = CMD_FW_BOOT;
384786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req);
385786baecfSMauro Carvalho Chehab 	if (ret < 0)
386786baecfSMauro Carvalho Chehab 		goto err;
387786baecfSMauro Carvalho Chehab 
388786baecfSMauro Carvalho Chehab 	/* ensure firmware starts */
389786baecfSMauro Carvalho Chehab 	wbuf[0] = 1;
390786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req_fw_ver);
391786baecfSMauro Carvalho Chehab 	if (ret < 0)
392786baecfSMauro Carvalho Chehab 		goto err;
393786baecfSMauro Carvalho Chehab 
394786baecfSMauro Carvalho Chehab 	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
395786baecfSMauro Carvalho Chehab 		pr_err("%s: firmware did not run\n", KBUILD_MODNAME);
396786baecfSMauro Carvalho Chehab 		ret = -ENODEV;
397786baecfSMauro Carvalho Chehab 		goto err;
398786baecfSMauro Carvalho Chehab 	}
399786baecfSMauro Carvalho Chehab 
400786baecfSMauro Carvalho Chehab 	pr_info("%s: firmware version=%d.%d.%d.%d", KBUILD_MODNAME,
401786baecfSMauro Carvalho Chehab 			rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
402786baecfSMauro Carvalho Chehab 
403786baecfSMauro Carvalho Chehab 	return 0;
404786baecfSMauro Carvalho Chehab 
405786baecfSMauro Carvalho Chehab err:
406786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
407786baecfSMauro Carvalho Chehab 
408786baecfSMauro Carvalho Chehab 	return ret;
409786baecfSMauro Carvalho Chehab }
410786baecfSMauro Carvalho Chehab 
411786baecfSMauro Carvalho Chehab static int af9035_download_firmware_it9135(struct dvb_usb_device *d,
412786baecfSMauro Carvalho Chehab 		const struct firmware *fw)
413786baecfSMauro Carvalho Chehab {
414786baecfSMauro Carvalho Chehab 	int ret, i, i_prev;
415786baecfSMauro Carvalho Chehab 	u8 wbuf[1];
416786baecfSMauro Carvalho Chehab 	u8 rbuf[4];
417786baecfSMauro Carvalho Chehab 	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
418786baecfSMauro Carvalho Chehab 	struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL };
419786baecfSMauro Carvalho Chehab 	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
420786baecfSMauro Carvalho Chehab 	#define HDR_SIZE 7
421786baecfSMauro Carvalho Chehab 
422786baecfSMauro Carvalho Chehab 	/*
423786baecfSMauro Carvalho Chehab 	 * There seems to be following firmware header. Meaning of bytes 0-3
424786baecfSMauro Carvalho Chehab 	 * is unknown.
425786baecfSMauro Carvalho Chehab 	 *
426786baecfSMauro Carvalho Chehab 	 * 0: 3
427786baecfSMauro Carvalho Chehab 	 * 1: 0, 1
428786baecfSMauro Carvalho Chehab 	 * 2: 0
429786baecfSMauro Carvalho Chehab 	 * 3: 1, 2, 3
430786baecfSMauro Carvalho Chehab 	 * 4: addr MSB
431786baecfSMauro Carvalho Chehab 	 * 5: addr LSB
432786baecfSMauro Carvalho Chehab 	 * 6: count of data bytes ?
433786baecfSMauro Carvalho Chehab 	 */
434786baecfSMauro Carvalho Chehab 
435786baecfSMauro Carvalho Chehab 	for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) {
436786baecfSMauro Carvalho Chehab 		if (i == fw->size ||
437786baecfSMauro Carvalho Chehab 				(fw->data[i + 0] == 0x03 &&
438786baecfSMauro Carvalho Chehab 				(fw->data[i + 1] == 0x00 ||
439786baecfSMauro Carvalho Chehab 				fw->data[i + 1] == 0x01) &&
440786baecfSMauro Carvalho Chehab 				fw->data[i + 2] == 0x00)) {
441786baecfSMauro Carvalho Chehab 			req_fw_dl.wlen = i - i_prev;
442786baecfSMauro Carvalho Chehab 			req_fw_dl.wbuf = (u8 *) &fw->data[i_prev];
443786baecfSMauro Carvalho Chehab 			i_prev = i;
444786baecfSMauro Carvalho Chehab 			ret = af9035_ctrl_msg(d, &req_fw_dl);
445786baecfSMauro Carvalho Chehab 			if (ret < 0)
446786baecfSMauro Carvalho Chehab 				goto err;
447786baecfSMauro Carvalho Chehab 
448786baecfSMauro Carvalho Chehab 			pr_debug("%s: data uploaded=%d\n", __func__, i);
449786baecfSMauro Carvalho Chehab 		}
450786baecfSMauro Carvalho Chehab 	}
451786baecfSMauro Carvalho Chehab 
452786baecfSMauro Carvalho Chehab 	/* firmware loaded, request boot */
453786baecfSMauro Carvalho Chehab 	req.cmd = CMD_FW_BOOT;
454786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req);
455786baecfSMauro Carvalho Chehab 	if (ret < 0)
456786baecfSMauro Carvalho Chehab 		goto err;
457786baecfSMauro Carvalho Chehab 
458786baecfSMauro Carvalho Chehab 	/* ensure firmware starts */
459786baecfSMauro Carvalho Chehab 	wbuf[0] = 1;
460786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req_fw_ver);
461786baecfSMauro Carvalho Chehab 	if (ret < 0)
462786baecfSMauro Carvalho Chehab 		goto err;
463786baecfSMauro Carvalho Chehab 
464786baecfSMauro Carvalho Chehab 	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
465786baecfSMauro Carvalho Chehab 		pr_err("%s: firmware did not run\n", KBUILD_MODNAME);
466786baecfSMauro Carvalho Chehab 		ret = -ENODEV;
467786baecfSMauro Carvalho Chehab 		goto err;
468786baecfSMauro Carvalho Chehab 	}
469786baecfSMauro Carvalho Chehab 
470786baecfSMauro Carvalho Chehab 	pr_info("%s: firmware version=%d.%d.%d.%d", KBUILD_MODNAME,
471786baecfSMauro Carvalho Chehab 			rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
472786baecfSMauro Carvalho Chehab 
473786baecfSMauro Carvalho Chehab 	return 0;
474786baecfSMauro Carvalho Chehab 
475786baecfSMauro Carvalho Chehab err:
476786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
477786baecfSMauro Carvalho Chehab 
478786baecfSMauro Carvalho Chehab 	return ret;
479786baecfSMauro Carvalho Chehab }
480786baecfSMauro Carvalho Chehab 
481786baecfSMauro Carvalho Chehab static int af9035_read_config(struct dvb_usb_device *d)
482786baecfSMauro Carvalho Chehab {
483786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
484786baecfSMauro Carvalho Chehab 	int ret, i, eeprom_shift = 0;
485786baecfSMauro Carvalho Chehab 	u8 tmp;
486786baecfSMauro Carvalho Chehab 	u16 tmp16;
487786baecfSMauro Carvalho Chehab 
488786baecfSMauro Carvalho Chehab 	/* check if there is dual tuners */
489786baecfSMauro Carvalho Chehab 	ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp);
490786baecfSMauro Carvalho Chehab 	if (ret < 0)
491786baecfSMauro Carvalho Chehab 		goto err;
492786baecfSMauro Carvalho Chehab 
493786baecfSMauro Carvalho Chehab 	state->dual_mode = tmp;
494786baecfSMauro Carvalho Chehab 	pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode);
495786baecfSMauro Carvalho Chehab 
496786baecfSMauro Carvalho Chehab 	for (i = 0; i < state->dual_mode + 1; i++) {
497786baecfSMauro Carvalho Chehab 		/* tuner */
498786baecfSMauro Carvalho Chehab 		ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp);
499786baecfSMauro Carvalho Chehab 		if (ret < 0)
500786baecfSMauro Carvalho Chehab 			goto err;
501786baecfSMauro Carvalho Chehab 
502786baecfSMauro Carvalho Chehab 		state->af9033_config[i].tuner = tmp;
503786baecfSMauro Carvalho Chehab 		pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp);
504786baecfSMauro Carvalho Chehab 
505786baecfSMauro Carvalho Chehab 		switch (tmp) {
506786baecfSMauro Carvalho Chehab 		case AF9033_TUNER_TUA9001:
507786baecfSMauro Carvalho Chehab 		case AF9033_TUNER_FC0011:
508786baecfSMauro Carvalho Chehab 		case AF9033_TUNER_MXL5007T:
509786baecfSMauro Carvalho Chehab 		case AF9033_TUNER_TDA18218:
510786baecfSMauro Carvalho Chehab 			state->af9033_config[i].spec_inv = 1;
511786baecfSMauro Carvalho Chehab 			break;
512786baecfSMauro Carvalho Chehab 		default:
513786baecfSMauro Carvalho Chehab 			pr_info("%s: tuner ID=%02x not supported, please " \
514786baecfSMauro Carvalho Chehab 					"report!", KBUILD_MODNAME, tmp);
515786baecfSMauro Carvalho Chehab 		};
516786baecfSMauro Carvalho Chehab 
517786baecfSMauro Carvalho Chehab 		/* tuner IF frequency */
518786baecfSMauro Carvalho Chehab 		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
519786baecfSMauro Carvalho Chehab 		if (ret < 0)
520786baecfSMauro Carvalho Chehab 			goto err;
521786baecfSMauro Carvalho Chehab 
522786baecfSMauro Carvalho Chehab 		tmp16 = tmp;
523786baecfSMauro Carvalho Chehab 
524786baecfSMauro Carvalho Chehab 		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp);
525786baecfSMauro Carvalho Chehab 		if (ret < 0)
526786baecfSMauro Carvalho Chehab 			goto err;
527786baecfSMauro Carvalho Chehab 
528786baecfSMauro Carvalho Chehab 		tmp16 |= tmp << 8;
529786baecfSMauro Carvalho Chehab 
530786baecfSMauro Carvalho Chehab 		pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16);
531786baecfSMauro Carvalho Chehab 
532786baecfSMauro Carvalho Chehab 		eeprom_shift = 0x10; /* shift for the 2nd tuner params */
533786baecfSMauro Carvalho Chehab 	}
534786baecfSMauro Carvalho Chehab 
535786baecfSMauro Carvalho Chehab 	/* get demod clock */
536786baecfSMauro Carvalho Chehab 	ret = af9035_rd_reg(d, 0x00d800, &tmp);
537786baecfSMauro Carvalho Chehab 	if (ret < 0)
538786baecfSMauro Carvalho Chehab 		goto err;
539786baecfSMauro Carvalho Chehab 
540786baecfSMauro Carvalho Chehab 	tmp = (tmp >> 0) & 0x0f;
541786baecfSMauro Carvalho Chehab 
542786baecfSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
543786baecfSMauro Carvalho Chehab 		state->af9033_config[i].clock = clock_lut[tmp];
544786baecfSMauro Carvalho Chehab 
545786baecfSMauro Carvalho Chehab 	return 0;
546786baecfSMauro Carvalho Chehab 
547786baecfSMauro Carvalho Chehab err:
548786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
549786baecfSMauro Carvalho Chehab 
550786baecfSMauro Carvalho Chehab 	return ret;
551786baecfSMauro Carvalho Chehab }
552786baecfSMauro Carvalho Chehab 
553786baecfSMauro Carvalho Chehab static int af9035_read_config_it9135(struct dvb_usb_device *d)
554786baecfSMauro Carvalho Chehab {
555786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
556786baecfSMauro Carvalho Chehab 	int ret, i;
557786baecfSMauro Carvalho Chehab 	u8 tmp;
558786baecfSMauro Carvalho Chehab 
559786baecfSMauro Carvalho Chehab 	state->dual_mode = false;
560786baecfSMauro Carvalho Chehab 
561786baecfSMauro Carvalho Chehab 	/* get demod clock */
562786baecfSMauro Carvalho Chehab 	ret = af9035_rd_reg(d, 0x00d800, &tmp);
563786baecfSMauro Carvalho Chehab 	if (ret < 0)
564786baecfSMauro Carvalho Chehab 		goto err;
565786baecfSMauro Carvalho Chehab 
566786baecfSMauro Carvalho Chehab 	tmp = (tmp >> 0) & 0x0f;
567786baecfSMauro Carvalho Chehab 
568786baecfSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
569786baecfSMauro Carvalho Chehab 		state->af9033_config[i].clock = clock_lut_it9135[tmp];
570786baecfSMauro Carvalho Chehab 
571786baecfSMauro Carvalho Chehab 	return 0;
572786baecfSMauro Carvalho Chehab 
573786baecfSMauro Carvalho Chehab err:
574786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
575786baecfSMauro Carvalho Chehab 
576786baecfSMauro Carvalho Chehab 	return ret;
577786baecfSMauro Carvalho Chehab }
578786baecfSMauro Carvalho Chehab 
579786baecfSMauro Carvalho Chehab static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
580786baecfSMauro Carvalho Chehab 		int cmd, int arg)
581786baecfSMauro Carvalho Chehab {
582786baecfSMauro Carvalho Chehab 	int ret;
583786baecfSMauro Carvalho Chehab 
584786baecfSMauro Carvalho Chehab 	switch (cmd) {
585786baecfSMauro Carvalho Chehab 	case FC0011_FE_CALLBACK_POWER:
586786baecfSMauro Carvalho Chehab 		/* Tuner enable */
587786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1);
588786baecfSMauro Carvalho Chehab 		if (ret < 0)
589786baecfSMauro Carvalho Chehab 			goto err;
590786baecfSMauro Carvalho Chehab 
591786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1);
592786baecfSMauro Carvalho Chehab 		if (ret < 0)
593786baecfSMauro Carvalho Chehab 			goto err;
594786baecfSMauro Carvalho Chehab 
595786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1);
596786baecfSMauro Carvalho Chehab 		if (ret < 0)
597786baecfSMauro Carvalho Chehab 			goto err;
598786baecfSMauro Carvalho Chehab 
599786baecfSMauro Carvalho Chehab 		/* LED */
600786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1);
601786baecfSMauro Carvalho Chehab 		if (ret < 0)
602786baecfSMauro Carvalho Chehab 			goto err;
603786baecfSMauro Carvalho Chehab 
604786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1);
605786baecfSMauro Carvalho Chehab 		if (ret < 0)
606786baecfSMauro Carvalho Chehab 			goto err;
607786baecfSMauro Carvalho Chehab 
608786baecfSMauro Carvalho Chehab 		usleep_range(10000, 50000);
609786baecfSMauro Carvalho Chehab 		break;
610786baecfSMauro Carvalho Chehab 	case FC0011_FE_CALLBACK_RESET:
611786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0xd8e9, 1);
612786baecfSMauro Carvalho Chehab 		if (ret < 0)
613786baecfSMauro Carvalho Chehab 			goto err;
614786baecfSMauro Carvalho Chehab 
615786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0xd8e8, 1);
616786baecfSMauro Carvalho Chehab 		if (ret < 0)
617786baecfSMauro Carvalho Chehab 			goto err;
618786baecfSMauro Carvalho Chehab 
619786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0xd8e7, 1);
620786baecfSMauro Carvalho Chehab 		if (ret < 0)
621786baecfSMauro Carvalho Chehab 			goto err;
622786baecfSMauro Carvalho Chehab 
623786baecfSMauro Carvalho Chehab 		usleep_range(10000, 20000);
624786baecfSMauro Carvalho Chehab 
625786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0xd8e7, 0);
626786baecfSMauro Carvalho Chehab 		if (ret < 0)
627786baecfSMauro Carvalho Chehab 			goto err;
628786baecfSMauro Carvalho Chehab 
629786baecfSMauro Carvalho Chehab 		usleep_range(10000, 20000);
630786baecfSMauro Carvalho Chehab 		break;
631786baecfSMauro Carvalho Chehab 	default:
632786baecfSMauro Carvalho Chehab 		ret = -EINVAL;
633786baecfSMauro Carvalho Chehab 		goto err;
634786baecfSMauro Carvalho Chehab 	}
635786baecfSMauro Carvalho Chehab 
636786baecfSMauro Carvalho Chehab 	return 0;
637786baecfSMauro Carvalho Chehab 
638786baecfSMauro Carvalho Chehab err:
639786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
640786baecfSMauro Carvalho Chehab 
641786baecfSMauro Carvalho Chehab 	return ret;
642786baecfSMauro Carvalho Chehab }
643786baecfSMauro Carvalho Chehab 
644786baecfSMauro Carvalho Chehab static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
645786baecfSMauro Carvalho Chehab {
646786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
647786baecfSMauro Carvalho Chehab 
648786baecfSMauro Carvalho Chehab 	switch (state->af9033_config[0].tuner) {
649786baecfSMauro Carvalho Chehab 	case AF9033_TUNER_FC0011:
650786baecfSMauro Carvalho Chehab 		return af9035_fc0011_tuner_callback(d, cmd, arg);
651786baecfSMauro Carvalho Chehab 	default:
652786baecfSMauro Carvalho Chehab 		break;
653786baecfSMauro Carvalho Chehab 	}
654786baecfSMauro Carvalho Chehab 
655786baecfSMauro Carvalho Chehab 	return -ENODEV;
656786baecfSMauro Carvalho Chehab }
657786baecfSMauro Carvalho Chehab 
658786baecfSMauro Carvalho Chehab static int af9035_frontend_callback(void *adapter_priv, int component,
659786baecfSMauro Carvalho Chehab 				    int cmd, int arg)
660786baecfSMauro Carvalho Chehab {
661786baecfSMauro Carvalho Chehab 	struct i2c_adapter *adap = adapter_priv;
662786baecfSMauro Carvalho Chehab 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
663786baecfSMauro Carvalho Chehab 
664786baecfSMauro Carvalho Chehab 	switch (component) {
665786baecfSMauro Carvalho Chehab 	case DVB_FRONTEND_COMPONENT_TUNER:
666786baecfSMauro Carvalho Chehab 		return af9035_tuner_callback(d, cmd, arg);
667786baecfSMauro Carvalho Chehab 	default:
668786baecfSMauro Carvalho Chehab 		break;
669786baecfSMauro Carvalho Chehab 	}
670786baecfSMauro Carvalho Chehab 
671786baecfSMauro Carvalho Chehab 	return -EINVAL;
672786baecfSMauro Carvalho Chehab }
673786baecfSMauro Carvalho Chehab 
674786baecfSMauro Carvalho Chehab static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
675786baecfSMauro Carvalho Chehab {
676786baecfSMauro Carvalho Chehab 	struct state *state = adap_to_priv(adap);
677786baecfSMauro Carvalho Chehab 	struct dvb_usb_device *d = adap_to_d(adap);
678786baecfSMauro Carvalho Chehab 	int ret;
679786baecfSMauro Carvalho Chehab 
680786baecfSMauro Carvalho Chehab 	if (!state->af9033_config[adap->id].tuner) {
681786baecfSMauro Carvalho Chehab 		/* unsupported tuner */
682786baecfSMauro Carvalho Chehab 		ret = -ENODEV;
683786baecfSMauro Carvalho Chehab 		goto err;
684786baecfSMauro Carvalho Chehab 	}
685786baecfSMauro Carvalho Chehab 
686786baecfSMauro Carvalho Chehab 	if (adap->id == 0) {
687786baecfSMauro Carvalho Chehab 		state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
688786baecfSMauro Carvalho Chehab 		state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
689786baecfSMauro Carvalho Chehab 
690786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00417f,
691786baecfSMauro Carvalho Chehab 				state->af9033_config[1].i2c_addr);
692786baecfSMauro Carvalho Chehab 		if (ret < 0)
693786baecfSMauro Carvalho Chehab 			goto err;
694786baecfSMauro Carvalho Chehab 
695786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d81a,
696786baecfSMauro Carvalho Chehab 				state->dual_mode);
697786baecfSMauro Carvalho Chehab 		if (ret < 0)
698786baecfSMauro Carvalho Chehab 			goto err;
699786baecfSMauro Carvalho Chehab 	}
700786baecfSMauro Carvalho Chehab 
701786baecfSMauro Carvalho Chehab 	/* attach demodulator */
702786baecfSMauro Carvalho Chehab 	adap->fe[0] = dvb_attach(af9033_attach,
703786baecfSMauro Carvalho Chehab 			&state->af9033_config[adap->id], &d->i2c_adap);
704786baecfSMauro Carvalho Chehab 	if (adap->fe[0] == NULL) {
705786baecfSMauro Carvalho Chehab 		ret = -ENODEV;
706786baecfSMauro Carvalho Chehab 		goto err;
707786baecfSMauro Carvalho Chehab 	}
708786baecfSMauro Carvalho Chehab 
709786baecfSMauro Carvalho Chehab 	/* disable I2C-gate */
710786baecfSMauro Carvalho Chehab 	adap->fe[0]->ops.i2c_gate_ctrl = NULL;
711786baecfSMauro Carvalho Chehab 	adap->fe[0]->callback = af9035_frontend_callback;
712786baecfSMauro Carvalho Chehab 
713786baecfSMauro Carvalho Chehab 	return 0;
714786baecfSMauro Carvalho Chehab 
715786baecfSMauro Carvalho Chehab err:
716786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
717786baecfSMauro Carvalho Chehab 
718786baecfSMauro Carvalho Chehab 	return ret;
719786baecfSMauro Carvalho Chehab }
720786baecfSMauro Carvalho Chehab 
721786baecfSMauro Carvalho Chehab static struct tua9001_config af9035_tua9001_config = {
722786baecfSMauro Carvalho Chehab 	.i2c_addr = 0x60,
723786baecfSMauro Carvalho Chehab };
724786baecfSMauro Carvalho Chehab 
725786baecfSMauro Carvalho Chehab static const struct fc0011_config af9035_fc0011_config = {
726786baecfSMauro Carvalho Chehab 	.i2c_address = 0x60,
727786baecfSMauro Carvalho Chehab };
728786baecfSMauro Carvalho Chehab 
729786baecfSMauro Carvalho Chehab static struct mxl5007t_config af9035_mxl5007t_config = {
730786baecfSMauro Carvalho Chehab 	.xtal_freq_hz = MxL_XTAL_24_MHZ,
731786baecfSMauro Carvalho Chehab 	.if_freq_hz = MxL_IF_4_57_MHZ,
732786baecfSMauro Carvalho Chehab 	.invert_if = 0,
733786baecfSMauro Carvalho Chehab 	.loop_thru_enable = 0,
734786baecfSMauro Carvalho Chehab 	.clk_out_enable = 0,
735786baecfSMauro Carvalho Chehab 	.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
736786baecfSMauro Carvalho Chehab };
737786baecfSMauro Carvalho Chehab 
738786baecfSMauro Carvalho Chehab static struct tda18218_config af9035_tda18218_config = {
739786baecfSMauro Carvalho Chehab 	.i2c_address = 0x60,
740786baecfSMauro Carvalho Chehab 	.i2c_wr_max = 21,
741786baecfSMauro Carvalho Chehab };
742786baecfSMauro Carvalho Chehab 
743786baecfSMauro Carvalho Chehab static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
744786baecfSMauro Carvalho Chehab {
745786baecfSMauro Carvalho Chehab 	struct state *state = adap_to_priv(adap);
746786baecfSMauro Carvalho Chehab 	struct dvb_usb_device *d = adap_to_d(adap);
747786baecfSMauro Carvalho Chehab 	int ret;
748786baecfSMauro Carvalho Chehab 	struct dvb_frontend *fe;
749786baecfSMauro Carvalho Chehab 
750786baecfSMauro Carvalho Chehab 	switch (state->af9033_config[adap->id].tuner) {
751786baecfSMauro Carvalho Chehab 	case AF9033_TUNER_TUA9001:
752786baecfSMauro Carvalho Chehab 		/* AF9035 gpiot3 = TUA9001 RESETN
753786baecfSMauro Carvalho Chehab 		   AF9035 gpiot2 = TUA9001 RXEN */
754786baecfSMauro Carvalho Chehab 
755786baecfSMauro Carvalho Chehab 		/* configure gpiot2 and gpiot2 as output */
756786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01);
757786baecfSMauro Carvalho Chehab 		if (ret < 0)
758786baecfSMauro Carvalho Chehab 			goto err;
759786baecfSMauro Carvalho Chehab 
760786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01);
761786baecfSMauro Carvalho Chehab 		if (ret < 0)
762786baecfSMauro Carvalho Chehab 			goto err;
763786baecfSMauro Carvalho Chehab 
764786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01);
765786baecfSMauro Carvalho Chehab 		if (ret < 0)
766786baecfSMauro Carvalho Chehab 			goto err;
767786baecfSMauro Carvalho Chehab 
768786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01);
769786baecfSMauro Carvalho Chehab 		if (ret < 0)
770786baecfSMauro Carvalho Chehab 			goto err;
771786baecfSMauro Carvalho Chehab 
772786baecfSMauro Carvalho Chehab 		/* reset tuner */
773786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8e7, 0x00, 0x01);
774786baecfSMauro Carvalho Chehab 		if (ret < 0)
775786baecfSMauro Carvalho Chehab 			goto err;
776786baecfSMauro Carvalho Chehab 
777786baecfSMauro Carvalho Chehab 		usleep_range(2000, 20000);
778786baecfSMauro Carvalho Chehab 
779786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8e7, 0x01, 0x01);
780786baecfSMauro Carvalho Chehab 		if (ret < 0)
781786baecfSMauro Carvalho Chehab 			goto err;
782786baecfSMauro Carvalho Chehab 
783786baecfSMauro Carvalho Chehab 		/* activate tuner RX */
784786baecfSMauro Carvalho Chehab 		/* TODO: use callback for TUA9001 RXEN */
785786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, 0x00d8eb, 0x01, 0x01);
786786baecfSMauro Carvalho Chehab 		if (ret < 0)
787786baecfSMauro Carvalho Chehab 			goto err;
788786baecfSMauro Carvalho Chehab 
789786baecfSMauro Carvalho Chehab 		/* attach tuner */
790786baecfSMauro Carvalho Chehab 		fe = dvb_attach(tua9001_attach, adap->fe[0],
791786baecfSMauro Carvalho Chehab 				&d->i2c_adap, &af9035_tua9001_config);
792786baecfSMauro Carvalho Chehab 		break;
793786baecfSMauro Carvalho Chehab 	case AF9033_TUNER_FC0011:
794786baecfSMauro Carvalho Chehab 		fe = dvb_attach(fc0011_attach, adap->fe[0],
795786baecfSMauro Carvalho Chehab 				&d->i2c_adap, &af9035_fc0011_config);
796786baecfSMauro Carvalho Chehab 		break;
797786baecfSMauro Carvalho Chehab 	case AF9033_TUNER_MXL5007T:
798786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8e0, 1);
799786baecfSMauro Carvalho Chehab 		if (ret < 0)
800786baecfSMauro Carvalho Chehab 			goto err;
801786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8e1, 1);
802786baecfSMauro Carvalho Chehab 		if (ret < 0)
803786baecfSMauro Carvalho Chehab 			goto err;
804786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8df, 0);
805786baecfSMauro Carvalho Chehab 		if (ret < 0)
806786baecfSMauro Carvalho Chehab 			goto err;
807786baecfSMauro Carvalho Chehab 
808786baecfSMauro Carvalho Chehab 		msleep(30);
809786baecfSMauro Carvalho Chehab 
810786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8df, 1);
811786baecfSMauro Carvalho Chehab 		if (ret < 0)
812786baecfSMauro Carvalho Chehab 			goto err;
813786baecfSMauro Carvalho Chehab 
814786baecfSMauro Carvalho Chehab 		msleep(300);
815786baecfSMauro Carvalho Chehab 
816786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8c0, 1);
817786baecfSMauro Carvalho Chehab 		if (ret < 0)
818786baecfSMauro Carvalho Chehab 			goto err;
819786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8c1, 1);
820786baecfSMauro Carvalho Chehab 		if (ret < 0)
821786baecfSMauro Carvalho Chehab 			goto err;
822786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8bf, 0);
823786baecfSMauro Carvalho Chehab 		if (ret < 0)
824786baecfSMauro Carvalho Chehab 			goto err;
825786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8b4, 1);
826786baecfSMauro Carvalho Chehab 		if (ret < 0)
827786baecfSMauro Carvalho Chehab 			goto err;
828786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8b5, 1);
829786baecfSMauro Carvalho Chehab 		if (ret < 0)
830786baecfSMauro Carvalho Chehab 			goto err;
831786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg(d, 0x00d8b3, 1);
832786baecfSMauro Carvalho Chehab 		if (ret < 0)
833786baecfSMauro Carvalho Chehab 			goto err;
834786baecfSMauro Carvalho Chehab 
835786baecfSMauro Carvalho Chehab 		/* attach tuner */
836786baecfSMauro Carvalho Chehab 		fe = dvb_attach(mxl5007t_attach, adap->fe[0],
837786baecfSMauro Carvalho Chehab 				&d->i2c_adap, 0x60, &af9035_mxl5007t_config);
838786baecfSMauro Carvalho Chehab 		break;
839786baecfSMauro Carvalho Chehab 	case AF9033_TUNER_TDA18218:
840786baecfSMauro Carvalho Chehab 		/* attach tuner */
841786baecfSMauro Carvalho Chehab 		fe = dvb_attach(tda18218_attach, adap->fe[0],
842786baecfSMauro Carvalho Chehab 				&d->i2c_adap, &af9035_tda18218_config);
843786baecfSMauro Carvalho Chehab 		break;
844786baecfSMauro Carvalho Chehab 	default:
845786baecfSMauro Carvalho Chehab 		fe = NULL;
846786baecfSMauro Carvalho Chehab 	}
847786baecfSMauro Carvalho Chehab 
848786baecfSMauro Carvalho Chehab 	if (fe == NULL) {
849786baecfSMauro Carvalho Chehab 		ret = -ENODEV;
850786baecfSMauro Carvalho Chehab 		goto err;
851786baecfSMauro Carvalho Chehab 	}
852786baecfSMauro Carvalho Chehab 
853786baecfSMauro Carvalho Chehab 	return 0;
854786baecfSMauro Carvalho Chehab 
855786baecfSMauro Carvalho Chehab err:
856786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
857786baecfSMauro Carvalho Chehab 
858786baecfSMauro Carvalho Chehab 	return ret;
859786baecfSMauro Carvalho Chehab }
860786baecfSMauro Carvalho Chehab 
861786baecfSMauro Carvalho Chehab static int af9035_init(struct dvb_usb_device *d)
862786baecfSMauro Carvalho Chehab {
863786baecfSMauro Carvalho Chehab 	struct state *state = d_to_priv(d);
864786baecfSMauro Carvalho Chehab 	int ret, i;
865786baecfSMauro Carvalho Chehab 	u16 frame_size = 87 * 188 / 4;
866786baecfSMauro Carvalho Chehab 	u8  packet_size = 512 / 4;
867786baecfSMauro Carvalho Chehab 	struct reg_val_mask tab[] = {
868786baecfSMauro Carvalho Chehab 		{ 0x80f99d, 0x01, 0x01 },
869786baecfSMauro Carvalho Chehab 		{ 0x80f9a4, 0x01, 0x01 },
870786baecfSMauro Carvalho Chehab 		{ 0x00dd11, 0x00, 0x20 },
871786baecfSMauro Carvalho Chehab 		{ 0x00dd11, 0x00, 0x40 },
872786baecfSMauro Carvalho Chehab 		{ 0x00dd13, 0x00, 0x20 },
873786baecfSMauro Carvalho Chehab 		{ 0x00dd13, 0x00, 0x40 },
874786baecfSMauro Carvalho Chehab 		{ 0x00dd11, 0x20, 0x20 },
875786baecfSMauro Carvalho Chehab 		{ 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
876786baecfSMauro Carvalho Chehab 		{ 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
877786baecfSMauro Carvalho Chehab 		{ 0x00dd0c, packet_size, 0xff},
878786baecfSMauro Carvalho Chehab 		{ 0x00dd11, state->dual_mode << 6, 0x40 },
879786baecfSMauro Carvalho Chehab 		{ 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
880786baecfSMauro Carvalho Chehab 		{ 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
881786baecfSMauro Carvalho Chehab 		{ 0x00dd0d, packet_size, 0xff },
882786baecfSMauro Carvalho Chehab 		{ 0x80f9a3, 0x00, 0x01 },
883786baecfSMauro Carvalho Chehab 		{ 0x80f9cd, 0x00, 0x01 },
884786baecfSMauro Carvalho Chehab 		{ 0x80f99d, 0x00, 0x01 },
885786baecfSMauro Carvalho Chehab 		{ 0x80f9a4, 0x00, 0x01 },
886786baecfSMauro Carvalho Chehab 	};
887786baecfSMauro Carvalho Chehab 
888786baecfSMauro Carvalho Chehab 	pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n",
889786baecfSMauro Carvalho Chehab 		__func__, d->udev->speed, frame_size, packet_size);
890786baecfSMauro Carvalho Chehab 
891786baecfSMauro Carvalho Chehab 	/* init endpoints */
892786baecfSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(tab); i++) {
893786baecfSMauro Carvalho Chehab 		ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
894786baecfSMauro Carvalho Chehab 				tab[i].mask);
895786baecfSMauro Carvalho Chehab 		if (ret < 0)
896786baecfSMauro Carvalho Chehab 			goto err;
897786baecfSMauro Carvalho Chehab 	}
898786baecfSMauro Carvalho Chehab 
899786baecfSMauro Carvalho Chehab 	return 0;
900786baecfSMauro Carvalho Chehab 
901786baecfSMauro Carvalho Chehab err:
902786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
903786baecfSMauro Carvalho Chehab 
904786baecfSMauro Carvalho Chehab 	return ret;
905786baecfSMauro Carvalho Chehab }
906786baecfSMauro Carvalho Chehab 
907786baecfSMauro Carvalho Chehab static int af9035_rc_query(struct dvb_usb_device *d)
908786baecfSMauro Carvalho Chehab {
909786baecfSMauro Carvalho Chehab 	unsigned int key;
910786baecfSMauro Carvalho Chehab 	unsigned char b[4];
911786baecfSMauro Carvalho Chehab 	int ret;
912786baecfSMauro Carvalho Chehab 	struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
913786baecfSMauro Carvalho Chehab 
914786baecfSMauro Carvalho Chehab 	ret = af9035_ctrl_msg(d, &req);
915786baecfSMauro Carvalho Chehab 	if (ret < 0)
916786baecfSMauro Carvalho Chehab 		goto err;
917786baecfSMauro Carvalho Chehab 
918786baecfSMauro Carvalho Chehab 	if ((b[2] + b[3]) == 0xff) {
919786baecfSMauro Carvalho Chehab 		if ((b[0] + b[1]) == 0xff) {
920786baecfSMauro Carvalho Chehab 			/* NEC */
921786baecfSMauro Carvalho Chehab 			key = b[0] << 8 | b[2];
922786baecfSMauro Carvalho Chehab 		} else {
923786baecfSMauro Carvalho Chehab 			/* ext. NEC */
924786baecfSMauro Carvalho Chehab 			key = b[0] << 16 | b[1] << 8 | b[2];
925786baecfSMauro Carvalho Chehab 		}
926786baecfSMauro Carvalho Chehab 	} else {
927786baecfSMauro Carvalho Chehab 		key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
928786baecfSMauro Carvalho Chehab 	}
929786baecfSMauro Carvalho Chehab 
930786baecfSMauro Carvalho Chehab 	rc_keydown(d->rc_dev, key, 0);
931786baecfSMauro Carvalho Chehab 
932786baecfSMauro Carvalho Chehab err:
933786baecfSMauro Carvalho Chehab 	/* ignore errors */
934786baecfSMauro Carvalho Chehab 	return 0;
935786baecfSMauro Carvalho Chehab }
936786baecfSMauro Carvalho Chehab 
937786baecfSMauro Carvalho Chehab static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
938786baecfSMauro Carvalho Chehab {
939786baecfSMauro Carvalho Chehab 	int ret;
940786baecfSMauro Carvalho Chehab 	u8 tmp;
941786baecfSMauro Carvalho Chehab 
942786baecfSMauro Carvalho Chehab 	ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
943786baecfSMauro Carvalho Chehab 	if (ret < 0)
944786baecfSMauro Carvalho Chehab 		goto err;
945786baecfSMauro Carvalho Chehab 
946786baecfSMauro Carvalho Chehab 	pr_debug("%s: ir_mode=%02x\n", __func__, tmp);
947786baecfSMauro Carvalho Chehab 
948786baecfSMauro Carvalho Chehab 	/* don't activate rc if in HID mode or if not available */
949786baecfSMauro Carvalho Chehab 	if (tmp == 5) {
950786baecfSMauro Carvalho Chehab 		ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
951786baecfSMauro Carvalho Chehab 		if (ret < 0)
952786baecfSMauro Carvalho Chehab 			goto err;
953786baecfSMauro Carvalho Chehab 
954786baecfSMauro Carvalho Chehab 		pr_debug("%s: ir_type=%02x\n", __func__, tmp);
955786baecfSMauro Carvalho Chehab 
956786baecfSMauro Carvalho Chehab 		switch (tmp) {
957786baecfSMauro Carvalho Chehab 		case 0: /* NEC */
958786baecfSMauro Carvalho Chehab 		default:
959786baecfSMauro Carvalho Chehab 			rc->allowed_protos = RC_TYPE_NEC;
960786baecfSMauro Carvalho Chehab 			break;
961786baecfSMauro Carvalho Chehab 		case 1: /* RC6 */
962786baecfSMauro Carvalho Chehab 			rc->allowed_protos = RC_TYPE_RC6;
963786baecfSMauro Carvalho Chehab 			break;
964786baecfSMauro Carvalho Chehab 		}
965786baecfSMauro Carvalho Chehab 
966786baecfSMauro Carvalho Chehab 		rc->query = af9035_rc_query;
967786baecfSMauro Carvalho Chehab 		rc->interval = 500;
968786baecfSMauro Carvalho Chehab 
969786baecfSMauro Carvalho Chehab 		/* load empty to enable rc */
970786baecfSMauro Carvalho Chehab 		if (!rc->map_name)
971786baecfSMauro Carvalho Chehab 			rc->map_name = RC_MAP_EMPTY;
972786baecfSMauro Carvalho Chehab 	}
973786baecfSMauro Carvalho Chehab 
974786baecfSMauro Carvalho Chehab 	return 0;
975786baecfSMauro Carvalho Chehab 
976786baecfSMauro Carvalho Chehab err:
977786baecfSMauro Carvalho Chehab 	pr_debug("%s: failed=%d\n", __func__, ret);
978786baecfSMauro Carvalho Chehab 
979786baecfSMauro Carvalho Chehab 	return ret;
980786baecfSMauro Carvalho Chehab }
981786baecfSMauro Carvalho Chehab 
982786baecfSMauro Carvalho Chehab /* interface 0 is used by DVB-T receiver and
983786baecfSMauro Carvalho Chehab    interface 1 is for remote controller (HID) */
984786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties af9035_props = {
985786baecfSMauro Carvalho Chehab 	.driver_name = KBUILD_MODNAME,
986786baecfSMauro Carvalho Chehab 	.owner = THIS_MODULE,
987786baecfSMauro Carvalho Chehab 	.adapter_nr = adapter_nr,
988786baecfSMauro Carvalho Chehab 	.size_of_priv = sizeof(struct state),
989786baecfSMauro Carvalho Chehab 
990786baecfSMauro Carvalho Chehab 	.generic_bulk_ctrl_endpoint = 0x02,
991786baecfSMauro Carvalho Chehab 	.generic_bulk_ctrl_endpoint_response = 0x81,
992786baecfSMauro Carvalho Chehab 
993786baecfSMauro Carvalho Chehab 	.identify_state = af9035_identify_state,
994786baecfSMauro Carvalho Chehab 	.firmware = "dvb-usb-af9035-02.fw",
995786baecfSMauro Carvalho Chehab 	.download_firmware = af9035_download_firmware,
996786baecfSMauro Carvalho Chehab 
997786baecfSMauro Carvalho Chehab 	.i2c_algo = &af9035_i2c_algo,
998786baecfSMauro Carvalho Chehab 	.read_config = af9035_read_config,
999786baecfSMauro Carvalho Chehab 	.frontend_attach = af9035_frontend_attach,
1000786baecfSMauro Carvalho Chehab 	.tuner_attach = af9035_tuner_attach,
1001786baecfSMauro Carvalho Chehab 	.init = af9035_init,
1002786baecfSMauro Carvalho Chehab 	.get_rc_config = af9035_get_rc_config,
1003786baecfSMauro Carvalho Chehab 
1004786baecfSMauro Carvalho Chehab 	.num_adapters = 1,
1005786baecfSMauro Carvalho Chehab 	.adapter = {
1006786baecfSMauro Carvalho Chehab 		{
1007786baecfSMauro Carvalho Chehab 			.stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
1008786baecfSMauro Carvalho Chehab 		}, {
1009786baecfSMauro Carvalho Chehab 			.stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
1010786baecfSMauro Carvalho Chehab 		},
1011786baecfSMauro Carvalho Chehab 	},
1012786baecfSMauro Carvalho Chehab };
1013786baecfSMauro Carvalho Chehab 
1014786baecfSMauro Carvalho Chehab static const struct dvb_usb_device_properties it9135_props = {
1015786baecfSMauro Carvalho Chehab 	.driver_name = KBUILD_MODNAME,
1016786baecfSMauro Carvalho Chehab 	.owner = THIS_MODULE,
1017786baecfSMauro Carvalho Chehab 	.adapter_nr = adapter_nr,
1018786baecfSMauro Carvalho Chehab 	.size_of_priv = sizeof(struct state),
1019786baecfSMauro Carvalho Chehab 
1020786baecfSMauro Carvalho Chehab 	.generic_bulk_ctrl_endpoint = 0x02,
1021786baecfSMauro Carvalho Chehab 	.generic_bulk_ctrl_endpoint_response = 0x81,
1022786baecfSMauro Carvalho Chehab 
1023786baecfSMauro Carvalho Chehab 	.identify_state = af9035_identify_state,
1024786baecfSMauro Carvalho Chehab 	.firmware = "dvb-usb-it9135-01.fw",
1025786baecfSMauro Carvalho Chehab 	.download_firmware = af9035_download_firmware_it9135,
1026786baecfSMauro Carvalho Chehab 
1027786baecfSMauro Carvalho Chehab 	.i2c_algo = &af9035_i2c_algo,
1028786baecfSMauro Carvalho Chehab 	.read_config = af9035_read_config_it9135,
1029786baecfSMauro Carvalho Chehab 	.frontend_attach = af9035_frontend_attach,
1030786baecfSMauro Carvalho Chehab 	.tuner_attach = af9035_tuner_attach,
1031786baecfSMauro Carvalho Chehab 	.init = af9035_init,
1032786baecfSMauro Carvalho Chehab 	.get_rc_config = af9035_get_rc_config,
1033786baecfSMauro Carvalho Chehab 
1034786baecfSMauro Carvalho Chehab 	.num_adapters = 1,
1035786baecfSMauro Carvalho Chehab 	.adapter = {
1036786baecfSMauro Carvalho Chehab 		{
1037786baecfSMauro Carvalho Chehab 			.stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
1038786baecfSMauro Carvalho Chehab 		}, {
1039786baecfSMauro Carvalho Chehab 			.stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
1040786baecfSMauro Carvalho Chehab 		},
1041786baecfSMauro Carvalho Chehab 	},
1042786baecfSMauro Carvalho Chehab };
1043786baecfSMauro Carvalho Chehab 
1044786baecfSMauro Carvalho Chehab static const struct usb_device_id af9035_id_table[] = {
1045786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035,
1046786baecfSMauro Carvalho Chehab 		&af9035_props, "Afatech AF9035 reference design", NULL) },
1047786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000,
1048786baecfSMauro Carvalho Chehab 		&af9035_props, "Afatech AF9035 reference design", NULL) },
1049786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001,
1050786baecfSMauro Carvalho Chehab 		&af9035_props, "Afatech AF9035 reference design", NULL) },
1051786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002,
1052786baecfSMauro Carvalho Chehab 		&af9035_props, "Afatech AF9035 reference design", NULL) },
1053786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003,
1054786baecfSMauro Carvalho Chehab 		&af9035_props, "Afatech AF9035 reference design", NULL) },
1055786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK,
1056786baecfSMauro Carvalho Chehab 		&af9035_props, "TerraTec Cinergy T Stick", NULL) },
1057786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835,
1058786baecfSMauro Carvalho Chehab 		&af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
1059786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835,
1060786baecfSMauro Carvalho Chehab 		&af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
1061786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867,
1062786baecfSMauro Carvalho Chehab 		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
1063786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867,
1064786baecfSMauro Carvalho Chehab 		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
1065786baecfSMauro Carvalho Chehab 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR,
1066786baecfSMauro Carvalho Chehab 		&af9035_props, "AVerMedia Twinstar (A825)", NULL) },
1067786baecfSMauro Carvalho Chehab 	{ }
1068786baecfSMauro Carvalho Chehab };
1069786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, af9035_id_table);
1070786baecfSMauro Carvalho Chehab 
1071786baecfSMauro Carvalho Chehab static struct usb_driver af9035_usb_driver = {
1072786baecfSMauro Carvalho Chehab 	.name = KBUILD_MODNAME,
1073786baecfSMauro Carvalho Chehab 	.id_table = af9035_id_table,
1074786baecfSMauro Carvalho Chehab 	.probe = dvb_usbv2_probe,
1075786baecfSMauro Carvalho Chehab 	.disconnect = dvb_usbv2_disconnect,
1076786baecfSMauro Carvalho Chehab 	.suspend = dvb_usbv2_suspend,
1077786baecfSMauro Carvalho Chehab 	.resume = dvb_usbv2_resume,
1078786baecfSMauro Carvalho Chehab 	.no_dynamic_id = 1,
1079786baecfSMauro Carvalho Chehab 	.soft_unbind = 1,
1080786baecfSMauro Carvalho Chehab };
1081786baecfSMauro Carvalho Chehab 
1082786baecfSMauro Carvalho Chehab module_usb_driver(af9035_usb_driver);
1083786baecfSMauro Carvalho Chehab 
1084786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
1085786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9035 driver");
1086786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL");
1087