18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* DVB USB framework compliant Linux driver for the
38c2ecf20Sopenharmony_ci *	DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
48c2ecf20Sopenharmony_ci *	TeVii S421, S480, S482, S600, S630, S632, S650, S660, S662,
58c2ecf20Sopenharmony_ci *	Prof 1100, 7500,
68c2ecf20Sopenharmony_ci *	Geniatech SU3000, T220,
78c2ecf20Sopenharmony_ci *	TechnoTrend S2-4600,
88c2ecf20Sopenharmony_ci *	Terratec Cinergy S2 cards
98c2ecf20Sopenharmony_ci * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by)
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#include <media/dvb-usb-ids.h>
148c2ecf20Sopenharmony_ci#include "dw2102.h"
158c2ecf20Sopenharmony_ci#include "si21xx.h"
168c2ecf20Sopenharmony_ci#include "stv0299.h"
178c2ecf20Sopenharmony_ci#include "z0194a.h"
188c2ecf20Sopenharmony_ci#include "stv0288.h"
198c2ecf20Sopenharmony_ci#include "stb6000.h"
208c2ecf20Sopenharmony_ci#include "eds1547.h"
218c2ecf20Sopenharmony_ci#include "cx24116.h"
228c2ecf20Sopenharmony_ci#include "tda1002x.h"
238c2ecf20Sopenharmony_ci#include "mt312.h"
248c2ecf20Sopenharmony_ci#include "zl10039.h"
258c2ecf20Sopenharmony_ci#include "ts2020.h"
268c2ecf20Sopenharmony_ci#include "ds3000.h"
278c2ecf20Sopenharmony_ci#include "stv0900.h"
288c2ecf20Sopenharmony_ci#include "stv6110.h"
298c2ecf20Sopenharmony_ci#include "stb6100.h"
308c2ecf20Sopenharmony_ci#include "stb6100_proc.h"
318c2ecf20Sopenharmony_ci#include "m88rs2000.h"
328c2ecf20Sopenharmony_ci#include "tda18271.h"
338c2ecf20Sopenharmony_ci#include "cxd2820r.h"
348c2ecf20Sopenharmony_ci#include "m88ds3103.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */
378c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE  64
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define DW210X_READ_MSG 0
418c2ecf20Sopenharmony_ci#define DW210X_WRITE_MSG 1
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define REG_1F_SYMBOLRATE_BYTE0 0x1f
448c2ecf20Sopenharmony_ci#define REG_20_SYMBOLRATE_BYTE1 0x20
458c2ecf20Sopenharmony_ci#define REG_21_SYMBOLRATE_BYTE2 0x21
468c2ecf20Sopenharmony_ci/* on my own*/
478c2ecf20Sopenharmony_ci#define DW2102_VOLTAGE_CTRL (0x1800)
488c2ecf20Sopenharmony_ci#define SU3000_STREAM_CTRL (0x1900)
498c2ecf20Sopenharmony_ci#define DW2102_RC_QUERY (0x1a00)
508c2ecf20Sopenharmony_ci#define DW2102_LED_CTRL (0x1b00)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define DW2101_FIRMWARE "dvb-usb-dw2101.fw"
538c2ecf20Sopenharmony_ci#define DW2102_FIRMWARE "dvb-usb-dw2102.fw"
548c2ecf20Sopenharmony_ci#define DW2104_FIRMWARE "dvb-usb-dw2104.fw"
558c2ecf20Sopenharmony_ci#define DW3101_FIRMWARE "dvb-usb-dw3101.fw"
568c2ecf20Sopenharmony_ci#define S630_FIRMWARE   "dvb-usb-s630.fw"
578c2ecf20Sopenharmony_ci#define S660_FIRMWARE   "dvb-usb-s660.fw"
588c2ecf20Sopenharmony_ci#define P1100_FIRMWARE  "dvb-usb-p1100.fw"
598c2ecf20Sopenharmony_ci#define P7500_FIRMWARE  "dvb-usb-p7500.fw"
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define	err_str "did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware"
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct dw2102_state {
648c2ecf20Sopenharmony_ci	u8 initialized;
658c2ecf20Sopenharmony_ci	u8 last_lock;
668c2ecf20Sopenharmony_ci	u8 data[MAX_XFER_SIZE + 4];
678c2ecf20Sopenharmony_ci	struct i2c_client *i2c_client_demod;
688c2ecf20Sopenharmony_ci	struct i2c_client *i2c_client_tuner;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* fe hook functions*/
718c2ecf20Sopenharmony_ci	int (*old_set_voltage)(struct dvb_frontend *f, enum fe_sec_voltage v);
728c2ecf20Sopenharmony_ci	int (*fe_read_status)(struct dvb_frontend *fe,
738c2ecf20Sopenharmony_ci			      enum fe_status *status);
748c2ecf20Sopenharmony_ci};
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/* debug */
778c2ecf20Sopenharmony_cistatic int dvb_usb_dw2102_debug;
788c2ecf20Sopenharmony_cimodule_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
798c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
808c2ecf20Sopenharmony_ci						DVB_USB_DEBUG_STATUS);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/* demod probe */
838c2ecf20Sopenharmony_cistatic int demod_probe = 1;
848c2ecf20Sopenharmony_cimodule_param_named(demod, demod_probe, int, 0644);
858c2ecf20Sopenharmony_ciMODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 4=stv0903+stb6100(or-able)).");
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
908c2ecf20Sopenharmony_ci			u16 index, u8 * data, u16 len, int flags)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	int ret;
938c2ecf20Sopenharmony_ci	u8 *u8buf;
948c2ecf20Sopenharmony_ci	unsigned int pipe = (flags == DW210X_READ_MSG) ?
958c2ecf20Sopenharmony_ci				usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
968c2ecf20Sopenharmony_ci	u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	u8buf = kmalloc(len, GFP_KERNEL);
998c2ecf20Sopenharmony_ci	if (!u8buf)
1008c2ecf20Sopenharmony_ci		return -ENOMEM;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (flags == DW210X_WRITE_MSG)
1048c2ecf20Sopenharmony_ci		memcpy(u8buf, data, len);
1058c2ecf20Sopenharmony_ci	ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
1068c2ecf20Sopenharmony_ci				value, index , u8buf, len, 2000);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (flags == DW210X_READ_MSG)
1098c2ecf20Sopenharmony_ci		memcpy(data, u8buf, len);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	kfree(u8buf);
1128c2ecf20Sopenharmony_ci	return ret;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/* I2C */
1168c2ecf20Sopenharmony_cistatic int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
1178c2ecf20Sopenharmony_ci		int num)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
1208c2ecf20Sopenharmony_ci	int i = 0;
1218c2ecf20Sopenharmony_ci	u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
1228c2ecf20Sopenharmony_ci	u16 value;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (!d)
1258c2ecf20Sopenharmony_ci		return -ENODEV;
1268c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
1278c2ecf20Sopenharmony_ci		return -EAGAIN;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	switch (num) {
1308c2ecf20Sopenharmony_ci	case 2:
1318c2ecf20Sopenharmony_ci		if (msg[0].len < 1) {
1328c2ecf20Sopenharmony_ci			num = -EOPNOTSUPP;
1338c2ecf20Sopenharmony_ci			break;
1348c2ecf20Sopenharmony_ci		}
1358c2ecf20Sopenharmony_ci		/* read stv0299 register */
1368c2ecf20Sopenharmony_ci		value = msg[0].buf[0];/* register */
1378c2ecf20Sopenharmony_ci		for (i = 0; i < msg[1].len; i++) {
1388c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb5, value + i, 0,
1398c2ecf20Sopenharmony_ci					buf6, 2, DW210X_READ_MSG);
1408c2ecf20Sopenharmony_ci			msg[1].buf[i] = buf6[0];
1418c2ecf20Sopenharmony_ci		}
1428c2ecf20Sopenharmony_ci		break;
1438c2ecf20Sopenharmony_ci	case 1:
1448c2ecf20Sopenharmony_ci		switch (msg[0].addr) {
1458c2ecf20Sopenharmony_ci		case 0x68:
1468c2ecf20Sopenharmony_ci			if (msg[0].len < 2) {
1478c2ecf20Sopenharmony_ci				num = -EOPNOTSUPP;
1488c2ecf20Sopenharmony_ci				break;
1498c2ecf20Sopenharmony_ci			}
1508c2ecf20Sopenharmony_ci			/* write to stv0299 register */
1518c2ecf20Sopenharmony_ci			buf6[0] = 0x2a;
1528c2ecf20Sopenharmony_ci			buf6[1] = msg[0].buf[0];
1538c2ecf20Sopenharmony_ci			buf6[2] = msg[0].buf[1];
1548c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb2, 0, 0,
1558c2ecf20Sopenharmony_ci					buf6, 3, DW210X_WRITE_MSG);
1568c2ecf20Sopenharmony_ci			break;
1578c2ecf20Sopenharmony_ci		case 0x60:
1588c2ecf20Sopenharmony_ci			if (msg[0].flags == 0) {
1598c2ecf20Sopenharmony_ci				if (msg[0].len < 4) {
1608c2ecf20Sopenharmony_ci					num = -EOPNOTSUPP;
1618c2ecf20Sopenharmony_ci					break;
1628c2ecf20Sopenharmony_ci				}
1638c2ecf20Sopenharmony_ci			/* write to tuner pll */
1648c2ecf20Sopenharmony_ci				buf6[0] = 0x2c;
1658c2ecf20Sopenharmony_ci				buf6[1] = 5;
1668c2ecf20Sopenharmony_ci				buf6[2] = 0xc0;
1678c2ecf20Sopenharmony_ci				buf6[3] = msg[0].buf[0];
1688c2ecf20Sopenharmony_ci				buf6[4] = msg[0].buf[1];
1698c2ecf20Sopenharmony_ci				buf6[5] = msg[0].buf[2];
1708c2ecf20Sopenharmony_ci				buf6[6] = msg[0].buf[3];
1718c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0xb2, 0, 0,
1728c2ecf20Sopenharmony_ci						buf6, 7, DW210X_WRITE_MSG);
1738c2ecf20Sopenharmony_ci			} else {
1748c2ecf20Sopenharmony_ci				if (msg[0].len < 1) {
1758c2ecf20Sopenharmony_ci					num = -EOPNOTSUPP;
1768c2ecf20Sopenharmony_ci					break;
1778c2ecf20Sopenharmony_ci				}
1788c2ecf20Sopenharmony_ci			/* read from tuner */
1798c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0xb5, 0, 0,
1808c2ecf20Sopenharmony_ci						buf6, 1, DW210X_READ_MSG);
1818c2ecf20Sopenharmony_ci				msg[0].buf[0] = buf6[0];
1828c2ecf20Sopenharmony_ci			}
1838c2ecf20Sopenharmony_ci			break;
1848c2ecf20Sopenharmony_ci		case (DW2102_RC_QUERY):
1858c2ecf20Sopenharmony_ci			if (msg[0].len < 2) {
1868c2ecf20Sopenharmony_ci				num = -EOPNOTSUPP;
1878c2ecf20Sopenharmony_ci				break;
1888c2ecf20Sopenharmony_ci			}
1898c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
1908c2ecf20Sopenharmony_ci					buf6, 2, DW210X_READ_MSG);
1918c2ecf20Sopenharmony_ci			msg[0].buf[0] = buf6[0];
1928c2ecf20Sopenharmony_ci			msg[0].buf[1] = buf6[1];
1938c2ecf20Sopenharmony_ci			break;
1948c2ecf20Sopenharmony_ci		case (DW2102_VOLTAGE_CTRL):
1958c2ecf20Sopenharmony_ci			if (msg[0].len < 1) {
1968c2ecf20Sopenharmony_ci				num = -EOPNOTSUPP;
1978c2ecf20Sopenharmony_ci				break;
1988c2ecf20Sopenharmony_ci			}
1998c2ecf20Sopenharmony_ci			buf6[0] = 0x30;
2008c2ecf20Sopenharmony_ci			buf6[1] = msg[0].buf[0];
2018c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb2, 0, 0,
2028c2ecf20Sopenharmony_ci					buf6, 2, DW210X_WRITE_MSG);
2038c2ecf20Sopenharmony_ci			break;
2048c2ecf20Sopenharmony_ci		}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		break;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
2108c2ecf20Sopenharmony_ci	return num;
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
2148c2ecf20Sopenharmony_ci						struct i2c_msg msg[], int num)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
2178c2ecf20Sopenharmony_ci	u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (!d)
2208c2ecf20Sopenharmony_ci		return -ENODEV;
2218c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
2228c2ecf20Sopenharmony_ci		return -EAGAIN;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	switch (num) {
2258c2ecf20Sopenharmony_ci	case 2:
2268c2ecf20Sopenharmony_ci		if (msg[0].len != 1) {
2278c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is not 1!\n",
2288c2ecf20Sopenharmony_ci			     msg[0].len);
2298c2ecf20Sopenharmony_ci			num = -EOPNOTSUPP;
2308c2ecf20Sopenharmony_ci			break;
2318c2ecf20Sopenharmony_ci		}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci		if (2 + msg[1].len > sizeof(buf6)) {
2348c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is too big!\n",
2358c2ecf20Sopenharmony_ci			     msg[1].len);
2368c2ecf20Sopenharmony_ci			num = -EOPNOTSUPP;
2378c2ecf20Sopenharmony_ci			break;
2388c2ecf20Sopenharmony_ci		}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci		/* read si2109 register by number */
2418c2ecf20Sopenharmony_ci		buf6[0] = msg[0].addr << 1;
2428c2ecf20Sopenharmony_ci		buf6[1] = msg[0].len;
2438c2ecf20Sopenharmony_ci		buf6[2] = msg[0].buf[0];
2448c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc2, 0, 0,
2458c2ecf20Sopenharmony_ci				buf6, msg[0].len + 2, DW210X_WRITE_MSG);
2468c2ecf20Sopenharmony_ci		/* read si2109 register */
2478c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
2488c2ecf20Sopenharmony_ci				buf6, msg[1].len + 2, DW210X_READ_MSG);
2498c2ecf20Sopenharmony_ci		memcpy(msg[1].buf, buf6 + 2, msg[1].len);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci		break;
2528c2ecf20Sopenharmony_ci	case 1:
2538c2ecf20Sopenharmony_ci		switch (msg[0].addr) {
2548c2ecf20Sopenharmony_ci		case 0x68:
2558c2ecf20Sopenharmony_ci			if (2 + msg[0].len > sizeof(buf6)) {
2568c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
2578c2ecf20Sopenharmony_ci				     msg[0].len);
2588c2ecf20Sopenharmony_ci				num = -EOPNOTSUPP;
2598c2ecf20Sopenharmony_ci				break;
2608c2ecf20Sopenharmony_ci			}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci			/* write to si2109 register */
2638c2ecf20Sopenharmony_ci			buf6[0] = msg[0].addr << 1;
2648c2ecf20Sopenharmony_ci			buf6[1] = msg[0].len;
2658c2ecf20Sopenharmony_ci			memcpy(buf6 + 2, msg[0].buf, msg[0].len);
2668c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
2678c2ecf20Sopenharmony_ci					msg[0].len + 2, DW210X_WRITE_MSG);
2688c2ecf20Sopenharmony_ci			break;
2698c2ecf20Sopenharmony_ci		case(DW2102_RC_QUERY):
2708c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
2718c2ecf20Sopenharmony_ci					buf6, 2, DW210X_READ_MSG);
2728c2ecf20Sopenharmony_ci			msg[0].buf[0] = buf6[0];
2738c2ecf20Sopenharmony_ci			msg[0].buf[1] = buf6[1];
2748c2ecf20Sopenharmony_ci			break;
2758c2ecf20Sopenharmony_ci		case(DW2102_VOLTAGE_CTRL):
2768c2ecf20Sopenharmony_ci			buf6[0] = 0x30;
2778c2ecf20Sopenharmony_ci			buf6[1] = msg[0].buf[0];
2788c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb2, 0, 0,
2798c2ecf20Sopenharmony_ci					buf6, 2, DW210X_WRITE_MSG);
2808c2ecf20Sopenharmony_ci			break;
2818c2ecf20Sopenharmony_ci		}
2828c2ecf20Sopenharmony_ci		break;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
2868c2ecf20Sopenharmony_ci	return num;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
2928c2ecf20Sopenharmony_ci	int ret;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (!d)
2958c2ecf20Sopenharmony_ci		return -ENODEV;
2968c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
2978c2ecf20Sopenharmony_ci		return -EAGAIN;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	switch (num) {
3008c2ecf20Sopenharmony_ci	case 2: {
3018c2ecf20Sopenharmony_ci		/* read */
3028c2ecf20Sopenharmony_ci		/* first write first register number */
3038c2ecf20Sopenharmony_ci		u8 ibuf[MAX_XFER_SIZE], obuf[3];
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci		if (2 + msg[0].len != sizeof(obuf)) {
3068c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is not 1!\n",
3078c2ecf20Sopenharmony_ci			     msg[0].len);
3088c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
3098c2ecf20Sopenharmony_ci			goto unlock;
3108c2ecf20Sopenharmony_ci		}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		if (2 + msg[1].len > sizeof(ibuf)) {
3138c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is too big!\n",
3148c2ecf20Sopenharmony_ci			     msg[1].len);
3158c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
3168c2ecf20Sopenharmony_ci			goto unlock;
3178c2ecf20Sopenharmony_ci		}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci		obuf[0] = msg[0].addr << 1;
3208c2ecf20Sopenharmony_ci		obuf[1] = msg[0].len;
3218c2ecf20Sopenharmony_ci		obuf[2] = msg[0].buf[0];
3228c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc2, 0, 0,
3238c2ecf20Sopenharmony_ci				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
3248c2ecf20Sopenharmony_ci		/* second read registers */
3258c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
3268c2ecf20Sopenharmony_ci				ibuf, msg[1].len + 2, DW210X_READ_MSG);
3278c2ecf20Sopenharmony_ci		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		break;
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci	case 1:
3328c2ecf20Sopenharmony_ci		switch (msg[0].addr) {
3338c2ecf20Sopenharmony_ci		case 0x68: {
3348c2ecf20Sopenharmony_ci			/* write to register */
3358c2ecf20Sopenharmony_ci			u8 obuf[MAX_XFER_SIZE];
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci			if (2 + msg[0].len > sizeof(obuf)) {
3388c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
3398c2ecf20Sopenharmony_ci				     msg[1].len);
3408c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
3418c2ecf20Sopenharmony_ci				goto unlock;
3428c2ecf20Sopenharmony_ci			}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci			obuf[0] = msg[0].addr << 1;
3458c2ecf20Sopenharmony_ci			obuf[1] = msg[0].len;
3468c2ecf20Sopenharmony_ci			memcpy(obuf + 2, msg[0].buf, msg[0].len);
3478c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xc2, 0, 0,
3488c2ecf20Sopenharmony_ci					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
3498c2ecf20Sopenharmony_ci			break;
3508c2ecf20Sopenharmony_ci		}
3518c2ecf20Sopenharmony_ci		case 0x61: {
3528c2ecf20Sopenharmony_ci			/* write to tuner */
3538c2ecf20Sopenharmony_ci			u8 obuf[MAX_XFER_SIZE];
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci			if (2 + msg[0].len > sizeof(obuf)) {
3568c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
3578c2ecf20Sopenharmony_ci				     msg[1].len);
3588c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
3598c2ecf20Sopenharmony_ci				goto unlock;
3608c2ecf20Sopenharmony_ci			}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci			obuf[0] = msg[0].addr << 1;
3638c2ecf20Sopenharmony_ci			obuf[1] = msg[0].len;
3648c2ecf20Sopenharmony_ci			memcpy(obuf + 2, msg[0].buf, msg[0].len);
3658c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xc2, 0, 0,
3668c2ecf20Sopenharmony_ci					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
3678c2ecf20Sopenharmony_ci			break;
3688c2ecf20Sopenharmony_ci		}
3698c2ecf20Sopenharmony_ci		case(DW2102_RC_QUERY): {
3708c2ecf20Sopenharmony_ci			u8 ibuf[2];
3718c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
3728c2ecf20Sopenharmony_ci					ibuf, 2, DW210X_READ_MSG);
3738c2ecf20Sopenharmony_ci			memcpy(msg[0].buf, ibuf , 2);
3748c2ecf20Sopenharmony_ci			break;
3758c2ecf20Sopenharmony_ci		}
3768c2ecf20Sopenharmony_ci		case(DW2102_VOLTAGE_CTRL): {
3778c2ecf20Sopenharmony_ci			u8 obuf[2];
3788c2ecf20Sopenharmony_ci			obuf[0] = 0x30;
3798c2ecf20Sopenharmony_ci			obuf[1] = msg[0].buf[0];
3808c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb2, 0, 0,
3818c2ecf20Sopenharmony_ci					obuf, 2, DW210X_WRITE_MSG);
3828c2ecf20Sopenharmony_ci			break;
3838c2ecf20Sopenharmony_ci		}
3848c2ecf20Sopenharmony_ci		}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		break;
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci	ret = num;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ciunlock:
3918c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
3928c2ecf20Sopenharmony_ci	return ret;
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
3988c2ecf20Sopenharmony_ci	int len, i, j, ret;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	if (!d)
4018c2ecf20Sopenharmony_ci		return -ENODEV;
4028c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
4038c2ecf20Sopenharmony_ci		return -EAGAIN;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	for (j = 0; j < num; j++) {
4068c2ecf20Sopenharmony_ci		switch (msg[j].addr) {
4078c2ecf20Sopenharmony_ci		case(DW2102_RC_QUERY): {
4088c2ecf20Sopenharmony_ci			u8 ibuf[2];
4098c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
4108c2ecf20Sopenharmony_ci					ibuf, 2, DW210X_READ_MSG);
4118c2ecf20Sopenharmony_ci			memcpy(msg[j].buf, ibuf , 2);
4128c2ecf20Sopenharmony_ci			break;
4138c2ecf20Sopenharmony_ci		}
4148c2ecf20Sopenharmony_ci		case(DW2102_VOLTAGE_CTRL): {
4158c2ecf20Sopenharmony_ci			u8 obuf[2];
4168c2ecf20Sopenharmony_ci			obuf[0] = 0x30;
4178c2ecf20Sopenharmony_ci			obuf[1] = msg[j].buf[0];
4188c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb2, 0, 0,
4198c2ecf20Sopenharmony_ci					obuf, 2, DW210X_WRITE_MSG);
4208c2ecf20Sopenharmony_ci			break;
4218c2ecf20Sopenharmony_ci		}
4228c2ecf20Sopenharmony_ci		/*case 0x55: cx24116
4238c2ecf20Sopenharmony_ci		case 0x6a: stv0903
4248c2ecf20Sopenharmony_ci		case 0x68: ds3000, stv0903
4258c2ecf20Sopenharmony_ci		case 0x60: ts2020, stv6110, stb6100 */
4268c2ecf20Sopenharmony_ci		default: {
4278c2ecf20Sopenharmony_ci			if (msg[j].flags == I2C_M_RD) {
4288c2ecf20Sopenharmony_ci				/* read registers */
4298c2ecf20Sopenharmony_ci				u8  ibuf[MAX_XFER_SIZE];
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci				if (2 + msg[j].len > sizeof(ibuf)) {
4328c2ecf20Sopenharmony_ci					warn("i2c rd: len=%d is too big!\n",
4338c2ecf20Sopenharmony_ci					     msg[j].len);
4348c2ecf20Sopenharmony_ci					ret = -EOPNOTSUPP;
4358c2ecf20Sopenharmony_ci					goto unlock;
4368c2ecf20Sopenharmony_ci				}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0xc3,
4398c2ecf20Sopenharmony_ci						(msg[j].addr << 1) + 1, 0,
4408c2ecf20Sopenharmony_ci						ibuf, msg[j].len + 2,
4418c2ecf20Sopenharmony_ci						DW210X_READ_MSG);
4428c2ecf20Sopenharmony_ci				memcpy(msg[j].buf, ibuf + 2, msg[j].len);
4438c2ecf20Sopenharmony_ci				mdelay(10);
4448c2ecf20Sopenharmony_ci			} else if (((msg[j].buf[0] == 0xb0) &&
4458c2ecf20Sopenharmony_ci						(msg[j].addr == 0x68)) ||
4468c2ecf20Sopenharmony_ci						((msg[j].buf[0] == 0xf7) &&
4478c2ecf20Sopenharmony_ci						(msg[j].addr == 0x55))) {
4488c2ecf20Sopenharmony_ci				/* write firmware */
4498c2ecf20Sopenharmony_ci				u8 obuf[19];
4508c2ecf20Sopenharmony_ci				obuf[0] = msg[j].addr << 1;
4518c2ecf20Sopenharmony_ci				obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
4528c2ecf20Sopenharmony_ci				obuf[2] = msg[j].buf[0];
4538c2ecf20Sopenharmony_ci				len = msg[j].len - 1;
4548c2ecf20Sopenharmony_ci				i = 1;
4558c2ecf20Sopenharmony_ci				do {
4568c2ecf20Sopenharmony_ci					memcpy(obuf + 3, msg[j].buf + i,
4578c2ecf20Sopenharmony_ci							(len > 16 ? 16 : len));
4588c2ecf20Sopenharmony_ci					dw210x_op_rw(d->udev, 0xc2, 0, 0,
4598c2ecf20Sopenharmony_ci						obuf, (len > 16 ? 16 : len) + 3,
4608c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
4618c2ecf20Sopenharmony_ci					i += 16;
4628c2ecf20Sopenharmony_ci					len -= 16;
4638c2ecf20Sopenharmony_ci				} while (len > 0);
4648c2ecf20Sopenharmony_ci			} else {
4658c2ecf20Sopenharmony_ci				/* write registers */
4668c2ecf20Sopenharmony_ci				u8 obuf[MAX_XFER_SIZE];
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci				if (2 + msg[j].len > sizeof(obuf)) {
4698c2ecf20Sopenharmony_ci					warn("i2c wr: len=%d is too big!\n",
4708c2ecf20Sopenharmony_ci					     msg[j].len);
4718c2ecf20Sopenharmony_ci					ret = -EOPNOTSUPP;
4728c2ecf20Sopenharmony_ci					goto unlock;
4738c2ecf20Sopenharmony_ci				}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci				obuf[0] = msg[j].addr << 1;
4768c2ecf20Sopenharmony_ci				obuf[1] = msg[j].len;
4778c2ecf20Sopenharmony_ci				memcpy(obuf + 2, msg[j].buf, msg[j].len);
4788c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0xc2, 0, 0,
4798c2ecf20Sopenharmony_ci						obuf, msg[j].len + 2,
4808c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
4818c2ecf20Sopenharmony_ci			}
4828c2ecf20Sopenharmony_ci			break;
4838c2ecf20Sopenharmony_ci		}
4848c2ecf20Sopenharmony_ci		}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci	ret = num;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ciunlock:
4908c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
4918c2ecf20Sopenharmony_ci	return ret;
4928c2ecf20Sopenharmony_ci}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
4958c2ecf20Sopenharmony_ci								int num)
4968c2ecf20Sopenharmony_ci{
4978c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
4988c2ecf20Sopenharmony_ci	int ret;
4998c2ecf20Sopenharmony_ci	int i;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	if (!d)
5028c2ecf20Sopenharmony_ci		return -ENODEV;
5038c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
5048c2ecf20Sopenharmony_ci		return -EAGAIN;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	switch (num) {
5078c2ecf20Sopenharmony_ci	case 2: {
5088c2ecf20Sopenharmony_ci		/* read */
5098c2ecf20Sopenharmony_ci		/* first write first register number */
5108c2ecf20Sopenharmony_ci		u8 ibuf[MAX_XFER_SIZE], obuf[3];
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci		if (2 + msg[0].len != sizeof(obuf)) {
5138c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is not 1!\n",
5148c2ecf20Sopenharmony_ci			     msg[0].len);
5158c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
5168c2ecf20Sopenharmony_ci			goto unlock;
5178c2ecf20Sopenharmony_ci		}
5188c2ecf20Sopenharmony_ci		if (2 + msg[1].len > sizeof(ibuf)) {
5198c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is too big!\n",
5208c2ecf20Sopenharmony_ci			     msg[1].len);
5218c2ecf20Sopenharmony_ci			ret = -EOPNOTSUPP;
5228c2ecf20Sopenharmony_ci			goto unlock;
5238c2ecf20Sopenharmony_ci		}
5248c2ecf20Sopenharmony_ci		obuf[0] = msg[0].addr << 1;
5258c2ecf20Sopenharmony_ci		obuf[1] = msg[0].len;
5268c2ecf20Sopenharmony_ci		obuf[2] = msg[0].buf[0];
5278c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc2, 0, 0,
5288c2ecf20Sopenharmony_ci				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
5298c2ecf20Sopenharmony_ci		/* second read registers */
5308c2ecf20Sopenharmony_ci		dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
5318c2ecf20Sopenharmony_ci				ibuf, msg[1].len + 2, DW210X_READ_MSG);
5328c2ecf20Sopenharmony_ci		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci		break;
5358c2ecf20Sopenharmony_ci	}
5368c2ecf20Sopenharmony_ci	case 1:
5378c2ecf20Sopenharmony_ci		switch (msg[0].addr) {
5388c2ecf20Sopenharmony_ci		case 0x60:
5398c2ecf20Sopenharmony_ci		case 0x0c: {
5408c2ecf20Sopenharmony_ci			/* write to register */
5418c2ecf20Sopenharmony_ci			u8 obuf[MAX_XFER_SIZE];
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci			if (2 + msg[0].len > sizeof(obuf)) {
5448c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
5458c2ecf20Sopenharmony_ci				     msg[0].len);
5468c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
5478c2ecf20Sopenharmony_ci				goto unlock;
5488c2ecf20Sopenharmony_ci			}
5498c2ecf20Sopenharmony_ci			obuf[0] = msg[0].addr << 1;
5508c2ecf20Sopenharmony_ci			obuf[1] = msg[0].len;
5518c2ecf20Sopenharmony_ci			memcpy(obuf + 2, msg[0].buf, msg[0].len);
5528c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xc2, 0, 0,
5538c2ecf20Sopenharmony_ci					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
5548c2ecf20Sopenharmony_ci			break;
5558c2ecf20Sopenharmony_ci		}
5568c2ecf20Sopenharmony_ci		case(DW2102_RC_QUERY): {
5578c2ecf20Sopenharmony_ci			u8 ibuf[2];
5588c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
5598c2ecf20Sopenharmony_ci					ibuf, 2, DW210X_READ_MSG);
5608c2ecf20Sopenharmony_ci			memcpy(msg[0].buf, ibuf , 2);
5618c2ecf20Sopenharmony_ci			break;
5628c2ecf20Sopenharmony_ci		}
5638c2ecf20Sopenharmony_ci		}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci		break;
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
5698c2ecf20Sopenharmony_ci		deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
5708c2ecf20Sopenharmony_ci				msg[i].flags == 0 ? ">>>" : "<<<");
5718c2ecf20Sopenharmony_ci		debug_dump(msg[i].buf, msg[i].len, deb_xfer);
5728c2ecf20Sopenharmony_ci	}
5738c2ecf20Sopenharmony_ci	ret = num;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ciunlock:
5768c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
5778c2ecf20Sopenharmony_ci	return ret;
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cistatic int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
5818c2ecf20Sopenharmony_ci								int num)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
5848c2ecf20Sopenharmony_ci	struct usb_device *udev;
5858c2ecf20Sopenharmony_ci	int len, i, j, ret;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (!d)
5888c2ecf20Sopenharmony_ci		return -ENODEV;
5898c2ecf20Sopenharmony_ci	udev = d->udev;
5908c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
5918c2ecf20Sopenharmony_ci		return -EAGAIN;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	for (j = 0; j < num; j++) {
5948c2ecf20Sopenharmony_ci		switch (msg[j].addr) {
5958c2ecf20Sopenharmony_ci		case (DW2102_RC_QUERY): {
5968c2ecf20Sopenharmony_ci			u8 ibuf[5];
5978c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0xb8, 0, 0,
5988c2ecf20Sopenharmony_ci					ibuf, 5, DW210X_READ_MSG);
5998c2ecf20Sopenharmony_ci			memcpy(msg[j].buf, ibuf + 3, 2);
6008c2ecf20Sopenharmony_ci			break;
6018c2ecf20Sopenharmony_ci		}
6028c2ecf20Sopenharmony_ci		case (DW2102_VOLTAGE_CTRL): {
6038c2ecf20Sopenharmony_ci			u8 obuf[2];
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci			obuf[0] = 1;
6068c2ecf20Sopenharmony_ci			obuf[1] = msg[j].buf[1];/* off-on */
6078c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0x8a, 0, 0,
6088c2ecf20Sopenharmony_ci					obuf, 2, DW210X_WRITE_MSG);
6098c2ecf20Sopenharmony_ci			obuf[0] = 3;
6108c2ecf20Sopenharmony_ci			obuf[1] = msg[j].buf[0];/* 13v-18v */
6118c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0x8a, 0, 0,
6128c2ecf20Sopenharmony_ci					obuf, 2, DW210X_WRITE_MSG);
6138c2ecf20Sopenharmony_ci			break;
6148c2ecf20Sopenharmony_ci		}
6158c2ecf20Sopenharmony_ci		case (DW2102_LED_CTRL): {
6168c2ecf20Sopenharmony_ci			u8 obuf[2];
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci			obuf[0] = 5;
6198c2ecf20Sopenharmony_ci			obuf[1] = msg[j].buf[0];
6208c2ecf20Sopenharmony_ci			dw210x_op_rw(d->udev, 0x8a, 0, 0,
6218c2ecf20Sopenharmony_ci					obuf, 2, DW210X_WRITE_MSG);
6228c2ecf20Sopenharmony_ci			break;
6238c2ecf20Sopenharmony_ci		}
6248c2ecf20Sopenharmony_ci		/*case 0x55: cx24116
6258c2ecf20Sopenharmony_ci		case 0x6a: stv0903
6268c2ecf20Sopenharmony_ci		case 0x68: ds3000, stv0903, rs2000
6278c2ecf20Sopenharmony_ci		case 0x60: ts2020, stv6110, stb6100
6288c2ecf20Sopenharmony_ci		case 0xa0: eeprom */
6298c2ecf20Sopenharmony_ci		default: {
6308c2ecf20Sopenharmony_ci			if (msg[j].flags == I2C_M_RD) {
6318c2ecf20Sopenharmony_ci				/* read registers */
6328c2ecf20Sopenharmony_ci				u8 ibuf[MAX_XFER_SIZE];
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci				if (msg[j].len > sizeof(ibuf)) {
6358c2ecf20Sopenharmony_ci					warn("i2c rd: len=%d is too big!\n",
6368c2ecf20Sopenharmony_ci					     msg[j].len);
6378c2ecf20Sopenharmony_ci					ret = -EOPNOTSUPP;
6388c2ecf20Sopenharmony_ci					goto unlock;
6398c2ecf20Sopenharmony_ci				}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0x91, 0, 0,
6428c2ecf20Sopenharmony_ci						ibuf, msg[j].len,
6438c2ecf20Sopenharmony_ci						DW210X_READ_MSG);
6448c2ecf20Sopenharmony_ci				memcpy(msg[j].buf, ibuf, msg[j].len);
6458c2ecf20Sopenharmony_ci				break;
6468c2ecf20Sopenharmony_ci			} else if ((msg[j].buf[0] == 0xb0) &&
6478c2ecf20Sopenharmony_ci						(msg[j].addr == 0x68)) {
6488c2ecf20Sopenharmony_ci				/* write firmware */
6498c2ecf20Sopenharmony_ci				u8 obuf[19];
6508c2ecf20Sopenharmony_ci				obuf[0] = (msg[j].len > 16 ?
6518c2ecf20Sopenharmony_ci						18 : msg[j].len + 1);
6528c2ecf20Sopenharmony_ci				obuf[1] = msg[j].addr << 1;
6538c2ecf20Sopenharmony_ci				obuf[2] = msg[j].buf[0];
6548c2ecf20Sopenharmony_ci				len = msg[j].len - 1;
6558c2ecf20Sopenharmony_ci				i = 1;
6568c2ecf20Sopenharmony_ci				do {
6578c2ecf20Sopenharmony_ci					memcpy(obuf + 3, msg[j].buf + i,
6588c2ecf20Sopenharmony_ci							(len > 16 ? 16 : len));
6598c2ecf20Sopenharmony_ci					dw210x_op_rw(d->udev, 0x80, 0, 0,
6608c2ecf20Sopenharmony_ci						obuf, (len > 16 ? 16 : len) + 3,
6618c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
6628c2ecf20Sopenharmony_ci					i += 16;
6638c2ecf20Sopenharmony_ci					len -= 16;
6648c2ecf20Sopenharmony_ci				} while (len > 0);
6658c2ecf20Sopenharmony_ci			} else if (j < (num - 1)) {
6668c2ecf20Sopenharmony_ci				/* write register addr before read */
6678c2ecf20Sopenharmony_ci				u8 obuf[MAX_XFER_SIZE];
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci				if (2 + msg[j].len > sizeof(obuf)) {
6708c2ecf20Sopenharmony_ci					warn("i2c wr: len=%d is too big!\n",
6718c2ecf20Sopenharmony_ci					     msg[j].len);
6728c2ecf20Sopenharmony_ci					ret = -EOPNOTSUPP;
6738c2ecf20Sopenharmony_ci					goto unlock;
6748c2ecf20Sopenharmony_ci				}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci				obuf[0] = msg[j + 1].len;
6778c2ecf20Sopenharmony_ci				obuf[1] = (msg[j].addr << 1);
6788c2ecf20Sopenharmony_ci				memcpy(obuf + 2, msg[j].buf, msg[j].len);
6798c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev,
6808c2ecf20Sopenharmony_ci						le16_to_cpu(udev->descriptor.idProduct) ==
6818c2ecf20Sopenharmony_ci						0x7500 ? 0x92 : 0x90, 0, 0,
6828c2ecf20Sopenharmony_ci						obuf, msg[j].len + 2,
6838c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
6848c2ecf20Sopenharmony_ci				break;
6858c2ecf20Sopenharmony_ci			} else {
6868c2ecf20Sopenharmony_ci				/* write registers */
6878c2ecf20Sopenharmony_ci				u8 obuf[MAX_XFER_SIZE];
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci				if (2 + msg[j].len > sizeof(obuf)) {
6908c2ecf20Sopenharmony_ci					warn("i2c wr: len=%d is too big!\n",
6918c2ecf20Sopenharmony_ci					     msg[j].len);
6928c2ecf20Sopenharmony_ci					ret = -EOPNOTSUPP;
6938c2ecf20Sopenharmony_ci					goto unlock;
6948c2ecf20Sopenharmony_ci				}
6958c2ecf20Sopenharmony_ci				obuf[0] = msg[j].len + 1;
6968c2ecf20Sopenharmony_ci				obuf[1] = (msg[j].addr << 1);
6978c2ecf20Sopenharmony_ci				memcpy(obuf + 2, msg[j].buf, msg[j].len);
6988c2ecf20Sopenharmony_ci				dw210x_op_rw(d->udev, 0x80, 0, 0,
6998c2ecf20Sopenharmony_ci						obuf, msg[j].len + 2,
7008c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
7018c2ecf20Sopenharmony_ci				break;
7028c2ecf20Sopenharmony_ci			}
7038c2ecf20Sopenharmony_ci			break;
7048c2ecf20Sopenharmony_ci		}
7058c2ecf20Sopenharmony_ci		}
7068c2ecf20Sopenharmony_ci	}
7078c2ecf20Sopenharmony_ci	ret = num;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ciunlock:
7108c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
7118c2ecf20Sopenharmony_ci	return ret;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
7158c2ecf20Sopenharmony_ci								int num)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
7188c2ecf20Sopenharmony_ci	struct dw2102_state *state;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	if (!d)
7218c2ecf20Sopenharmony_ci		return -ENODEV;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	state = d->priv;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
7268c2ecf20Sopenharmony_ci		return -EAGAIN;
7278c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->data_mutex) < 0) {
7288c2ecf20Sopenharmony_ci		mutex_unlock(&d->i2c_mutex);
7298c2ecf20Sopenharmony_ci		return -EAGAIN;
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	switch (num) {
7338c2ecf20Sopenharmony_ci	case 1:
7348c2ecf20Sopenharmony_ci		switch (msg[0].addr) {
7358c2ecf20Sopenharmony_ci		case SU3000_STREAM_CTRL:
7368c2ecf20Sopenharmony_ci			state->data[0] = msg[0].buf[0] + 0x36;
7378c2ecf20Sopenharmony_ci			state->data[1] = 3;
7388c2ecf20Sopenharmony_ci			state->data[2] = 0;
7398c2ecf20Sopenharmony_ci			if (dvb_usb_generic_rw(d, state->data, 3,
7408c2ecf20Sopenharmony_ci					state->data, 0, 0) < 0)
7418c2ecf20Sopenharmony_ci				err("i2c transfer failed.");
7428c2ecf20Sopenharmony_ci			break;
7438c2ecf20Sopenharmony_ci		case DW2102_RC_QUERY:
7448c2ecf20Sopenharmony_ci			state->data[0] = 0x10;
7458c2ecf20Sopenharmony_ci			if (dvb_usb_generic_rw(d, state->data, 1,
7468c2ecf20Sopenharmony_ci					state->data, 2, 0) < 0)
7478c2ecf20Sopenharmony_ci				err("i2c transfer failed.");
7488c2ecf20Sopenharmony_ci			msg[0].buf[1] = state->data[0];
7498c2ecf20Sopenharmony_ci			msg[0].buf[0] = state->data[1];
7508c2ecf20Sopenharmony_ci			break;
7518c2ecf20Sopenharmony_ci		default:
7528c2ecf20Sopenharmony_ci			if (3 + msg[0].len > sizeof(state->data)) {
7538c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
7548c2ecf20Sopenharmony_ci				     msg[0].len);
7558c2ecf20Sopenharmony_ci				num = -EOPNOTSUPP;
7568c2ecf20Sopenharmony_ci				break;
7578c2ecf20Sopenharmony_ci			}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci			/* always i2c write*/
7608c2ecf20Sopenharmony_ci			state->data[0] = 0x08;
7618c2ecf20Sopenharmony_ci			state->data[1] = msg[0].addr;
7628c2ecf20Sopenharmony_ci			state->data[2] = msg[0].len;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci			memcpy(&state->data[3], msg[0].buf, msg[0].len);
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci			if (dvb_usb_generic_rw(d, state->data, msg[0].len + 3,
7678c2ecf20Sopenharmony_ci						state->data, 1, 0) < 0)
7688c2ecf20Sopenharmony_ci				err("i2c transfer failed.");
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci		break;
7728c2ecf20Sopenharmony_ci	case 2:
7738c2ecf20Sopenharmony_ci		/* always i2c read */
7748c2ecf20Sopenharmony_ci		if (4 + msg[0].len > sizeof(state->data)) {
7758c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is too big!\n",
7768c2ecf20Sopenharmony_ci			     msg[0].len);
7778c2ecf20Sopenharmony_ci			num = -EOPNOTSUPP;
7788c2ecf20Sopenharmony_ci			break;
7798c2ecf20Sopenharmony_ci		}
7808c2ecf20Sopenharmony_ci		if (1 + msg[1].len > sizeof(state->data)) {
7818c2ecf20Sopenharmony_ci			warn("i2c rd: len=%d is too big!\n",
7828c2ecf20Sopenharmony_ci			     msg[1].len);
7838c2ecf20Sopenharmony_ci			num = -EOPNOTSUPP;
7848c2ecf20Sopenharmony_ci			break;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci		state->data[0] = 0x09;
7888c2ecf20Sopenharmony_ci		state->data[1] = msg[0].len;
7898c2ecf20Sopenharmony_ci		state->data[2] = msg[1].len;
7908c2ecf20Sopenharmony_ci		state->data[3] = msg[0].addr;
7918c2ecf20Sopenharmony_ci		memcpy(&state->data[4], msg[0].buf, msg[0].len);
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci		if (dvb_usb_generic_rw(d, state->data, msg[0].len + 4,
7948c2ecf20Sopenharmony_ci					state->data, msg[1].len + 1, 0) < 0)
7958c2ecf20Sopenharmony_ci			err("i2c transfer failed.");
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		memcpy(msg[1].buf, &state->data[1], msg[1].len);
7988c2ecf20Sopenharmony_ci		break;
7998c2ecf20Sopenharmony_ci	default:
8008c2ecf20Sopenharmony_ci		warn("more than 2 i2c messages at a time is not handled yet.");
8018c2ecf20Sopenharmony_ci		break;
8028c2ecf20Sopenharmony_ci	}
8038c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
8048c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
8058c2ecf20Sopenharmony_ci	return num;
8068c2ecf20Sopenharmony_ci}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_cistatic u32 dw210x_i2c_func(struct i2c_adapter *adapter)
8098c2ecf20Sopenharmony_ci{
8108c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C;
8118c2ecf20Sopenharmony_ci}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_cistatic struct i2c_algorithm dw2102_i2c_algo = {
8148c2ecf20Sopenharmony_ci	.master_xfer = dw2102_i2c_transfer,
8158c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8168c2ecf20Sopenharmony_ci};
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_cistatic struct i2c_algorithm dw2102_serit_i2c_algo = {
8198c2ecf20Sopenharmony_ci	.master_xfer = dw2102_serit_i2c_transfer,
8208c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8218c2ecf20Sopenharmony_ci};
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic struct i2c_algorithm dw2102_earda_i2c_algo = {
8248c2ecf20Sopenharmony_ci	.master_xfer = dw2102_earda_i2c_transfer,
8258c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8268c2ecf20Sopenharmony_ci};
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_cistatic struct i2c_algorithm dw2104_i2c_algo = {
8298c2ecf20Sopenharmony_ci	.master_xfer = dw2104_i2c_transfer,
8308c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8318c2ecf20Sopenharmony_ci};
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic struct i2c_algorithm dw3101_i2c_algo = {
8348c2ecf20Sopenharmony_ci	.master_xfer = dw3101_i2c_transfer,
8358c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8368c2ecf20Sopenharmony_ci};
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_cistatic struct i2c_algorithm s6x0_i2c_algo = {
8398c2ecf20Sopenharmony_ci	.master_xfer = s6x0_i2c_transfer,
8408c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8418c2ecf20Sopenharmony_ci};
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_cistatic struct i2c_algorithm su3000_i2c_algo = {
8448c2ecf20Sopenharmony_ci	.master_xfer = su3000_i2c_transfer,
8458c2ecf20Sopenharmony_ci	.functionality = dw210x_i2c_func,
8468c2ecf20Sopenharmony_ci};
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_cistatic int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
8498c2ecf20Sopenharmony_ci{
8508c2ecf20Sopenharmony_ci	int i;
8518c2ecf20Sopenharmony_ci	u8 ibuf[] = {0, 0};
8528c2ecf20Sopenharmony_ci	u8 eeprom[256], eepromline[16];
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++) {
8558c2ecf20Sopenharmony_ci		if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
8568c2ecf20Sopenharmony_ci			err("read eeprom failed.");
8578c2ecf20Sopenharmony_ci			return -1;
8588c2ecf20Sopenharmony_ci		} else {
8598c2ecf20Sopenharmony_ci			eepromline[i%16] = ibuf[0];
8608c2ecf20Sopenharmony_ci			eeprom[i] = ibuf[0];
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci		if ((i % 16) == 15) {
8638c2ecf20Sopenharmony_ci			deb_xfer("%02x: ", i - 15);
8648c2ecf20Sopenharmony_ci			debug_dump(eepromline, 16, deb_xfer);
8658c2ecf20Sopenharmony_ci		}
8668c2ecf20Sopenharmony_ci	}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	memcpy(mac, eeprom + 8, 6);
8698c2ecf20Sopenharmony_ci	return 0;
8708c2ecf20Sopenharmony_ci};
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
8738c2ecf20Sopenharmony_ci{
8748c2ecf20Sopenharmony_ci	int i, ret;
8758c2ecf20Sopenharmony_ci	u8 ibuf[] = { 0 }, obuf[] = { 0 };
8768c2ecf20Sopenharmony_ci	u8 eeprom[256], eepromline[16];
8778c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
8788c2ecf20Sopenharmony_ci		{
8798c2ecf20Sopenharmony_ci			.addr = 0xa0 >> 1,
8808c2ecf20Sopenharmony_ci			.flags = 0,
8818c2ecf20Sopenharmony_ci			.buf = obuf,
8828c2ecf20Sopenharmony_ci			.len = 1,
8838c2ecf20Sopenharmony_ci		}, {
8848c2ecf20Sopenharmony_ci			.addr = 0xa0 >> 1,
8858c2ecf20Sopenharmony_ci			.flags = I2C_M_RD,
8868c2ecf20Sopenharmony_ci			.buf = ibuf,
8878c2ecf20Sopenharmony_ci			.len = 1,
8888c2ecf20Sopenharmony_ci		}
8898c2ecf20Sopenharmony_ci	};
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++) {
8928c2ecf20Sopenharmony_ci		obuf[0] = i;
8938c2ecf20Sopenharmony_ci		ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
8948c2ecf20Sopenharmony_ci		if (ret != 2) {
8958c2ecf20Sopenharmony_ci			err("read eeprom failed.");
8968c2ecf20Sopenharmony_ci			return -1;
8978c2ecf20Sopenharmony_ci		} else {
8988c2ecf20Sopenharmony_ci			eepromline[i % 16] = ibuf[0];
8998c2ecf20Sopenharmony_ci			eeprom[i] = ibuf[0];
9008c2ecf20Sopenharmony_ci		}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci		if ((i % 16) == 15) {
9038c2ecf20Sopenharmony_ci			deb_xfer("%02x: ", i - 15);
9048c2ecf20Sopenharmony_ci			debug_dump(eepromline, 16, deb_xfer);
9058c2ecf20Sopenharmony_ci		}
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	memcpy(mac, eeprom + 16, 6);
9098c2ecf20Sopenharmony_ci	return 0;
9108c2ecf20Sopenharmony_ci};
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_cistatic int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci	static u8 command_start[] = {0x00};
9158c2ecf20Sopenharmony_ci	static u8 command_stop[] = {0x01};
9168c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
9178c2ecf20Sopenharmony_ci		.addr = SU3000_STREAM_CTRL,
9188c2ecf20Sopenharmony_ci		.flags = 0,
9198c2ecf20Sopenharmony_ci		.buf = onoff ? command_start : command_stop,
9208c2ecf20Sopenharmony_ci		.len = 1
9218c2ecf20Sopenharmony_ci	};
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return 0;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic int su3000_power_ctrl(struct dvb_usb_device *d, int i)
9298c2ecf20Sopenharmony_ci{
9308c2ecf20Sopenharmony_ci	struct dw2102_state *state = (struct dw2102_state *)d->priv;
9318c2ecf20Sopenharmony_ci	int ret = 0;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	info("%s: %d, initialized %d", __func__, i, state->initialized);
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	if (i && !state->initialized) {
9368c2ecf20Sopenharmony_ci		mutex_lock(&d->data_mutex);
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		state->data[0] = 0xde;
9398c2ecf20Sopenharmony_ci		state->data[1] = 0;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci		state->initialized = 1;
9428c2ecf20Sopenharmony_ci		/* reset board */
9438c2ecf20Sopenharmony_ci		ret = dvb_usb_generic_rw(d, state->data, 2, NULL, 0, 0);
9448c2ecf20Sopenharmony_ci		mutex_unlock(&d->data_mutex);
9458c2ecf20Sopenharmony_ci	}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	return ret;
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cistatic int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	int i;
9538c2ecf20Sopenharmony_ci	u8 obuf[] = { 0x1f, 0xf0 };
9548c2ecf20Sopenharmony_ci	u8 ibuf[] = { 0 };
9558c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
9568c2ecf20Sopenharmony_ci		{
9578c2ecf20Sopenharmony_ci			.addr = 0x51,
9588c2ecf20Sopenharmony_ci			.flags = 0,
9598c2ecf20Sopenharmony_ci			.buf = obuf,
9608c2ecf20Sopenharmony_ci			.len = 2,
9618c2ecf20Sopenharmony_ci		}, {
9628c2ecf20Sopenharmony_ci			.addr = 0x51,
9638c2ecf20Sopenharmony_ci			.flags = I2C_M_RD,
9648c2ecf20Sopenharmony_ci			.buf = ibuf,
9658c2ecf20Sopenharmony_ci			.len = 1,
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci		}
9688c2ecf20Sopenharmony_ci	};
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
9718c2ecf20Sopenharmony_ci		obuf[1] = 0xf0 + i;
9728c2ecf20Sopenharmony_ci		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
9738c2ecf20Sopenharmony_ci			return -1;
9748c2ecf20Sopenharmony_ci		else
9758c2ecf20Sopenharmony_ci			mac[i] = ibuf[0];
9768c2ecf20Sopenharmony_ci	}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	return 0;
9798c2ecf20Sopenharmony_ci}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_cistatic int su3000_identify_state(struct usb_device *udev,
9828c2ecf20Sopenharmony_ci				 const struct dvb_usb_device_properties *props,
9838c2ecf20Sopenharmony_ci				 const struct dvb_usb_device_description **desc,
9848c2ecf20Sopenharmony_ci				 int *cold)
9858c2ecf20Sopenharmony_ci{
9868c2ecf20Sopenharmony_ci	info("%s", __func__);
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	*cold = 0;
9898c2ecf20Sopenharmony_ci	return 0;
9908c2ecf20Sopenharmony_ci}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_cistatic int dw210x_set_voltage(struct dvb_frontend *fe,
9938c2ecf20Sopenharmony_ci			      enum fe_sec_voltage voltage)
9948c2ecf20Sopenharmony_ci{
9958c2ecf20Sopenharmony_ci	static u8 command_13v[] = {0x00, 0x01};
9968c2ecf20Sopenharmony_ci	static u8 command_18v[] = {0x01, 0x01};
9978c2ecf20Sopenharmony_ci	static u8 command_off[] = {0x00, 0x00};
9988c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
9998c2ecf20Sopenharmony_ci		.addr = DW2102_VOLTAGE_CTRL,
10008c2ecf20Sopenharmony_ci		.flags = 0,
10018c2ecf20Sopenharmony_ci		.buf = command_off,
10028c2ecf20Sopenharmony_ci		.len = 2,
10038c2ecf20Sopenharmony_ci	};
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *udev_adap =
10068c2ecf20Sopenharmony_ci		(struct dvb_usb_adapter *)(fe->dvb->priv);
10078c2ecf20Sopenharmony_ci	if (voltage == SEC_VOLTAGE_18)
10088c2ecf20Sopenharmony_ci		msg.buf = command_18v;
10098c2ecf20Sopenharmony_ci	else if (voltage == SEC_VOLTAGE_13)
10108c2ecf20Sopenharmony_ci		msg.buf = command_13v;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	return 0;
10158c2ecf20Sopenharmony_ci}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_cistatic int s660_set_voltage(struct dvb_frontend *fe,
10188c2ecf20Sopenharmony_ci			    enum fe_sec_voltage voltage)
10198c2ecf20Sopenharmony_ci{
10208c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *d =
10218c2ecf20Sopenharmony_ci		(struct dvb_usb_adapter *)(fe->dvb->priv);
10228c2ecf20Sopenharmony_ci	struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	dw210x_set_voltage(fe, voltage);
10258c2ecf20Sopenharmony_ci	if (st->old_set_voltage)
10268c2ecf20Sopenharmony_ci		st->old_set_voltage(fe, voltage);
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	return 0;
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_cistatic void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
10328c2ecf20Sopenharmony_ci{
10338c2ecf20Sopenharmony_ci	static u8 led_off[] = { 0 };
10348c2ecf20Sopenharmony_ci	static u8 led_on[] = { 1 };
10358c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
10368c2ecf20Sopenharmony_ci		.addr = DW2102_LED_CTRL,
10378c2ecf20Sopenharmony_ci		.flags = 0,
10388c2ecf20Sopenharmony_ci		.buf = led_off,
10398c2ecf20Sopenharmony_ci		.len = 1
10408c2ecf20Sopenharmony_ci	};
10418c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *udev_adap =
10428c2ecf20Sopenharmony_ci		(struct dvb_usb_adapter *)(fe->dvb->priv);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (offon)
10458c2ecf20Sopenharmony_ci		msg.buf = led_on;
10468c2ecf20Sopenharmony_ci	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
10478c2ecf20Sopenharmony_ci}
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cistatic int tt_s2_4600_read_status(struct dvb_frontend *fe,
10508c2ecf20Sopenharmony_ci				  enum fe_status *status)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *d =
10538c2ecf20Sopenharmony_ci		(struct dvb_usb_adapter *)(fe->dvb->priv);
10548c2ecf20Sopenharmony_ci	struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
10558c2ecf20Sopenharmony_ci	int ret;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	ret = st->fe_read_status(fe, status);
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	/* resync slave fifo when signal change from unlock to lock */
10608c2ecf20Sopenharmony_ci	if ((*status & FE_HAS_LOCK) && (!st->last_lock))
10618c2ecf20Sopenharmony_ci		su3000_streaming_ctrl(d, 1);
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	st->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0;
10648c2ecf20Sopenharmony_ci	return ret;
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic struct stv0299_config sharp_z0194a_config = {
10688c2ecf20Sopenharmony_ci	.demod_address = 0x68,
10698c2ecf20Sopenharmony_ci	.inittab = sharp_z0194a_inittab,
10708c2ecf20Sopenharmony_ci	.mclk = 88000000UL,
10718c2ecf20Sopenharmony_ci	.invert = 1,
10728c2ecf20Sopenharmony_ci	.skip_reinit = 0,
10738c2ecf20Sopenharmony_ci	.lock_output = STV0299_LOCKOUTPUT_1,
10748c2ecf20Sopenharmony_ci	.volt13_op0_op1 = STV0299_VOLT13_OP1,
10758c2ecf20Sopenharmony_ci	.min_delay_ms = 100,
10768c2ecf20Sopenharmony_ci	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
10778c2ecf20Sopenharmony_ci};
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic struct cx24116_config dw2104_config = {
10808c2ecf20Sopenharmony_ci	.demod_address = 0x55,
10818c2ecf20Sopenharmony_ci	.mpg_clk_pos_pol = 0x01,
10828c2ecf20Sopenharmony_ci};
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_cistatic struct si21xx_config serit_sp1511lhb_config = {
10858c2ecf20Sopenharmony_ci	.demod_address = 0x68,
10868c2ecf20Sopenharmony_ci	.min_delay_ms = 100,
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci};
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_cistatic struct tda10023_config dw3101_tda10023_config = {
10918c2ecf20Sopenharmony_ci	.demod_address = 0x0c,
10928c2ecf20Sopenharmony_ci	.invert = 1,
10938c2ecf20Sopenharmony_ci};
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_cistatic struct mt312_config zl313_config = {
10968c2ecf20Sopenharmony_ci	.demod_address = 0x0e,
10978c2ecf20Sopenharmony_ci};
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_cistatic struct ds3000_config dw2104_ds3000_config = {
11008c2ecf20Sopenharmony_ci	.demod_address = 0x68,
11018c2ecf20Sopenharmony_ci};
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_cistatic struct ts2020_config dw2104_ts2020_config = {
11048c2ecf20Sopenharmony_ci	.tuner_address = 0x60,
11058c2ecf20Sopenharmony_ci	.clk_out_div = 1,
11068c2ecf20Sopenharmony_ci	.frequency_div = 1060000,
11078c2ecf20Sopenharmony_ci};
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_cistatic struct ds3000_config s660_ds3000_config = {
11108c2ecf20Sopenharmony_ci	.demod_address = 0x68,
11118c2ecf20Sopenharmony_ci	.ci_mode = 1,
11128c2ecf20Sopenharmony_ci	.set_lock_led = dw210x_led_ctrl,
11138c2ecf20Sopenharmony_ci};
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic struct ts2020_config s660_ts2020_config = {
11168c2ecf20Sopenharmony_ci	.tuner_address = 0x60,
11178c2ecf20Sopenharmony_ci	.clk_out_div = 1,
11188c2ecf20Sopenharmony_ci	.frequency_div = 1146000,
11198c2ecf20Sopenharmony_ci};
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_cistatic struct stv0900_config dw2104a_stv0900_config = {
11228c2ecf20Sopenharmony_ci	.demod_address = 0x6a,
11238c2ecf20Sopenharmony_ci	.demod_mode = 0,
11248c2ecf20Sopenharmony_ci	.xtal = 27000000,
11258c2ecf20Sopenharmony_ci	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
11268c2ecf20Sopenharmony_ci	.diseqc_mode = 2,/* 2/3 PWM */
11278c2ecf20Sopenharmony_ci	.tun1_maddress = 0,/* 0x60 */
11288c2ecf20Sopenharmony_ci	.tun1_adc = 0,/* 2 Vpp */
11298c2ecf20Sopenharmony_ci	.path1_mode = 3,
11308c2ecf20Sopenharmony_ci};
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_cistatic struct stb6100_config dw2104a_stb6100_config = {
11338c2ecf20Sopenharmony_ci	.tuner_address = 0x60,
11348c2ecf20Sopenharmony_ci	.refclock = 27000000,
11358c2ecf20Sopenharmony_ci};
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cistatic struct stv0900_config dw2104_stv0900_config = {
11388c2ecf20Sopenharmony_ci	.demod_address = 0x68,
11398c2ecf20Sopenharmony_ci	.demod_mode = 0,
11408c2ecf20Sopenharmony_ci	.xtal = 8000000,
11418c2ecf20Sopenharmony_ci	.clkmode = 3,
11428c2ecf20Sopenharmony_ci	.diseqc_mode = 2,
11438c2ecf20Sopenharmony_ci	.tun1_maddress = 0,
11448c2ecf20Sopenharmony_ci	.tun1_adc = 1,/* 1 Vpp */
11458c2ecf20Sopenharmony_ci	.path1_mode = 3,
11468c2ecf20Sopenharmony_ci};
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_cistatic struct stv6110_config dw2104_stv6110_config = {
11498c2ecf20Sopenharmony_ci	.i2c_address = 0x60,
11508c2ecf20Sopenharmony_ci	.mclk = 16000000,
11518c2ecf20Sopenharmony_ci	.clk_div = 1,
11528c2ecf20Sopenharmony_ci};
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_cistatic struct stv0900_config prof_7500_stv0900_config = {
11558c2ecf20Sopenharmony_ci	.demod_address = 0x6a,
11568c2ecf20Sopenharmony_ci	.demod_mode = 0,
11578c2ecf20Sopenharmony_ci	.xtal = 27000000,
11588c2ecf20Sopenharmony_ci	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
11598c2ecf20Sopenharmony_ci	.diseqc_mode = 2,/* 2/3 PWM */
11608c2ecf20Sopenharmony_ci	.tun1_maddress = 0,/* 0x60 */
11618c2ecf20Sopenharmony_ci	.tun1_adc = 0,/* 2 Vpp */
11628c2ecf20Sopenharmony_ci	.path1_mode = 3,
11638c2ecf20Sopenharmony_ci	.tun1_type = 3,
11648c2ecf20Sopenharmony_ci	.set_lock_led = dw210x_led_ctrl,
11658c2ecf20Sopenharmony_ci};
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_cistatic struct ds3000_config su3000_ds3000_config = {
11688c2ecf20Sopenharmony_ci	.demod_address = 0x68,
11698c2ecf20Sopenharmony_ci	.ci_mode = 1,
11708c2ecf20Sopenharmony_ci	.set_lock_led = dw210x_led_ctrl,
11718c2ecf20Sopenharmony_ci};
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_cistatic struct cxd2820r_config cxd2820r_config = {
11748c2ecf20Sopenharmony_ci	.i2c_address = 0x6c, /* (0xd8 >> 1) */
11758c2ecf20Sopenharmony_ci	.ts_mode = 0x38,
11768c2ecf20Sopenharmony_ci	.ts_clock_inv = 1,
11778c2ecf20Sopenharmony_ci};
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_cistatic struct tda18271_config tda18271_config = {
11808c2ecf20Sopenharmony_ci	.output_opt = TDA18271_OUTPUT_LT_OFF,
11818c2ecf20Sopenharmony_ci	.gate = TDA18271_GATE_DIGITAL,
11828c2ecf20Sopenharmony_ci};
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_cistatic u8 m88rs2000_inittab[] = {
11858c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x9a, 0x30,
11868c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x00, 0x01,
11878c2ecf20Sopenharmony_ci	WRITE_DELAY, 0x19, 0x00,
11888c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x00, 0x00,
11898c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x9a, 0xb0,
11908c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x81, 0xc1,
11918c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x81, 0x81,
11928c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x86, 0xc6,
11938c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x9a, 0x30,
11948c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0xf0, 0x80,
11958c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0xf1, 0xbf,
11968c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0xb0, 0x45,
11978c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0xb2, 0x01,
11988c2ecf20Sopenharmony_ci	DEMOD_WRITE, 0x9a, 0xb0,
11998c2ecf20Sopenharmony_ci	0xff, 0xaa, 0xff
12008c2ecf20Sopenharmony_ci};
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_cistatic struct m88rs2000_config s421_m88rs2000_config = {
12038c2ecf20Sopenharmony_ci	.demod_addr = 0x68,
12048c2ecf20Sopenharmony_ci	.inittab = m88rs2000_inittab,
12058c2ecf20Sopenharmony_ci};
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_cistatic int dw2104_frontend_attach(struct dvb_usb_adapter *d)
12088c2ecf20Sopenharmony_ci{
12098c2ecf20Sopenharmony_ci	struct dvb_tuner_ops *tuner_ops = NULL;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	if (demod_probe & 4) {
12128c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
12138c2ecf20Sopenharmony_ci				&d->dev->i2c_adap, 0);
12148c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
12158c2ecf20Sopenharmony_ci			if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
12168c2ecf20Sopenharmony_ci					&dw2104a_stb6100_config,
12178c2ecf20Sopenharmony_ci					&d->dev->i2c_adap)) {
12188c2ecf20Sopenharmony_ci				tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
12198c2ecf20Sopenharmony_ci				tuner_ops->set_frequency = stb6100_set_freq;
12208c2ecf20Sopenharmony_ci				tuner_ops->get_frequency = stb6100_get_freq;
12218c2ecf20Sopenharmony_ci				tuner_ops->set_bandwidth = stb6100_set_bandw;
12228c2ecf20Sopenharmony_ci				tuner_ops->get_bandwidth = stb6100_get_bandw;
12238c2ecf20Sopenharmony_ci				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12248c2ecf20Sopenharmony_ci				info("Attached STV0900+STB6100!");
12258c2ecf20Sopenharmony_ci				return 0;
12268c2ecf20Sopenharmony_ci			}
12278c2ecf20Sopenharmony_ci		}
12288c2ecf20Sopenharmony_ci	}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (demod_probe & 2) {
12318c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
12328c2ecf20Sopenharmony_ci				&d->dev->i2c_adap, 0);
12338c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
12348c2ecf20Sopenharmony_ci			if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
12358c2ecf20Sopenharmony_ci					&dw2104_stv6110_config,
12368c2ecf20Sopenharmony_ci					&d->dev->i2c_adap)) {
12378c2ecf20Sopenharmony_ci				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12388c2ecf20Sopenharmony_ci				info("Attached STV0900+STV6110A!");
12398c2ecf20Sopenharmony_ci				return 0;
12408c2ecf20Sopenharmony_ci			}
12418c2ecf20Sopenharmony_ci		}
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	if (demod_probe & 1) {
12458c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
12468c2ecf20Sopenharmony_ci				&d->dev->i2c_adap);
12478c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
12488c2ecf20Sopenharmony_ci			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12498c2ecf20Sopenharmony_ci			info("Attached cx24116!");
12508c2ecf20Sopenharmony_ci			return 0;
12518c2ecf20Sopenharmony_ci		}
12528c2ecf20Sopenharmony_ci	}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
12558c2ecf20Sopenharmony_ci			&d->dev->i2c_adap);
12568c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe != NULL) {
12578c2ecf20Sopenharmony_ci		dvb_attach(ts2020_attach, d->fe_adap[0].fe,
12588c2ecf20Sopenharmony_ci			&dw2104_ts2020_config, &d->dev->i2c_adap);
12598c2ecf20Sopenharmony_ci		d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12608c2ecf20Sopenharmony_ci		info("Attached DS3000!");
12618c2ecf20Sopenharmony_ci		return 0;
12628c2ecf20Sopenharmony_ci	}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	return -EIO;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dw2102_properties;
12688c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dw2104_properties;
12698c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties s6x0_properties;
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_cistatic int dw2102_frontend_attach(struct dvb_usb_adapter *d)
12728c2ecf20Sopenharmony_ci{
12738c2ecf20Sopenharmony_ci	if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
12748c2ecf20Sopenharmony_ci		/*dw2102_properties.adapter->tuner_attach = NULL;*/
12758c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
12768c2ecf20Sopenharmony_ci					&d->dev->i2c_adap);
12778c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
12788c2ecf20Sopenharmony_ci			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12798c2ecf20Sopenharmony_ci			info("Attached si21xx!");
12808c2ecf20Sopenharmony_ci			return 0;
12818c2ecf20Sopenharmony_ci		}
12828c2ecf20Sopenharmony_ci	}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
12858c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
12868c2ecf20Sopenharmony_ci					&d->dev->i2c_adap);
12878c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
12888c2ecf20Sopenharmony_ci			if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
12898c2ecf20Sopenharmony_ci					&d->dev->i2c_adap)) {
12908c2ecf20Sopenharmony_ci				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
12918c2ecf20Sopenharmony_ci				info("Attached stv0288!");
12928c2ecf20Sopenharmony_ci				return 0;
12938c2ecf20Sopenharmony_ci			}
12948c2ecf20Sopenharmony_ci		}
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
12988c2ecf20Sopenharmony_ci		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
12998c2ecf20Sopenharmony_ci		d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
13008c2ecf20Sopenharmony_ci					&d->dev->i2c_adap);
13018c2ecf20Sopenharmony_ci		if (d->fe_adap[0].fe != NULL) {
13028c2ecf20Sopenharmony_ci			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
13038c2ecf20Sopenharmony_ci			info("Attached stv0299!");
13048c2ecf20Sopenharmony_ci			return 0;
13058c2ecf20Sopenharmony_ci		}
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci	return -EIO;
13088c2ecf20Sopenharmony_ci}
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_cistatic int dw3101_frontend_attach(struct dvb_usb_adapter *d)
13118c2ecf20Sopenharmony_ci{
13128c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
13138c2ecf20Sopenharmony_ci				&d->dev->i2c_adap, 0x48);
13148c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe != NULL) {
13158c2ecf20Sopenharmony_ci		info("Attached tda10023!");
13168c2ecf20Sopenharmony_ci		return 0;
13178c2ecf20Sopenharmony_ci	}
13188c2ecf20Sopenharmony_ci	return -EIO;
13198c2ecf20Sopenharmony_ci}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cistatic int zl100313_frontend_attach(struct dvb_usb_adapter *d)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
13248c2ecf20Sopenharmony_ci			&d->dev->i2c_adap);
13258c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe != NULL) {
13268c2ecf20Sopenharmony_ci		if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
13278c2ecf20Sopenharmony_ci				&d->dev->i2c_adap)) {
13288c2ecf20Sopenharmony_ci			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
13298c2ecf20Sopenharmony_ci			info("Attached zl100313+zl10039!");
13308c2ecf20Sopenharmony_ci			return 0;
13318c2ecf20Sopenharmony_ci		}
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	return -EIO;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_cistatic int stv0288_frontend_attach(struct dvb_usb_adapter *d)
13388c2ecf20Sopenharmony_ci{
13398c2ecf20Sopenharmony_ci	u8 obuf[] = {7, 1};
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
13428c2ecf20Sopenharmony_ci			&d->dev->i2c_adap);
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe == NULL)
13458c2ecf20Sopenharmony_ci		return -EIO;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
13488c2ecf20Sopenharmony_ci		return -EIO;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	info("Attached stv0288+stb6000!");
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	return 0;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci}
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_cistatic int ds3000_frontend_attach(struct dvb_usb_adapter *d)
13618c2ecf20Sopenharmony_ci{
13628c2ecf20Sopenharmony_ci	struct dw2102_state *st = d->dev->priv;
13638c2ecf20Sopenharmony_ci	u8 obuf[] = {7, 1};
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config,
13668c2ecf20Sopenharmony_ci			&d->dev->i2c_adap);
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe == NULL)
13698c2ecf20Sopenharmony_ci		return -EIO;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	dvb_attach(ts2020_attach, d->fe_adap[0].fe, &s660_ts2020_config,
13728c2ecf20Sopenharmony_ci		&d->dev->i2c_adap);
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
13758c2ecf20Sopenharmony_ci	d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	info("Attached ds3000+ts2020!");
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	return 0;
13828c2ecf20Sopenharmony_ci}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_cistatic int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
13858c2ecf20Sopenharmony_ci{
13868c2ecf20Sopenharmony_ci	u8 obuf[] = {7, 1};
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
13898c2ecf20Sopenharmony_ci					&d->dev->i2c_adap, 0);
13908c2ecf20Sopenharmony_ci	if (d->fe_adap[0].fe == NULL)
13918c2ecf20Sopenharmony_ci		return -EIO;
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci	info("Attached STV0900+STB6100A!");
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	return 0;
14008c2ecf20Sopenharmony_ci}
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_cistatic int su3000_frontend_attach(struct dvb_usb_adapter *adap)
14038c2ecf20Sopenharmony_ci{
14048c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
14058c2ecf20Sopenharmony_ci	struct dw2102_state *state = d->priv;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	mutex_lock(&d->data_mutex);
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14108c2ecf20Sopenharmony_ci	state->data[1] = 0x80;
14118c2ecf20Sopenharmony_ci	state->data[2] = 0;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14148c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14178c2ecf20Sopenharmony_ci	state->data[1] = 0x02;
14188c2ecf20Sopenharmony_ci	state->data[2] = 1;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14218c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14228c2ecf20Sopenharmony_ci	msleep(300);
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14258c2ecf20Sopenharmony_ci	state->data[1] = 0x83;
14268c2ecf20Sopenharmony_ci	state->data[2] = 0;
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14298c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14328c2ecf20Sopenharmony_ci	state->data[1] = 0x83;
14338c2ecf20Sopenharmony_ci	state->data[2] = 1;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14368c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	state->data[0] = 0x51;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0)
14418c2ecf20Sopenharmony_ci		err("command 0x51 transfer failed.");
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
14468c2ecf20Sopenharmony_ci					&d->i2c_adap);
14478c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe == NULL)
14488c2ecf20Sopenharmony_ci		return -EIO;
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe,
14518c2ecf20Sopenharmony_ci				&dw2104_ts2020_config,
14528c2ecf20Sopenharmony_ci				&d->i2c_adap)) {
14538c2ecf20Sopenharmony_ci		info("Attached DS3000/TS2020!");
14548c2ecf20Sopenharmony_ci		return 0;
14558c2ecf20Sopenharmony_ci	}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	info("Failed to attach DS3000/TS2020!");
14588c2ecf20Sopenharmony_ci	return -EIO;
14598c2ecf20Sopenharmony_ci}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_cistatic int t220_frontend_attach(struct dvb_usb_adapter *adap)
14628c2ecf20Sopenharmony_ci{
14638c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
14648c2ecf20Sopenharmony_ci	struct dw2102_state *state = d->priv;
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	mutex_lock(&d->data_mutex);
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14698c2ecf20Sopenharmony_ci	state->data[1] = 0x87;
14708c2ecf20Sopenharmony_ci	state->data[2] = 0x0;
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14738c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14768c2ecf20Sopenharmony_ci	state->data[1] = 0x86;
14778c2ecf20Sopenharmony_ci	state->data[2] = 1;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14808c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14838c2ecf20Sopenharmony_ci	state->data[1] = 0x80;
14848c2ecf20Sopenharmony_ci	state->data[2] = 0;
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14878c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	msleep(50);
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
14928c2ecf20Sopenharmony_ci	state->data[1] = 0x80;
14938c2ecf20Sopenharmony_ci	state->data[2] = 1;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
14968c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	state->data[0] = 0x51;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0)
15018c2ecf20Sopenharmony_ci		err("command 0x51 transfer failed.");
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config,
15068c2ecf20Sopenharmony_ci					&d->i2c_adap, NULL);
15078c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe != NULL) {
15088c2ecf20Sopenharmony_ci		if (dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0x60,
15098c2ecf20Sopenharmony_ci					&d->i2c_adap, &tda18271_config)) {
15108c2ecf20Sopenharmony_ci			info("Attached TDA18271HD/CXD2820R!");
15118c2ecf20Sopenharmony_ci			return 0;
15128c2ecf20Sopenharmony_ci		}
15138c2ecf20Sopenharmony_ci	}
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	info("Failed to attach TDA18271HD/CXD2820R!");
15168c2ecf20Sopenharmony_ci	return -EIO;
15178c2ecf20Sopenharmony_ci}
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_cistatic int m88rs2000_frontend_attach(struct dvb_usb_adapter *adap)
15208c2ecf20Sopenharmony_ci{
15218c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
15228c2ecf20Sopenharmony_ci	struct dw2102_state *state = d->priv;
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	mutex_lock(&d->data_mutex);
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	state->data[0] = 0x51;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0)
15298c2ecf20Sopenharmony_ci		err("command 0x51 transfer failed.");
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach,
15348c2ecf20Sopenharmony_ci					&s421_m88rs2000_config,
15358c2ecf20Sopenharmony_ci					&d->i2c_adap);
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe == NULL)
15388c2ecf20Sopenharmony_ci		return -EIO;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	if (dvb_attach(ts2020_attach, adap->fe_adap[0].fe,
15418c2ecf20Sopenharmony_ci				&dw2104_ts2020_config,
15428c2ecf20Sopenharmony_ci				&d->i2c_adap)) {
15438c2ecf20Sopenharmony_ci		info("Attached RS2000/TS2020!");
15448c2ecf20Sopenharmony_ci		return 0;
15458c2ecf20Sopenharmony_ci	}
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	info("Failed to attach RS2000/TS2020!");
15488c2ecf20Sopenharmony_ci	return -EIO;
15498c2ecf20Sopenharmony_ci}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_cistatic int tt_s2_4600_frontend_attach_probe_demod(struct dvb_usb_device *d,
15528c2ecf20Sopenharmony_ci						  const int probe_addr)
15538c2ecf20Sopenharmony_ci{
15548c2ecf20Sopenharmony_ci	struct dw2102_state *state = d->priv;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	state->data[0] = 0x9;
15578c2ecf20Sopenharmony_ci	state->data[1] = 0x1;
15588c2ecf20Sopenharmony_ci	state->data[2] = 0x1;
15598c2ecf20Sopenharmony_ci	state->data[3] = probe_addr;
15608c2ecf20Sopenharmony_ci	state->data[4] = 0x0;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 5, state->data, 2, 0) < 0) {
15638c2ecf20Sopenharmony_ci		err("i2c probe for address 0x%x failed.", probe_addr);
15648c2ecf20Sopenharmony_ci		return 0;
15658c2ecf20Sopenharmony_ci	}
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	if (state->data[0] != 8) /* fail(7) or error, no device at address */
15688c2ecf20Sopenharmony_ci		return 0;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	/* probing successful */
15718c2ecf20Sopenharmony_ci	return 1;
15728c2ecf20Sopenharmony_ci}
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_cistatic int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
15758c2ecf20Sopenharmony_ci{
15768c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
15778c2ecf20Sopenharmony_ci	struct dw2102_state *state = d->priv;
15788c2ecf20Sopenharmony_ci	struct i2c_adapter *i2c_adapter;
15798c2ecf20Sopenharmony_ci	struct i2c_client *client;
15808c2ecf20Sopenharmony_ci	struct i2c_board_info board_info;
15818c2ecf20Sopenharmony_ci	struct m88ds3103_platform_data m88ds3103_pdata = {};
15828c2ecf20Sopenharmony_ci	struct ts2020_config ts2020_config = {};
15838c2ecf20Sopenharmony_ci	int demod_addr;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	mutex_lock(&d->data_mutex);
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
15888c2ecf20Sopenharmony_ci	state->data[1] = 0x80;
15898c2ecf20Sopenharmony_ci	state->data[2] = 0x0;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
15928c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
15958c2ecf20Sopenharmony_ci	state->data[1] = 0x02;
15968c2ecf20Sopenharmony_ci	state->data[2] = 1;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
15998c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
16008c2ecf20Sopenharmony_ci	msleep(300);
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
16038c2ecf20Sopenharmony_ci	state->data[1] = 0x83;
16048c2ecf20Sopenharmony_ci	state->data[2] = 0;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
16078c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	state->data[0] = 0xe;
16108c2ecf20Sopenharmony_ci	state->data[1] = 0x83;
16118c2ecf20Sopenharmony_ci	state->data[2] = 1;
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 3, state->data, 1, 0) < 0)
16148c2ecf20Sopenharmony_ci		err("command 0x0e transfer failed.");
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci	state->data[0] = 0x51;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0)
16198c2ecf20Sopenharmony_ci		err("command 0x51 transfer failed.");
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	/* probe for demodulator i2c address */
16228c2ecf20Sopenharmony_ci	demod_addr = -1;
16238c2ecf20Sopenharmony_ci	if (tt_s2_4600_frontend_attach_probe_demod(d, 0x68))
16248c2ecf20Sopenharmony_ci		demod_addr = 0x68;
16258c2ecf20Sopenharmony_ci	else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x69))
16268c2ecf20Sopenharmony_ci		demod_addr = 0x69;
16278c2ecf20Sopenharmony_ci	else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x6a))
16288c2ecf20Sopenharmony_ci		demod_addr = 0x6a;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	if (demod_addr < 0) {
16338c2ecf20Sopenharmony_ci		err("probing for demodulator failed. Is the external power switched on?");
16348c2ecf20Sopenharmony_ci		return -ENODEV;
16358c2ecf20Sopenharmony_ci	}
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	/* attach demod */
16388c2ecf20Sopenharmony_ci	m88ds3103_pdata.clk = 27000000;
16398c2ecf20Sopenharmony_ci	m88ds3103_pdata.i2c_wr_max = 33;
16408c2ecf20Sopenharmony_ci	m88ds3103_pdata.ts_mode = M88DS3103_TS_CI;
16418c2ecf20Sopenharmony_ci	m88ds3103_pdata.ts_clk = 16000;
16428c2ecf20Sopenharmony_ci	m88ds3103_pdata.ts_clk_pol = 0;
16438c2ecf20Sopenharmony_ci	m88ds3103_pdata.spec_inv = 0;
16448c2ecf20Sopenharmony_ci	m88ds3103_pdata.agc = 0x99;
16458c2ecf20Sopenharmony_ci	m88ds3103_pdata.agc_inv = 0;
16468c2ecf20Sopenharmony_ci	m88ds3103_pdata.clk_out = M88DS3103_CLOCK_OUT_ENABLED;
16478c2ecf20Sopenharmony_ci	m88ds3103_pdata.envelope_mode = 0;
16488c2ecf20Sopenharmony_ci	m88ds3103_pdata.lnb_hv_pol = 1;
16498c2ecf20Sopenharmony_ci	m88ds3103_pdata.lnb_en_pol = 0;
16508c2ecf20Sopenharmony_ci	memset(&board_info, 0, sizeof(board_info));
16518c2ecf20Sopenharmony_ci	if (demod_addr == 0x6a)
16528c2ecf20Sopenharmony_ci		strscpy(board_info.type, "m88ds3103b", I2C_NAME_SIZE);
16538c2ecf20Sopenharmony_ci	else
16548c2ecf20Sopenharmony_ci		strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
16558c2ecf20Sopenharmony_ci	board_info.addr = demod_addr;
16568c2ecf20Sopenharmony_ci	board_info.platform_data = &m88ds3103_pdata;
16578c2ecf20Sopenharmony_ci	request_module("m88ds3103");
16588c2ecf20Sopenharmony_ci	client = i2c_new_client_device(&d->i2c_adap, &board_info);
16598c2ecf20Sopenharmony_ci	if (!i2c_client_has_driver(client))
16608c2ecf20Sopenharmony_ci		return -ENODEV;
16618c2ecf20Sopenharmony_ci	if (!try_module_get(client->dev.driver->owner)) {
16628c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
16638c2ecf20Sopenharmony_ci		return -ENODEV;
16648c2ecf20Sopenharmony_ci	}
16658c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = m88ds3103_pdata.get_dvb_frontend(client);
16668c2ecf20Sopenharmony_ci	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client);
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	state->i2c_client_demod = client;
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	/* attach tuner */
16718c2ecf20Sopenharmony_ci	ts2020_config.fe = adap->fe_adap[0].fe;
16728c2ecf20Sopenharmony_ci	memset(&board_info, 0, sizeof(board_info));
16738c2ecf20Sopenharmony_ci	strscpy(board_info.type, "ts2022", I2C_NAME_SIZE);
16748c2ecf20Sopenharmony_ci	board_info.addr = 0x60;
16758c2ecf20Sopenharmony_ci	board_info.platform_data = &ts2020_config;
16768c2ecf20Sopenharmony_ci	request_module("ts2020");
16778c2ecf20Sopenharmony_ci	client = i2c_new_client_device(i2c_adapter, &board_info);
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	if (!i2c_client_has_driver(client)) {
16808c2ecf20Sopenharmony_ci		dvb_frontend_detach(adap->fe_adap[0].fe);
16818c2ecf20Sopenharmony_ci		return -ENODEV;
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	if (!try_module_get(client->dev.driver->owner)) {
16858c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
16868c2ecf20Sopenharmony_ci		dvb_frontend_detach(adap->fe_adap[0].fe);
16878c2ecf20Sopenharmony_ci		return -ENODEV;
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	/* delegate signal strength measurement to tuner */
16918c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe->ops.read_signal_strength =
16928c2ecf20Sopenharmony_ci			adap->fe_adap[0].fe->ops.tuner_ops.get_rf_strength;
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	state->i2c_client_tuner = client;
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_ci	/* hook fe: need to resync the slave fifo when signal locks */
16978c2ecf20Sopenharmony_ci	state->fe_read_status = adap->fe_adap[0].fe->ops.read_status;
16988c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe->ops.read_status = tt_s2_4600_read_status;
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci	state->last_lock = 0;
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	return 0;
17038c2ecf20Sopenharmony_ci}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_cistatic int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
17088c2ecf20Sopenharmony_ci		&adap->dev->i2c_adap, DVB_PLL_OPERA1);
17098c2ecf20Sopenharmony_ci	return 0;
17108c2ecf20Sopenharmony_ci}
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_cistatic int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
17138c2ecf20Sopenharmony_ci{
17148c2ecf20Sopenharmony_ci	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
17158c2ecf20Sopenharmony_ci		&adap->dev->i2c_adap, DVB_PLL_TUA6034);
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	return 0;
17188c2ecf20Sopenharmony_ci}
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_cistatic int dw2102_rc_query(struct dvb_usb_device *d)
17218c2ecf20Sopenharmony_ci{
17228c2ecf20Sopenharmony_ci	u8 key[2];
17238c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
17248c2ecf20Sopenharmony_ci		.addr = DW2102_RC_QUERY,
17258c2ecf20Sopenharmony_ci		.flags = I2C_M_RD,
17268c2ecf20Sopenharmony_ci		.buf = key,
17278c2ecf20Sopenharmony_ci		.len = 2
17288c2ecf20Sopenharmony_ci	};
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
17318c2ecf20Sopenharmony_ci		if (msg.buf[0] != 0xff) {
17328c2ecf20Sopenharmony_ci			deb_rc("%s: rc code: %x, %x\n",
17338c2ecf20Sopenharmony_ci					__func__, key[0], key[1]);
17348c2ecf20Sopenharmony_ci			rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN, key[0], 0);
17358c2ecf20Sopenharmony_ci		}
17368c2ecf20Sopenharmony_ci	}
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	return 0;
17398c2ecf20Sopenharmony_ci}
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_cistatic int prof_rc_query(struct dvb_usb_device *d)
17428c2ecf20Sopenharmony_ci{
17438c2ecf20Sopenharmony_ci	u8 key[2];
17448c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
17458c2ecf20Sopenharmony_ci		.addr = DW2102_RC_QUERY,
17468c2ecf20Sopenharmony_ci		.flags = I2C_M_RD,
17478c2ecf20Sopenharmony_ci		.buf = key,
17488c2ecf20Sopenharmony_ci		.len = 2
17498c2ecf20Sopenharmony_ci	};
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
17528c2ecf20Sopenharmony_ci		if (msg.buf[0] != 0xff) {
17538c2ecf20Sopenharmony_ci			deb_rc("%s: rc code: %x, %x\n",
17548c2ecf20Sopenharmony_ci					__func__, key[0], key[1]);
17558c2ecf20Sopenharmony_ci			rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN, key[0] ^ 0xff,
17568c2ecf20Sopenharmony_ci				   0);
17578c2ecf20Sopenharmony_ci		}
17588c2ecf20Sopenharmony_ci	}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	return 0;
17618c2ecf20Sopenharmony_ci}
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_cistatic int su3000_rc_query(struct dvb_usb_device *d)
17648c2ecf20Sopenharmony_ci{
17658c2ecf20Sopenharmony_ci	u8 key[2];
17668c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
17678c2ecf20Sopenharmony_ci		.addr = DW2102_RC_QUERY,
17688c2ecf20Sopenharmony_ci		.flags = I2C_M_RD,
17698c2ecf20Sopenharmony_ci		.buf = key,
17708c2ecf20Sopenharmony_ci		.len = 2
17718c2ecf20Sopenharmony_ci	};
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
17748c2ecf20Sopenharmony_ci		if (msg.buf[0] != 0xff) {
17758c2ecf20Sopenharmony_ci			deb_rc("%s: rc code: %x, %x\n",
17768c2ecf20Sopenharmony_ci					__func__, key[0], key[1]);
17778c2ecf20Sopenharmony_ci			rc_keydown(d->rc_dev, RC_PROTO_RC5,
17788c2ecf20Sopenharmony_ci				   RC_SCANCODE_RC5(key[1], key[0]), 0);
17798c2ecf20Sopenharmony_ci		}
17808c2ecf20Sopenharmony_ci	}
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	return 0;
17838c2ecf20Sopenharmony_ci}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_cienum dw2102_table_entry {
17868c2ecf20Sopenharmony_ci	CYPRESS_DW2102,
17878c2ecf20Sopenharmony_ci	CYPRESS_DW2101,
17888c2ecf20Sopenharmony_ci	CYPRESS_DW2104,
17898c2ecf20Sopenharmony_ci	TEVII_S650,
17908c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S,
17918c2ecf20Sopenharmony_ci	CYPRESS_DW3101,
17928c2ecf20Sopenharmony_ci	TEVII_S630,
17938c2ecf20Sopenharmony_ci	PROF_1100,
17948c2ecf20Sopenharmony_ci	TEVII_S660,
17958c2ecf20Sopenharmony_ci	PROF_7500,
17968c2ecf20Sopenharmony_ci	GENIATECH_SU3000,
17978c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2,
17988c2ecf20Sopenharmony_ci	TEVII_S480_1,
17998c2ecf20Sopenharmony_ci	TEVII_S480_2,
18008c2ecf20Sopenharmony_ci	X3M_SPC1400HD,
18018c2ecf20Sopenharmony_ci	TEVII_S421,
18028c2ecf20Sopenharmony_ci	TEVII_S632,
18038c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_R2,
18048c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_R3,
18058c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_R4,
18068c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_1,
18078c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_2,
18088c2ecf20Sopenharmony_ci	GOTVIEW_SAT_HD,
18098c2ecf20Sopenharmony_ci	GENIATECH_T220,
18108c2ecf20Sopenharmony_ci	TECHNOTREND_S2_4600,
18118c2ecf20Sopenharmony_ci	TEVII_S482_1,
18128c2ecf20Sopenharmony_ci	TEVII_S482_2,
18138c2ecf20Sopenharmony_ci	TERRATEC_CINERGY_S2_BOX,
18148c2ecf20Sopenharmony_ci	TEVII_S662
18158c2ecf20Sopenharmony_ci};
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_cistatic struct usb_device_id dw2102_table[] = {
18188c2ecf20Sopenharmony_ci	[CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
18198c2ecf20Sopenharmony_ci	[CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
18208c2ecf20Sopenharmony_ci	[CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
18218c2ecf20Sopenharmony_ci	[TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
18228c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S)},
18238c2ecf20Sopenharmony_ci	[CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
18248c2ecf20Sopenharmony_ci	[TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
18258c2ecf20Sopenharmony_ci	[PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
18268c2ecf20Sopenharmony_ci	[TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
18278c2ecf20Sopenharmony_ci	[PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
18288c2ecf20Sopenharmony_ci	[GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
18298c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)},
18308c2ecf20Sopenharmony_ci	[TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
18318c2ecf20Sopenharmony_ci	[TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
18328c2ecf20Sopenharmony_ci	[X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
18338c2ecf20Sopenharmony_ci	[TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)},
18348c2ecf20Sopenharmony_ci	[TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)},
18358c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC,
18368c2ecf20Sopenharmony_ci				    USB_PID_TERRATEC_CINERGY_S2_R2)},
18378c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC,
18388c2ecf20Sopenharmony_ci				    USB_PID_TERRATEC_CINERGY_S2_R3)},
18398c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC,
18408c2ecf20Sopenharmony_ci				    USB_PID_TERRATEC_CINERGY_S2_R4)},
18418c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_1] = {USB_DEVICE(USB_VID_TERRATEC_2,
18428c2ecf20Sopenharmony_ci				   USB_PID_TERRATEC_CINERGY_S2_1)},
18438c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_2] = {USB_DEVICE(USB_VID_TERRATEC_2,
18448c2ecf20Sopenharmony_ci				   USB_PID_TERRATEC_CINERGY_S2_2)},
18458c2ecf20Sopenharmony_ci	[GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
18468c2ecf20Sopenharmony_ci	[GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)},
18478c2ecf20Sopenharmony_ci	[TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND,
18488c2ecf20Sopenharmony_ci		USB_PID_TECHNOTREND_CONNECT_S2_4600)},
18498c2ecf20Sopenharmony_ci	[TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)},
18508c2ecf20Sopenharmony_ci	[TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)},
18518c2ecf20Sopenharmony_ci	[TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)},
18528c2ecf20Sopenharmony_ci	[TEVII_S662] = {USB_DEVICE(0x9022, USB_PID_TEVII_S662)},
18538c2ecf20Sopenharmony_ci	{ }
18548c2ecf20Sopenharmony_ci};
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, dw2102_table);
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_cistatic int dw2102_load_firmware(struct usb_device *dev,
18598c2ecf20Sopenharmony_ci			const struct firmware *frmwr)
18608c2ecf20Sopenharmony_ci{
18618c2ecf20Sopenharmony_ci	u8 *b, *p;
18628c2ecf20Sopenharmony_ci	int ret = 0, i;
18638c2ecf20Sopenharmony_ci	u8 reset;
18648c2ecf20Sopenharmony_ci	u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
18658c2ecf20Sopenharmony_ci	const struct firmware *fw;
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	switch (le16_to_cpu(dev->descriptor.idProduct)) {
18688c2ecf20Sopenharmony_ci	case 0x2101:
18698c2ecf20Sopenharmony_ci		ret = request_firmware(&fw, DW2101_FIRMWARE, &dev->dev);
18708c2ecf20Sopenharmony_ci		if (ret != 0) {
18718c2ecf20Sopenharmony_ci			err(err_str, DW2101_FIRMWARE);
18728c2ecf20Sopenharmony_ci			return ret;
18738c2ecf20Sopenharmony_ci		}
18748c2ecf20Sopenharmony_ci		break;
18758c2ecf20Sopenharmony_ci	default:
18768c2ecf20Sopenharmony_ci		fw = frmwr;
18778c2ecf20Sopenharmony_ci		break;
18788c2ecf20Sopenharmony_ci	}
18798c2ecf20Sopenharmony_ci	info("start downloading DW210X firmware");
18808c2ecf20Sopenharmony_ci	p = kmalloc(fw->size, GFP_KERNEL);
18818c2ecf20Sopenharmony_ci	reset = 1;
18828c2ecf20Sopenharmony_ci	/*stop the CPU*/
18838c2ecf20Sopenharmony_ci	dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
18848c2ecf20Sopenharmony_ci	dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	if (p != NULL) {
18878c2ecf20Sopenharmony_ci		memcpy(p, fw->data, fw->size);
18888c2ecf20Sopenharmony_ci		for (i = 0; i < fw->size; i += 0x40) {
18898c2ecf20Sopenharmony_ci			b = (u8 *) p + i;
18908c2ecf20Sopenharmony_ci			if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
18918c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG) != 0x40) {
18928c2ecf20Sopenharmony_ci				err("error while transferring firmware");
18938c2ecf20Sopenharmony_ci				ret = -EINVAL;
18948c2ecf20Sopenharmony_ci				break;
18958c2ecf20Sopenharmony_ci			}
18968c2ecf20Sopenharmony_ci		}
18978c2ecf20Sopenharmony_ci		/* restart the CPU */
18988c2ecf20Sopenharmony_ci		reset = 0;
18998c2ecf20Sopenharmony_ci		if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
19008c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG) != 1) {
19018c2ecf20Sopenharmony_ci			err("could not restart the USB controller CPU.");
19028c2ecf20Sopenharmony_ci			ret = -EINVAL;
19038c2ecf20Sopenharmony_ci		}
19048c2ecf20Sopenharmony_ci		if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
19058c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG) != 1) {
19068c2ecf20Sopenharmony_ci			err("could not restart the USB controller CPU.");
19078c2ecf20Sopenharmony_ci			ret = -EINVAL;
19088c2ecf20Sopenharmony_ci		}
19098c2ecf20Sopenharmony_ci		/* init registers */
19108c2ecf20Sopenharmony_ci		switch (le16_to_cpu(dev->descriptor.idProduct)) {
19118c2ecf20Sopenharmony_ci		case USB_PID_TEVII_S650:
19128c2ecf20Sopenharmony_ci			dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC;
19138c2ecf20Sopenharmony_ci			fallthrough;
19148c2ecf20Sopenharmony_ci		case USB_PID_DW2104:
19158c2ecf20Sopenharmony_ci			reset = 1;
19168c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
19178c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG);
19188c2ecf20Sopenharmony_ci			fallthrough;
19198c2ecf20Sopenharmony_ci		case USB_PID_DW3101:
19208c2ecf20Sopenharmony_ci			reset = 0;
19218c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
19228c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG);
19238c2ecf20Sopenharmony_ci			break;
19248c2ecf20Sopenharmony_ci		case USB_PID_TERRATEC_CINERGY_S:
19258c2ecf20Sopenharmony_ci		case USB_PID_DW2102:
19268c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
19278c2ecf20Sopenharmony_ci					DW210X_WRITE_MSG);
19288c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
19298c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19308c2ecf20Sopenharmony_ci			/* check STV0299 frontend  */
19318c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
19328c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19338c2ecf20Sopenharmony_ci			if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
19348c2ecf20Sopenharmony_ci				dw2102_properties.i2c_algo = &dw2102_i2c_algo;
19358c2ecf20Sopenharmony_ci				dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
19368c2ecf20Sopenharmony_ci				break;
19378c2ecf20Sopenharmony_ci			} else {
19388c2ecf20Sopenharmony_ci				/* check STV0288 frontend  */
19398c2ecf20Sopenharmony_ci				reset16[0] = 0xd0;
19408c2ecf20Sopenharmony_ci				reset16[1] = 1;
19418c2ecf20Sopenharmony_ci				reset16[2] = 0;
19428c2ecf20Sopenharmony_ci				dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
19438c2ecf20Sopenharmony_ci						DW210X_WRITE_MSG);
19448c2ecf20Sopenharmony_ci				dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
19458c2ecf20Sopenharmony_ci						DW210X_READ_MSG);
19468c2ecf20Sopenharmony_ci				if (reset16[2] == 0x11) {
19478c2ecf20Sopenharmony_ci					dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
19488c2ecf20Sopenharmony_ci					break;
19498c2ecf20Sopenharmony_ci				}
19508c2ecf20Sopenharmony_ci			}
19518c2ecf20Sopenharmony_ci			fallthrough;
19528c2ecf20Sopenharmony_ci		case 0x2101:
19538c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
19548c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19558c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
19568c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19578c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
19588c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19598c2ecf20Sopenharmony_ci			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
19608c2ecf20Sopenharmony_ci					DW210X_READ_MSG);
19618c2ecf20Sopenharmony_ci			break;
19628c2ecf20Sopenharmony_ci		}
19638c2ecf20Sopenharmony_ci
19648c2ecf20Sopenharmony_ci		msleep(100);
19658c2ecf20Sopenharmony_ci		kfree(p);
19668c2ecf20Sopenharmony_ci	}
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	if (le16_to_cpu(dev->descriptor.idProduct) == 0x2101)
19698c2ecf20Sopenharmony_ci		release_firmware(fw);
19708c2ecf20Sopenharmony_ci	return ret;
19718c2ecf20Sopenharmony_ci}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dw2102_properties = {
19748c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
19758c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
19768c2ecf20Sopenharmony_ci	.firmware = DW2102_FIRMWARE,
19778c2ecf20Sopenharmony_ci	.no_reconnect = 1,
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	.i2c_algo = &dw2102_serit_i2c_algo,
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	.rc.core = {
19828c2ecf20Sopenharmony_ci		.rc_interval = 150,
19838c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_DM1105_NEC,
19848c2ecf20Sopenharmony_ci		.module_name = "dw2102",
19858c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
19868c2ecf20Sopenharmony_ci		.rc_query = dw2102_rc_query,
19878c2ecf20Sopenharmony_ci	},
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
19908c2ecf20Sopenharmony_ci	/* parameter for the MPEG2-data transfer */
19918c2ecf20Sopenharmony_ci	.num_adapters = 1,
19928c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
19938c2ecf20Sopenharmony_ci	.read_mac_address = dw210x_read_mac_address,
19948c2ecf20Sopenharmony_ci	.adapter = {
19958c2ecf20Sopenharmony_ci		{
19968c2ecf20Sopenharmony_ci		.num_frontends = 1,
19978c2ecf20Sopenharmony_ci		.fe = {{
19988c2ecf20Sopenharmony_ci			.frontend_attach = dw2102_frontend_attach,
19998c2ecf20Sopenharmony_ci			.stream = {
20008c2ecf20Sopenharmony_ci				.type = USB_BULK,
20018c2ecf20Sopenharmony_ci				.count = 8,
20028c2ecf20Sopenharmony_ci				.endpoint = 0x82,
20038c2ecf20Sopenharmony_ci				.u = {
20048c2ecf20Sopenharmony_ci					.bulk = {
20058c2ecf20Sopenharmony_ci						.buffersize = 4096,
20068c2ecf20Sopenharmony_ci					}
20078c2ecf20Sopenharmony_ci				}
20088c2ecf20Sopenharmony_ci			},
20098c2ecf20Sopenharmony_ci		}},
20108c2ecf20Sopenharmony_ci		}
20118c2ecf20Sopenharmony_ci	},
20128c2ecf20Sopenharmony_ci	.num_device_descs = 3,
20138c2ecf20Sopenharmony_ci	.devices = {
20148c2ecf20Sopenharmony_ci		{"DVBWorld DVB-S 2102 USB2.0",
20158c2ecf20Sopenharmony_ci			{&dw2102_table[CYPRESS_DW2102], NULL},
20168c2ecf20Sopenharmony_ci			{NULL},
20178c2ecf20Sopenharmony_ci		},
20188c2ecf20Sopenharmony_ci		{"DVBWorld DVB-S 2101 USB2.0",
20198c2ecf20Sopenharmony_ci			{&dw2102_table[CYPRESS_DW2101], NULL},
20208c2ecf20Sopenharmony_ci			{NULL},
20218c2ecf20Sopenharmony_ci		},
20228c2ecf20Sopenharmony_ci		{"TerraTec Cinergy S USB",
20238c2ecf20Sopenharmony_ci			{&dw2102_table[TERRATEC_CINERGY_S], NULL},
20248c2ecf20Sopenharmony_ci			{NULL},
20258c2ecf20Sopenharmony_ci		},
20268c2ecf20Sopenharmony_ci	}
20278c2ecf20Sopenharmony_ci};
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dw2104_properties = {
20308c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
20318c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
20328c2ecf20Sopenharmony_ci	.firmware = DW2104_FIRMWARE,
20338c2ecf20Sopenharmony_ci	.no_reconnect = 1,
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	.i2c_algo = &dw2104_i2c_algo,
20368c2ecf20Sopenharmony_ci	.rc.core = {
20378c2ecf20Sopenharmony_ci		.rc_interval = 150,
20388c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_DM1105_NEC,
20398c2ecf20Sopenharmony_ci		.module_name = "dw2102",
20408c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
20418c2ecf20Sopenharmony_ci		.rc_query = dw2102_rc_query,
20428c2ecf20Sopenharmony_ci	},
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
20458c2ecf20Sopenharmony_ci	/* parameter for the MPEG2-data transfer */
20468c2ecf20Sopenharmony_ci	.num_adapters = 1,
20478c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
20488c2ecf20Sopenharmony_ci	.read_mac_address = dw210x_read_mac_address,
20498c2ecf20Sopenharmony_ci	.adapter = {
20508c2ecf20Sopenharmony_ci		{
20518c2ecf20Sopenharmony_ci		.num_frontends = 1,
20528c2ecf20Sopenharmony_ci		.fe = {{
20538c2ecf20Sopenharmony_ci			.frontend_attach = dw2104_frontend_attach,
20548c2ecf20Sopenharmony_ci			.stream = {
20558c2ecf20Sopenharmony_ci				.type = USB_BULK,
20568c2ecf20Sopenharmony_ci				.count = 8,
20578c2ecf20Sopenharmony_ci				.endpoint = 0x82,
20588c2ecf20Sopenharmony_ci				.u = {
20598c2ecf20Sopenharmony_ci					.bulk = {
20608c2ecf20Sopenharmony_ci						.buffersize = 4096,
20618c2ecf20Sopenharmony_ci					}
20628c2ecf20Sopenharmony_ci				}
20638c2ecf20Sopenharmony_ci			},
20648c2ecf20Sopenharmony_ci		}},
20658c2ecf20Sopenharmony_ci		}
20668c2ecf20Sopenharmony_ci	},
20678c2ecf20Sopenharmony_ci	.num_device_descs = 2,
20688c2ecf20Sopenharmony_ci	.devices = {
20698c2ecf20Sopenharmony_ci		{ "DVBWorld DW2104 USB2.0",
20708c2ecf20Sopenharmony_ci			{&dw2102_table[CYPRESS_DW2104], NULL},
20718c2ecf20Sopenharmony_ci			{NULL},
20728c2ecf20Sopenharmony_ci		},
20738c2ecf20Sopenharmony_ci		{ "TeVii S650 USB2.0",
20748c2ecf20Sopenharmony_ci			{&dw2102_table[TEVII_S650], NULL},
20758c2ecf20Sopenharmony_ci			{NULL},
20768c2ecf20Sopenharmony_ci		},
20778c2ecf20Sopenharmony_ci	}
20788c2ecf20Sopenharmony_ci};
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties dw3101_properties = {
20818c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
20828c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
20838c2ecf20Sopenharmony_ci	.firmware = DW3101_FIRMWARE,
20848c2ecf20Sopenharmony_ci	.no_reconnect = 1,
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci	.i2c_algo = &dw3101_i2c_algo,
20878c2ecf20Sopenharmony_ci	.rc.core = {
20888c2ecf20Sopenharmony_ci		.rc_interval = 150,
20898c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_DM1105_NEC,
20908c2ecf20Sopenharmony_ci		.module_name = "dw2102",
20918c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
20928c2ecf20Sopenharmony_ci		.rc_query = dw2102_rc_query,
20938c2ecf20Sopenharmony_ci	},
20948c2ecf20Sopenharmony_ci
20958c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
20968c2ecf20Sopenharmony_ci	/* parameter for the MPEG2-data transfer */
20978c2ecf20Sopenharmony_ci	.num_adapters = 1,
20988c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
20998c2ecf20Sopenharmony_ci	.read_mac_address = dw210x_read_mac_address,
21008c2ecf20Sopenharmony_ci	.adapter = {
21018c2ecf20Sopenharmony_ci		{
21028c2ecf20Sopenharmony_ci		.num_frontends = 1,
21038c2ecf20Sopenharmony_ci		.fe = {{
21048c2ecf20Sopenharmony_ci			.frontend_attach = dw3101_frontend_attach,
21058c2ecf20Sopenharmony_ci			.tuner_attach = dw3101_tuner_attach,
21068c2ecf20Sopenharmony_ci			.stream = {
21078c2ecf20Sopenharmony_ci				.type = USB_BULK,
21088c2ecf20Sopenharmony_ci				.count = 8,
21098c2ecf20Sopenharmony_ci				.endpoint = 0x82,
21108c2ecf20Sopenharmony_ci				.u = {
21118c2ecf20Sopenharmony_ci					.bulk = {
21128c2ecf20Sopenharmony_ci						.buffersize = 4096,
21138c2ecf20Sopenharmony_ci					}
21148c2ecf20Sopenharmony_ci				}
21158c2ecf20Sopenharmony_ci			},
21168c2ecf20Sopenharmony_ci		}},
21178c2ecf20Sopenharmony_ci		}
21188c2ecf20Sopenharmony_ci	},
21198c2ecf20Sopenharmony_ci	.num_device_descs = 1,
21208c2ecf20Sopenharmony_ci	.devices = {
21218c2ecf20Sopenharmony_ci		{ "DVBWorld DVB-C 3101 USB2.0",
21228c2ecf20Sopenharmony_ci			{&dw2102_table[CYPRESS_DW3101], NULL},
21238c2ecf20Sopenharmony_ci			{NULL},
21248c2ecf20Sopenharmony_ci		},
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci};
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties s6x0_properties = {
21298c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
21308c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
21318c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
21328c2ecf20Sopenharmony_ci	.firmware = S630_FIRMWARE,
21338c2ecf20Sopenharmony_ci	.no_reconnect = 1,
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci	.i2c_algo = &s6x0_i2c_algo,
21368c2ecf20Sopenharmony_ci	.rc.core = {
21378c2ecf20Sopenharmony_ci		.rc_interval = 150,
21388c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_TEVII_NEC,
21398c2ecf20Sopenharmony_ci		.module_name = "dw2102",
21408c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
21418c2ecf20Sopenharmony_ci		.rc_query = dw2102_rc_query,
21428c2ecf20Sopenharmony_ci	},
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
21458c2ecf20Sopenharmony_ci	.num_adapters = 1,
21468c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
21478c2ecf20Sopenharmony_ci	.read_mac_address = s6x0_read_mac_address,
21488c2ecf20Sopenharmony_ci	.adapter = {
21498c2ecf20Sopenharmony_ci		{
21508c2ecf20Sopenharmony_ci		.num_frontends = 1,
21518c2ecf20Sopenharmony_ci		.fe = {{
21528c2ecf20Sopenharmony_ci			.frontend_attach = zl100313_frontend_attach,
21538c2ecf20Sopenharmony_ci			.stream = {
21548c2ecf20Sopenharmony_ci				.type = USB_BULK,
21558c2ecf20Sopenharmony_ci				.count = 8,
21568c2ecf20Sopenharmony_ci				.endpoint = 0x82,
21578c2ecf20Sopenharmony_ci				.u = {
21588c2ecf20Sopenharmony_ci					.bulk = {
21598c2ecf20Sopenharmony_ci						.buffersize = 4096,
21608c2ecf20Sopenharmony_ci					}
21618c2ecf20Sopenharmony_ci				}
21628c2ecf20Sopenharmony_ci			},
21638c2ecf20Sopenharmony_ci		}},
21648c2ecf20Sopenharmony_ci		}
21658c2ecf20Sopenharmony_ci	},
21668c2ecf20Sopenharmony_ci	.num_device_descs = 1,
21678c2ecf20Sopenharmony_ci	.devices = {
21688c2ecf20Sopenharmony_ci		{"TeVii S630 USB",
21698c2ecf20Sopenharmony_ci			{&dw2102_table[TEVII_S630], NULL},
21708c2ecf20Sopenharmony_ci			{NULL},
21718c2ecf20Sopenharmony_ci		},
21728c2ecf20Sopenharmony_ci	}
21738c2ecf20Sopenharmony_ci};
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties p1100_properties = {
21768c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
21778c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
21788c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
21798c2ecf20Sopenharmony_ci	.firmware = P1100_FIRMWARE,
21808c2ecf20Sopenharmony_ci	.no_reconnect = 1,
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	.i2c_algo = &s6x0_i2c_algo,
21838c2ecf20Sopenharmony_ci	.rc.core = {
21848c2ecf20Sopenharmony_ci		.rc_interval = 150,
21858c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_TBS_NEC,
21868c2ecf20Sopenharmony_ci		.module_name = "dw2102",
21878c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
21888c2ecf20Sopenharmony_ci		.rc_query = prof_rc_query,
21898c2ecf20Sopenharmony_ci	},
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
21928c2ecf20Sopenharmony_ci	.num_adapters = 1,
21938c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
21948c2ecf20Sopenharmony_ci	.read_mac_address = s6x0_read_mac_address,
21958c2ecf20Sopenharmony_ci	.adapter = {
21968c2ecf20Sopenharmony_ci		{
21978c2ecf20Sopenharmony_ci			.num_frontends = 1,
21988c2ecf20Sopenharmony_ci			.fe = {{
21998c2ecf20Sopenharmony_ci				.frontend_attach = stv0288_frontend_attach,
22008c2ecf20Sopenharmony_ci				.stream = {
22018c2ecf20Sopenharmony_ci					.type = USB_BULK,
22028c2ecf20Sopenharmony_ci					.count = 8,
22038c2ecf20Sopenharmony_ci					.endpoint = 0x82,
22048c2ecf20Sopenharmony_ci					.u = {
22058c2ecf20Sopenharmony_ci						.bulk = {
22068c2ecf20Sopenharmony_ci							.buffersize = 4096,
22078c2ecf20Sopenharmony_ci						}
22088c2ecf20Sopenharmony_ci					}
22098c2ecf20Sopenharmony_ci				},
22108c2ecf20Sopenharmony_ci			} },
22118c2ecf20Sopenharmony_ci		}
22128c2ecf20Sopenharmony_ci	},
22138c2ecf20Sopenharmony_ci	.num_device_descs = 1,
22148c2ecf20Sopenharmony_ci	.devices = {
22158c2ecf20Sopenharmony_ci		{"Prof 1100 USB ",
22168c2ecf20Sopenharmony_ci			{&dw2102_table[PROF_1100], NULL},
22178c2ecf20Sopenharmony_ci			{NULL},
22188c2ecf20Sopenharmony_ci		},
22198c2ecf20Sopenharmony_ci	}
22208c2ecf20Sopenharmony_ci};
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties s660_properties = {
22238c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
22248c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
22258c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
22268c2ecf20Sopenharmony_ci	.firmware = S660_FIRMWARE,
22278c2ecf20Sopenharmony_ci	.no_reconnect = 1,
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_ci	.i2c_algo = &s6x0_i2c_algo,
22308c2ecf20Sopenharmony_ci	.rc.core = {
22318c2ecf20Sopenharmony_ci		.rc_interval = 150,
22328c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_TEVII_NEC,
22338c2ecf20Sopenharmony_ci		.module_name = "dw2102",
22348c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
22358c2ecf20Sopenharmony_ci		.rc_query = dw2102_rc_query,
22368c2ecf20Sopenharmony_ci	},
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
22398c2ecf20Sopenharmony_ci	.num_adapters = 1,
22408c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
22418c2ecf20Sopenharmony_ci	.read_mac_address = s6x0_read_mac_address,
22428c2ecf20Sopenharmony_ci	.adapter = {
22438c2ecf20Sopenharmony_ci		{
22448c2ecf20Sopenharmony_ci			.num_frontends = 1,
22458c2ecf20Sopenharmony_ci			.fe = {{
22468c2ecf20Sopenharmony_ci				.frontend_attach = ds3000_frontend_attach,
22478c2ecf20Sopenharmony_ci				.stream = {
22488c2ecf20Sopenharmony_ci					.type = USB_BULK,
22498c2ecf20Sopenharmony_ci					.count = 8,
22508c2ecf20Sopenharmony_ci					.endpoint = 0x82,
22518c2ecf20Sopenharmony_ci					.u = {
22528c2ecf20Sopenharmony_ci						.bulk = {
22538c2ecf20Sopenharmony_ci							.buffersize = 4096,
22548c2ecf20Sopenharmony_ci						}
22558c2ecf20Sopenharmony_ci					}
22568c2ecf20Sopenharmony_ci				},
22578c2ecf20Sopenharmony_ci			} },
22588c2ecf20Sopenharmony_ci		}
22598c2ecf20Sopenharmony_ci	},
22608c2ecf20Sopenharmony_ci	.num_device_descs = 3,
22618c2ecf20Sopenharmony_ci	.devices = {
22628c2ecf20Sopenharmony_ci		{"TeVii S660 USB",
22638c2ecf20Sopenharmony_ci			{&dw2102_table[TEVII_S660], NULL},
22648c2ecf20Sopenharmony_ci			{NULL},
22658c2ecf20Sopenharmony_ci		},
22668c2ecf20Sopenharmony_ci		{"TeVii S480.1 USB",
22678c2ecf20Sopenharmony_ci			{&dw2102_table[TEVII_S480_1], NULL},
22688c2ecf20Sopenharmony_ci			{NULL},
22698c2ecf20Sopenharmony_ci		},
22708c2ecf20Sopenharmony_ci		{"TeVii S480.2 USB",
22718c2ecf20Sopenharmony_ci			{&dw2102_table[TEVII_S480_2], NULL},
22728c2ecf20Sopenharmony_ci			{NULL},
22738c2ecf20Sopenharmony_ci		},
22748c2ecf20Sopenharmony_ci	}
22758c2ecf20Sopenharmony_ci};
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties p7500_properties = {
22788c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
22798c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
22808c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
22818c2ecf20Sopenharmony_ci	.firmware = P7500_FIRMWARE,
22828c2ecf20Sopenharmony_ci	.no_reconnect = 1,
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci	.i2c_algo = &s6x0_i2c_algo,
22858c2ecf20Sopenharmony_ci	.rc.core = {
22868c2ecf20Sopenharmony_ci		.rc_interval = 150,
22878c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_TBS_NEC,
22888c2ecf20Sopenharmony_ci		.module_name = "dw2102",
22898c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_NEC,
22908c2ecf20Sopenharmony_ci		.rc_query = prof_rc_query,
22918c2ecf20Sopenharmony_ci	},
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x81,
22948c2ecf20Sopenharmony_ci	.num_adapters = 1,
22958c2ecf20Sopenharmony_ci	.download_firmware = dw2102_load_firmware,
22968c2ecf20Sopenharmony_ci	.read_mac_address = s6x0_read_mac_address,
22978c2ecf20Sopenharmony_ci	.adapter = {
22988c2ecf20Sopenharmony_ci		{
22998c2ecf20Sopenharmony_ci			.num_frontends = 1,
23008c2ecf20Sopenharmony_ci			.fe = {{
23018c2ecf20Sopenharmony_ci				.frontend_attach = prof_7500_frontend_attach,
23028c2ecf20Sopenharmony_ci				.stream = {
23038c2ecf20Sopenharmony_ci					.type = USB_BULK,
23048c2ecf20Sopenharmony_ci					.count = 8,
23058c2ecf20Sopenharmony_ci					.endpoint = 0x82,
23068c2ecf20Sopenharmony_ci					.u = {
23078c2ecf20Sopenharmony_ci						.bulk = {
23088c2ecf20Sopenharmony_ci							.buffersize = 4096,
23098c2ecf20Sopenharmony_ci						}
23108c2ecf20Sopenharmony_ci					}
23118c2ecf20Sopenharmony_ci				},
23128c2ecf20Sopenharmony_ci			} },
23138c2ecf20Sopenharmony_ci		}
23148c2ecf20Sopenharmony_ci	},
23158c2ecf20Sopenharmony_ci	.num_device_descs = 1,
23168c2ecf20Sopenharmony_ci	.devices = {
23178c2ecf20Sopenharmony_ci		{"Prof 7500 USB DVB-S2",
23188c2ecf20Sopenharmony_ci			{&dw2102_table[PROF_7500], NULL},
23198c2ecf20Sopenharmony_ci			{NULL},
23208c2ecf20Sopenharmony_ci		},
23218c2ecf20Sopenharmony_ci	}
23228c2ecf20Sopenharmony_ci};
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties su3000_properties = {
23258c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
23268c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
23278c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
23288c2ecf20Sopenharmony_ci	.power_ctrl = su3000_power_ctrl,
23298c2ecf20Sopenharmony_ci	.num_adapters = 1,
23308c2ecf20Sopenharmony_ci	.identify_state	= su3000_identify_state,
23318c2ecf20Sopenharmony_ci	.i2c_algo = &su3000_i2c_algo,
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci	.rc.core = {
23348c2ecf20Sopenharmony_ci		.rc_interval = 150,
23358c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_SU3000,
23368c2ecf20Sopenharmony_ci		.module_name = "dw2102",
23378c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_RC5,
23388c2ecf20Sopenharmony_ci		.rc_query = su3000_rc_query,
23398c2ecf20Sopenharmony_ci	},
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci	.read_mac_address = su3000_read_mac_address,
23428c2ecf20Sopenharmony_ci
23438c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci	.adapter = {
23468c2ecf20Sopenharmony_ci		{
23478c2ecf20Sopenharmony_ci		.num_frontends = 1,
23488c2ecf20Sopenharmony_ci		.fe = {{
23498c2ecf20Sopenharmony_ci			.streaming_ctrl   = su3000_streaming_ctrl,
23508c2ecf20Sopenharmony_ci			.frontend_attach  = su3000_frontend_attach,
23518c2ecf20Sopenharmony_ci			.stream = {
23528c2ecf20Sopenharmony_ci				.type = USB_BULK,
23538c2ecf20Sopenharmony_ci				.count = 8,
23548c2ecf20Sopenharmony_ci				.endpoint = 0x82,
23558c2ecf20Sopenharmony_ci				.u = {
23568c2ecf20Sopenharmony_ci					.bulk = {
23578c2ecf20Sopenharmony_ci						.buffersize = 4096,
23588c2ecf20Sopenharmony_ci					}
23598c2ecf20Sopenharmony_ci				}
23608c2ecf20Sopenharmony_ci			}
23618c2ecf20Sopenharmony_ci		}},
23628c2ecf20Sopenharmony_ci		}
23638c2ecf20Sopenharmony_ci	},
23648c2ecf20Sopenharmony_ci	.num_device_descs = 8,
23658c2ecf20Sopenharmony_ci	.devices = {
23668c2ecf20Sopenharmony_ci		{ "SU3000HD DVB-S USB2.0",
23678c2ecf20Sopenharmony_ci			{ &dw2102_table[GENIATECH_SU3000], NULL },
23688c2ecf20Sopenharmony_ci			{ NULL },
23698c2ecf20Sopenharmony_ci		},
23708c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 USB HD",
23718c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2], NULL },
23728c2ecf20Sopenharmony_ci			{ NULL },
23738c2ecf20Sopenharmony_ci		},
23748c2ecf20Sopenharmony_ci		{ "X3M TV SPC1400HD PCI",
23758c2ecf20Sopenharmony_ci			{ &dw2102_table[X3M_SPC1400HD], NULL },
23768c2ecf20Sopenharmony_ci			{ NULL },
23778c2ecf20Sopenharmony_ci		},
23788c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 USB HD Rev.2",
23798c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL },
23808c2ecf20Sopenharmony_ci			{ NULL },
23818c2ecf20Sopenharmony_ci		},
23828c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 USB HD Rev.3",
23838c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2_R3], NULL },
23848c2ecf20Sopenharmony_ci			{ NULL },
23858c2ecf20Sopenharmony_ci		},
23868c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 PCIe Dual Port 1",
23878c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2_1], NULL },
23888c2ecf20Sopenharmony_ci			{ NULL },
23898c2ecf20Sopenharmony_ci		},
23908c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 PCIe Dual Port 2",
23918c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2_2], NULL },
23928c2ecf20Sopenharmony_ci			{ NULL },
23938c2ecf20Sopenharmony_ci		},
23948c2ecf20Sopenharmony_ci		{ "GOTVIEW Satellite HD",
23958c2ecf20Sopenharmony_ci			{ &dw2102_table[GOTVIEW_SAT_HD], NULL },
23968c2ecf20Sopenharmony_ci			{ NULL },
23978c2ecf20Sopenharmony_ci		},
23988c2ecf20Sopenharmony_ci	}
23998c2ecf20Sopenharmony_ci};
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties s421_properties = {
24028c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
24038c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
24048c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
24058c2ecf20Sopenharmony_ci	.power_ctrl = su3000_power_ctrl,
24068c2ecf20Sopenharmony_ci	.num_adapters = 1,
24078c2ecf20Sopenharmony_ci	.identify_state	= su3000_identify_state,
24088c2ecf20Sopenharmony_ci	.i2c_algo = &su3000_i2c_algo,
24098c2ecf20Sopenharmony_ci
24108c2ecf20Sopenharmony_ci	.rc.core = {
24118c2ecf20Sopenharmony_ci		.rc_interval = 150,
24128c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_SU3000,
24138c2ecf20Sopenharmony_ci		.module_name = "dw2102",
24148c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_RC5,
24158c2ecf20Sopenharmony_ci		.rc_query = su3000_rc_query,
24168c2ecf20Sopenharmony_ci	},
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	.read_mac_address = su3000_read_mac_address,
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
24218c2ecf20Sopenharmony_ci
24228c2ecf20Sopenharmony_ci	.adapter = {
24238c2ecf20Sopenharmony_ci		{
24248c2ecf20Sopenharmony_ci		.num_frontends = 1,
24258c2ecf20Sopenharmony_ci		.fe = {{
24268c2ecf20Sopenharmony_ci			.streaming_ctrl   = su3000_streaming_ctrl,
24278c2ecf20Sopenharmony_ci			.frontend_attach  = m88rs2000_frontend_attach,
24288c2ecf20Sopenharmony_ci			.stream = {
24298c2ecf20Sopenharmony_ci				.type = USB_BULK,
24308c2ecf20Sopenharmony_ci				.count = 8,
24318c2ecf20Sopenharmony_ci				.endpoint = 0x82,
24328c2ecf20Sopenharmony_ci				.u = {
24338c2ecf20Sopenharmony_ci					.bulk = {
24348c2ecf20Sopenharmony_ci						.buffersize = 4096,
24358c2ecf20Sopenharmony_ci					}
24368c2ecf20Sopenharmony_ci				}
24378c2ecf20Sopenharmony_ci			}
24388c2ecf20Sopenharmony_ci		} },
24398c2ecf20Sopenharmony_ci		}
24408c2ecf20Sopenharmony_ci	},
24418c2ecf20Sopenharmony_ci	.num_device_descs = 2,
24428c2ecf20Sopenharmony_ci	.devices = {
24438c2ecf20Sopenharmony_ci		{ "TeVii S421 PCI",
24448c2ecf20Sopenharmony_ci			{ &dw2102_table[TEVII_S421], NULL },
24458c2ecf20Sopenharmony_ci			{ NULL },
24468c2ecf20Sopenharmony_ci		},
24478c2ecf20Sopenharmony_ci		{ "TeVii S632 USB",
24488c2ecf20Sopenharmony_ci			{ &dw2102_table[TEVII_S632], NULL },
24498c2ecf20Sopenharmony_ci			{ NULL },
24508c2ecf20Sopenharmony_ci		},
24518c2ecf20Sopenharmony_ci	}
24528c2ecf20Sopenharmony_ci};
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties t220_properties = {
24558c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
24568c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
24578c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
24588c2ecf20Sopenharmony_ci	.power_ctrl = su3000_power_ctrl,
24598c2ecf20Sopenharmony_ci	.num_adapters = 1,
24608c2ecf20Sopenharmony_ci	.identify_state	= su3000_identify_state,
24618c2ecf20Sopenharmony_ci	.i2c_algo = &su3000_i2c_algo,
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	.rc.core = {
24648c2ecf20Sopenharmony_ci		.rc_interval = 150,
24658c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_SU3000,
24668c2ecf20Sopenharmony_ci		.module_name = "dw2102",
24678c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_RC5,
24688c2ecf20Sopenharmony_ci		.rc_query = su3000_rc_query,
24698c2ecf20Sopenharmony_ci	},
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_ci	.read_mac_address = su3000_read_mac_address,
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
24748c2ecf20Sopenharmony_ci
24758c2ecf20Sopenharmony_ci	.adapter = {
24768c2ecf20Sopenharmony_ci		{
24778c2ecf20Sopenharmony_ci		.num_frontends = 1,
24788c2ecf20Sopenharmony_ci		.fe = { {
24798c2ecf20Sopenharmony_ci			.streaming_ctrl   = su3000_streaming_ctrl,
24808c2ecf20Sopenharmony_ci			.frontend_attach  = t220_frontend_attach,
24818c2ecf20Sopenharmony_ci			.stream = {
24828c2ecf20Sopenharmony_ci				.type = USB_BULK,
24838c2ecf20Sopenharmony_ci				.count = 8,
24848c2ecf20Sopenharmony_ci				.endpoint = 0x82,
24858c2ecf20Sopenharmony_ci				.u = {
24868c2ecf20Sopenharmony_ci					.bulk = {
24878c2ecf20Sopenharmony_ci						.buffersize = 4096,
24888c2ecf20Sopenharmony_ci					}
24898c2ecf20Sopenharmony_ci				}
24908c2ecf20Sopenharmony_ci			}
24918c2ecf20Sopenharmony_ci		} },
24928c2ecf20Sopenharmony_ci		}
24938c2ecf20Sopenharmony_ci	},
24948c2ecf20Sopenharmony_ci	.num_device_descs = 1,
24958c2ecf20Sopenharmony_ci	.devices = {
24968c2ecf20Sopenharmony_ci		{ "Geniatech T220 DVB-T/T2 USB2.0",
24978c2ecf20Sopenharmony_ci			{ &dw2102_table[GENIATECH_T220], NULL },
24988c2ecf20Sopenharmony_ci			{ NULL },
24998c2ecf20Sopenharmony_ci		},
25008c2ecf20Sopenharmony_ci	}
25018c2ecf20Sopenharmony_ci};
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties tt_s2_4600_properties = {
25048c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
25058c2ecf20Sopenharmony_ci	.usb_ctrl = DEVICE_SPECIFIC,
25068c2ecf20Sopenharmony_ci	.size_of_priv = sizeof(struct dw2102_state),
25078c2ecf20Sopenharmony_ci	.power_ctrl = su3000_power_ctrl,
25088c2ecf20Sopenharmony_ci	.num_adapters = 1,
25098c2ecf20Sopenharmony_ci	.identify_state	= su3000_identify_state,
25108c2ecf20Sopenharmony_ci	.i2c_algo = &su3000_i2c_algo,
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	.rc.core = {
25138c2ecf20Sopenharmony_ci		.rc_interval = 250,
25148c2ecf20Sopenharmony_ci		.rc_codes = RC_MAP_TT_1500,
25158c2ecf20Sopenharmony_ci		.module_name = "dw2102",
25168c2ecf20Sopenharmony_ci		.allowed_protos   = RC_PROTO_BIT_RC5,
25178c2ecf20Sopenharmony_ci		.rc_query = su3000_rc_query,
25188c2ecf20Sopenharmony_ci	},
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	.read_mac_address = su3000_read_mac_address,
25218c2ecf20Sopenharmony_ci
25228c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci	.adapter = {
25258c2ecf20Sopenharmony_ci		{
25268c2ecf20Sopenharmony_ci		.num_frontends = 1,
25278c2ecf20Sopenharmony_ci		.fe = {{
25288c2ecf20Sopenharmony_ci			.streaming_ctrl   = su3000_streaming_ctrl,
25298c2ecf20Sopenharmony_ci			.frontend_attach  = tt_s2_4600_frontend_attach,
25308c2ecf20Sopenharmony_ci			.stream = {
25318c2ecf20Sopenharmony_ci				.type = USB_BULK,
25328c2ecf20Sopenharmony_ci				.count = 8,
25338c2ecf20Sopenharmony_ci				.endpoint = 0x82,
25348c2ecf20Sopenharmony_ci				.u = {
25358c2ecf20Sopenharmony_ci					.bulk = {
25368c2ecf20Sopenharmony_ci						.buffersize = 4096,
25378c2ecf20Sopenharmony_ci					}
25388c2ecf20Sopenharmony_ci				}
25398c2ecf20Sopenharmony_ci			}
25408c2ecf20Sopenharmony_ci		} },
25418c2ecf20Sopenharmony_ci		}
25428c2ecf20Sopenharmony_ci	},
25438c2ecf20Sopenharmony_ci	.num_device_descs = 5,
25448c2ecf20Sopenharmony_ci	.devices = {
25458c2ecf20Sopenharmony_ci		{ "TechnoTrend TT-connect S2-4600",
25468c2ecf20Sopenharmony_ci			{ &dw2102_table[TECHNOTREND_S2_4600], NULL },
25478c2ecf20Sopenharmony_ci			{ NULL },
25488c2ecf20Sopenharmony_ci		},
25498c2ecf20Sopenharmony_ci		{ "TeVii S482 (tuner 1)",
25508c2ecf20Sopenharmony_ci			{ &dw2102_table[TEVII_S482_1], NULL },
25518c2ecf20Sopenharmony_ci			{ NULL },
25528c2ecf20Sopenharmony_ci		},
25538c2ecf20Sopenharmony_ci		{ "TeVii S482 (tuner 2)",
25548c2ecf20Sopenharmony_ci			{ &dw2102_table[TEVII_S482_2], NULL },
25558c2ecf20Sopenharmony_ci			{ NULL },
25568c2ecf20Sopenharmony_ci		},
25578c2ecf20Sopenharmony_ci		{ "Terratec Cinergy S2 USB BOX",
25588c2ecf20Sopenharmony_ci			{ &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL },
25598c2ecf20Sopenharmony_ci			{ NULL },
25608c2ecf20Sopenharmony_ci		},
25618c2ecf20Sopenharmony_ci		{ "TeVii S662",
25628c2ecf20Sopenharmony_ci			{ &dw2102_table[TEVII_S662], NULL },
25638c2ecf20Sopenharmony_ci			{ NULL },
25648c2ecf20Sopenharmony_ci		},
25658c2ecf20Sopenharmony_ci	}
25668c2ecf20Sopenharmony_ci};
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_cistatic int dw2102_probe(struct usb_interface *intf,
25698c2ecf20Sopenharmony_ci		const struct usb_device_id *id)
25708c2ecf20Sopenharmony_ci{
25718c2ecf20Sopenharmony_ci	if (!(dvb_usb_device_init(intf, &dw2102_properties,
25728c2ecf20Sopenharmony_ci			          THIS_MODULE, NULL, adapter_nr) &&
25738c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &dw2104_properties,
25748c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25758c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &dw3101_properties,
25768c2ecf20Sopenharmony_ci			          THIS_MODULE, NULL, adapter_nr) &&
25778c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &s6x0_properties,
25788c2ecf20Sopenharmony_ci			          THIS_MODULE, NULL, adapter_nr) &&
25798c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &p1100_properties,
25808c2ecf20Sopenharmony_ci			          THIS_MODULE, NULL, adapter_nr) &&
25818c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &s660_properties,
25828c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25838c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &p7500_properties,
25848c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25858c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &s421_properties,
25868c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25878c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &su3000_properties,
25888c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25898c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &t220_properties,
25908c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr) &&
25918c2ecf20Sopenharmony_ci	      dvb_usb_device_init(intf, &tt_s2_4600_properties,
25928c2ecf20Sopenharmony_ci				  THIS_MODULE, NULL, adapter_nr))) {
25938c2ecf20Sopenharmony_ci
25948c2ecf20Sopenharmony_ci		return 0;
25958c2ecf20Sopenharmony_ci	}
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_ci	return -ENODEV;
25988c2ecf20Sopenharmony_ci}
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_cistatic void dw2102_disconnect(struct usb_interface *intf)
26018c2ecf20Sopenharmony_ci{
26028c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = usb_get_intfdata(intf);
26038c2ecf20Sopenharmony_ci	struct dw2102_state *st = (struct dw2102_state *)d->priv;
26048c2ecf20Sopenharmony_ci	struct i2c_client *client;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	/* remove I2C client for tuner */
26078c2ecf20Sopenharmony_ci	client = st->i2c_client_tuner;
26088c2ecf20Sopenharmony_ci	if (client) {
26098c2ecf20Sopenharmony_ci		module_put(client->dev.driver->owner);
26108c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
26118c2ecf20Sopenharmony_ci	}
26128c2ecf20Sopenharmony_ci
26138c2ecf20Sopenharmony_ci	/* remove I2C client for demodulator */
26148c2ecf20Sopenharmony_ci	client = st->i2c_client_demod;
26158c2ecf20Sopenharmony_ci	if (client) {
26168c2ecf20Sopenharmony_ci		module_put(client->dev.driver->owner);
26178c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
26188c2ecf20Sopenharmony_ci	}
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ci	dvb_usb_device_exit(intf);
26218c2ecf20Sopenharmony_ci}
26228c2ecf20Sopenharmony_ci
26238c2ecf20Sopenharmony_cistatic struct usb_driver dw2102_driver = {
26248c2ecf20Sopenharmony_ci	.name = "dw2102",
26258c2ecf20Sopenharmony_ci	.probe = dw2102_probe,
26268c2ecf20Sopenharmony_ci	.disconnect = dw2102_disconnect,
26278c2ecf20Sopenharmony_ci	.id_table = dw2102_table,
26288c2ecf20Sopenharmony_ci};
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_cimodule_usb_driver(dw2102_driver);
26318c2ecf20Sopenharmony_ci
26328c2ecf20Sopenharmony_ciMODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
26338c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101 USB2.0, TeVii S421, S480, S482, S600, S630, S632, S650, TeVii S660, S662, Prof 1100, 7500 USB2.0, Geniatech SU3000, T220, TechnoTrend S2-4600, Terratec Cinergy S2 devices");
26348c2ecf20Sopenharmony_ciMODULE_VERSION("0.1");
26358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
26368c2ecf20Sopenharmony_ciMODULE_FIRMWARE(DW2101_FIRMWARE);
26378c2ecf20Sopenharmony_ciMODULE_FIRMWARE(DW2102_FIRMWARE);
26388c2ecf20Sopenharmony_ciMODULE_FIRMWARE(DW2104_FIRMWARE);
26398c2ecf20Sopenharmony_ciMODULE_FIRMWARE(DW3101_FIRMWARE);
26408c2ecf20Sopenharmony_ciMODULE_FIRMWARE(S630_FIRMWARE);
26418c2ecf20Sopenharmony_ciMODULE_FIRMWARE(S660_FIRMWARE);
26428c2ecf20Sopenharmony_ciMODULE_FIRMWARE(P1100_FIRMWARE);
26438c2ecf20Sopenharmony_ciMODULE_FIRMWARE(P7500_FIRMWARE);
2644