18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Afatech AF9035 DVB USB driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
68c2ecf20Sopenharmony_ci * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "af9035.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */
128c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE  64
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic u16 af9035_checksum(const u8 *buf, size_t len)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	size_t i;
198c2ecf20Sopenharmony_ci	u16 checksum = 0;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	for (i = 1; i < len; i++) {
228c2ecf20Sopenharmony_ci		if (i % 2)
238c2ecf20Sopenharmony_ci			checksum += buf[i] << 8;
248c2ecf20Sopenharmony_ci		else
258c2ecf20Sopenharmony_ci			checksum += buf[i];
268c2ecf20Sopenharmony_ci	}
278c2ecf20Sopenharmony_ci	checksum = ~checksum;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	return checksum;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci#define REQ_HDR_LEN 4 /* send header size */
358c2ecf20Sopenharmony_ci#define ACK_HDR_LEN 3 /* rece header size */
368c2ecf20Sopenharmony_ci#define CHECKSUM_LEN 2
378c2ecf20Sopenharmony_ci#define USB_TIMEOUT 2000
388c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
398c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
408c2ecf20Sopenharmony_ci	int ret, wlen, rlen;
418c2ecf20Sopenharmony_ci	u16 checksum, tmp_checksum;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	mutex_lock(&d->usb_mutex);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	/* buffer overflow check */
468c2ecf20Sopenharmony_ci	if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
478c2ecf20Sopenharmony_ci			req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
488c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "too much data wlen=%d rlen=%d\n",
498c2ecf20Sopenharmony_ci			req->wlen, req->rlen);
508c2ecf20Sopenharmony_ci		ret = -EINVAL;
518c2ecf20Sopenharmony_ci		goto exit;
528c2ecf20Sopenharmony_ci	}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
558c2ecf20Sopenharmony_ci	state->buf[1] = req->mbox;
568c2ecf20Sopenharmony_ci	state->buf[2] = req->cmd;
578c2ecf20Sopenharmony_ci	state->buf[3] = state->seq++;
588c2ecf20Sopenharmony_ci	memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN;
618c2ecf20Sopenharmony_ci	rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	/* calc and add checksum */
648c2ecf20Sopenharmony_ci	checksum = af9035_checksum(state->buf, state->buf[0] - 1);
658c2ecf20Sopenharmony_ci	state->buf[state->buf[0] - 1] = (checksum >> 8);
668c2ecf20Sopenharmony_ci	state->buf[state->buf[0] - 0] = (checksum & 0xff);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* no ack for these packets */
698c2ecf20Sopenharmony_ci	if (req->cmd == CMD_FW_DL)
708c2ecf20Sopenharmony_ci		rlen = 0;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	ret = dvb_usbv2_generic_rw_locked(d,
738c2ecf20Sopenharmony_ci			state->buf, wlen, state->buf, rlen);
748c2ecf20Sopenharmony_ci	if (ret)
758c2ecf20Sopenharmony_ci		goto exit;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* no ack for those packets */
788c2ecf20Sopenharmony_ci	if (req->cmd == CMD_FW_DL)
798c2ecf20Sopenharmony_ci		goto exit;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/* verify checksum */
828c2ecf20Sopenharmony_ci	checksum = af9035_checksum(state->buf, rlen - 2);
838c2ecf20Sopenharmony_ci	tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1];
848c2ecf20Sopenharmony_ci	if (tmp_checksum != checksum) {
858c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "command=%02x checksum mismatch (%04x != %04x)\n",
868c2ecf20Sopenharmony_ci			req->cmd, tmp_checksum, checksum);
878c2ecf20Sopenharmony_ci		ret = -EIO;
888c2ecf20Sopenharmony_ci		goto exit;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* check status */
928c2ecf20Sopenharmony_ci	if (state->buf[2]) {
938c2ecf20Sopenharmony_ci		/* fw returns status 1 when IR code was not received */
948c2ecf20Sopenharmony_ci		if (req->cmd == CMD_IR_GET || state->buf[2] == 1) {
958c2ecf20Sopenharmony_ci			ret = 1;
968c2ecf20Sopenharmony_ci			goto exit;
978c2ecf20Sopenharmony_ci		}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "command=%02x failed fw error=%d\n",
1008c2ecf20Sopenharmony_ci			req->cmd, state->buf[2]);
1018c2ecf20Sopenharmony_ci		ret = -EIO;
1028c2ecf20Sopenharmony_ci		goto exit;
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	/* read request, copy returned data to return buf */
1068c2ecf20Sopenharmony_ci	if (req->rlen)
1078c2ecf20Sopenharmony_ci		memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen);
1088c2ecf20Sopenharmony_ciexit:
1098c2ecf20Sopenharmony_ci	mutex_unlock(&d->usb_mutex);
1108c2ecf20Sopenharmony_ci	return ret;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/* write multiple registers */
1148c2ecf20Sopenharmony_cistatic int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
1178c2ecf20Sopenharmony_ci	u8 wbuf[MAX_XFER_SIZE];
1188c2ecf20Sopenharmony_ci	u8 mbox = (reg >> 16) & 0xff;
1198c2ecf20Sopenharmony_ci	struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL };
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	if (6 + len > sizeof(wbuf)) {
1228c2ecf20Sopenharmony_ci		dev_warn(&intf->dev, "i2c wr: len=%d is too big!\n", len);
1238c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	wbuf[0] = len;
1278c2ecf20Sopenharmony_ci	wbuf[1] = 2;
1288c2ecf20Sopenharmony_ci	wbuf[2] = 0;
1298c2ecf20Sopenharmony_ci	wbuf[3] = 0;
1308c2ecf20Sopenharmony_ci	wbuf[4] = (reg >> 8) & 0xff;
1318c2ecf20Sopenharmony_ci	wbuf[5] = (reg >> 0) & 0xff;
1328c2ecf20Sopenharmony_ci	memcpy(&wbuf[6], val, len);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return af9035_ctrl_msg(d, &req);
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci/* read multiple registers */
1388c2ecf20Sopenharmony_cistatic int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff };
1418c2ecf20Sopenharmony_ci	u8 mbox = (reg >> 16) & 0xff;
1428c2ecf20Sopenharmony_ci	struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val };
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	return af9035_ctrl_msg(d, &req);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci/* write single register */
1488c2ecf20Sopenharmony_cistatic int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	return af9035_wr_regs(d, reg, &val, 1);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* read single register */
1548c2ecf20Sopenharmony_cistatic int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	return af9035_rd_regs(d, reg, val, 1);
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* write single register with mask */
1608c2ecf20Sopenharmony_cistatic int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
1618c2ecf20Sopenharmony_ci		u8 mask)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	int ret;
1648c2ecf20Sopenharmony_ci	u8 tmp;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	/* no need for read if whole reg is written */
1678c2ecf20Sopenharmony_ci	if (mask != 0xff) {
1688c2ecf20Sopenharmony_ci		ret = af9035_rd_regs(d, reg, &tmp, 1);
1698c2ecf20Sopenharmony_ci		if (ret)
1708c2ecf20Sopenharmony_ci			return ret;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci		val &= mask;
1738c2ecf20Sopenharmony_ci		tmp &= ~mask;
1748c2ecf20Sopenharmony_ci		val |= tmp;
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	return af9035_wr_regs(d, reg, &val, 1);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
1818c2ecf20Sopenharmony_ci		u8 addr, void *platform_data, struct i2c_adapter *adapter)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	int ret, num;
1848c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
1858c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
1868c2ecf20Sopenharmony_ci	struct i2c_client *client;
1878c2ecf20Sopenharmony_ci	struct i2c_board_info board_info = {
1888c2ecf20Sopenharmony_ci		.addr = addr,
1898c2ecf20Sopenharmony_ci		.platform_data = platform_data,
1908c2ecf20Sopenharmony_ci	};
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	strscpy(board_info.type, type, I2C_NAME_SIZE);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	/* find first free client */
1958c2ecf20Sopenharmony_ci	for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) {
1968c2ecf20Sopenharmony_ci		if (state->i2c_client[num] == NULL)
1978c2ecf20Sopenharmony_ci			break;
1988c2ecf20Sopenharmony_ci	}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "num=%d\n", num);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if (num == AF9035_I2C_CLIENT_MAX) {
2038c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "I2C client out of index\n");
2048c2ecf20Sopenharmony_ci		ret = -ENODEV;
2058c2ecf20Sopenharmony_ci		goto err;
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	request_module("%s", board_info.type);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* register I2C device */
2118c2ecf20Sopenharmony_ci	client = i2c_new_client_device(adapter, &board_info);
2128c2ecf20Sopenharmony_ci	if (!i2c_client_has_driver(client)) {
2138c2ecf20Sopenharmony_ci		ret = -ENODEV;
2148c2ecf20Sopenharmony_ci		goto err;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* increase I2C driver usage count */
2188c2ecf20Sopenharmony_ci	if (!try_module_get(client->dev.driver->owner)) {
2198c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
2208c2ecf20Sopenharmony_ci		ret = -ENODEV;
2218c2ecf20Sopenharmony_ci		goto err;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	state->i2c_client[num] = client;
2258c2ecf20Sopenharmony_ci	return 0;
2268c2ecf20Sopenharmony_cierr:
2278c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
2288c2ecf20Sopenharmony_ci	return ret;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic void af9035_del_i2c_dev(struct dvb_usb_device *d)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	int num;
2348c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
2358c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
2368c2ecf20Sopenharmony_ci	struct i2c_client *client;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* find last used client */
2398c2ecf20Sopenharmony_ci	num = AF9035_I2C_CLIENT_MAX;
2408c2ecf20Sopenharmony_ci	while (num--) {
2418c2ecf20Sopenharmony_ci		if (state->i2c_client[num] != NULL)
2428c2ecf20Sopenharmony_ci			break;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "num=%d\n", num);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (num == -1) {
2488c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "I2C client out of index\n");
2498c2ecf20Sopenharmony_ci		goto err;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	client = state->i2c_client[num];
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* decrease I2C driver usage count */
2558c2ecf20Sopenharmony_ci	module_put(client->dev.driver->owner);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* unregister I2C device */
2588c2ecf20Sopenharmony_ci	i2c_unregister_device(client);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	state->i2c_client[num] = NULL;
2618c2ecf20Sopenharmony_ci	return;
2628c2ecf20Sopenharmony_cierr:
2638c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed\n");
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic int af9035_i2c_master_xfer(struct i2c_adapter *adap,
2678c2ecf20Sopenharmony_ci		struct i2c_msg msg[], int num)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
2708c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
2718c2ecf20Sopenharmony_ci	int ret;
2728c2ecf20Sopenharmony_ci	u32 reg;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
2758c2ecf20Sopenharmony_ci		return -EAGAIN;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	/*
2788c2ecf20Sopenharmony_ci	 * AF9035 I2C sub header is 5 bytes long. Meaning of those bytes are:
2798c2ecf20Sopenharmony_ci	 * 0: data len
2808c2ecf20Sopenharmony_ci	 * 1: I2C addr << 1
2818c2ecf20Sopenharmony_ci	 * 2: reg addr len
2828c2ecf20Sopenharmony_ci	 *    byte 3 and 4 can be used as reg addr
2838c2ecf20Sopenharmony_ci	 * 3: reg addr MSB
2848c2ecf20Sopenharmony_ci	 *    used when reg addr len is set to 2
2858c2ecf20Sopenharmony_ci	 * 4: reg addr LSB
2868c2ecf20Sopenharmony_ci	 *    used when reg addr len is set to 1 or 2
2878c2ecf20Sopenharmony_ci	 *
2888c2ecf20Sopenharmony_ci	 * For the simplify we do not use register addr at all.
2898c2ecf20Sopenharmony_ci	 * NOTE: As a firmware knows tuner type there is very small possibility
2908c2ecf20Sopenharmony_ci	 * there could be some tuner I2C hacks done by firmware and this may
2918c2ecf20Sopenharmony_ci	 * lead problems if firmware expects those bytes are used.
2928c2ecf20Sopenharmony_ci	 *
2938c2ecf20Sopenharmony_ci	 * TODO: Here is few hacks. AF9035 chip integrates AF9033 demodulator.
2948c2ecf20Sopenharmony_ci	 * IT9135 chip integrates AF9033 demodulator and RF tuner. For dual
2958c2ecf20Sopenharmony_ci	 * tuner devices, there is also external AF9033 demodulator connected
2968c2ecf20Sopenharmony_ci	 * via external I2C bus. All AF9033 demod I2C traffic, both single and
2978c2ecf20Sopenharmony_ci	 * dual tuner configuration, is covered by firmware - actual USB IO
2988c2ecf20Sopenharmony_ci	 * looks just like a memory access.
2998c2ecf20Sopenharmony_ci	 * In case of IT913x chip, there is own tuner driver. It is implemented
3008c2ecf20Sopenharmony_ci	 * currently as a I2C driver, even tuner IP block is likely build
3018c2ecf20Sopenharmony_ci	 * directly into the demodulator memory space and there is no own I2C
3028c2ecf20Sopenharmony_ci	 * bus. I2C subsystem does not allow register multiple devices to same
3038c2ecf20Sopenharmony_ci	 * bus, having same slave address. Due to that we reuse demod address,
3048c2ecf20Sopenharmony_ci	 * shifted by one bit, on that case.
3058c2ecf20Sopenharmony_ci	 *
3068c2ecf20Sopenharmony_ci	 * For IT930x we use a different command and the sub header is
3078c2ecf20Sopenharmony_ci	 * different as well:
3088c2ecf20Sopenharmony_ci	 * 0: data len
3098c2ecf20Sopenharmony_ci	 * 1: I2C bus (0x03 seems to be only value used)
3108c2ecf20Sopenharmony_ci	 * 2: I2C addr << 1
3118c2ecf20Sopenharmony_ci	 */
3128c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_WRITE_READ(_msg, _num) \
3138c2ecf20Sopenharmony_ci	(_num == 2 && !(_msg[0].flags & I2C_M_RD) && (_msg[1].flags & I2C_M_RD))
3148c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_WRITE(_msg, _num) \
3158c2ecf20Sopenharmony_ci	(_num == 1 && !(_msg[0].flags & I2C_M_RD))
3168c2ecf20Sopenharmony_ci#define AF9035_IS_I2C_XFER_READ(_msg, _num) \
3178c2ecf20Sopenharmony_ci	(_num == 1 && (_msg[0].flags & I2C_M_RD))
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	if (AF9035_IS_I2C_XFER_WRITE_READ(msg, num)) {
3208c2ecf20Sopenharmony_ci		if (msg[0].len > 40 || msg[1].len > 40) {
3218c2ecf20Sopenharmony_ci			/* TODO: correct limits > 40 */
3228c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
3238c2ecf20Sopenharmony_ci		} else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
3248c2ecf20Sopenharmony_ci			   (msg[0].addr == state->af9033_i2c_addr[1])) {
3258c2ecf20Sopenharmony_ci			if (msg[0].len < 3 || msg[1].len < 1) {
3268c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
3278c2ecf20Sopenharmony_ci				goto unlock;
3288c2ecf20Sopenharmony_ci			}
3298c2ecf20Sopenharmony_ci			/* demod access via firmware interface */
3308c2ecf20Sopenharmony_ci			reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
3318c2ecf20Sopenharmony_ci					msg[0].buf[2];
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci			if (msg[0].addr == state->af9033_i2c_addr[1])
3348c2ecf20Sopenharmony_ci				reg |= 0x100000;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci			ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
3378c2ecf20Sopenharmony_ci					msg[1].len);
3388c2ecf20Sopenharmony_ci		} else if (state->no_read) {
3398c2ecf20Sopenharmony_ci			memset(msg[1].buf, 0, msg[1].len);
3408c2ecf20Sopenharmony_ci			ret = 0;
3418c2ecf20Sopenharmony_ci		} else {
3428c2ecf20Sopenharmony_ci			/* I2C write + read */
3438c2ecf20Sopenharmony_ci			u8 buf[MAX_XFER_SIZE];
3448c2ecf20Sopenharmony_ci			struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len,
3458c2ecf20Sopenharmony_ci					buf, msg[1].len, msg[1].buf };
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
3488c2ecf20Sopenharmony_ci				req.cmd = CMD_GENERIC_I2C_RD;
3498c2ecf20Sopenharmony_ci				req.wlen = 3 + msg[0].len;
3508c2ecf20Sopenharmony_ci			}
3518c2ecf20Sopenharmony_ci			req.mbox |= ((msg[0].addr & 0x80)  >>  3);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci			buf[0] = msg[1].len;
3548c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
3558c2ecf20Sopenharmony_ci				buf[1] = 0x03; /* I2C bus */
3568c2ecf20Sopenharmony_ci				buf[2] = msg[0].addr << 1;
3578c2ecf20Sopenharmony_ci				memcpy(&buf[3], msg[0].buf, msg[0].len);
3588c2ecf20Sopenharmony_ci			} else {
3598c2ecf20Sopenharmony_ci				buf[1] = msg[0].addr << 1;
3608c2ecf20Sopenharmony_ci				buf[3] = 0x00; /* reg addr MSB */
3618c2ecf20Sopenharmony_ci				buf[4] = 0x00; /* reg addr LSB */
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci				/* Keep prev behavior for write req len > 2*/
3648c2ecf20Sopenharmony_ci				if (msg[0].len > 2) {
3658c2ecf20Sopenharmony_ci					buf[2] = 0x00; /* reg addr len */
3668c2ecf20Sopenharmony_ci					memcpy(&buf[5], msg[0].buf, msg[0].len);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci				/* Use reg addr fields if write req len <= 2 */
3698c2ecf20Sopenharmony_ci				} else {
3708c2ecf20Sopenharmony_ci					req.wlen = 5;
3718c2ecf20Sopenharmony_ci					buf[2] = msg[0].len;
3728c2ecf20Sopenharmony_ci					if (msg[0].len == 2) {
3738c2ecf20Sopenharmony_ci						buf[3] = msg[0].buf[0];
3748c2ecf20Sopenharmony_ci						buf[4] = msg[0].buf[1];
3758c2ecf20Sopenharmony_ci					} else if (msg[0].len == 1) {
3768c2ecf20Sopenharmony_ci						buf[4] = msg[0].buf[0];
3778c2ecf20Sopenharmony_ci					}
3788c2ecf20Sopenharmony_ci				}
3798c2ecf20Sopenharmony_ci			}
3808c2ecf20Sopenharmony_ci			ret = af9035_ctrl_msg(d, &req);
3818c2ecf20Sopenharmony_ci		}
3828c2ecf20Sopenharmony_ci	} else if (AF9035_IS_I2C_XFER_WRITE(msg, num)) {
3838c2ecf20Sopenharmony_ci		if (msg[0].len > 40) {
3848c2ecf20Sopenharmony_ci			/* TODO: correct limits > 40 */
3858c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
3868c2ecf20Sopenharmony_ci		} else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
3878c2ecf20Sopenharmony_ci			   (msg[0].addr == state->af9033_i2c_addr[1])) {
3888c2ecf20Sopenharmony_ci			if (msg[0].len < 3) {
3898c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
3908c2ecf20Sopenharmony_ci				goto unlock;
3918c2ecf20Sopenharmony_ci			}
3928c2ecf20Sopenharmony_ci			/* demod access via firmware interface */
3938c2ecf20Sopenharmony_ci			reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
3948c2ecf20Sopenharmony_ci					msg[0].buf[2];
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci			if (msg[0].addr == state->af9033_i2c_addr[1])
3978c2ecf20Sopenharmony_ci				reg |= 0x100000;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci			ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3);
4008c2ecf20Sopenharmony_ci		} else {
4018c2ecf20Sopenharmony_ci			/* I2C write */
4028c2ecf20Sopenharmony_ci			u8 buf[MAX_XFER_SIZE];
4038c2ecf20Sopenharmony_ci			struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len,
4048c2ecf20Sopenharmony_ci					buf, 0, NULL };
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
4078c2ecf20Sopenharmony_ci				req.cmd = CMD_GENERIC_I2C_WR;
4088c2ecf20Sopenharmony_ci				req.wlen = 3 + msg[0].len;
4098c2ecf20Sopenharmony_ci			}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci			req.mbox |= ((msg[0].addr & 0x80)  >>  3);
4128c2ecf20Sopenharmony_ci			buf[0] = msg[0].len;
4138c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
4148c2ecf20Sopenharmony_ci				buf[1] = 0x03; /* I2C bus */
4158c2ecf20Sopenharmony_ci				buf[2] = msg[0].addr << 1;
4168c2ecf20Sopenharmony_ci				memcpy(&buf[3], msg[0].buf, msg[0].len);
4178c2ecf20Sopenharmony_ci			} else {
4188c2ecf20Sopenharmony_ci				buf[1] = msg[0].addr << 1;
4198c2ecf20Sopenharmony_ci				buf[2] = 0x00; /* reg addr len */
4208c2ecf20Sopenharmony_ci				buf[3] = 0x00; /* reg addr MSB */
4218c2ecf20Sopenharmony_ci				buf[4] = 0x00; /* reg addr LSB */
4228c2ecf20Sopenharmony_ci				memcpy(&buf[5], msg[0].buf, msg[0].len);
4238c2ecf20Sopenharmony_ci			}
4248c2ecf20Sopenharmony_ci			ret = af9035_ctrl_msg(d, &req);
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci	} else if (AF9035_IS_I2C_XFER_READ(msg, num)) {
4278c2ecf20Sopenharmony_ci		if (msg[0].len > 40) {
4288c2ecf20Sopenharmony_ci			/* TODO: correct limits > 40 */
4298c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
4308c2ecf20Sopenharmony_ci		} else if (state->no_read) {
4318c2ecf20Sopenharmony_ci			memset(msg[0].buf, 0, msg[0].len);
4328c2ecf20Sopenharmony_ci			ret = 0;
4338c2ecf20Sopenharmony_ci		} else {
4348c2ecf20Sopenharmony_ci			/* I2C read */
4358c2ecf20Sopenharmony_ci			u8 buf[5];
4368c2ecf20Sopenharmony_ci			struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
4378c2ecf20Sopenharmony_ci						buf, msg[0].len, msg[0].buf };
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
4408c2ecf20Sopenharmony_ci				req.cmd = CMD_GENERIC_I2C_RD;
4418c2ecf20Sopenharmony_ci				req.wlen = 3;
4428c2ecf20Sopenharmony_ci			}
4438c2ecf20Sopenharmony_ci			req.mbox |= ((msg[0].addr & 0x80)  >>  3);
4448c2ecf20Sopenharmony_ci			buf[0] = msg[0].len;
4458c2ecf20Sopenharmony_ci			if (state->chip_type == 0x9306) {
4468c2ecf20Sopenharmony_ci				buf[1] = 0x03; /* I2C bus */
4478c2ecf20Sopenharmony_ci				buf[2] = msg[0].addr << 1;
4488c2ecf20Sopenharmony_ci			} else {
4498c2ecf20Sopenharmony_ci				buf[1] = msg[0].addr << 1;
4508c2ecf20Sopenharmony_ci				buf[2] = 0x00; /* reg addr len */
4518c2ecf20Sopenharmony_ci				buf[3] = 0x00; /* reg addr MSB */
4528c2ecf20Sopenharmony_ci				buf[4] = 0x00; /* reg addr LSB */
4538c2ecf20Sopenharmony_ci			}
4548c2ecf20Sopenharmony_ci			ret = af9035_ctrl_msg(d, &req);
4558c2ecf20Sopenharmony_ci		}
4568c2ecf20Sopenharmony_ci	} else {
4578c2ecf20Sopenharmony_ci		/*
4588c2ecf20Sopenharmony_ci		 * We support only three kind of I2C transactions:
4598c2ecf20Sopenharmony_ci		 * 1) 1 x write + 1 x read (repeated start)
4608c2ecf20Sopenharmony_ci		 * 2) 1 x write
4618c2ecf20Sopenharmony_ci		 * 3) 1 x read
4628c2ecf20Sopenharmony_ci		 */
4638c2ecf20Sopenharmony_ci		ret = -EOPNOTSUPP;
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ciunlock:
4678c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	if (ret < 0)
4708c2ecf20Sopenharmony_ci		return ret;
4718c2ecf20Sopenharmony_ci	else
4728c2ecf20Sopenharmony_ci		return num;
4738c2ecf20Sopenharmony_ci}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_cistatic u32 af9035_i2c_functionality(struct i2c_adapter *adapter)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C;
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic struct i2c_algorithm af9035_i2c_algo = {
4818c2ecf20Sopenharmony_ci	.master_xfer = af9035_i2c_master_xfer,
4828c2ecf20Sopenharmony_ci	.functionality = af9035_i2c_functionality,
4838c2ecf20Sopenharmony_ci};
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic int af9035_identify_state(struct dvb_usb_device *d, const char **name)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
4888c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
4898c2ecf20Sopenharmony_ci	int ret, i, ts_mode_invalid;
4908c2ecf20Sopenharmony_ci	unsigned int utmp, eeprom_addr;
4918c2ecf20Sopenharmony_ci	u8 tmp;
4928c2ecf20Sopenharmony_ci	u8 wbuf[1] = { 1 };
4938c2ecf20Sopenharmony_ci	u8 rbuf[4];
4948c2ecf20Sopenharmony_ci	struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
4958c2ecf20Sopenharmony_ci			sizeof(rbuf), rbuf };
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	ret = af9035_rd_regs(d, 0x1222, rbuf, 3);
4988c2ecf20Sopenharmony_ci	if (ret < 0)
4998c2ecf20Sopenharmony_ci		goto err;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	state->chip_version = rbuf[0];
5028c2ecf20Sopenharmony_ci	state->chip_type = rbuf[2] << 8 | rbuf[1] << 0;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	ret = af9035_rd_reg(d, 0x384f, &state->prechip_version);
5058c2ecf20Sopenharmony_ci	if (ret < 0)
5068c2ecf20Sopenharmony_ci		goto err;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	dev_info(&intf->dev, "prechip_version=%02x chip_version=%02x chip_type=%04x\n",
5098c2ecf20Sopenharmony_ci		 state->prechip_version, state->chip_version, state->chip_type);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	if (state->chip_type == 0x9135) {
5128c2ecf20Sopenharmony_ci		if (state->chip_version == 0x02) {
5138c2ecf20Sopenharmony_ci			*name = AF9035_FIRMWARE_IT9135_V2;
5148c2ecf20Sopenharmony_ci			utmp = 0x00461d;
5158c2ecf20Sopenharmony_ci		} else {
5168c2ecf20Sopenharmony_ci			*name = AF9035_FIRMWARE_IT9135_V1;
5178c2ecf20Sopenharmony_ci			utmp = 0x00461b;
5188c2ecf20Sopenharmony_ci		}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		/* Check if eeprom exists */
5218c2ecf20Sopenharmony_ci		ret = af9035_rd_reg(d, utmp, &tmp);
5228c2ecf20Sopenharmony_ci		if (ret < 0)
5238c2ecf20Sopenharmony_ci			goto err;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		if (tmp == 0x00) {
5268c2ecf20Sopenharmony_ci			dev_dbg(&intf->dev, "no eeprom\n");
5278c2ecf20Sopenharmony_ci			state->no_eeprom = true;
5288c2ecf20Sopenharmony_ci			goto check_firmware_status;
5298c2ecf20Sopenharmony_ci		}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci		eeprom_addr = EEPROM_BASE_IT9135;
5328c2ecf20Sopenharmony_ci	} else if (state->chip_type == 0x9306) {
5338c2ecf20Sopenharmony_ci		*name = AF9035_FIRMWARE_IT9303;
5348c2ecf20Sopenharmony_ci		state->no_eeprom = true;
5358c2ecf20Sopenharmony_ci		goto check_firmware_status;
5368c2ecf20Sopenharmony_ci	} else {
5378c2ecf20Sopenharmony_ci		*name = AF9035_FIRMWARE_AF9035;
5388c2ecf20Sopenharmony_ci		eeprom_addr = EEPROM_BASE_AF9035;
5398c2ecf20Sopenharmony_ci	}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	/* Read and store eeprom */
5428c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i += 32) {
5438c2ecf20Sopenharmony_ci		ret = af9035_rd_regs(d, eeprom_addr + i, &state->eeprom[i], 32);
5448c2ecf20Sopenharmony_ci		if (ret < 0)
5458c2ecf20Sopenharmony_ci			goto err;
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "eeprom dump:\n");
5498c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i += 16)
5508c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "%*ph\n", 16, &state->eeprom[i]);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	/* check for dual tuner mode */
5538c2ecf20Sopenharmony_ci	tmp = state->eeprom[EEPROM_TS_MODE];
5548c2ecf20Sopenharmony_ci	ts_mode_invalid = 0;
5558c2ecf20Sopenharmony_ci	switch (tmp) {
5568c2ecf20Sopenharmony_ci	case 0:
5578c2ecf20Sopenharmony_ci		break;
5588c2ecf20Sopenharmony_ci	case 1:
5598c2ecf20Sopenharmony_ci	case 3:
5608c2ecf20Sopenharmony_ci		state->dual_mode = true;
5618c2ecf20Sopenharmony_ci		break;
5628c2ecf20Sopenharmony_ci	case 5:
5638c2ecf20Sopenharmony_ci		if (state->chip_type != 0x9135 && state->chip_type != 0x9306)
5648c2ecf20Sopenharmony_ci			state->dual_mode = true;	/* AF9035 */
5658c2ecf20Sopenharmony_ci		else
5668c2ecf20Sopenharmony_ci			ts_mode_invalid = 1;
5678c2ecf20Sopenharmony_ci		break;
5688c2ecf20Sopenharmony_ci	default:
5698c2ecf20Sopenharmony_ci		ts_mode_invalid = 1;
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "ts mode=%d dual mode=%d\n", tmp, state->dual_mode);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	if (ts_mode_invalid)
5758c2ecf20Sopenharmony_ci		dev_info(&intf->dev, "ts mode=%d not supported, defaulting to single tuner mode!", tmp);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cicheck_firmware_status:
5788c2ecf20Sopenharmony_ci	ret = af9035_ctrl_msg(d, &req);
5798c2ecf20Sopenharmony_ci	if (ret < 0)
5808c2ecf20Sopenharmony_ci		goto err;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "reply=%*ph\n", 4, rbuf);
5838c2ecf20Sopenharmony_ci	if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])
5848c2ecf20Sopenharmony_ci		ret = WARM;
5858c2ecf20Sopenharmony_ci	else
5868c2ecf20Sopenharmony_ci		ret = COLD;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return ret;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_cierr:
5918c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	return ret;
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic int af9035_download_firmware_old(struct dvb_usb_device *d,
5978c2ecf20Sopenharmony_ci		const struct firmware *fw)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
6008c2ecf20Sopenharmony_ci	int ret, i, j, len;
6018c2ecf20Sopenharmony_ci	u8 wbuf[1];
6028c2ecf20Sopenharmony_ci	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
6038c2ecf20Sopenharmony_ci	struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL };
6048c2ecf20Sopenharmony_ci	u8 hdr_core;
6058c2ecf20Sopenharmony_ci	u16 hdr_addr, hdr_data_len, hdr_checksum;
6068c2ecf20Sopenharmony_ci	#define MAX_DATA 58
6078c2ecf20Sopenharmony_ci	#define HDR_SIZE 7
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	/*
6108c2ecf20Sopenharmony_ci	 * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info!
6118c2ecf20Sopenharmony_ci	 *
6128c2ecf20Sopenharmony_ci	 * byte 0: MCS 51 core
6138c2ecf20Sopenharmony_ci	 *  There are two inside the AF9035 (1=Link and 2=OFDM) with separate
6148c2ecf20Sopenharmony_ci	 *  address spaces
6158c2ecf20Sopenharmony_ci	 * byte 1-2: Big endian destination address
6168c2ecf20Sopenharmony_ci	 * byte 3-4: Big endian number of data bytes following the header
6178c2ecf20Sopenharmony_ci	 * byte 5-6: Big endian header checksum, apparently ignored by the chip
6188c2ecf20Sopenharmony_ci	 *  Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256)
6198c2ecf20Sopenharmony_ci	 */
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	for (i = fw->size; i > HDR_SIZE;) {
6228c2ecf20Sopenharmony_ci		hdr_core = fw->data[fw->size - i + 0];
6238c2ecf20Sopenharmony_ci		hdr_addr = fw->data[fw->size - i + 1] << 8;
6248c2ecf20Sopenharmony_ci		hdr_addr |= fw->data[fw->size - i + 2] << 0;
6258c2ecf20Sopenharmony_ci		hdr_data_len = fw->data[fw->size - i + 3] << 8;
6268c2ecf20Sopenharmony_ci		hdr_data_len |= fw->data[fw->size - i + 4] << 0;
6278c2ecf20Sopenharmony_ci		hdr_checksum = fw->data[fw->size - i + 5] << 8;
6288c2ecf20Sopenharmony_ci		hdr_checksum |= fw->data[fw->size - i + 6] << 0;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "core=%d addr=%04x data_len=%d checksum=%04x\n",
6318c2ecf20Sopenharmony_ci			hdr_core, hdr_addr, hdr_data_len, hdr_checksum);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci		if (((hdr_core != 1) && (hdr_core != 2)) ||
6348c2ecf20Sopenharmony_ci				(hdr_data_len > i)) {
6358c2ecf20Sopenharmony_ci			dev_dbg(&intf->dev, "bad firmware\n");
6368c2ecf20Sopenharmony_ci			break;
6378c2ecf20Sopenharmony_ci		}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci		/* download begin packet */
6408c2ecf20Sopenharmony_ci		req.cmd = CMD_FW_DL_BEGIN;
6418c2ecf20Sopenharmony_ci		ret = af9035_ctrl_msg(d, &req);
6428c2ecf20Sopenharmony_ci		if (ret < 0)
6438c2ecf20Sopenharmony_ci			goto err;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci		/* download firmware packet(s) */
6468c2ecf20Sopenharmony_ci		for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) {
6478c2ecf20Sopenharmony_ci			len = j;
6488c2ecf20Sopenharmony_ci			if (len > MAX_DATA)
6498c2ecf20Sopenharmony_ci				len = MAX_DATA;
6508c2ecf20Sopenharmony_ci			req_fw_dl.wlen = len;
6518c2ecf20Sopenharmony_ci			req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i +
6528c2ecf20Sopenharmony_ci					HDR_SIZE + hdr_data_len - j];
6538c2ecf20Sopenharmony_ci			ret = af9035_ctrl_msg(d, &req_fw_dl);
6548c2ecf20Sopenharmony_ci			if (ret < 0)
6558c2ecf20Sopenharmony_ci				goto err;
6568c2ecf20Sopenharmony_ci		}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci		/* download end packet */
6598c2ecf20Sopenharmony_ci		req.cmd = CMD_FW_DL_END;
6608c2ecf20Sopenharmony_ci		ret = af9035_ctrl_msg(d, &req);
6618c2ecf20Sopenharmony_ci		if (ret < 0)
6628c2ecf20Sopenharmony_ci			goto err;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci		i -= hdr_data_len + HDR_SIZE;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "data uploaded=%zu\n", fw->size - i);
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	/* print warn if firmware is bad, continue and see what happens */
6708c2ecf20Sopenharmony_ci	if (i)
6718c2ecf20Sopenharmony_ci		dev_warn(&intf->dev, "bad firmware\n");
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	return 0;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cierr:
6768c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	return ret;
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_cistatic int af9035_download_firmware_new(struct dvb_usb_device *d,
6828c2ecf20Sopenharmony_ci		const struct firmware *fw)
6838c2ecf20Sopenharmony_ci{
6848c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
6858c2ecf20Sopenharmony_ci	int ret, i, i_prev;
6868c2ecf20Sopenharmony_ci	struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL };
6878c2ecf20Sopenharmony_ci	#define HDR_SIZE 7
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	/*
6908c2ecf20Sopenharmony_ci	 * There seems to be following firmware header. Meaning of bytes 0-3
6918c2ecf20Sopenharmony_ci	 * is unknown.
6928c2ecf20Sopenharmony_ci	 *
6938c2ecf20Sopenharmony_ci	 * 0: 3
6948c2ecf20Sopenharmony_ci	 * 1: 0, 1
6958c2ecf20Sopenharmony_ci	 * 2: 0
6968c2ecf20Sopenharmony_ci	 * 3: 1, 2, 3
6978c2ecf20Sopenharmony_ci	 * 4: addr MSB
6988c2ecf20Sopenharmony_ci	 * 5: addr LSB
6998c2ecf20Sopenharmony_ci	 * 6: count of data bytes ?
7008c2ecf20Sopenharmony_ci	 */
7018c2ecf20Sopenharmony_ci	for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) {
7028c2ecf20Sopenharmony_ci		if (i == fw->size ||
7038c2ecf20Sopenharmony_ci				(fw->data[i + 0] == 0x03 &&
7048c2ecf20Sopenharmony_ci				(fw->data[i + 1] == 0x00 ||
7058c2ecf20Sopenharmony_ci				fw->data[i + 1] == 0x01) &&
7068c2ecf20Sopenharmony_ci				fw->data[i + 2] == 0x00)) {
7078c2ecf20Sopenharmony_ci			req_fw_dl.wlen = i - i_prev;
7088c2ecf20Sopenharmony_ci			req_fw_dl.wbuf = (u8 *) &fw->data[i_prev];
7098c2ecf20Sopenharmony_ci			i_prev = i;
7108c2ecf20Sopenharmony_ci			ret = af9035_ctrl_msg(d, &req_fw_dl);
7118c2ecf20Sopenharmony_ci			if (ret < 0)
7128c2ecf20Sopenharmony_ci				goto err;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci			dev_dbg(&intf->dev, "data uploaded=%d\n", i);
7158c2ecf20Sopenharmony_ci		}
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	return 0;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cierr:
7218c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return ret;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic int af9035_download_firmware(struct dvb_usb_device *d,
7278c2ecf20Sopenharmony_ci		const struct firmware *fw)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
7308c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
7318c2ecf20Sopenharmony_ci	int ret;
7328c2ecf20Sopenharmony_ci	u8 wbuf[1];
7338c2ecf20Sopenharmony_ci	u8 rbuf[4];
7348c2ecf20Sopenharmony_ci	u8 tmp;
7358c2ecf20Sopenharmony_ci	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
7368c2ecf20Sopenharmony_ci	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf };
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "\n");
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	/*
7418c2ecf20Sopenharmony_ci	 * In case of dual tuner configuration we need to do some extra
7428c2ecf20Sopenharmony_ci	 * initialization in order to download firmware to slave demod too,
7438c2ecf20Sopenharmony_ci	 * which is done by master demod.
7448c2ecf20Sopenharmony_ci	 * Master feeds also clock and controls power via GPIO.
7458c2ecf20Sopenharmony_ci	 */
7468c2ecf20Sopenharmony_ci	if (state->dual_mode) {
7478c2ecf20Sopenharmony_ci		/* configure gpioh1, reset & power slave demod */
7488c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01);
7498c2ecf20Sopenharmony_ci		if (ret < 0)
7508c2ecf20Sopenharmony_ci			goto err;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01);
7538c2ecf20Sopenharmony_ci		if (ret < 0)
7548c2ecf20Sopenharmony_ci			goto err;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01);
7578c2ecf20Sopenharmony_ci		if (ret < 0)
7588c2ecf20Sopenharmony_ci			goto err;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci		usleep_range(10000, 50000);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01);
7638c2ecf20Sopenharmony_ci		if (ret < 0)
7648c2ecf20Sopenharmony_ci			goto err;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci		/* tell the slave I2C address */
7678c2ecf20Sopenharmony_ci		tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR];
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci		/* Use default I2C address if eeprom has no address set */
7708c2ecf20Sopenharmony_ci		if (!tmp)
7718c2ecf20Sopenharmony_ci			tmp = 0x1d << 1; /* 8-bit format used by chip */
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci		if ((state->chip_type == 0x9135) ||
7748c2ecf20Sopenharmony_ci				(state->chip_type == 0x9306)) {
7758c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x004bfb, tmp);
7768c2ecf20Sopenharmony_ci			if (ret < 0)
7778c2ecf20Sopenharmony_ci				goto err;
7788c2ecf20Sopenharmony_ci		} else {
7798c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00417f, tmp);
7808c2ecf20Sopenharmony_ci			if (ret < 0)
7818c2ecf20Sopenharmony_ci				goto err;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci			/* enable clock out */
7848c2ecf20Sopenharmony_ci			ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01);
7858c2ecf20Sopenharmony_ci			if (ret < 0)
7868c2ecf20Sopenharmony_ci				goto err;
7878c2ecf20Sopenharmony_ci		}
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	if (fw->data[0] == 0x01)
7918c2ecf20Sopenharmony_ci		ret = af9035_download_firmware_old(d, fw);
7928c2ecf20Sopenharmony_ci	else
7938c2ecf20Sopenharmony_ci		ret = af9035_download_firmware_new(d, fw);
7948c2ecf20Sopenharmony_ci	if (ret < 0)
7958c2ecf20Sopenharmony_ci		goto err;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	/* firmware loaded, request boot */
7988c2ecf20Sopenharmony_ci	req.cmd = CMD_FW_BOOT;
7998c2ecf20Sopenharmony_ci	ret = af9035_ctrl_msg(d, &req);
8008c2ecf20Sopenharmony_ci	if (ret < 0)
8018c2ecf20Sopenharmony_ci		goto err;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	/* ensure firmware starts */
8048c2ecf20Sopenharmony_ci	wbuf[0] = 1;
8058c2ecf20Sopenharmony_ci	ret = af9035_ctrl_msg(d, &req_fw_ver);
8068c2ecf20Sopenharmony_ci	if (ret < 0)
8078c2ecf20Sopenharmony_ci		goto err;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
8108c2ecf20Sopenharmony_ci		dev_err(&intf->dev, "firmware did not run\n");
8118c2ecf20Sopenharmony_ci		ret = -ENODEV;
8128c2ecf20Sopenharmony_ci		goto err;
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	dev_info(&intf->dev, "firmware version=%d.%d.%d.%d",
8168c2ecf20Sopenharmony_ci		 rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	return 0;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_cierr:
8218c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	return ret;
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_cistatic int af9035_read_config(struct dvb_usb_device *d)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
8298c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
8308c2ecf20Sopenharmony_ci	int ret, i;
8318c2ecf20Sopenharmony_ci	u8 tmp;
8328c2ecf20Sopenharmony_ci	u16 tmp16;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	/* Demod I2C address */
8358c2ecf20Sopenharmony_ci	state->af9033_i2c_addr[0] = 0x1c;
8368c2ecf20Sopenharmony_ci	state->af9033_i2c_addr[1] = 0x1d;
8378c2ecf20Sopenharmony_ci	state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X;
8388c2ecf20Sopenharmony_ci	state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X;
8398c2ecf20Sopenharmony_ci	state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
8408c2ecf20Sopenharmony_ci	state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
8418c2ecf20Sopenharmony_ci	state->it930x_addresses = 0;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	if (state->chip_type == 0x9135) {
8448c2ecf20Sopenharmony_ci		/* feed clock for integrated RF tuner */
8458c2ecf20Sopenharmony_ci		state->af9033_config[0].dyn0_clk = true;
8468c2ecf20Sopenharmony_ci		state->af9033_config[1].dyn0_clk = true;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		if (state->chip_version == 0x02) {
8498c2ecf20Sopenharmony_ci			state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60;
8508c2ecf20Sopenharmony_ci			state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60;
8518c2ecf20Sopenharmony_ci		} else {
8528c2ecf20Sopenharmony_ci			state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38;
8538c2ecf20Sopenharmony_ci			state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38;
8548c2ecf20Sopenharmony_ci		}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		if (state->no_eeprom) {
8578c2ecf20Sopenharmony_ci			/* Remote controller to NEC polling by default */
8588c2ecf20Sopenharmony_ci			state->ir_mode = 0x05;
8598c2ecf20Sopenharmony_ci			state->ir_type = 0x00;
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci			goto skip_eeprom;
8628c2ecf20Sopenharmony_ci		}
8638c2ecf20Sopenharmony_ci	} else if (state->chip_type == 0x9306) {
8648c2ecf20Sopenharmony_ci		/*
8658c2ecf20Sopenharmony_ci		 * IT930x is an USB bridge, only single demod-single tuner
8668c2ecf20Sopenharmony_ci		 * configurations seen so far.
8678c2ecf20Sopenharmony_ci		 */
8688c2ecf20Sopenharmony_ci		if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) &&
8698c2ecf20Sopenharmony_ci		    (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_AVERMEDIA_TD310)) {
8708c2ecf20Sopenharmony_ci			state->it930x_addresses = 1;
8718c2ecf20Sopenharmony_ci		}
8728c2ecf20Sopenharmony_ci		return 0;
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	/* Remote controller */
8768c2ecf20Sopenharmony_ci	state->ir_mode = state->eeprom[EEPROM_IR_MODE];
8778c2ecf20Sopenharmony_ci	state->ir_type = state->eeprom[EEPROM_IR_TYPE];
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	if (state->dual_mode) {
8808c2ecf20Sopenharmony_ci		/* Read 2nd demodulator I2C address. 8-bit format on eeprom */
8818c2ecf20Sopenharmony_ci		tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR];
8828c2ecf20Sopenharmony_ci		if (tmp)
8838c2ecf20Sopenharmony_ci			state->af9033_i2c_addr[1] = tmp >> 1;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "2nd demod I2C addr=%02x\n",
8868c2ecf20Sopenharmony_ci			state->af9033_i2c_addr[1]);
8878c2ecf20Sopenharmony_ci	}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	for (i = 0; i < state->dual_mode + 1; i++) {
8908c2ecf20Sopenharmony_ci		unsigned int eeprom_offset = 0;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci		/* tuner */
8938c2ecf20Sopenharmony_ci		tmp = state->eeprom[EEPROM_1_TUNER_ID + eeprom_offset];
8948c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "[%d]tuner=%02x\n", i, tmp);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci		/* tuner sanity check */
8978c2ecf20Sopenharmony_ci		if (state->chip_type == 0x9135) {
8988c2ecf20Sopenharmony_ci			if (state->chip_version == 0x02) {
8998c2ecf20Sopenharmony_ci				/* IT9135 BX (v2) */
9008c2ecf20Sopenharmony_ci				switch (tmp) {
9018c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_60:
9028c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_61:
9038c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_62:
9048c2ecf20Sopenharmony_ci					state->af9033_config[i].tuner = tmp;
9058c2ecf20Sopenharmony_ci					break;
9068c2ecf20Sopenharmony_ci				}
9078c2ecf20Sopenharmony_ci			} else {
9088c2ecf20Sopenharmony_ci				/* IT9135 AX (v1) */
9098c2ecf20Sopenharmony_ci				switch (tmp) {
9108c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_38:
9118c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_51:
9128c2ecf20Sopenharmony_ci				case AF9033_TUNER_IT9135_52:
9138c2ecf20Sopenharmony_ci					state->af9033_config[i].tuner = tmp;
9148c2ecf20Sopenharmony_ci					break;
9158c2ecf20Sopenharmony_ci				}
9168c2ecf20Sopenharmony_ci			}
9178c2ecf20Sopenharmony_ci		} else {
9188c2ecf20Sopenharmony_ci			/* AF9035 */
9198c2ecf20Sopenharmony_ci			state->af9033_config[i].tuner = tmp;
9208c2ecf20Sopenharmony_ci		}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		if (state->af9033_config[i].tuner != tmp) {
9238c2ecf20Sopenharmony_ci			dev_info(&intf->dev, "[%d] overriding tuner from %02x to %02x\n",
9248c2ecf20Sopenharmony_ci				 i, tmp, state->af9033_config[i].tuner);
9258c2ecf20Sopenharmony_ci		}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci		switch (state->af9033_config[i].tuner) {
9288c2ecf20Sopenharmony_ci		case AF9033_TUNER_TUA9001:
9298c2ecf20Sopenharmony_ci		case AF9033_TUNER_FC0011:
9308c2ecf20Sopenharmony_ci		case AF9033_TUNER_MXL5007T:
9318c2ecf20Sopenharmony_ci		case AF9033_TUNER_TDA18218:
9328c2ecf20Sopenharmony_ci		case AF9033_TUNER_FC2580:
9338c2ecf20Sopenharmony_ci		case AF9033_TUNER_FC0012:
9348c2ecf20Sopenharmony_ci			state->af9033_config[i].spec_inv = 1;
9358c2ecf20Sopenharmony_ci			break;
9368c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_38:
9378c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_51:
9388c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_52:
9398c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_60:
9408c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_61:
9418c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_62:
9428c2ecf20Sopenharmony_ci			break;
9438c2ecf20Sopenharmony_ci		default:
9448c2ecf20Sopenharmony_ci			dev_warn(&intf->dev, "tuner id=%02x not supported, please report!",
9458c2ecf20Sopenharmony_ci				 tmp);
9468c2ecf20Sopenharmony_ci		}
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci		/* disable dual mode if driver does not support it */
9498c2ecf20Sopenharmony_ci		if (i == 1)
9508c2ecf20Sopenharmony_ci			switch (state->af9033_config[i].tuner) {
9518c2ecf20Sopenharmony_ci			case AF9033_TUNER_FC0012:
9528c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_38:
9538c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_51:
9548c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_52:
9558c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_60:
9568c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_61:
9578c2ecf20Sopenharmony_ci			case AF9033_TUNER_IT9135_62:
9588c2ecf20Sopenharmony_ci			case AF9033_TUNER_MXL5007T:
9598c2ecf20Sopenharmony_ci				break;
9608c2ecf20Sopenharmony_ci			default:
9618c2ecf20Sopenharmony_ci				state->dual_mode = false;
9628c2ecf20Sopenharmony_ci				dev_info(&intf->dev, "driver does not support 2nd tuner and will disable it");
9638c2ecf20Sopenharmony_ci		}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci		/* tuner IF frequency */
9668c2ecf20Sopenharmony_ci		tmp = state->eeprom[EEPROM_1_IF_L + eeprom_offset];
9678c2ecf20Sopenharmony_ci		tmp16 = tmp << 0;
9688c2ecf20Sopenharmony_ci		tmp = state->eeprom[EEPROM_1_IF_H + eeprom_offset];
9698c2ecf20Sopenharmony_ci		tmp16 |= tmp << 8;
9708c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "[%d]IF=%d\n", i, tmp16);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci		eeprom_offset += 0x10; /* shift for the 2nd tuner params */
9738c2ecf20Sopenharmony_ci	}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ciskip_eeprom:
9768c2ecf20Sopenharmony_ci	/* get demod clock */
9778c2ecf20Sopenharmony_ci	ret = af9035_rd_reg(d, 0x00d800, &tmp);
9788c2ecf20Sopenharmony_ci	if (ret < 0)
9798c2ecf20Sopenharmony_ci		goto err;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	tmp = (tmp >> 0) & 0x0f;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) {
9848c2ecf20Sopenharmony_ci		if (state->chip_type == 0x9135)
9858c2ecf20Sopenharmony_ci			state->af9033_config[i].clock = clock_lut_it9135[tmp];
9868c2ecf20Sopenharmony_ci		else
9878c2ecf20Sopenharmony_ci			state->af9033_config[i].clock = clock_lut_af9035[tmp];
9888c2ecf20Sopenharmony_ci	}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	state->no_read = false;
9918c2ecf20Sopenharmony_ci	/* Some MXL5007T devices cannot properly handle tuner I2C read ops. */
9928c2ecf20Sopenharmony_ci	if (state->af9033_config[0].tuner == AF9033_TUNER_MXL5007T &&
9938c2ecf20Sopenharmony_ci		le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA)
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci		switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
9968c2ecf20Sopenharmony_ci		case USB_PID_AVERMEDIA_A867:
9978c2ecf20Sopenharmony_ci		case USB_PID_AVERMEDIA_TWINSTAR:
9988c2ecf20Sopenharmony_ci			dev_info(&intf->dev,
9998c2ecf20Sopenharmony_ci				 "Device may have issues with I2C read operations. Enabling fix.\n");
10008c2ecf20Sopenharmony_ci			state->no_read = true;
10018c2ecf20Sopenharmony_ci			break;
10028c2ecf20Sopenharmony_ci		}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	return 0;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_cierr:
10078c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	return ret;
10108c2ecf20Sopenharmony_ci}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_cistatic int af9035_tua9001_tuner_callback(struct dvb_usb_device *d,
10138c2ecf20Sopenharmony_ci		int cmd, int arg)
10148c2ecf20Sopenharmony_ci{
10158c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
10168c2ecf20Sopenharmony_ci	int ret;
10178c2ecf20Sopenharmony_ci	u8 val;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "cmd=%d arg=%d\n", cmd, arg);
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/*
10228c2ecf20Sopenharmony_ci	 * CEN     always enabled by hardware wiring
10238c2ecf20Sopenharmony_ci	 * RESETN  GPIOT3
10248c2ecf20Sopenharmony_ci	 * RXEN    GPIOT2
10258c2ecf20Sopenharmony_ci	 */
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	switch (cmd) {
10288c2ecf20Sopenharmony_ci	case TUA9001_CMD_RESETN:
10298c2ecf20Sopenharmony_ci		if (arg)
10308c2ecf20Sopenharmony_ci			val = 0x00;
10318c2ecf20Sopenharmony_ci		else
10328c2ecf20Sopenharmony_ci			val = 0x01;
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01);
10358c2ecf20Sopenharmony_ci		if (ret < 0)
10368c2ecf20Sopenharmony_ci			goto err;
10378c2ecf20Sopenharmony_ci		break;
10388c2ecf20Sopenharmony_ci	case TUA9001_CMD_RXEN:
10398c2ecf20Sopenharmony_ci		if (arg)
10408c2ecf20Sopenharmony_ci			val = 0x01;
10418c2ecf20Sopenharmony_ci		else
10428c2ecf20Sopenharmony_ci			val = 0x00;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01);
10458c2ecf20Sopenharmony_ci		if (ret < 0)
10468c2ecf20Sopenharmony_ci			goto err;
10478c2ecf20Sopenharmony_ci		break;
10488c2ecf20Sopenharmony_ci	}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	return 0;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_cierr:
10538c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	return ret;
10568c2ecf20Sopenharmony_ci}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_cistatic int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
10608c2ecf20Sopenharmony_ci		int cmd, int arg)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
10638c2ecf20Sopenharmony_ci	int ret;
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	switch (cmd) {
10668c2ecf20Sopenharmony_ci	case FC0011_FE_CALLBACK_POWER:
10678c2ecf20Sopenharmony_ci		/* Tuner enable */
10688c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1);
10698c2ecf20Sopenharmony_ci		if (ret < 0)
10708c2ecf20Sopenharmony_ci			goto err;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1);
10738c2ecf20Sopenharmony_ci		if (ret < 0)
10748c2ecf20Sopenharmony_ci			goto err;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1);
10778c2ecf20Sopenharmony_ci		if (ret < 0)
10788c2ecf20Sopenharmony_ci			goto err;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		/* LED */
10818c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1);
10828c2ecf20Sopenharmony_ci		if (ret < 0)
10838c2ecf20Sopenharmony_ci			goto err;
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1);
10868c2ecf20Sopenharmony_ci		if (ret < 0)
10878c2ecf20Sopenharmony_ci			goto err;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci		usleep_range(10000, 50000);
10908c2ecf20Sopenharmony_ci		break;
10918c2ecf20Sopenharmony_ci	case FC0011_FE_CALLBACK_RESET:
10928c2ecf20Sopenharmony_ci		ret = af9035_wr_reg(d, 0xd8e9, 1);
10938c2ecf20Sopenharmony_ci		if (ret < 0)
10948c2ecf20Sopenharmony_ci			goto err;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		ret = af9035_wr_reg(d, 0xd8e8, 1);
10978c2ecf20Sopenharmony_ci		if (ret < 0)
10988c2ecf20Sopenharmony_ci			goto err;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci		ret = af9035_wr_reg(d, 0xd8e7, 1);
11018c2ecf20Sopenharmony_ci		if (ret < 0)
11028c2ecf20Sopenharmony_ci			goto err;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci		ret = af9035_wr_reg(d, 0xd8e7, 0);
11078c2ecf20Sopenharmony_ci		if (ret < 0)
11088c2ecf20Sopenharmony_ci			goto err;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
11118c2ecf20Sopenharmony_ci		break;
11128c2ecf20Sopenharmony_ci	default:
11138c2ecf20Sopenharmony_ci		ret = -EINVAL;
11148c2ecf20Sopenharmony_ci		goto err;
11158c2ecf20Sopenharmony_ci	}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	return 0;
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_cierr:
11208c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	return ret;
11238c2ecf20Sopenharmony_ci}
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_cistatic int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
11268c2ecf20Sopenharmony_ci{
11278c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	switch (state->af9033_config[0].tuner) {
11308c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC0011:
11318c2ecf20Sopenharmony_ci		return af9035_fc0011_tuner_callback(d, cmd, arg);
11328c2ecf20Sopenharmony_ci	case AF9033_TUNER_TUA9001:
11338c2ecf20Sopenharmony_ci		return af9035_tua9001_tuner_callback(d, cmd, arg);
11348c2ecf20Sopenharmony_ci	default:
11358c2ecf20Sopenharmony_ci		break;
11368c2ecf20Sopenharmony_ci	}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	return 0;
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_cistatic int af9035_frontend_callback(void *adapter_priv, int component,
11428c2ecf20Sopenharmony_ci				    int cmd, int arg)
11438c2ecf20Sopenharmony_ci{
11448c2ecf20Sopenharmony_ci	struct i2c_adapter *adap = adapter_priv;
11458c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
11468c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "component=%d cmd=%d arg=%d\n",
11498c2ecf20Sopenharmony_ci		component, cmd, arg);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	switch (component) {
11528c2ecf20Sopenharmony_ci	case DVB_FRONTEND_COMPONENT_TUNER:
11538c2ecf20Sopenharmony_ci		return af9035_tuner_callback(d, cmd, arg);
11548c2ecf20Sopenharmony_ci	default:
11558c2ecf20Sopenharmony_ci		break;
11568c2ecf20Sopenharmony_ci	}
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	return 0;
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_cistatic int af9035_get_adapter_count(struct dvb_usb_device *d)
11628c2ecf20Sopenharmony_ci{
11638c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	return state->dual_mode + 1;
11668c2ecf20Sopenharmony_ci}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_cistatic int af9035_frontend_attach(struct dvb_usb_adapter *adap)
11698c2ecf20Sopenharmony_ci{
11708c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
11718c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
11728c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
11738c2ecf20Sopenharmony_ci	int ret;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	if (!state->af9033_config[adap->id].tuner) {
11788c2ecf20Sopenharmony_ci		/* unsupported tuner */
11798c2ecf20Sopenharmony_ci		ret = -ENODEV;
11808c2ecf20Sopenharmony_ci		goto err;
11818c2ecf20Sopenharmony_ci	}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	state->af9033_config[adap->id].fe = &adap->fe[0];
11848c2ecf20Sopenharmony_ci	state->af9033_config[adap->id].ops = &state->ops;
11858c2ecf20Sopenharmony_ci	ret = af9035_add_i2c_dev(d, "af9033", state->af9033_i2c_addr[adap->id],
11868c2ecf20Sopenharmony_ci			&state->af9033_config[adap->id], &d->i2c_adap);
11878c2ecf20Sopenharmony_ci	if (ret)
11888c2ecf20Sopenharmony_ci		goto err;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	if (adap->fe[0] == NULL) {
11918c2ecf20Sopenharmony_ci		ret = -ENODEV;
11928c2ecf20Sopenharmony_ci		goto err;
11938c2ecf20Sopenharmony_ci	}
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	/* disable I2C-gate */
11968c2ecf20Sopenharmony_ci	adap->fe[0]->ops.i2c_gate_ctrl = NULL;
11978c2ecf20Sopenharmony_ci	adap->fe[0]->callback = af9035_frontend_callback;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	return 0;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_cierr:
12028c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	return ret;
12058c2ecf20Sopenharmony_ci}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci/*
12088c2ecf20Sopenharmony_ci * The I2C speed register is calculated with:
12098c2ecf20Sopenharmony_ci *	I2C speed register = (1000000000 / (24.4 * 16 * I2C_speed))
12108c2ecf20Sopenharmony_ci *
12118c2ecf20Sopenharmony_ci * The default speed register for it930x is 7, with means a
12128c2ecf20Sopenharmony_ci * speed of ~366 kbps
12138c2ecf20Sopenharmony_ci */
12148c2ecf20Sopenharmony_ci#define I2C_SPEED_366K 7
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_cistatic int it930x_frontend_attach(struct dvb_usb_adapter *adap)
12178c2ecf20Sopenharmony_ci{
12188c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
12198c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
12208c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
12218c2ecf20Sopenharmony_ci	int ret;
12228c2ecf20Sopenharmony_ci	struct si2168_config si2168_config;
12238c2ecf20Sopenharmony_ci	struct i2c_adapter *adapter;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	/* I2C master bus 2 clock speed 366k */
12288c2ecf20Sopenharmony_ci	ret = af9035_wr_reg(d, 0x00f6a7, I2C_SPEED_366K);
12298c2ecf20Sopenharmony_ci	if (ret < 0)
12308c2ecf20Sopenharmony_ci		goto err;
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	/* I2C master bus 1,3 clock speed 366k */
12338c2ecf20Sopenharmony_ci	ret = af9035_wr_reg(d, 0x00f103, I2C_SPEED_366K);
12348c2ecf20Sopenharmony_ci	if (ret < 0)
12358c2ecf20Sopenharmony_ci		goto err;
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	/* set gpio11 low */
12388c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8d4, 0x01, 0x01);
12398c2ecf20Sopenharmony_ci	if (ret < 0)
12408c2ecf20Sopenharmony_ci		goto err;
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8d5, 0x01, 0x01);
12438c2ecf20Sopenharmony_ci	if (ret < 0)
12448c2ecf20Sopenharmony_ci		goto err;
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8d3, 0x01, 0x01);
12478c2ecf20Sopenharmony_ci	if (ret < 0)
12488c2ecf20Sopenharmony_ci		goto err;
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	/* Tuner enable using gpiot2_en, gpiot2_on and gpiot2_o (reset) */
12518c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8b8, 0x01, 0x01);
12528c2ecf20Sopenharmony_ci	if (ret < 0)
12538c2ecf20Sopenharmony_ci		goto err;
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8b9, 0x01, 0x01);
12568c2ecf20Sopenharmony_ci	if (ret < 0)
12578c2ecf20Sopenharmony_ci		goto err;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8b7, 0x00, 0x01);
12608c2ecf20Sopenharmony_ci	if (ret < 0)
12618c2ecf20Sopenharmony_ci		goto err;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	msleep(200);
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	ret = af9035_wr_reg_mask(d, 0xd8b7, 0x01, 0x01);
12668c2ecf20Sopenharmony_ci	if (ret < 0)
12678c2ecf20Sopenharmony_ci		goto err;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	memset(&si2168_config, 0, sizeof(si2168_config));
12708c2ecf20Sopenharmony_ci	si2168_config.i2c_adapter = &adapter;
12718c2ecf20Sopenharmony_ci	si2168_config.fe = &adap->fe[0];
12728c2ecf20Sopenharmony_ci	si2168_config.ts_mode = SI2168_TS_SERIAL;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	state->af9033_config[adap->id].fe = &adap->fe[0];
12758c2ecf20Sopenharmony_ci	state->af9033_config[adap->id].ops = &state->ops;
12768c2ecf20Sopenharmony_ci	ret = af9035_add_i2c_dev(d, "si2168",
12778c2ecf20Sopenharmony_ci				 it930x_addresses_table[state->it930x_addresses].frontend_i2c_addr,
12788c2ecf20Sopenharmony_ci				 &si2168_config, &d->i2c_adap);
12798c2ecf20Sopenharmony_ci	if (ret)
12808c2ecf20Sopenharmony_ci		goto err;
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	if (adap->fe[0] == NULL) {
12838c2ecf20Sopenharmony_ci		ret = -ENODEV;
12848c2ecf20Sopenharmony_ci		goto err;
12858c2ecf20Sopenharmony_ci	}
12868c2ecf20Sopenharmony_ci	state->i2c_adapter_demod = adapter;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	return 0;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_cierr:
12918c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	return ret;
12948c2ecf20Sopenharmony_ci}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_cistatic int af9035_frontend_detach(struct dvb_usb_adapter *adap)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
12998c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
13008c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	if (adap->id == 1) {
13058c2ecf20Sopenharmony_ci		if (state->i2c_client[1])
13068c2ecf20Sopenharmony_ci			af9035_del_i2c_dev(d);
13078c2ecf20Sopenharmony_ci	} else if (adap->id == 0) {
13088c2ecf20Sopenharmony_ci		if (state->i2c_client[0])
13098c2ecf20Sopenharmony_ci			af9035_del_i2c_dev(d);
13108c2ecf20Sopenharmony_ci	}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	return 0;
13138c2ecf20Sopenharmony_ci}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_cistatic const struct fc0011_config af9035_fc0011_config = {
13168c2ecf20Sopenharmony_ci	.i2c_address = 0x60,
13178c2ecf20Sopenharmony_ci};
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_cistatic struct mxl5007t_config af9035_mxl5007t_config[] = {
13208c2ecf20Sopenharmony_ci	{
13218c2ecf20Sopenharmony_ci		.xtal_freq_hz = MxL_XTAL_24_MHZ,
13228c2ecf20Sopenharmony_ci		.if_freq_hz = MxL_IF_4_57_MHZ,
13238c2ecf20Sopenharmony_ci		.invert_if = 0,
13248c2ecf20Sopenharmony_ci		.loop_thru_enable = 0,
13258c2ecf20Sopenharmony_ci		.clk_out_enable = 0,
13268c2ecf20Sopenharmony_ci		.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
13278c2ecf20Sopenharmony_ci	}, {
13288c2ecf20Sopenharmony_ci		.xtal_freq_hz = MxL_XTAL_24_MHZ,
13298c2ecf20Sopenharmony_ci		.if_freq_hz = MxL_IF_4_57_MHZ,
13308c2ecf20Sopenharmony_ci		.invert_if = 0,
13318c2ecf20Sopenharmony_ci		.loop_thru_enable = 1,
13328c2ecf20Sopenharmony_ci		.clk_out_enable = 1,
13338c2ecf20Sopenharmony_ci		.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
13348c2ecf20Sopenharmony_ci	}
13358c2ecf20Sopenharmony_ci};
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_cistatic struct tda18218_config af9035_tda18218_config = {
13388c2ecf20Sopenharmony_ci	.i2c_address = 0x60,
13398c2ecf20Sopenharmony_ci	.i2c_wr_max = 21,
13408c2ecf20Sopenharmony_ci};
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_cistatic const struct fc0012_config af9035_fc0012_config[] = {
13438c2ecf20Sopenharmony_ci	{
13448c2ecf20Sopenharmony_ci		.i2c_address = 0x63,
13458c2ecf20Sopenharmony_ci		.xtal_freq = FC_XTAL_36_MHZ,
13468c2ecf20Sopenharmony_ci		.dual_master = true,
13478c2ecf20Sopenharmony_ci		.loop_through = true,
13488c2ecf20Sopenharmony_ci		.clock_out = true,
13498c2ecf20Sopenharmony_ci	}, {
13508c2ecf20Sopenharmony_ci		.i2c_address = 0x63 | 0x80, /* I2C bus select hack */
13518c2ecf20Sopenharmony_ci		.xtal_freq = FC_XTAL_36_MHZ,
13528c2ecf20Sopenharmony_ci		.dual_master = true,
13538c2ecf20Sopenharmony_ci	}
13548c2ecf20Sopenharmony_ci};
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_cistatic int af9035_tuner_attach(struct dvb_usb_adapter *adap)
13578c2ecf20Sopenharmony_ci{
13588c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
13598c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
13608c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
13618c2ecf20Sopenharmony_ci	int ret;
13628c2ecf20Sopenharmony_ci	struct dvb_frontend *fe;
13638c2ecf20Sopenharmony_ci	struct i2c_msg msg[1];
13648c2ecf20Sopenharmony_ci	u8 tuner_addr;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	/*
13698c2ecf20Sopenharmony_ci	 * XXX: Hack used in that function: we abuse unused I2C address bit [7]
13708c2ecf20Sopenharmony_ci	 * to carry info about used I2C bus for dual tuner configuration.
13718c2ecf20Sopenharmony_ci	 */
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	switch (state->af9033_config[adap->id].tuner) {
13748c2ecf20Sopenharmony_ci	case AF9033_TUNER_TUA9001: {
13758c2ecf20Sopenharmony_ci		struct tua9001_platform_data tua9001_pdata = {
13768c2ecf20Sopenharmony_ci			.dvb_frontend = adap->fe[0],
13778c2ecf20Sopenharmony_ci		};
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci		/*
13808c2ecf20Sopenharmony_ci		 * AF9035 gpiot3 = TUA9001 RESETN
13818c2ecf20Sopenharmony_ci		 * AF9035 gpiot2 = TUA9001 RXEN
13828c2ecf20Sopenharmony_ci		 */
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci		/* configure gpiot2 and gpiot2 as output */
13858c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01);
13868c2ecf20Sopenharmony_ci		if (ret < 0)
13878c2ecf20Sopenharmony_ci			goto err;
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01);
13908c2ecf20Sopenharmony_ci		if (ret < 0)
13918c2ecf20Sopenharmony_ci			goto err;
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01);
13948c2ecf20Sopenharmony_ci		if (ret < 0)
13958c2ecf20Sopenharmony_ci			goto err;
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01);
13988c2ecf20Sopenharmony_ci		if (ret < 0)
13998c2ecf20Sopenharmony_ci			goto err;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci		/* attach tuner */
14028c2ecf20Sopenharmony_ci		ret = af9035_add_i2c_dev(d, "tua9001", 0x60, &tua9001_pdata,
14038c2ecf20Sopenharmony_ci					 &d->i2c_adap);
14048c2ecf20Sopenharmony_ci		if (ret)
14058c2ecf20Sopenharmony_ci			goto err;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci		fe = adap->fe[0];
14088c2ecf20Sopenharmony_ci		break;
14098c2ecf20Sopenharmony_ci	}
14108c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC0011:
14118c2ecf20Sopenharmony_ci		fe = dvb_attach(fc0011_attach, adap->fe[0],
14128c2ecf20Sopenharmony_ci				&d->i2c_adap, &af9035_fc0011_config);
14138c2ecf20Sopenharmony_ci		break;
14148c2ecf20Sopenharmony_ci	case AF9033_TUNER_MXL5007T:
14158c2ecf20Sopenharmony_ci		if (adap->id == 0) {
14168c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8e0, 1);
14178c2ecf20Sopenharmony_ci			if (ret < 0)
14188c2ecf20Sopenharmony_ci				goto err;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8e1, 1);
14218c2ecf20Sopenharmony_ci			if (ret < 0)
14228c2ecf20Sopenharmony_ci				goto err;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8df, 0);
14258c2ecf20Sopenharmony_ci			if (ret < 0)
14268c2ecf20Sopenharmony_ci				goto err;
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci			msleep(30);
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8df, 1);
14318c2ecf20Sopenharmony_ci			if (ret < 0)
14328c2ecf20Sopenharmony_ci				goto err;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci			msleep(300);
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8c0, 1);
14378c2ecf20Sopenharmony_ci			if (ret < 0)
14388c2ecf20Sopenharmony_ci				goto err;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8c1, 1);
14418c2ecf20Sopenharmony_ci			if (ret < 0)
14428c2ecf20Sopenharmony_ci				goto err;
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8bf, 0);
14458c2ecf20Sopenharmony_ci			if (ret < 0)
14468c2ecf20Sopenharmony_ci				goto err;
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8b4, 1);
14498c2ecf20Sopenharmony_ci			if (ret < 0)
14508c2ecf20Sopenharmony_ci				goto err;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8b5, 1);
14538c2ecf20Sopenharmony_ci			if (ret < 0)
14548c2ecf20Sopenharmony_ci				goto err;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci			ret = af9035_wr_reg(d, 0x00d8b3, 1);
14578c2ecf20Sopenharmony_ci			if (ret < 0)
14588c2ecf20Sopenharmony_ci				goto err;
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci			tuner_addr = 0x60;
14618c2ecf20Sopenharmony_ci		} else {
14628c2ecf20Sopenharmony_ci			tuner_addr = 0x60 | 0x80; /* I2C bus hack */
14638c2ecf20Sopenharmony_ci		}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci		/* attach tuner */
14668c2ecf20Sopenharmony_ci		fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap,
14678c2ecf20Sopenharmony_ci				tuner_addr, &af9035_mxl5007t_config[adap->id]);
14688c2ecf20Sopenharmony_ci		break;
14698c2ecf20Sopenharmony_ci	case AF9033_TUNER_TDA18218:
14708c2ecf20Sopenharmony_ci		/* attach tuner */
14718c2ecf20Sopenharmony_ci		fe = dvb_attach(tda18218_attach, adap->fe[0],
14728c2ecf20Sopenharmony_ci				&d->i2c_adap, &af9035_tda18218_config);
14738c2ecf20Sopenharmony_ci		break;
14748c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC2580: {
14758c2ecf20Sopenharmony_ci		struct fc2580_platform_data fc2580_pdata = {
14768c2ecf20Sopenharmony_ci			.dvb_frontend = adap->fe[0],
14778c2ecf20Sopenharmony_ci		};
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci		/* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on  */
14808c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01);
14818c2ecf20Sopenharmony_ci		if (ret < 0)
14828c2ecf20Sopenharmony_ci			goto err;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01);
14858c2ecf20Sopenharmony_ci		if (ret < 0)
14868c2ecf20Sopenharmony_ci			goto err;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01);
14898c2ecf20Sopenharmony_ci		if (ret < 0)
14908c2ecf20Sopenharmony_ci			goto err;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci		usleep_range(10000, 50000);
14938c2ecf20Sopenharmony_ci		/* attach tuner */
14948c2ecf20Sopenharmony_ci		ret = af9035_add_i2c_dev(d, "fc2580", 0x56, &fc2580_pdata,
14958c2ecf20Sopenharmony_ci					 &d->i2c_adap);
14968c2ecf20Sopenharmony_ci		if (ret)
14978c2ecf20Sopenharmony_ci			goto err;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci		fe = adap->fe[0];
15008c2ecf20Sopenharmony_ci		break;
15018c2ecf20Sopenharmony_ci	}
15028c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC0012:
15038c2ecf20Sopenharmony_ci		/*
15048c2ecf20Sopenharmony_ci		 * AF9035 gpiot2 = FC0012 enable
15058c2ecf20Sopenharmony_ci		 * XXX: there seems to be something on gpioh8 too, but on my
15068c2ecf20Sopenharmony_ci		 * my test I didn't find any difference.
15078c2ecf20Sopenharmony_ci		 */
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci		if (adap->id == 0) {
15108c2ecf20Sopenharmony_ci			/* configure gpiot2 as output and high */
15118c2ecf20Sopenharmony_ci			ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01);
15128c2ecf20Sopenharmony_ci			if (ret < 0)
15138c2ecf20Sopenharmony_ci				goto err;
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci			ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01);
15168c2ecf20Sopenharmony_ci			if (ret < 0)
15178c2ecf20Sopenharmony_ci				goto err;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci			ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01);
15208c2ecf20Sopenharmony_ci			if (ret < 0)
15218c2ecf20Sopenharmony_ci				goto err;
15228c2ecf20Sopenharmony_ci		} else {
15238c2ecf20Sopenharmony_ci			/*
15248c2ecf20Sopenharmony_ci			 * FIXME: That belongs for the FC0012 driver.
15258c2ecf20Sopenharmony_ci			 * Write 02 to FC0012 master tuner register 0d directly
15268c2ecf20Sopenharmony_ci			 * in order to make slave tuner working.
15278c2ecf20Sopenharmony_ci			 */
15288c2ecf20Sopenharmony_ci			msg[0].addr = 0x63;
15298c2ecf20Sopenharmony_ci			msg[0].flags = 0;
15308c2ecf20Sopenharmony_ci			msg[0].len = 2;
15318c2ecf20Sopenharmony_ci			msg[0].buf = "\x0d\x02";
15328c2ecf20Sopenharmony_ci			ret = i2c_transfer(&d->i2c_adap, msg, 1);
15338c2ecf20Sopenharmony_ci			if (ret < 0)
15348c2ecf20Sopenharmony_ci				goto err;
15358c2ecf20Sopenharmony_ci		}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci		usleep_range(10000, 50000);
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci		fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap,
15408c2ecf20Sopenharmony_ci				&af9035_fc0012_config[adap->id]);
15418c2ecf20Sopenharmony_ci		break;
15428c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_38:
15438c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_51:
15448c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_52:
15458c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
15468c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
15478c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
15488c2ecf20Sopenharmony_ci	{
15498c2ecf20Sopenharmony_ci		struct platform_device *pdev;
15508c2ecf20Sopenharmony_ci		const char *name;
15518c2ecf20Sopenharmony_ci		struct it913x_platform_data it913x_pdata = {
15528c2ecf20Sopenharmony_ci			.regmap = state->af9033_config[adap->id].regmap,
15538c2ecf20Sopenharmony_ci			.fe = adap->fe[0],
15548c2ecf20Sopenharmony_ci		};
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci		switch (state->af9033_config[adap->id].tuner) {
15578c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_38:
15588c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_51:
15598c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_52:
15608c2ecf20Sopenharmony_ci			name = "it9133ax-tuner";
15618c2ecf20Sopenharmony_ci			break;
15628c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_60:
15638c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_61:
15648c2ecf20Sopenharmony_ci		case AF9033_TUNER_IT9135_62:
15658c2ecf20Sopenharmony_ci			name = "it9133bx-tuner";
15668c2ecf20Sopenharmony_ci			break;
15678c2ecf20Sopenharmony_ci		default:
15688c2ecf20Sopenharmony_ci			ret = -ENODEV;
15698c2ecf20Sopenharmony_ci			goto err;
15708c2ecf20Sopenharmony_ci		}
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci		if (state->dual_mode) {
15738c2ecf20Sopenharmony_ci			if (adap->id == 0)
15748c2ecf20Sopenharmony_ci				it913x_pdata.role = IT913X_ROLE_DUAL_MASTER;
15758c2ecf20Sopenharmony_ci			else
15768c2ecf20Sopenharmony_ci				it913x_pdata.role = IT913X_ROLE_DUAL_SLAVE;
15778c2ecf20Sopenharmony_ci		} else {
15788c2ecf20Sopenharmony_ci			it913x_pdata.role = IT913X_ROLE_SINGLE;
15798c2ecf20Sopenharmony_ci		}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci		request_module("%s", "it913x");
15828c2ecf20Sopenharmony_ci		pdev = platform_device_register_data(&d->intf->dev, name,
15838c2ecf20Sopenharmony_ci						     PLATFORM_DEVID_AUTO,
15848c2ecf20Sopenharmony_ci						     &it913x_pdata,
15858c2ecf20Sopenharmony_ci						     sizeof(it913x_pdata));
15868c2ecf20Sopenharmony_ci		if (IS_ERR(pdev) || !pdev->dev.driver) {
15878c2ecf20Sopenharmony_ci			ret = -ENODEV;
15888c2ecf20Sopenharmony_ci			goto err;
15898c2ecf20Sopenharmony_ci		}
15908c2ecf20Sopenharmony_ci		if (!try_module_get(pdev->dev.driver->owner)) {
15918c2ecf20Sopenharmony_ci			platform_device_unregister(pdev);
15928c2ecf20Sopenharmony_ci			ret = -ENODEV;
15938c2ecf20Sopenharmony_ci			goto err;
15948c2ecf20Sopenharmony_ci		}
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci		state->platform_device_tuner[adap->id] = pdev;
15978c2ecf20Sopenharmony_ci		fe = adap->fe[0];
15988c2ecf20Sopenharmony_ci		break;
15998c2ecf20Sopenharmony_ci	}
16008c2ecf20Sopenharmony_ci	default:
16018c2ecf20Sopenharmony_ci		fe = NULL;
16028c2ecf20Sopenharmony_ci	}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	if (fe == NULL) {
16058c2ecf20Sopenharmony_ci		ret = -ENODEV;
16068c2ecf20Sopenharmony_ci		goto err;
16078c2ecf20Sopenharmony_ci	}
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	return 0;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cierr:
16128c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	return ret;
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_cistatic int it930x_tuner_attach(struct dvb_usb_adapter *adap)
16188c2ecf20Sopenharmony_ci{
16198c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
16208c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
16218c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
16228c2ecf20Sopenharmony_ci	int ret;
16238c2ecf20Sopenharmony_ci	struct si2157_config si2157_config;
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	memset(&si2157_config, 0, sizeof(si2157_config));
16288c2ecf20Sopenharmony_ci	si2157_config.fe = adap->fe[0];
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	/*
16318c2ecf20Sopenharmony_ci	 * HACK: The Logilink VG0022A and TerraTec TC2 Stick have
16328c2ecf20Sopenharmony_ci	 * a bug: when the si2157 firmware that came with the device
16338c2ecf20Sopenharmony_ci	 * is replaced by a new one, the I2C transfers to the tuner
16348c2ecf20Sopenharmony_ci	 * will return just 0xff.
16358c2ecf20Sopenharmony_ci	 *
16368c2ecf20Sopenharmony_ci	 * Probably, the vendor firmware has some patch specifically
16378c2ecf20Sopenharmony_ci	 * designed for this device. So, we can't replace by the
16388c2ecf20Sopenharmony_ci	 * generic firmware. The right solution would be to extract
16398c2ecf20Sopenharmony_ci	 * the si2157 firmware from the original driver and ask the
16408c2ecf20Sopenharmony_ci	 * driver to load the specifically designed firmware, but,
16418c2ecf20Sopenharmony_ci	 * while we don't have that, the next best solution is to just
16428c2ecf20Sopenharmony_ci	 * keep the original firmware at the device.
16438c2ecf20Sopenharmony_ci	 */
16448c2ecf20Sopenharmony_ci	if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_DEXATEK &&
16458c2ecf20Sopenharmony_ci	     le16_to_cpu(d->udev->descriptor.idProduct) == 0x0100) ||
16468c2ecf20Sopenharmony_ci	    (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_TERRATEC &&
16478c2ecf20Sopenharmony_ci	     le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_TERRATEC_CINERGY_TC2_STICK))
16488c2ecf20Sopenharmony_ci		si2157_config.dont_load_firmware = true;
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	si2157_config.if_port = it930x_addresses_table[state->it930x_addresses].tuner_if_port;
16518c2ecf20Sopenharmony_ci	ret = af9035_add_i2c_dev(d, "si2157",
16528c2ecf20Sopenharmony_ci				 it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr,
16538c2ecf20Sopenharmony_ci				 &si2157_config, state->i2c_adapter_demod);
16548c2ecf20Sopenharmony_ci	if (ret)
16558c2ecf20Sopenharmony_ci		goto err;
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	return 0;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_cierr:
16608c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	return ret;
16638c2ecf20Sopenharmony_ci}
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_cistatic int it930x_tuner_detach(struct dvb_usb_adapter *adap)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
16698c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
16708c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	if (adap->id == 1) {
16758c2ecf20Sopenharmony_ci		if (state->i2c_client[3])
16768c2ecf20Sopenharmony_ci			af9035_del_i2c_dev(d);
16778c2ecf20Sopenharmony_ci	} else if (adap->id == 0) {
16788c2ecf20Sopenharmony_ci		if (state->i2c_client[1])
16798c2ecf20Sopenharmony_ci			af9035_del_i2c_dev(d);
16808c2ecf20Sopenharmony_ci	}
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	return 0;
16838c2ecf20Sopenharmony_ci}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_cistatic int af9035_tuner_detach(struct dvb_usb_adapter *adap)
16878c2ecf20Sopenharmony_ci{
16888c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
16898c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap_to_d(adap);
16908c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap->id=%d\n", adap->id);
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	switch (state->af9033_config[adap->id].tuner) {
16958c2ecf20Sopenharmony_ci	case AF9033_TUNER_TUA9001:
16968c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC2580:
16978c2ecf20Sopenharmony_ci		if (adap->id == 1) {
16988c2ecf20Sopenharmony_ci			if (state->i2c_client[3])
16998c2ecf20Sopenharmony_ci				af9035_del_i2c_dev(d);
17008c2ecf20Sopenharmony_ci		} else if (adap->id == 0) {
17018c2ecf20Sopenharmony_ci			if (state->i2c_client[1])
17028c2ecf20Sopenharmony_ci				af9035_del_i2c_dev(d);
17038c2ecf20Sopenharmony_ci		}
17048c2ecf20Sopenharmony_ci		break;
17058c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_38:
17068c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_51:
17078c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_52:
17088c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
17098c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
17108c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
17118c2ecf20Sopenharmony_ci	{
17128c2ecf20Sopenharmony_ci		struct platform_device *pdev;
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci		pdev = state->platform_device_tuner[adap->id];
17158c2ecf20Sopenharmony_ci		if (pdev) {
17168c2ecf20Sopenharmony_ci			module_put(pdev->dev.driver->owner);
17178c2ecf20Sopenharmony_ci			platform_device_unregister(pdev);
17188c2ecf20Sopenharmony_ci		}
17198c2ecf20Sopenharmony_ci		break;
17208c2ecf20Sopenharmony_ci	}
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	return 0;
17248c2ecf20Sopenharmony_ci}
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_cistatic int af9035_init(struct dvb_usb_device *d)
17278c2ecf20Sopenharmony_ci{
17288c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
17298c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
17308c2ecf20Sopenharmony_ci	int ret, i;
17318c2ecf20Sopenharmony_ci	u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4;
17328c2ecf20Sopenharmony_ci	u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4;
17338c2ecf20Sopenharmony_ci	struct reg_val_mask tab[] = {
17348c2ecf20Sopenharmony_ci		{ 0x80f99d, 0x01, 0x01 },
17358c2ecf20Sopenharmony_ci		{ 0x80f9a4, 0x01, 0x01 },
17368c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x00, 0x20 },
17378c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x00, 0x40 },
17388c2ecf20Sopenharmony_ci		{ 0x00dd13, 0x00, 0x20 },
17398c2ecf20Sopenharmony_ci		{ 0x00dd13, 0x00, 0x40 },
17408c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x20, 0x20 },
17418c2ecf20Sopenharmony_ci		{ 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
17428c2ecf20Sopenharmony_ci		{ 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
17438c2ecf20Sopenharmony_ci		{ 0x00dd0c, packet_size, 0xff},
17448c2ecf20Sopenharmony_ci		{ 0x00dd11, state->dual_mode << 6, 0x40 },
17458c2ecf20Sopenharmony_ci		{ 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
17468c2ecf20Sopenharmony_ci		{ 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
17478c2ecf20Sopenharmony_ci		{ 0x00dd0d, packet_size, 0xff },
17488c2ecf20Sopenharmony_ci		{ 0x80f9a3, state->dual_mode, 0x01 },
17498c2ecf20Sopenharmony_ci		{ 0x80f9cd, state->dual_mode, 0x01 },
17508c2ecf20Sopenharmony_ci		{ 0x80f99d, 0x00, 0x01 },
17518c2ecf20Sopenharmony_ci		{ 0x80f9a4, 0x00, 0x01 },
17528c2ecf20Sopenharmony_ci	};
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n",
17558c2ecf20Sopenharmony_ci		d->udev->speed, frame_size, packet_size);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	/* init endpoints */
17588c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tab); i++) {
17598c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
17608c2ecf20Sopenharmony_ci				tab[i].mask);
17618c2ecf20Sopenharmony_ci		if (ret < 0)
17628c2ecf20Sopenharmony_ci			goto err;
17638c2ecf20Sopenharmony_ci	}
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	return 0;
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_cierr:
17688c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci	return ret;
17718c2ecf20Sopenharmony_ci}
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_cistatic int it930x_init(struct dvb_usb_device *d)
17748c2ecf20Sopenharmony_ci{
17758c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
17768c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
17778c2ecf20Sopenharmony_ci	int ret, i;
17788c2ecf20Sopenharmony_ci	u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 816) * 188 / 4;
17798c2ecf20Sopenharmony_ci	u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4;
17808c2ecf20Sopenharmony_ci	struct reg_val_mask tab[] = {
17818c2ecf20Sopenharmony_ci		{ 0x00da1a, 0x00, 0x01 }, /* ignore_sync_byte */
17828c2ecf20Sopenharmony_ci		{ 0x00f41f, 0x04, 0x04 }, /* dvbt_inten */
17838c2ecf20Sopenharmony_ci		{ 0x00da10, 0x00, 0x01 }, /* mpeg_full_speed */
17848c2ecf20Sopenharmony_ci		{ 0x00f41a, 0x01, 0x01 }, /* dvbt_en */
17858c2ecf20Sopenharmony_ci		{ 0x00da1d, 0x01, 0x01 }, /* mp2_sw_rst, reset EP4 */
17868c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x00, 0x20 }, /* ep4_tx_en, disable EP4 */
17878c2ecf20Sopenharmony_ci		{ 0x00dd13, 0x00, 0x20 }, /* ep4_tx_nak, disable EP4 NAK */
17888c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x20, 0x20 }, /* ep4_tx_en, enable EP4 */
17898c2ecf20Sopenharmony_ci		{ 0x00dd11, 0x00, 0x40 }, /* ep5_tx_en, disable EP5 */
17908c2ecf20Sopenharmony_ci		{ 0x00dd13, 0x00, 0x40 }, /* ep5_tx_nak, disable EP5 NAK */
17918c2ecf20Sopenharmony_ci		{ 0x00dd11, state->dual_mode << 6, 0x40 }, /* enable EP5 */
17928c2ecf20Sopenharmony_ci		{ 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
17938c2ecf20Sopenharmony_ci		{ 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
17948c2ecf20Sopenharmony_ci		{ 0x00dd0c, packet_size, 0xff},
17958c2ecf20Sopenharmony_ci		{ 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
17968c2ecf20Sopenharmony_ci		{ 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
17978c2ecf20Sopenharmony_ci		{ 0x00dd0d, packet_size, 0xff },
17988c2ecf20Sopenharmony_ci		{ 0x00da1d, 0x00, 0x01 }, /* mp2_sw_rst, disable */
17998c2ecf20Sopenharmony_ci		{ 0x00d833, 0x01, 0xff }, /* slew rate ctrl: slew rate boosts */
18008c2ecf20Sopenharmony_ci		{ 0x00d830, 0x00, 0xff }, /* Bit 0 of output driving control */
18018c2ecf20Sopenharmony_ci		{ 0x00d831, 0x01, 0xff }, /* Bit 1 of output driving control */
18028c2ecf20Sopenharmony_ci		{ 0x00d832, 0x00, 0xff }, /* Bit 2 of output driving control */
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci		/* suspend gpio1 for TS-C */
18058c2ecf20Sopenharmony_ci		{ 0x00d8b0, 0x01, 0xff }, /* gpio1 */
18068c2ecf20Sopenharmony_ci		{ 0x00d8b1, 0x01, 0xff }, /* gpio1 */
18078c2ecf20Sopenharmony_ci		{ 0x00d8af, 0x00, 0xff }, /* gpio1 */
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci		/* suspend gpio7 for TS-D */
18108c2ecf20Sopenharmony_ci		{ 0x00d8c4, 0x01, 0xff }, /* gpio7 */
18118c2ecf20Sopenharmony_ci		{ 0x00d8c5, 0x01, 0xff }, /* gpio7 */
18128c2ecf20Sopenharmony_ci		{ 0x00d8c3, 0x00, 0xff }, /* gpio7 */
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci		/* suspend gpio13 for TS-B */
18158c2ecf20Sopenharmony_ci		{ 0x00d8dc, 0x01, 0xff }, /* gpio13 */
18168c2ecf20Sopenharmony_ci		{ 0x00d8dd, 0x01, 0xff }, /* gpio13 */
18178c2ecf20Sopenharmony_ci		{ 0x00d8db, 0x00, 0xff }, /* gpio13 */
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci		/* suspend gpio14 for TS-E */
18208c2ecf20Sopenharmony_ci		{ 0x00d8e4, 0x01, 0xff }, /* gpio14 */
18218c2ecf20Sopenharmony_ci		{ 0x00d8e5, 0x01, 0xff }, /* gpio14 */
18228c2ecf20Sopenharmony_ci		{ 0x00d8e3, 0x00, 0xff }, /* gpio14 */
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci		/* suspend gpio15 for TS-A */
18258c2ecf20Sopenharmony_ci		{ 0x00d8e8, 0x01, 0xff }, /* gpio15 */
18268c2ecf20Sopenharmony_ci		{ 0x00d8e9, 0x01, 0xff }, /* gpio15 */
18278c2ecf20Sopenharmony_ci		{ 0x00d8e7, 0x00, 0xff }, /* gpio15 */
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci		{ 0x00da58, 0x00, 0x01 }, /* ts_in_src, serial */
18308c2ecf20Sopenharmony_ci		{ 0x00da73, 0x01, 0xff }, /* ts0_aggre_mode */
18318c2ecf20Sopenharmony_ci		{ 0x00da78, 0x47, 0xff }, /* ts0_sync_byte */
18328c2ecf20Sopenharmony_ci		{ 0x00da4c, 0x01, 0xff }, /* ts0_en */
18338c2ecf20Sopenharmony_ci		{ 0x00da5a, 0x1f, 0xff }, /* ts_fail_ignore */
18348c2ecf20Sopenharmony_ci	};
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "USB speed=%d frame_size=%04x packet_size=%02x\n",
18378c2ecf20Sopenharmony_ci		d->udev->speed, frame_size, packet_size);
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci	/* init endpoints */
18408c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tab); i++) {
18418c2ecf20Sopenharmony_ci		ret = af9035_wr_reg_mask(d, tab[i].reg,
18428c2ecf20Sopenharmony_ci				tab[i].val, tab[i].mask);
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci		if (ret < 0)
18458c2ecf20Sopenharmony_ci			goto err;
18468c2ecf20Sopenharmony_ci	}
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci	return 0;
18498c2ecf20Sopenharmony_cierr:
18508c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	return ret;
18538c2ecf20Sopenharmony_ci}
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_RC_CORE)
18578c2ecf20Sopenharmony_cistatic int af9035_rc_query(struct dvb_usb_device *d)
18588c2ecf20Sopenharmony_ci{
18598c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
18608c2ecf20Sopenharmony_ci	int ret;
18618c2ecf20Sopenharmony_ci	enum rc_proto proto;
18628c2ecf20Sopenharmony_ci	u32 key;
18638c2ecf20Sopenharmony_ci	u8 buf[4];
18648c2ecf20Sopenharmony_ci	struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf };
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	ret = af9035_ctrl_msg(d, &req);
18678c2ecf20Sopenharmony_ci	if (ret == 1)
18688c2ecf20Sopenharmony_ci		return 0;
18698c2ecf20Sopenharmony_ci	else if (ret < 0)
18708c2ecf20Sopenharmony_ci		goto err;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci	if ((buf[2] + buf[3]) == 0xff) {
18738c2ecf20Sopenharmony_ci		if ((buf[0] + buf[1]) == 0xff) {
18748c2ecf20Sopenharmony_ci			/* NEC standard 16bit */
18758c2ecf20Sopenharmony_ci			key = RC_SCANCODE_NEC(buf[0], buf[2]);
18768c2ecf20Sopenharmony_ci			proto = RC_PROTO_NEC;
18778c2ecf20Sopenharmony_ci		} else {
18788c2ecf20Sopenharmony_ci			/* NEC extended 24bit */
18798c2ecf20Sopenharmony_ci			key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]);
18808c2ecf20Sopenharmony_ci			proto = RC_PROTO_NECX;
18818c2ecf20Sopenharmony_ci		}
18828c2ecf20Sopenharmony_ci	} else {
18838c2ecf20Sopenharmony_ci		/* NEC full code 32bit */
18848c2ecf20Sopenharmony_ci		key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
18858c2ecf20Sopenharmony_ci					buf[2] << 8  | buf[3]);
18868c2ecf20Sopenharmony_ci		proto = RC_PROTO_NEC32;
18878c2ecf20Sopenharmony_ci	}
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "%*ph\n", 4, buf);
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	rc_keydown(d->rc_dev, proto, key, 0);
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci	return 0;
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_cierr:
18968c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "failed=%d\n", ret);
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	return ret;
18998c2ecf20Sopenharmony_ci}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_cistatic int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
19028c2ecf20Sopenharmony_ci{
19038c2ecf20Sopenharmony_ci	struct state *state = d_to_priv(d);
19048c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "ir_mode=%02x ir_type=%02x\n",
19078c2ecf20Sopenharmony_ci		state->ir_mode, state->ir_type);
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	/* don't activate rc if in HID mode or if not available */
19108c2ecf20Sopenharmony_ci	if (state->ir_mode == 0x05) {
19118c2ecf20Sopenharmony_ci		switch (state->ir_type) {
19128c2ecf20Sopenharmony_ci		case 0: /* NEC */
19138c2ecf20Sopenharmony_ci		default:
19148c2ecf20Sopenharmony_ci			rc->allowed_protos = RC_PROTO_BIT_NEC |
19158c2ecf20Sopenharmony_ci					RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32;
19168c2ecf20Sopenharmony_ci			break;
19178c2ecf20Sopenharmony_ci		case 1: /* RC6 */
19188c2ecf20Sopenharmony_ci			rc->allowed_protos = RC_PROTO_BIT_RC6_MCE;
19198c2ecf20Sopenharmony_ci			break;
19208c2ecf20Sopenharmony_ci		}
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci		rc->query = af9035_rc_query;
19238c2ecf20Sopenharmony_ci		rc->interval = 500;
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci		/* load empty to enable rc */
19268c2ecf20Sopenharmony_ci		if (!rc->map_name)
19278c2ecf20Sopenharmony_ci			rc->map_name = RC_MAP_EMPTY;
19288c2ecf20Sopenharmony_ci	}
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	return 0;
19318c2ecf20Sopenharmony_ci}
19328c2ecf20Sopenharmony_ci#else
19338c2ecf20Sopenharmony_ci	#define af9035_get_rc_config NULL
19348c2ecf20Sopenharmony_ci#endif
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_cistatic int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
19378c2ecf20Sopenharmony_ci		struct usb_data_stream_properties *stream)
19388c2ecf20Sopenharmony_ci{
19398c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = fe_to_d(fe);
19408c2ecf20Sopenharmony_ci	struct usb_interface *intf = d->intf;
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	dev_dbg(&intf->dev, "adap=%d\n", fe_to_adap(fe)->id);
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	if (d->udev->speed == USB_SPEED_FULL)
19458c2ecf20Sopenharmony_ci		stream->u.bulk.buffersize = 5 * 188;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	return 0;
19488c2ecf20Sopenharmony_ci}
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_cistatic int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
19518c2ecf20Sopenharmony_ci{
19528c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci	return state->ops.pid_filter_ctrl(adap->fe[0], onoff);
19558c2ecf20Sopenharmony_ci}
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_cistatic int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
19588c2ecf20Sopenharmony_ci		int onoff)
19598c2ecf20Sopenharmony_ci{
19608c2ecf20Sopenharmony_ci	struct state *state = adap_to_priv(adap);
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci	return state->ops.pid_filter(adap->fe[0], index, pid, onoff);
19638c2ecf20Sopenharmony_ci}
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_cistatic int af9035_probe(struct usb_interface *intf,
19668c2ecf20Sopenharmony_ci		const struct usb_device_id *id)
19678c2ecf20Sopenharmony_ci{
19688c2ecf20Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(intf);
19698c2ecf20Sopenharmony_ci	char manufacturer[sizeof("Afatech")];
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	memset(manufacturer, 0, sizeof(manufacturer));
19728c2ecf20Sopenharmony_ci	usb_string(udev, udev->descriptor.iManufacturer,
19738c2ecf20Sopenharmony_ci			manufacturer, sizeof(manufacturer));
19748c2ecf20Sopenharmony_ci	/*
19758c2ecf20Sopenharmony_ci	 * There is two devices having same ID but different chipset. One uses
19768c2ecf20Sopenharmony_ci	 * AF9015 and the other IT9135 chipset. Only difference seen on lsusb
19778c2ecf20Sopenharmony_ci	 * is iManufacturer string.
19788c2ecf20Sopenharmony_ci	 *
19798c2ecf20Sopenharmony_ci	 * idVendor           0x0ccd TerraTec Electronic GmbH
19808c2ecf20Sopenharmony_ci	 * idProduct          0x0099
19818c2ecf20Sopenharmony_ci	 * bcdDevice            2.00
19828c2ecf20Sopenharmony_ci	 * iManufacturer           1 Afatech
19838c2ecf20Sopenharmony_ci	 * iProduct                2 DVB-T 2
19848c2ecf20Sopenharmony_ci	 *
19858c2ecf20Sopenharmony_ci	 * idVendor           0x0ccd TerraTec Electronic GmbH
19868c2ecf20Sopenharmony_ci	 * idProduct          0x0099
19878c2ecf20Sopenharmony_ci	 * bcdDevice            2.00
19888c2ecf20Sopenharmony_ci	 * iManufacturer           1 ITE Technologies, Inc.
19898c2ecf20Sopenharmony_ci	 * iProduct                2 DVB-T TV Stick
19908c2ecf20Sopenharmony_ci	 */
19918c2ecf20Sopenharmony_ci	if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) &&
19928c2ecf20Sopenharmony_ci			(le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) {
19938c2ecf20Sopenharmony_ci		if (!strcmp("Afatech", manufacturer)) {
19948c2ecf20Sopenharmony_ci			dev_dbg(&udev->dev, "rejecting device\n");
19958c2ecf20Sopenharmony_ci			return -ENODEV;
19968c2ecf20Sopenharmony_ci		}
19978c2ecf20Sopenharmony_ci	}
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ci	return dvb_usbv2_probe(intf, id);
20008c2ecf20Sopenharmony_ci}
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci/* interface 0 is used by DVB-T receiver and
20038c2ecf20Sopenharmony_ci   interface 1 is for remote controller (HID) */
20048c2ecf20Sopenharmony_cistatic const struct dvb_usb_device_properties af9035_props = {
20058c2ecf20Sopenharmony_ci	.driver_name = KBUILD_MODNAME,
20068c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
20078c2ecf20Sopenharmony_ci	.adapter_nr = adapter_nr,
20088c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct state),
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x02,
20118c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint_response = 0x81,
20128c2ecf20Sopenharmony_ci
20138c2ecf20Sopenharmony_ci	.identify_state = af9035_identify_state,
20148c2ecf20Sopenharmony_ci	.download_firmware = af9035_download_firmware,
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	.i2c_algo = &af9035_i2c_algo,
20178c2ecf20Sopenharmony_ci	.read_config = af9035_read_config,
20188c2ecf20Sopenharmony_ci	.frontend_attach = af9035_frontend_attach,
20198c2ecf20Sopenharmony_ci	.frontend_detach = af9035_frontend_detach,
20208c2ecf20Sopenharmony_ci	.tuner_attach = af9035_tuner_attach,
20218c2ecf20Sopenharmony_ci	.tuner_detach = af9035_tuner_detach,
20228c2ecf20Sopenharmony_ci	.init = af9035_init,
20238c2ecf20Sopenharmony_ci	.get_rc_config = af9035_get_rc_config,
20248c2ecf20Sopenharmony_ci	.get_stream_config = af9035_get_stream_config,
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci	.get_adapter_count = af9035_get_adapter_count,
20278c2ecf20Sopenharmony_ci	.adapter = {
20288c2ecf20Sopenharmony_ci		{
20298c2ecf20Sopenharmony_ci			.caps = DVB_USB_ADAP_HAS_PID_FILTER |
20308c2ecf20Sopenharmony_ci				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci			.pid_filter_count = 32,
20338c2ecf20Sopenharmony_ci			.pid_filter_ctrl = af9035_pid_filter_ctrl,
20348c2ecf20Sopenharmony_ci			.pid_filter = af9035_pid_filter,
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci			.stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
20378c2ecf20Sopenharmony_ci		}, {
20388c2ecf20Sopenharmony_ci			.caps = DVB_USB_ADAP_HAS_PID_FILTER |
20398c2ecf20Sopenharmony_ci				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci			.pid_filter_count = 32,
20428c2ecf20Sopenharmony_ci			.pid_filter_ctrl = af9035_pid_filter_ctrl,
20438c2ecf20Sopenharmony_ci			.pid_filter = af9035_pid_filter,
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_ci			.stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
20468c2ecf20Sopenharmony_ci		},
20478c2ecf20Sopenharmony_ci	},
20488c2ecf20Sopenharmony_ci};
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_cistatic const struct dvb_usb_device_properties it930x_props = {
20518c2ecf20Sopenharmony_ci	.driver_name = KBUILD_MODNAME,
20528c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
20538c2ecf20Sopenharmony_ci	.adapter_nr = adapter_nr,
20548c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct state),
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x02,
20578c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint_response = 0x81,
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci	.identify_state = af9035_identify_state,
20608c2ecf20Sopenharmony_ci	.download_firmware = af9035_download_firmware,
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	.i2c_algo = &af9035_i2c_algo,
20638c2ecf20Sopenharmony_ci	.read_config = af9035_read_config,
20648c2ecf20Sopenharmony_ci	.frontend_attach = it930x_frontend_attach,
20658c2ecf20Sopenharmony_ci	.frontend_detach = af9035_frontend_detach,
20668c2ecf20Sopenharmony_ci	.tuner_attach = it930x_tuner_attach,
20678c2ecf20Sopenharmony_ci	.tuner_detach = it930x_tuner_detach,
20688c2ecf20Sopenharmony_ci	.init = it930x_init,
20698c2ecf20Sopenharmony_ci	.get_stream_config = af9035_get_stream_config,
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	.get_adapter_count = af9035_get_adapter_count,
20728c2ecf20Sopenharmony_ci	.adapter = {
20738c2ecf20Sopenharmony_ci		{
20748c2ecf20Sopenharmony_ci			.stream = DVB_USB_STREAM_BULK(0x84, 4, 816 * 188),
20758c2ecf20Sopenharmony_ci		}, {
20768c2ecf20Sopenharmony_ci			.stream = DVB_USB_STREAM_BULK(0x85, 4, 816 * 188),
20778c2ecf20Sopenharmony_ci		},
20788c2ecf20Sopenharmony_ci	},
20798c2ecf20Sopenharmony_ci};
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_cistatic const struct usb_device_id af9035_id_table[] = {
20828c2ecf20Sopenharmony_ci	/* AF9035 devices */
20838c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035,
20848c2ecf20Sopenharmony_ci		&af9035_props, "Afatech AF9035 reference design", NULL) },
20858c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000,
20868c2ecf20Sopenharmony_ci		&af9035_props, "Afatech AF9035 reference design", NULL) },
20878c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001,
20888c2ecf20Sopenharmony_ci		&af9035_props, "Afatech AF9035 reference design", NULL) },
20898c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002,
20908c2ecf20Sopenharmony_ci		&af9035_props, "Afatech AF9035 reference design", NULL) },
20918c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003,
20928c2ecf20Sopenharmony_ci		&af9035_props, "Afatech AF9035 reference design", NULL) },
20938c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK,
20948c2ecf20Sopenharmony_ci		&af9035_props, "TerraTec Cinergy T Stick", NULL) },
20958c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835,
20968c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
20978c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835,
20988c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
20998c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867,
21008c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
21018c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867,
21028c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
21038c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR,
21048c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia Twinstar (A825)", NULL) },
21058c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS,
21068c2ecf20Sopenharmony_ci		&af9035_props, "Asus U3100Mini Plus", NULL) },
21078c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa,
21088c2ecf20Sopenharmony_ci		&af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) },
21098c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, 0x0337,
21108c2ecf20Sopenharmony_ci		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
21118c2ecf20Sopenharmony_ci       { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_EVOLVEO_XTRATV_STICK,
21128c2ecf20Sopenharmony_ci	       &af9035_props, "EVOLVEO XtraTV stick", NULL) },
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci	/* IT9135 devices */
21158c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135,
21168c2ecf20Sopenharmony_ci		&af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) },
21178c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005,
21188c2ecf20Sopenharmony_ci		&af9035_props, "ITE 9135(9005) Generic", RC_MAP_IT913X_V2) },
21198c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006,
21208c2ecf20Sopenharmony_ci		&af9035_props, "ITE 9135(9006) Generic", RC_MAP_IT913X_V1) },
21218c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835,
21228c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia A835B(1835)", RC_MAP_IT913X_V2) },
21238c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835,
21248c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia A835B(2835)", RC_MAP_IT913X_V2) },
21258c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835,
21268c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia A835B(3835)", RC_MAP_IT913X_V2) },
21278c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835,
21288c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia A835B(4835)",	RC_MAP_IT913X_V2) },
21298c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD110,
21308c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia AverTV Volar HD 2 (TD110)", RC_MAP_AVERMEDIA_RM_KS) },
21318c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335,
21328c2ecf20Sopenharmony_ci		&af9035_props, "Avermedia H335", RC_MAP_IT913X_V2) },
21338c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09,
21348c2ecf20Sopenharmony_ci		&af9035_props, "Kworld UB499-2T T09", RC_MAP_IT913X_V1) },
21358c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137,
21368c2ecf20Sopenharmony_ci		&af9035_props, "Sveon STV22 Dual DVB-T HDTV",
21378c2ecf20Sopenharmony_ci							RC_MAP_IT913X_V1) },
21388c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2,
21398c2ecf20Sopenharmony_ci		&af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2",
21408c2ecf20Sopenharmony_ci							RC_MAP_IT913X_V1) },
21418c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T1,
21428c2ecf20Sopenharmony_ci		&af9035_props, "TerraTec T1", RC_MAP_IT913X_V1) },
21438c2ecf20Sopenharmony_ci	/* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
21448c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
21458c2ecf20Sopenharmony_ci		&af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)",
21468c2ecf20Sopenharmony_ci		NULL) },
21478c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05,
21488c2ecf20Sopenharmony_ci		&af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
21498c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900,
21508c2ecf20Sopenharmony_ci		&af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) },
21518c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E,
21528c2ecf20Sopenharmony_ci		&af9035_props, "PCTV AndroiDTV (78e)", RC_MAP_IT913X_V1) },
21538c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E,
21548c2ecf20Sopenharmony_ci		&af9035_props, "PCTV microStick (79e)", RC_MAP_IT913X_V2) },
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	/* IT930x devices */
21578c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303,
21588c2ecf20Sopenharmony_ci		&it930x_props, "ITE 9303 Generic", NULL) },
21598c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD310,
21608c2ecf20Sopenharmony_ci		&it930x_props, "AVerMedia TD310 DVB-T2", NULL) },
21618c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x0100,
21628c2ecf20Sopenharmony_ci		&it930x_props, "Logilink VG0022A", NULL) },
21638c2ecf20Sopenharmony_ci	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_TC2_STICK,
21648c2ecf20Sopenharmony_ci		&it930x_props, "TerraTec Cinergy TC2 Stick", NULL) },
21658c2ecf20Sopenharmony_ci	{ }
21668c2ecf20Sopenharmony_ci};
21678c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, af9035_id_table);
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_cistatic struct usb_driver af9035_usb_driver = {
21708c2ecf20Sopenharmony_ci	.name = KBUILD_MODNAME,
21718c2ecf20Sopenharmony_ci	.id_table = af9035_id_table,
21728c2ecf20Sopenharmony_ci	.probe = af9035_probe,
21738c2ecf20Sopenharmony_ci	.disconnect = dvb_usbv2_disconnect,
21748c2ecf20Sopenharmony_ci	.suspend = dvb_usbv2_suspend,
21758c2ecf20Sopenharmony_ci	.resume = dvb_usbv2_resume,
21768c2ecf20Sopenharmony_ci	.reset_resume = dvb_usbv2_reset_resume,
21778c2ecf20Sopenharmony_ci	.no_dynamic_id = 1,
21788c2ecf20Sopenharmony_ci	.soft_unbind = 1,
21798c2ecf20Sopenharmony_ci};
21808c2ecf20Sopenharmony_ci
21818c2ecf20Sopenharmony_cimodule_usb_driver(af9035_usb_driver);
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ciMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
21848c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Afatech AF9035 driver");
21858c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
21868c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_AF9035);
21878c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1);
21888c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2);
21898c2ecf20Sopenharmony_ciMODULE_FIRMWARE(AF9035_FIRMWARE_IT9303);
2190