18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* DVB USB compliant linux driver for Conexant USB reference design.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * The Conexant reference design I saw on their website was only for analogue
58c2ecf20Sopenharmony_ci * capturing (using the cx25842). The box I took to write this driver (reverse
68c2ecf20Sopenharmony_ci * engineered) is the one labeled Medion MD95700. In addition to the cx25842
78c2ecf20Sopenharmony_ci * for analogue capturing it also has a cx22702 DVB-T demodulator on the main
88c2ecf20Sopenharmony_ci * board. Besides it has a atiremote (X10) and a USB2.0 hub onboard.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Maybe it is a little bit premature to call this driver cxusb, but I assume
118c2ecf20Sopenharmony_ci * the USB protocol is identical or at least inherited from the reference
128c2ecf20Sopenharmony_ci * design, so it can be reused for the "analogue-only" device (if it will
138c2ecf20Sopenharmony_ci * appear at all).
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de)
178c2ecf20Sopenharmony_ci * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
188c2ecf20Sopenharmony_ci * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
198c2ecf20Sopenharmony_ci * Copyright (C) 2011, 2017 Maciej S. Szmigiero (mail@maciej.szmigiero.name)
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci#include <media/tuner.h>
248c2ecf20Sopenharmony_ci#include <linux/delay.h>
258c2ecf20Sopenharmony_ci#include <linux/device.h>
268c2ecf20Sopenharmony_ci#include <linux/kernel.h>
278c2ecf20Sopenharmony_ci#include <linux/slab.h>
288c2ecf20Sopenharmony_ci#include <linux/string.h>
298c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include "cxusb.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "cx22702.h"
348c2ecf20Sopenharmony_ci#include "lgdt330x.h"
358c2ecf20Sopenharmony_ci#include "mt352.h"
368c2ecf20Sopenharmony_ci#include "mt352_priv.h"
378c2ecf20Sopenharmony_ci#include "zl10353.h"
388c2ecf20Sopenharmony_ci#include "tuner-xc2028.h"
398c2ecf20Sopenharmony_ci#include "tuner-simple.h"
408c2ecf20Sopenharmony_ci#include "mxl5005s.h"
418c2ecf20Sopenharmony_ci#include "max2165.h"
428c2ecf20Sopenharmony_ci#include "dib7000p.h"
438c2ecf20Sopenharmony_ci#include "dib0070.h"
448c2ecf20Sopenharmony_ci#include "lgs8gxx.h"
458c2ecf20Sopenharmony_ci#include "atbm8830.h"
468c2ecf20Sopenharmony_ci#include "si2168.h"
478c2ecf20Sopenharmony_ci#include "si2157.h"
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* debug */
508c2ecf20Sopenharmony_ciint dvb_usb_cxusb_debug;
518c2ecf20Sopenharmony_cimodule_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
528c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (see cxusb.h)."
538c2ecf20Sopenharmony_ci		 DVB_USB_DEBUG_STATUS);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cienum cxusb_table_index {
588c2ecf20Sopenharmony_ci	MEDION_MD95700,
598c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_LG064F_COLD,
608c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_LG064F_WARM,
618c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_1_COLD,
628c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_1_WARM,
638c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_LGZ201_COLD,
648c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_LGZ201_WARM,
658c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_TH7579_COLD,
668c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_TH7579_WARM,
678c2ecf20Sopenharmony_ci	DIGITALNOW_BLUEBIRD_DUAL_1_COLD,
688c2ecf20Sopenharmony_ci	DIGITALNOW_BLUEBIRD_DUAL_1_WARM,
698c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_2_COLD,
708c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_2_WARM,
718c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_4,
728c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DVB_T_NANO_2,
738c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM,
748c2ecf20Sopenharmony_ci	AVERMEDIA_VOLAR_A868R,
758c2ecf20Sopenharmony_ci	DVICO_BLUEBIRD_DUAL_4_REV_2,
768c2ecf20Sopenharmony_ci	CONEXANT_D680_DMB,
778c2ecf20Sopenharmony_ci	MYGICA_D689,
788c2ecf20Sopenharmony_ci	NR__cxusb_table_index
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic struct usb_device_id cxusb_table[];
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciint cxusb_ctrl_msg(struct dvb_usb_device *d,
848c2ecf20Sopenharmony_ci		   u8 cmd, const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	struct cxusb_state *st = d->priv;
878c2ecf20Sopenharmony_ci	int ret;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (1 + wlen > MAX_XFER_SIZE) {
908c2ecf20Sopenharmony_ci		warn("i2c wr: len=%d is too big!\n", wlen);
918c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	if (rlen > MAX_XFER_SIZE) {
958c2ecf20Sopenharmony_ci		warn("i2c rd: len=%d is too big!\n", rlen);
968c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
978c2ecf20Sopenharmony_ci	}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	mutex_lock(&d->data_mutex);
1008c2ecf20Sopenharmony_ci	st->data[0] = cmd;
1018c2ecf20Sopenharmony_ci	memcpy(&st->data[1], wbuf, wlen);
1028c2ecf20Sopenharmony_ci	ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, st->data, rlen, 0);
1038c2ecf20Sopenharmony_ci	if (!ret && rbuf && rlen)
1048c2ecf20Sopenharmony_ci		memcpy(rbuf, st->data, rlen);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	mutex_unlock(&d->data_mutex);
1078c2ecf20Sopenharmony_ci	return ret;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/* GPIO */
1118c2ecf20Sopenharmony_cistatic void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct cxusb_state *st = d->priv;
1148c2ecf20Sopenharmony_ci	u8 o[2], i;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (st->gpio_write_state[GPIO_TUNER] == onoff &&
1178c2ecf20Sopenharmony_ci	    !st->gpio_write_refresh[GPIO_TUNER])
1188c2ecf20Sopenharmony_ci		return;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	o[0] = GPIO_TUNER;
1218c2ecf20Sopenharmony_ci	o[1] = onoff;
1228c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (i != 0x01)
1258c2ecf20Sopenharmony_ci		dev_info(&d->udev->dev, "gpio_write failed.\n");
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	st->gpio_write_state[GPIO_TUNER] = onoff;
1288c2ecf20Sopenharmony_ci	st->gpio_write_refresh[GPIO_TUNER] = false;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
1328c2ecf20Sopenharmony_ci				  u8 newval)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	u8 o[2], gpio_state;
1358c2ecf20Sopenharmony_ci	int rc;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	o[0] = 0xff & ~changemask;	/* mask of bits to keep */
1388c2ecf20Sopenharmony_ci	o[1] = newval & changemask;	/* new values for bits  */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
1418c2ecf20Sopenharmony_ci	if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
1428c2ecf20Sopenharmony_ci		dev_info(&d->udev->dev, "bluebird_gpio_write failed.\n");
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	return rc < 0 ? rc : gpio_state;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
1508c2ecf20Sopenharmony_ci	msleep(5);
1518c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
1608c2ecf20Sopenharmony_ci				     u8 addr, int onoff)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	u8  o[2] = {addr, onoff};
1638c2ecf20Sopenharmony_ci	u8  i;
1648c2ecf20Sopenharmony_ci	int rc;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	if (rc < 0)
1698c2ecf20Sopenharmony_ci		return rc;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (i == 0x01)
1728c2ecf20Sopenharmony_ci		return 0;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	dev_info(&d->udev->dev, "gpio_write failed.\n");
1758c2ecf20Sopenharmony_ci	return -EIO;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/* I2C */
1798c2ecf20Sopenharmony_cistatic int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
1808c2ecf20Sopenharmony_ci			  int num)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
1838c2ecf20Sopenharmony_ci	int ret;
1848c2ecf20Sopenharmony_ci	int i;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
1878c2ecf20Sopenharmony_ci		return -EAGAIN;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
1908c2ecf20Sopenharmony_ci		if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_MEDION)
1918c2ecf20Sopenharmony_ci			switch (msg[i].addr) {
1928c2ecf20Sopenharmony_ci			case 0x63:
1938c2ecf20Sopenharmony_ci				cxusb_gpio_tuner(d, 0);
1948c2ecf20Sopenharmony_ci				break;
1958c2ecf20Sopenharmony_ci			default:
1968c2ecf20Sopenharmony_ci				cxusb_gpio_tuner(d, 1);
1978c2ecf20Sopenharmony_ci				break;
1988c2ecf20Sopenharmony_ci			}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		if (msg[i].flags & I2C_M_RD) {
2018c2ecf20Sopenharmony_ci			/* read only */
2028c2ecf20Sopenharmony_ci			u8 obuf[3], ibuf[MAX_XFER_SIZE];
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci			if (1 + msg[i].len > sizeof(ibuf)) {
2058c2ecf20Sopenharmony_ci				warn("i2c rd: len=%d is too big!\n",
2068c2ecf20Sopenharmony_ci				     msg[i].len);
2078c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
2088c2ecf20Sopenharmony_ci				goto unlock;
2098c2ecf20Sopenharmony_ci			}
2108c2ecf20Sopenharmony_ci			obuf[0] = 0;
2118c2ecf20Sopenharmony_ci			obuf[1] = msg[i].len;
2128c2ecf20Sopenharmony_ci			obuf[2] = msg[i].addr;
2138c2ecf20Sopenharmony_ci			if (cxusb_ctrl_msg(d, CMD_I2C_READ,
2148c2ecf20Sopenharmony_ci					   obuf, 3,
2158c2ecf20Sopenharmony_ci					   ibuf, 1 + msg[i].len) < 0) {
2168c2ecf20Sopenharmony_ci				warn("i2c read failed");
2178c2ecf20Sopenharmony_ci				break;
2188c2ecf20Sopenharmony_ci			}
2198c2ecf20Sopenharmony_ci			memcpy(msg[i].buf, &ibuf[1], msg[i].len);
2208c2ecf20Sopenharmony_ci		} else if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD) &&
2218c2ecf20Sopenharmony_ci			   msg[i].addr == msg[i + 1].addr) {
2228c2ecf20Sopenharmony_ci			/* write to then read from same address */
2238c2ecf20Sopenharmony_ci			u8 obuf[MAX_XFER_SIZE], ibuf[MAX_XFER_SIZE];
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci			if (3 + msg[i].len > sizeof(obuf)) {
2268c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
2278c2ecf20Sopenharmony_ci				     msg[i].len);
2288c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
2298c2ecf20Sopenharmony_ci				goto unlock;
2308c2ecf20Sopenharmony_ci			}
2318c2ecf20Sopenharmony_ci			if (1 + msg[i + 1].len > sizeof(ibuf)) {
2328c2ecf20Sopenharmony_ci				warn("i2c rd: len=%d is too big!\n",
2338c2ecf20Sopenharmony_ci				     msg[i + 1].len);
2348c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
2358c2ecf20Sopenharmony_ci				goto unlock;
2368c2ecf20Sopenharmony_ci			}
2378c2ecf20Sopenharmony_ci			obuf[0] = msg[i].len;
2388c2ecf20Sopenharmony_ci			obuf[1] = msg[i + 1].len;
2398c2ecf20Sopenharmony_ci			obuf[2] = msg[i].addr;
2408c2ecf20Sopenharmony_ci			memcpy(&obuf[3], msg[i].buf, msg[i].len);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci			if (cxusb_ctrl_msg(d, CMD_I2C_READ,
2438c2ecf20Sopenharmony_ci					   obuf, 3 + msg[i].len,
2448c2ecf20Sopenharmony_ci					   ibuf, 1 + msg[i + 1].len) < 0)
2458c2ecf20Sopenharmony_ci				break;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci			if (ibuf[0] != 0x08)
2488c2ecf20Sopenharmony_ci				dev_info(&d->udev->dev, "i2c read may have failed\n");
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci			memcpy(msg[i + 1].buf, &ibuf[1], msg[i + 1].len);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci			i++;
2538c2ecf20Sopenharmony_ci		} else {
2548c2ecf20Sopenharmony_ci			/* write only */
2558c2ecf20Sopenharmony_ci			u8 obuf[MAX_XFER_SIZE], ibuf;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci			if (2 + msg[i].len > sizeof(obuf)) {
2588c2ecf20Sopenharmony_ci				warn("i2c wr: len=%d is too big!\n",
2598c2ecf20Sopenharmony_ci				     msg[i].len);
2608c2ecf20Sopenharmony_ci				ret = -EOPNOTSUPP;
2618c2ecf20Sopenharmony_ci				goto unlock;
2628c2ecf20Sopenharmony_ci			}
2638c2ecf20Sopenharmony_ci			obuf[0] = msg[i].addr;
2648c2ecf20Sopenharmony_ci			obuf[1] = msg[i].len;
2658c2ecf20Sopenharmony_ci			memcpy(&obuf[2], msg[i].buf, msg[i].len);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci			if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
2688c2ecf20Sopenharmony_ci					   2 + msg[i].len, &ibuf, 1) < 0)
2698c2ecf20Sopenharmony_ci				break;
2708c2ecf20Sopenharmony_ci			if (ibuf != 0x08)
2718c2ecf20Sopenharmony_ci				dev_info(&d->udev->dev, "i2c write may have failed\n");
2728c2ecf20Sopenharmony_ci		}
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	if (i == num)
2768c2ecf20Sopenharmony_ci		ret = num;
2778c2ecf20Sopenharmony_ci	else
2788c2ecf20Sopenharmony_ci		ret = -EREMOTEIO;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ciunlock:
2818c2ecf20Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
2828c2ecf20Sopenharmony_ci	return ret;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic u32 cxusb_i2c_func(struct i2c_adapter *adapter)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic struct i2c_algorithm cxusb_i2c_algo = {
2918c2ecf20Sopenharmony_ci	.master_xfer   = cxusb_i2c_xfer,
2928c2ecf20Sopenharmony_ci	.functionality = cxusb_i2c_func,
2938c2ecf20Sopenharmony_ci};
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic int _cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	u8 b = 0;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	dev_info(&d->udev->dev, "setting power %s\n", onoff ? "ON" : "OFF");
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	if (onoff)
3028c2ecf20Sopenharmony_ci		return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
3038c2ecf20Sopenharmony_ci	else
3048c2ecf20Sopenharmony_ci		return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	bool is_medion = d->props.devices[0].warm_ids[0] == &cxusb_table[MEDION_MD95700];
3108c2ecf20Sopenharmony_ci	int ret;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (is_medion && !onoff) {
3138c2ecf20Sopenharmony_ci		struct cxusb_medion_dev *cxdev = d->priv;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		mutex_lock(&cxdev->open_lock);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		if (cxdev->open_type == CXUSB_OPEN_ANALOG) {
3188c2ecf20Sopenharmony_ci			dev_info(&d->udev->dev, "preventing DVB core from setting power OFF while we are in analog mode\n");
3198c2ecf20Sopenharmony_ci			ret = -EBUSY;
3208c2ecf20Sopenharmony_ci			goto ret_unlock;
3218c2ecf20Sopenharmony_ci		}
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	ret = _cxusb_power_ctrl(d, onoff);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ciret_unlock:
3278c2ecf20Sopenharmony_ci	if (is_medion && !onoff) {
3288c2ecf20Sopenharmony_ci		struct cxusb_medion_dev *cxdev = d->priv;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		mutex_unlock(&cxdev->open_lock);
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	return ret;
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	int ret;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (!onoff)
3418c2ecf20Sopenharmony_ci		return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0);
3428c2ecf20Sopenharmony_ci	if (d->state == DVB_USB_STATE_INIT &&
3438c2ecf20Sopenharmony_ci	    usb_set_interface(d->udev, 0, 0) < 0)
3448c2ecf20Sopenharmony_ci		err("set interface failed");
3458c2ecf20Sopenharmony_ci	do {
3468c2ecf20Sopenharmony_ci		/* Nothing */
3478c2ecf20Sopenharmony_ci	} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
3488c2ecf20Sopenharmony_ci		 !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
3498c2ecf20Sopenharmony_ci		 !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	if (!ret) {
3528c2ecf20Sopenharmony_ci		/*
3538c2ecf20Sopenharmony_ci		 * FIXME: We don't know why, but we need to configure the
3548c2ecf20Sopenharmony_ci		 * lgdt3303 with the register settings below on resume
3558c2ecf20Sopenharmony_ci		 */
3568c2ecf20Sopenharmony_ci		int i;
3578c2ecf20Sopenharmony_ci		u8 buf;
3588c2ecf20Sopenharmony_ci		static const u8 bufs[] = {
3598c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x00, 0x7f,
3608c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x02, 0xfe,
3618c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x02, 0x01,
3628c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x00, 0x03,
3638c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x0d, 0x40,
3648c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x0e, 0x87,
3658c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x0f, 0x8e,
3668c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x10, 0x01,
3678c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x14, 0xd7,
3688c2ecf20Sopenharmony_ci			0x0e, 0x2, 0x47, 0x88,
3698c2ecf20Sopenharmony_ci		};
3708c2ecf20Sopenharmony_ci		msleep(20);
3718c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(bufs); i += 4 / sizeof(u8)) {
3728c2ecf20Sopenharmony_ci			ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE,
3738c2ecf20Sopenharmony_ci					     bufs + i, 4, &buf, 1);
3748c2ecf20Sopenharmony_ci			if (ret)
3758c2ecf20Sopenharmony_ci				break;
3768c2ecf20Sopenharmony_ci			if (buf != 0x8)
3778c2ecf20Sopenharmony_ci				return -EREMOTEIO;
3788c2ecf20Sopenharmony_ci		}
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci	return ret;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cistatic int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	u8 b = 0;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	if (onoff)
3888c2ecf20Sopenharmony_ci		return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
3898c2ecf20Sopenharmony_ci	else
3908c2ecf20Sopenharmony_ci		return 0;
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	int rc = 0;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	rc = cxusb_power_ctrl(d, onoff);
3988c2ecf20Sopenharmony_ci	if (!onoff)
3998c2ecf20Sopenharmony_ci		cxusb_nano2_led(d, 0);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	return rc;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	int ret;
4078c2ecf20Sopenharmony_ci	u8  b;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	ret = cxusb_power_ctrl(d, onoff);
4108c2ecf20Sopenharmony_ci	if (!onoff)
4118c2ecf20Sopenharmony_ci		return ret;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	msleep(128);
4148c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1);
4158c2ecf20Sopenharmony_ci	msleep(100);
4168c2ecf20Sopenharmony_ci	return ret;
4178c2ecf20Sopenharmony_ci}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	struct dvb_usb_device *dvbdev = adap->dev;
4228c2ecf20Sopenharmony_ci	bool is_medion = dvbdev->props.devices[0].warm_ids[0] ==
4238c2ecf20Sopenharmony_ci		&cxusb_table[MEDION_MD95700];
4248c2ecf20Sopenharmony_ci	u8 buf[2] = { 0x03, 0x00 };
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (is_medion && onoff) {
4278c2ecf20Sopenharmony_ci		int ret;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci		ret = cxusb_medion_get(dvbdev, CXUSB_OPEN_DIGITAL);
4308c2ecf20Sopenharmony_ci		if (ret != 0)
4318c2ecf20Sopenharmony_ci			return ret;
4328c2ecf20Sopenharmony_ci	}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	if (onoff)
4358c2ecf20Sopenharmony_ci		cxusb_ctrl_msg(dvbdev, CMD_STREAMING_ON, buf, 2, NULL, 0);
4368c2ecf20Sopenharmony_ci	else
4378c2ecf20Sopenharmony_ci		cxusb_ctrl_msg(dvbdev, CMD_STREAMING_OFF, NULL, 0, NULL, 0);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	if (is_medion && !onoff)
4408c2ecf20Sopenharmony_ci		cxusb_medion_put(dvbdev);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	return 0;
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_cistatic int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	if (onoff)
4488c2ecf20Sopenharmony_ci		cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0);
4498c2ecf20Sopenharmony_ci	else
4508c2ecf20Sopenharmony_ci		cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF,
4518c2ecf20Sopenharmony_ci			       NULL, 0, NULL, 0);
4528c2ecf20Sopenharmony_ci	return 0;
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_cistatic void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	int       ep = d->props.generic_bulk_ctrl_endpoint;
4588c2ecf20Sopenharmony_ci	const int timeout = 100;
4598c2ecf20Sopenharmony_ci	const int junk_len = 32;
4608c2ecf20Sopenharmony_ci	u8        *junk;
4618c2ecf20Sopenharmony_ci	int       rd_count;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	/* Discard remaining data in video pipe */
4648c2ecf20Sopenharmony_ci	junk = kmalloc(junk_len, GFP_KERNEL);
4658c2ecf20Sopenharmony_ci	if (!junk)
4668c2ecf20Sopenharmony_ci		return;
4678c2ecf20Sopenharmony_ci	while (1) {
4688c2ecf20Sopenharmony_ci		if (usb_bulk_msg(d->udev,
4698c2ecf20Sopenharmony_ci				 usb_rcvbulkpipe(d->udev, ep),
4708c2ecf20Sopenharmony_ci				 junk, junk_len, &rd_count, timeout) < 0)
4718c2ecf20Sopenharmony_ci			break;
4728c2ecf20Sopenharmony_ci		if (!rd_count)
4738c2ecf20Sopenharmony_ci			break;
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci	kfree(junk);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
4818c2ecf20Sopenharmony_ci	const int timeout = 100;
4828c2ecf20Sopenharmony_ci	const int junk_len = p->u.bulk.buffersize;
4838c2ecf20Sopenharmony_ci	u8        *junk;
4848c2ecf20Sopenharmony_ci	int       rd_count;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	/* Discard remaining data in video pipe */
4878c2ecf20Sopenharmony_ci	junk = kmalloc(junk_len, GFP_KERNEL);
4888c2ecf20Sopenharmony_ci	if (!junk)
4898c2ecf20Sopenharmony_ci		return;
4908c2ecf20Sopenharmony_ci	while (1) {
4918c2ecf20Sopenharmony_ci		if (usb_bulk_msg(d->udev,
4928c2ecf20Sopenharmony_ci				 usb_rcvbulkpipe(d->udev, p->endpoint),
4938c2ecf20Sopenharmony_ci				 junk, junk_len, &rd_count, timeout) < 0)
4948c2ecf20Sopenharmony_ci			break;
4958c2ecf20Sopenharmony_ci		if (!rd_count)
4968c2ecf20Sopenharmony_ci			break;
4978c2ecf20Sopenharmony_ci	}
4988c2ecf20Sopenharmony_ci	kfree(junk);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_streaming_ctrl(struct dvb_usb_adapter *adap,
5028c2ecf20Sopenharmony_ci					 int onoff)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	if (onoff) {
5058c2ecf20Sopenharmony_ci		u8 buf[2] = { 0x03, 0x00 };
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci		cxusb_d680_dmb_drain_video(adap->dev);
5088c2ecf20Sopenharmony_ci		return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON,
5098c2ecf20Sopenharmony_ci				      buf, sizeof(buf), NULL, 0);
5108c2ecf20Sopenharmony_ci	} else {
5118c2ecf20Sopenharmony_ci		int ret = cxusb_ctrl_msg(adap->dev,
5128c2ecf20Sopenharmony_ci					 CMD_STREAMING_OFF, NULL, 0, NULL, 0);
5138c2ecf20Sopenharmony_ci		return ret;
5148c2ecf20Sopenharmony_ci	}
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic int cxusb_rc_query(struct dvb_usb_device *d)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	u8 ircode[4];
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0)
5228c2ecf20Sopenharmony_ci		return 0;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (ircode[2] || ircode[3])
5258c2ecf20Sopenharmony_ci		rc_keydown(d->rc_dev, RC_PROTO_NEC,
5268c2ecf20Sopenharmony_ci			   RC_SCANCODE_NEC(~ircode[2] & 0xff, ircode[3]), 0);
5278c2ecf20Sopenharmony_ci	return 0;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic int cxusb_bluebird2_rc_query(struct dvb_usb_device *d)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	u8 ircode[4];
5338c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
5348c2ecf20Sopenharmony_ci		.addr = 0x6b,
5358c2ecf20Sopenharmony_ci		.flags = I2C_M_RD,
5368c2ecf20Sopenharmony_ci		.buf = ircode,
5378c2ecf20Sopenharmony_ci		.len = 4
5388c2ecf20Sopenharmony_ci	};
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
5418c2ecf20Sopenharmony_ci		return 0;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (ircode[1] || ircode[2])
5448c2ecf20Sopenharmony_ci		rc_keydown(d->rc_dev, RC_PROTO_NEC,
5458c2ecf20Sopenharmony_ci			   RC_SCANCODE_NEC(~ircode[1] & 0xff, ircode[2]), 0);
5468c2ecf20Sopenharmony_ci	return 0;
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	u8 ircode[2];
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
5548c2ecf20Sopenharmony_ci		return 0;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	if (ircode[0] || ircode[1])
5578c2ecf20Sopenharmony_ci		rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN,
5588c2ecf20Sopenharmony_ci			   RC_SCANCODE_RC5(ircode[0], ircode[1]), 0);
5598c2ecf20Sopenharmony_ci	return 0;
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cistatic int cxusb_dee1601_demod_init(struct dvb_frontend *fe)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x28 };
5658c2ecf20Sopenharmony_ci	static u8 reset[]          = { RESET,      0x80 };
5668c2ecf20Sopenharmony_ci	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
5678c2ecf20Sopenharmony_ci	static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0x20 };
5688c2ecf20Sopenharmony_ci	static u8 gpp_ctl_cfg[]    = { GPP_CTL,    0x33 };
5698c2ecf20Sopenharmony_ci	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	mt352_write(fe, clock_config,   sizeof(clock_config));
5728c2ecf20Sopenharmony_ci	udelay(200);
5738c2ecf20Sopenharmony_ci	mt352_write(fe, reset,          sizeof(reset));
5748c2ecf20Sopenharmony_ci	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
5778c2ecf20Sopenharmony_ci	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
5788c2ecf20Sopenharmony_ci	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	return 0;
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic int cxusb_mt352_demod_init(struct dvb_frontend *fe)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	/* used in both lgz201 and th7579 */
5868c2ecf20Sopenharmony_ci	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x29 };
5878c2ecf20Sopenharmony_ci	static u8 reset[]          = { RESET,      0x80 };
5888c2ecf20Sopenharmony_ci	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
5898c2ecf20Sopenharmony_ci	static u8 agc_cfg[]        = { AGC_TARGET, 0x24, 0x20 };
5908c2ecf20Sopenharmony_ci	static u8 gpp_ctl_cfg[]    = { GPP_CTL,    0x33 };
5918c2ecf20Sopenharmony_ci	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	mt352_write(fe, clock_config,   sizeof(clock_config));
5948c2ecf20Sopenharmony_ci	udelay(200);
5958c2ecf20Sopenharmony_ci	mt352_write(fe, reset,          sizeof(reset));
5968c2ecf20Sopenharmony_ci	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
5998c2ecf20Sopenharmony_ci	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
6008c2ecf20Sopenharmony_ci	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
6018c2ecf20Sopenharmony_ci	return 0;
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_cistatic struct cx22702_config cxusb_cx22702_config = {
6058c2ecf20Sopenharmony_ci	.demod_address = 0x63,
6068c2ecf20Sopenharmony_ci	.output_mode = CX22702_PARALLEL_OUTPUT,
6078c2ecf20Sopenharmony_ci};
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic struct lgdt330x_config cxusb_lgdt3303_config = {
6108c2ecf20Sopenharmony_ci	.demod_chip    = LGDT3303,
6118c2ecf20Sopenharmony_ci};
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic struct lgdt330x_config cxusb_aver_lgdt3303_config = {
6148c2ecf20Sopenharmony_ci	.demod_chip          = LGDT3303,
6158c2ecf20Sopenharmony_ci	.clock_polarity_flip = 2,
6168c2ecf20Sopenharmony_ci};
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_cistatic struct mt352_config cxusb_dee1601_config = {
6198c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6208c2ecf20Sopenharmony_ci	.demod_init    = cxusb_dee1601_demod_init,
6218c2ecf20Sopenharmony_ci};
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_dee1601_config = {
6248c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6258c2ecf20Sopenharmony_ci	.parallel_ts = 1,
6268c2ecf20Sopenharmony_ci};
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_cistatic struct mt352_config cxusb_mt352_config = {
6298c2ecf20Sopenharmony_ci	/* used in both lgz201 and th7579 */
6308c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6318c2ecf20Sopenharmony_ci	.demod_init    = cxusb_mt352_demod_init,
6328c2ecf20Sopenharmony_ci};
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_xc3028_config = {
6358c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6368c2ecf20Sopenharmony_ci	.if2 = 45600,
6378c2ecf20Sopenharmony_ci	.no_tuner = 1,
6388c2ecf20Sopenharmony_ci	.parallel_ts = 1,
6398c2ecf20Sopenharmony_ci};
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = {
6428c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6438c2ecf20Sopenharmony_ci	.if2 = 45600,
6448c2ecf20Sopenharmony_ci	.no_tuner = 1,
6458c2ecf20Sopenharmony_ci	.parallel_ts = 1,
6468c2ecf20Sopenharmony_ci	.disable_i2c_gate_ctrl = 1,
6478c2ecf20Sopenharmony_ci};
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cistatic struct mt352_config cxusb_mt352_xc3028_config = {
6508c2ecf20Sopenharmony_ci	.demod_address = 0x0f,
6518c2ecf20Sopenharmony_ci	.if2 = 4560,
6528c2ecf20Sopenharmony_ci	.no_tuner = 1,
6538c2ecf20Sopenharmony_ci	.demod_init = cxusb_mt352_demod_init,
6548c2ecf20Sopenharmony_ci};
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci/* FIXME: needs tweaking */
6578c2ecf20Sopenharmony_cistatic struct mxl5005s_config aver_a868r_tuner = {
6588c2ecf20Sopenharmony_ci	.i2c_address     = 0x63,
6598c2ecf20Sopenharmony_ci	.if_freq         = 6000000UL,
6608c2ecf20Sopenharmony_ci	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
6618c2ecf20Sopenharmony_ci	.agc_mode        = MXL_SINGLE_AGC,
6628c2ecf20Sopenharmony_ci	.tracking_filter = MXL_TF_C,
6638c2ecf20Sopenharmony_ci	.rssi_enable     = MXL_RSSI_ENABLE,
6648c2ecf20Sopenharmony_ci	.cap_select      = MXL_CAP_SEL_ENABLE,
6658c2ecf20Sopenharmony_ci	.div_out         = MXL_DIV_OUT_4,
6668c2ecf20Sopenharmony_ci	.clock_out       = MXL_CLOCK_OUT_DISABLE,
6678c2ecf20Sopenharmony_ci	.output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
6688c2ecf20Sopenharmony_ci	.top		 = MXL5005S_TOP_25P2,
6698c2ecf20Sopenharmony_ci	.mod_mode        = MXL_DIGITAL_MODE,
6708c2ecf20Sopenharmony_ci	.if_mode         = MXL_ZERO_IF,
6718c2ecf20Sopenharmony_ci	.AgcMasterByte   = 0x00,
6728c2ecf20Sopenharmony_ci};
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci/* FIXME: needs tweaking */
6758c2ecf20Sopenharmony_cistatic struct mxl5005s_config d680_dmb_tuner = {
6768c2ecf20Sopenharmony_ci	.i2c_address     = 0x63,
6778c2ecf20Sopenharmony_ci	.if_freq         = 36125000UL,
6788c2ecf20Sopenharmony_ci	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
6798c2ecf20Sopenharmony_ci	.agc_mode        = MXL_SINGLE_AGC,
6808c2ecf20Sopenharmony_ci	.tracking_filter = MXL_TF_C,
6818c2ecf20Sopenharmony_ci	.rssi_enable     = MXL_RSSI_ENABLE,
6828c2ecf20Sopenharmony_ci	.cap_select      = MXL_CAP_SEL_ENABLE,
6838c2ecf20Sopenharmony_ci	.div_out         = MXL_DIV_OUT_4,
6848c2ecf20Sopenharmony_ci	.clock_out       = MXL_CLOCK_OUT_DISABLE,
6858c2ecf20Sopenharmony_ci	.output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
6868c2ecf20Sopenharmony_ci	.top		 = MXL5005S_TOP_25P2,
6878c2ecf20Sopenharmony_ci	.mod_mode        = MXL_DIGITAL_MODE,
6888c2ecf20Sopenharmony_ci	.if_mode         = MXL_ZERO_IF,
6898c2ecf20Sopenharmony_ci	.AgcMasterByte   = 0x00,
6908c2ecf20Sopenharmony_ci};
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_cistatic struct max2165_config mygica_d689_max2165_cfg = {
6938c2ecf20Sopenharmony_ci	.i2c_address = 0x60,
6948c2ecf20Sopenharmony_ci	.osc_clk = 20
6958c2ecf20Sopenharmony_ci};
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci/* Callbacks for DVB USB */
6988c2ecf20Sopenharmony_cistatic int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct dvb_usb_device *dvbdev = adap->dev;
7018c2ecf20Sopenharmony_ci	bool is_medion = dvbdev->props.devices[0].warm_ids[0] ==
7028c2ecf20Sopenharmony_ci		&cxusb_table[MEDION_MD95700];
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
7058c2ecf20Sopenharmony_ci		   &dvbdev->i2c_adap, 0x61,
7068c2ecf20Sopenharmony_ci		   TUNER_PHILIPS_FMD1216ME_MK3);
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	if (is_medion && adap->fe_adap[0].fe)
7098c2ecf20Sopenharmony_ci		/*
7108c2ecf20Sopenharmony_ci		 * make sure that DVB core won't put to sleep (reset, really)
7118c2ecf20Sopenharmony_ci		 * tuner when we might be open in analog mode
7128c2ecf20Sopenharmony_ci		 */
7138c2ecf20Sopenharmony_ci		adap->fe_adap[0].fe->ops.tuner_ops.sleep = NULL;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	return 0;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_cistatic int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
7198c2ecf20Sopenharmony_ci{
7208c2ecf20Sopenharmony_ci	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
7218c2ecf20Sopenharmony_ci		   NULL, DVB_PLL_THOMSON_DTT7579);
7228c2ecf20Sopenharmony_ci	return 0;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cistatic int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
7288c2ecf20Sopenharmony_ci		   NULL, DVB_PLL_LG_Z201);
7298c2ecf20Sopenharmony_ci	return 0;
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_cistatic int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
7358c2ecf20Sopenharmony_ci		   NULL, DVB_PLL_THOMSON_DTT7579);
7368c2ecf20Sopenharmony_ci	return 0;
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
7408c2ecf20Sopenharmony_ci{
7418c2ecf20Sopenharmony_ci	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
7428c2ecf20Sopenharmony_ci		   &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
7438c2ecf20Sopenharmony_ci	return 0;
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic int dvico_bluebird_xc2028_callback(void *ptr, int component,
7478c2ecf20Sopenharmony_ci					  int command, int arg)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *adap = ptr;
7508c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	switch (command) {
7538c2ecf20Sopenharmony_ci	case XC2028_TUNER_RESET:
7548c2ecf20Sopenharmony_ci		dev_info(&d->udev->dev, "XC2028_TUNER_RESET %d\n", arg);
7558c2ecf20Sopenharmony_ci		cxusb_bluebird_gpio_pulse(d, 0x01, 1);
7568c2ecf20Sopenharmony_ci		break;
7578c2ecf20Sopenharmony_ci	case XC2028_RESET_CLK:
7588c2ecf20Sopenharmony_ci		dev_info(&d->udev->dev, "XC2028_RESET_CLK %d\n", arg);
7598c2ecf20Sopenharmony_ci		break;
7608c2ecf20Sopenharmony_ci	case XC2028_I2C_FLUSH:
7618c2ecf20Sopenharmony_ci		break;
7628c2ecf20Sopenharmony_ci	default:
7638c2ecf20Sopenharmony_ci		dev_info(&d->udev->dev, "unknown command %d, arg %d\n",
7648c2ecf20Sopenharmony_ci			 command, arg);
7658c2ecf20Sopenharmony_ci		return -EINVAL;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	return 0;
7698c2ecf20Sopenharmony_ci}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_cistatic int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct dvb_frontend	 *fe;
7748c2ecf20Sopenharmony_ci	struct xc2028_config	  cfg = {
7758c2ecf20Sopenharmony_ci		.i2c_adap  = &adap->dev->i2c_adap,
7768c2ecf20Sopenharmony_ci		.i2c_addr  = 0x61,
7778c2ecf20Sopenharmony_ci	};
7788c2ecf20Sopenharmony_ci	static struct xc2028_ctrl ctl = {
7798c2ecf20Sopenharmony_ci		.fname       = XC2028_DEFAULT_FIRMWARE,
7808c2ecf20Sopenharmony_ci		.max_len     = 64,
7818c2ecf20Sopenharmony_ci		.demod       = XC3028_FE_ZARLINK456,
7828c2ecf20Sopenharmony_ci	};
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	/* FIXME: generalize & move to common area */
7858c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
7888c2ecf20Sopenharmony_ci	if (!fe || !fe->ops.tuner_ops.set_config)
7898c2ecf20Sopenharmony_ci		return -EIO;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	fe->ops.tuner_ops.set_config(fe, &ctl);
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	return 0;
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_cistatic int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
7998c2ecf20Sopenharmony_ci		   &adap->dev->i2c_adap, &aver_a868r_tuner);
8008c2ecf20Sopenharmony_ci	return 0;
8018c2ecf20Sopenharmony_ci}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	struct dvb_frontend *fe;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
8088c2ecf20Sopenharmony_ci			&adap->dev->i2c_adap, &d680_dmb_tuner);
8098c2ecf20Sopenharmony_ci	return (!fe) ? -EIO : 0;
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cistatic int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct dvb_frontend *fe;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
8178c2ecf20Sopenharmony_ci			&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
8188c2ecf20Sopenharmony_ci	return (!fe) ? -EIO : 0;
8198c2ecf20Sopenharmony_ci}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_cistatic int cxusb_medion_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
8228c2ecf20Sopenharmony_ci{
8238c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *adap = fe->dvb->priv;
8248c2ecf20Sopenharmony_ci	struct dvb_usb_device *dvbdev = adap->dev;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	if (acquire)
8278c2ecf20Sopenharmony_ci		return cxusb_medion_get(dvbdev, CXUSB_OPEN_DIGITAL);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	cxusb_medion_put(dvbdev);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	return 0;
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_cistatic int cxusb_medion_set_mode(struct dvb_usb_device *dvbdev, bool digital)
8358c2ecf20Sopenharmony_ci{
8368c2ecf20Sopenharmony_ci	struct cxusb_state *st = dvbdev->priv;
8378c2ecf20Sopenharmony_ci	int ret;
8388c2ecf20Sopenharmony_ci	u8 b;
8398c2ecf20Sopenharmony_ci	unsigned int i;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	/*
8428c2ecf20Sopenharmony_ci	 * switching mode while doing an I2C transaction often causes
8438c2ecf20Sopenharmony_ci	 * the device to crash
8448c2ecf20Sopenharmony_ci	 */
8458c2ecf20Sopenharmony_ci	mutex_lock(&dvbdev->i2c_mutex);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	if (digital) {
8488c2ecf20Sopenharmony_ci		ret = usb_set_interface(dvbdev->udev, 0, 6);
8498c2ecf20Sopenharmony_ci		if (ret != 0) {
8508c2ecf20Sopenharmony_ci			dev_err(&dvbdev->udev->dev,
8518c2ecf20Sopenharmony_ci				"digital interface selection failed (%d)\n",
8528c2ecf20Sopenharmony_ci				ret);
8538c2ecf20Sopenharmony_ci			goto ret_unlock;
8548c2ecf20Sopenharmony_ci		}
8558c2ecf20Sopenharmony_ci	} else {
8568c2ecf20Sopenharmony_ci		ret = usb_set_interface(dvbdev->udev, 0, 1);
8578c2ecf20Sopenharmony_ci		if (ret != 0) {
8588c2ecf20Sopenharmony_ci			dev_err(&dvbdev->udev->dev,
8598c2ecf20Sopenharmony_ci				"analog interface selection failed (%d)\n",
8608c2ecf20Sopenharmony_ci				ret);
8618c2ecf20Sopenharmony_ci			goto ret_unlock;
8628c2ecf20Sopenharmony_ci		}
8638c2ecf20Sopenharmony_ci	}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	/* pipes need to be cleared after setting interface */
8668c2ecf20Sopenharmony_ci	ret = usb_clear_halt(dvbdev->udev, usb_rcvbulkpipe(dvbdev->udev, 1));
8678c2ecf20Sopenharmony_ci	if (ret != 0)
8688c2ecf20Sopenharmony_ci		dev_warn(&dvbdev->udev->dev,
8698c2ecf20Sopenharmony_ci			 "clear halt on IN pipe failed (%d)\n",
8708c2ecf20Sopenharmony_ci			 ret);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	ret = usb_clear_halt(dvbdev->udev, usb_sndbulkpipe(dvbdev->udev, 1));
8738c2ecf20Sopenharmony_ci	if (ret != 0)
8748c2ecf20Sopenharmony_ci		dev_warn(&dvbdev->udev->dev,
8758c2ecf20Sopenharmony_ci			 "clear halt on OUT pipe failed (%d)\n",
8768c2ecf20Sopenharmony_ci			 ret);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	ret = cxusb_ctrl_msg(dvbdev, digital ? CMD_DIGITAL : CMD_ANALOG,
8798c2ecf20Sopenharmony_ci			     NULL, 0, &b, 1);
8808c2ecf20Sopenharmony_ci	if (ret != 0) {
8818c2ecf20Sopenharmony_ci		dev_err(&dvbdev->udev->dev, "mode switch failed (%d)\n",
8828c2ecf20Sopenharmony_ci			ret);
8838c2ecf20Sopenharmony_ci		goto ret_unlock;
8848c2ecf20Sopenharmony_ci	}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	/* mode switch seems to reset GPIO states */
8878c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(st->gpio_write_refresh); i++)
8888c2ecf20Sopenharmony_ci		st->gpio_write_refresh[i] = true;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ciret_unlock:
8918c2ecf20Sopenharmony_ci	mutex_unlock(&dvbdev->i2c_mutex);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	return ret;
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_cistatic int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
8978c2ecf20Sopenharmony_ci{
8988c2ecf20Sopenharmony_ci	struct dvb_usb_device *dvbdev = adap->dev;
8998c2ecf20Sopenharmony_ci	bool is_medion = dvbdev->props.devices[0].warm_ids[0] ==
9008c2ecf20Sopenharmony_ci		&cxusb_table[MEDION_MD95700];
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	if (is_medion) {
9038c2ecf20Sopenharmony_ci		int ret;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci		ret = cxusb_medion_set_mode(dvbdev, true);
9068c2ecf20Sopenharmony_ci		if (ret)
9078c2ecf20Sopenharmony_ci			return ret;
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
9118c2ecf20Sopenharmony_ci					 &dvbdev->i2c_adap);
9128c2ecf20Sopenharmony_ci	if (!adap->fe_adap[0].fe)
9138c2ecf20Sopenharmony_ci		return -EIO;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	if (is_medion)
9168c2ecf20Sopenharmony_ci		adap->fe_adap[0].fe->ops.ts_bus_ctrl =
9178c2ecf20Sopenharmony_ci			cxusb_medion_fe_ts_bus_ctrl;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	return 0;
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_cistatic int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 7) < 0)
9258c2ecf20Sopenharmony_ci		err("set interface failed");
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
9308c2ecf20Sopenharmony_ci					 &cxusb_lgdt3303_config,
9318c2ecf20Sopenharmony_ci					 0x0e,
9328c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
9338c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
9348c2ecf20Sopenharmony_ci		return 0;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	return -EIO;
9378c2ecf20Sopenharmony_ci}
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_cistatic int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
9408c2ecf20Sopenharmony_ci{
9418c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
9428c2ecf20Sopenharmony_ci					 &cxusb_aver_lgdt3303_config,
9438c2ecf20Sopenharmony_ci					 0x0e,
9448c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
9458c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
9468c2ecf20Sopenharmony_ci		return 0;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	return -EIO;
9498c2ecf20Sopenharmony_ci}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_cistatic int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
9528c2ecf20Sopenharmony_ci{
9538c2ecf20Sopenharmony_ci	/* used in both lgz201 and th7579 */
9548c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
9558c2ecf20Sopenharmony_ci		err("set interface failed");
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
9608c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
9618c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
9628c2ecf20Sopenharmony_ci		return 0;
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	return -EIO;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cistatic int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
9708c2ecf20Sopenharmony_ci		err("set interface failed");
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
9758c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
9768c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
9778c2ecf20Sopenharmony_ci		return 0;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
9808c2ecf20Sopenharmony_ci					 &cxusb_zl10353_dee1601_config,
9818c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
9828c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
9838c2ecf20Sopenharmony_ci		return 0;
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	return -EIO;
9868c2ecf20Sopenharmony_ci}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_cistatic int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	u8 ircode[4];
9918c2ecf20Sopenharmony_ci	int i;
9928c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
9938c2ecf20Sopenharmony_ci		.addr = 0x6b,
9948c2ecf20Sopenharmony_ci		.flags = I2C_M_RD,
9958c2ecf20Sopenharmony_ci		.buf = ircode,
9968c2ecf20Sopenharmony_ci		.len = 4
9978c2ecf20Sopenharmony_ci	};
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
10008c2ecf20Sopenharmony_ci		err("set interface failed");
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	/* reset the tuner and demodulator */
10058c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
10068c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
10078c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe =
10108c2ecf20Sopenharmony_ci		dvb_attach(zl10353_attach,
10118c2ecf20Sopenharmony_ci			   &cxusb_zl10353_xc3028_config_no_i2c_gate,
10128c2ecf20Sopenharmony_ci			   &adap->dev->i2c_adap);
10138c2ecf20Sopenharmony_ci	if (!adap->fe_adap[0].fe)
10148c2ecf20Sopenharmony_ci		return -EIO;
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	/* try to determine if there is no IR decoder on the I2C bus */
10178c2ecf20Sopenharmony_ci	for (i = 0; adap->dev->props.rc.core.rc_codes && i < 5; i++) {
10188c2ecf20Sopenharmony_ci		msleep(20);
10198c2ecf20Sopenharmony_ci		if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
10208c2ecf20Sopenharmony_ci			goto no_IR;
10218c2ecf20Sopenharmony_ci		if (ircode[0] == 0 && ircode[1] == 0)
10228c2ecf20Sopenharmony_ci			continue;
10238c2ecf20Sopenharmony_ci		if (ircode[2] + ircode[3] != 0xff) {
10248c2ecf20Sopenharmony_cino_IR:
10258c2ecf20Sopenharmony_ci			adap->dev->props.rc.core.rc_codes = NULL;
10268c2ecf20Sopenharmony_ci			info("No IR receiver detected on this device.");
10278c2ecf20Sopenharmony_ci			break;
10288c2ecf20Sopenharmony_ci		}
10298c2ecf20Sopenharmony_ci	}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	return 0;
10328c2ecf20Sopenharmony_ci}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_cistatic struct dibx000_agc_config dib7070_agc_config = {
10358c2ecf20Sopenharmony_ci	.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	/*
10388c2ecf20Sopenharmony_ci	 * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
10398c2ecf20Sopenharmony_ci	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
10408c2ecf20Sopenharmony_ci	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
10418c2ecf20Sopenharmony_ci	 */
10428c2ecf20Sopenharmony_ci	.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
10438c2ecf20Sopenharmony_ci		 (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
10448c2ecf20Sopenharmony_ci	.inv_gain = 600,
10458c2ecf20Sopenharmony_ci	.time_stabiliz = 10,
10468c2ecf20Sopenharmony_ci	.alpha_level = 0,
10478c2ecf20Sopenharmony_ci	.thlock = 118,
10488c2ecf20Sopenharmony_ci	.wbd_inv = 0,
10498c2ecf20Sopenharmony_ci	.wbd_ref = 3530,
10508c2ecf20Sopenharmony_ci	.wbd_sel = 1,
10518c2ecf20Sopenharmony_ci	.wbd_alpha = 5,
10528c2ecf20Sopenharmony_ci	.agc1_max = 65535,
10538c2ecf20Sopenharmony_ci	.agc1_min = 0,
10548c2ecf20Sopenharmony_ci	.agc2_max = 65535,
10558c2ecf20Sopenharmony_ci	.agc2_min = 0,
10568c2ecf20Sopenharmony_ci	.agc1_pt1 = 0,
10578c2ecf20Sopenharmony_ci	.agc1_pt2 = 40,
10588c2ecf20Sopenharmony_ci	.agc1_pt3 = 183,
10598c2ecf20Sopenharmony_ci	.agc1_slope1 = 206,
10608c2ecf20Sopenharmony_ci	.agc1_slope2 = 255,
10618c2ecf20Sopenharmony_ci	.agc2_pt1 = 72,
10628c2ecf20Sopenharmony_ci	.agc2_pt2 = 152,
10638c2ecf20Sopenharmony_ci	.agc2_slope1 = 88,
10648c2ecf20Sopenharmony_ci	.agc2_slope2 = 90,
10658c2ecf20Sopenharmony_ci	.alpha_mant = 17,
10668c2ecf20Sopenharmony_ci	.alpha_exp = 27,
10678c2ecf20Sopenharmony_ci	.beta_mant = 23,
10688c2ecf20Sopenharmony_ci	.beta_exp = 51,
10698c2ecf20Sopenharmony_ci	.perform_agc_softsplit = 0,
10708c2ecf20Sopenharmony_ci};
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_cistatic struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
10738c2ecf20Sopenharmony_ci	.internal = 60000,
10748c2ecf20Sopenharmony_ci	.sampling = 15000,
10758c2ecf20Sopenharmony_ci	.pll_prediv = 1,
10768c2ecf20Sopenharmony_ci	.pll_ratio = 20,
10778c2ecf20Sopenharmony_ci	.pll_range = 3,
10788c2ecf20Sopenharmony_ci	.pll_reset = 1,
10798c2ecf20Sopenharmony_ci	.pll_bypass = 0,
10808c2ecf20Sopenharmony_ci	.enable_refdiv = 0,
10818c2ecf20Sopenharmony_ci	.bypclk_div = 0,
10828c2ecf20Sopenharmony_ci	.IO_CLK_en_core = 1,
10838c2ecf20Sopenharmony_ci	.ADClkSrc = 1,
10848c2ecf20Sopenharmony_ci	.modulo = 2,
10858c2ecf20Sopenharmony_ci	/* refsel, sel, freq_15k */
10868c2ecf20Sopenharmony_ci	.sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
10878c2ecf20Sopenharmony_ci	.ifreq = (0 << 25) | 0,
10888c2ecf20Sopenharmony_ci	.timf = 20452225,
10898c2ecf20Sopenharmony_ci	.xtal_hz = 12000000,
10908c2ecf20Sopenharmony_ci};
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_cistatic struct dib7000p_config cxusb_dualdig4_rev2_config = {
10938c2ecf20Sopenharmony_ci	.output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
10948c2ecf20Sopenharmony_ci	.output_mpeg2_in_188_bytes = 1,
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	.agc_config_count = 1,
10978c2ecf20Sopenharmony_ci	.agc = &dib7070_agc_config,
10988c2ecf20Sopenharmony_ci	.bw  = &dib7070_bw_config_12_mhz,
10998c2ecf20Sopenharmony_ci	.tuner_is_baseband = 1,
11008c2ecf20Sopenharmony_ci	.spur_protect = 1,
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	.gpio_dir = 0xfcef,
11038c2ecf20Sopenharmony_ci	.gpio_val = 0x0110,
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	.hostbus_diversity = 1,
11088c2ecf20Sopenharmony_ci};
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_cistruct dib0700_adapter_state {
11118c2ecf20Sopenharmony_ci	int (*set_param_save)(struct dvb_frontend *fe);
11128c2ecf20Sopenharmony_ci	struct dib7000p_ops dib7000p_ops;
11138c2ecf20Sopenharmony_ci};
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
11168c2ecf20Sopenharmony_ci{
11178c2ecf20Sopenharmony_ci	struct dib0700_adapter_state *state = adap->priv;
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
11208c2ecf20Sopenharmony_ci		err("set interface failed");
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
11278c2ecf20Sopenharmony_ci		return -ENODEV;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
11308c2ecf20Sopenharmony_ci						&cxusb_dualdig4_rev2_config) < 0) {
11318c2ecf20Sopenharmony_ci		pr_warn("Unable to enumerate dib7000p\n");
11328c2ecf20Sopenharmony_ci		return -ENODEV;
11338c2ecf20Sopenharmony_ci	}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
11368c2ecf20Sopenharmony_ci						       0x80,
11378c2ecf20Sopenharmony_ci						       &cxusb_dualdig4_rev2_config);
11388c2ecf20Sopenharmony_ci	if (!adap->fe_adap[0].fe)
11398c2ecf20Sopenharmony_ci		return -EIO;
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	return 0;
11428c2ecf20Sopenharmony_ci}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_cistatic int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
11458c2ecf20Sopenharmony_ci{
11468c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *adap = fe->dvb->priv;
11478c2ecf20Sopenharmony_ci	struct dib0700_adapter_state *state = adap->priv;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
11508c2ecf20Sopenharmony_ci}
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_cistatic int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
11538c2ecf20Sopenharmony_ci{
11548c2ecf20Sopenharmony_ci	return 0;
11558c2ecf20Sopenharmony_ci}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_cistatic struct dib0070_config dib7070p_dib0070_config = {
11588c2ecf20Sopenharmony_ci	.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
11598c2ecf20Sopenharmony_ci	.reset = dib7070_tuner_reset,
11608c2ecf20Sopenharmony_ci	.sleep = dib7070_tuner_sleep,
11618c2ecf20Sopenharmony_ci	.clock_khz = 12000,
11628c2ecf20Sopenharmony_ci};
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_cistatic int dib7070_set_param_override(struct dvb_frontend *fe)
11658c2ecf20Sopenharmony_ci{
11668c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
11678c2ecf20Sopenharmony_ci	struct dvb_usb_adapter *adap = fe->dvb->priv;
11688c2ecf20Sopenharmony_ci	struct dib0700_adapter_state *state = adap->priv;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	u16 offset;
11718c2ecf20Sopenharmony_ci	u8 band = BAND_OF_FREQUENCY(p->frequency / 1000);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	switch (band) {
11748c2ecf20Sopenharmony_ci	case BAND_VHF:
11758c2ecf20Sopenharmony_ci		offset = 950;
11768c2ecf20Sopenharmony_ci		break;
11778c2ecf20Sopenharmony_ci	default:
11788c2ecf20Sopenharmony_ci	case BAND_UHF:
11798c2ecf20Sopenharmony_ci		offset = 550;
11808c2ecf20Sopenharmony_ci		break;
11818c2ecf20Sopenharmony_ci	}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	return state->set_param_save(fe);
11868c2ecf20Sopenharmony_ci}
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_cistatic int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
11898c2ecf20Sopenharmony_ci{
11908c2ecf20Sopenharmony_ci	struct dib0700_adapter_state *st = adap->priv;
11918c2ecf20Sopenharmony_ci	struct i2c_adapter *tun_i2c;
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	/*
11948c2ecf20Sopenharmony_ci	 * No need to call dvb7000p_attach here, as it was called
11958c2ecf20Sopenharmony_ci	 * already, as frontend_attach method is called first, and
11968c2ecf20Sopenharmony_ci	 * tuner_attach is only called on success.
11978c2ecf20Sopenharmony_ci	 */
11988c2ecf20Sopenharmony_ci	tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
11998c2ecf20Sopenharmony_ci					DIBX000_I2C_INTERFACE_TUNER, 1);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
12028c2ecf20Sopenharmony_ci		       &dib7070p_dib0070_config) == NULL)
12038c2ecf20Sopenharmony_ci		return -ENODEV;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
12068c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
12078c2ecf20Sopenharmony_ci	return 0;
12088c2ecf20Sopenharmony_ci}
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_cistatic int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
12118c2ecf20Sopenharmony_ci{
12128c2ecf20Sopenharmony_ci	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
12138c2ecf20Sopenharmony_ci		err("set interface failed");
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	/* reset the tuner and demodulator */
12188c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
12198c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
12208c2ecf20Sopenharmony_ci	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
12238c2ecf20Sopenharmony_ci					 &cxusb_zl10353_xc3028_config,
12248c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
12258c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
12268c2ecf20Sopenharmony_ci		return 0;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
12298c2ecf20Sopenharmony_ci					 &cxusb_mt352_xc3028_config,
12308c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap);
12318c2ecf20Sopenharmony_ci	if (adap->fe_adap[0].fe)
12328c2ecf20Sopenharmony_ci		return 0;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	return -EIO;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic struct lgs8gxx_config d680_lgs8gl5_cfg = {
12388c2ecf20Sopenharmony_ci	.prod = LGS8GXX_PROD_LGS8GL5,
12398c2ecf20Sopenharmony_ci	.demod_address = 0x19,
12408c2ecf20Sopenharmony_ci	.serial_ts = 0,
12418c2ecf20Sopenharmony_ci	.ts_clk_pol = 0,
12428c2ecf20Sopenharmony_ci	.ts_clk_gated = 1,
12438c2ecf20Sopenharmony_ci	.if_clk_freq = 30400, /* 30.4 MHz */
12448c2ecf20Sopenharmony_ci	.if_freq = 5725, /* 5.725 MHz */
12458c2ecf20Sopenharmony_ci	.if_neg_center = 0,
12468c2ecf20Sopenharmony_ci	.ext_adc = 0,
12478c2ecf20Sopenharmony_ci	.adc_signed = 0,
12488c2ecf20Sopenharmony_ci	.if_neg_edge = 0,
12498c2ecf20Sopenharmony_ci};
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_cistatic int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
12528c2ecf20Sopenharmony_ci{
12538c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
12548c2ecf20Sopenharmony_ci	int n;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	/* Select required USB configuration */
12578c2ecf20Sopenharmony_ci	if (usb_set_interface(d->udev, 0, 0) < 0)
12588c2ecf20Sopenharmony_ci		err("set interface failed");
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	/* Unblock all USB pipes */
12618c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
12628c2ecf20Sopenharmony_ci		       usb_sndbulkpipe(d->udev,
12638c2ecf20Sopenharmony_ci				       d->props.generic_bulk_ctrl_endpoint));
12648c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
12658c2ecf20Sopenharmony_ci		       usb_rcvbulkpipe(d->udev,
12668c2ecf20Sopenharmony_ci				       d->props.generic_bulk_ctrl_endpoint));
12678c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
12688c2ecf20Sopenharmony_ci		       usb_rcvbulkpipe(d->udev,
12698c2ecf20Sopenharmony_ci				       d->props.adapter[0].fe[0].stream.endpoint));
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	/* Drain USB pipes to avoid hang after reboot */
12728c2ecf20Sopenharmony_ci	for (n = 0;  n < 5;  n++) {
12738c2ecf20Sopenharmony_ci		cxusb_d680_dmb_drain_message(d);
12748c2ecf20Sopenharmony_ci		cxusb_d680_dmb_drain_video(d);
12758c2ecf20Sopenharmony_ci		msleep(200);
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	/* Reset the tuner */
12798c2ecf20Sopenharmony_ci	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
12808c2ecf20Sopenharmony_ci		err("clear tuner gpio failed");
12818c2ecf20Sopenharmony_ci		return -EIO;
12828c2ecf20Sopenharmony_ci	}
12838c2ecf20Sopenharmony_ci	msleep(100);
12848c2ecf20Sopenharmony_ci	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
12858c2ecf20Sopenharmony_ci		err("set tuner gpio failed");
12868c2ecf20Sopenharmony_ci		return -EIO;
12878c2ecf20Sopenharmony_ci	}
12888c2ecf20Sopenharmony_ci	msleep(100);
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	/* Attach frontend */
12918c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach,
12928c2ecf20Sopenharmony_ci					 &d680_lgs8gl5_cfg, &d->i2c_adap);
12938c2ecf20Sopenharmony_ci	if (!adap->fe_adap[0].fe)
12948c2ecf20Sopenharmony_ci		return -EIO;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	return 0;
12978c2ecf20Sopenharmony_ci}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_cistatic struct atbm8830_config mygica_d689_atbm8830_cfg = {
13008c2ecf20Sopenharmony_ci	.prod = ATBM8830_PROD_8830,
13018c2ecf20Sopenharmony_ci	.demod_address = 0x40,
13028c2ecf20Sopenharmony_ci	.serial_ts = 0,
13038c2ecf20Sopenharmony_ci	.ts_sampling_edge = 1,
13048c2ecf20Sopenharmony_ci	.ts_clk_gated = 0,
13058c2ecf20Sopenharmony_ci	.osc_clk_freq = 30400, /* in kHz */
13068c2ecf20Sopenharmony_ci	.if_freq = 0, /* zero IF */
13078c2ecf20Sopenharmony_ci	.zif_swap_iq = 1,
13088c2ecf20Sopenharmony_ci	.agc_min = 0x2E,
13098c2ecf20Sopenharmony_ci	.agc_max = 0x90,
13108c2ecf20Sopenharmony_ci	.agc_hold_loop = 0,
13118c2ecf20Sopenharmony_ci};
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_cistatic int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
13148c2ecf20Sopenharmony_ci{
13158c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = adap->dev;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	/* Select required USB configuration */
13188c2ecf20Sopenharmony_ci	if (usb_set_interface(d->udev, 0, 0) < 0)
13198c2ecf20Sopenharmony_ci		err("set interface failed");
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	/* Unblock all USB pipes */
13228c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
13238c2ecf20Sopenharmony_ci		       usb_sndbulkpipe(d->udev,
13248c2ecf20Sopenharmony_ci				       d->props.generic_bulk_ctrl_endpoint));
13258c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
13268c2ecf20Sopenharmony_ci		       usb_rcvbulkpipe(d->udev,
13278c2ecf20Sopenharmony_ci				       d->props.generic_bulk_ctrl_endpoint));
13288c2ecf20Sopenharmony_ci	usb_clear_halt(d->udev,
13298c2ecf20Sopenharmony_ci		       usb_rcvbulkpipe(d->udev,
13308c2ecf20Sopenharmony_ci				       d->props.adapter[0].fe[0].stream.endpoint));
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	/* Reset the tuner */
13338c2ecf20Sopenharmony_ci	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
13348c2ecf20Sopenharmony_ci		err("clear tuner gpio failed");
13358c2ecf20Sopenharmony_ci		return -EIO;
13368c2ecf20Sopenharmony_ci	}
13378c2ecf20Sopenharmony_ci	msleep(100);
13388c2ecf20Sopenharmony_ci	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
13398c2ecf20Sopenharmony_ci		err("set tuner gpio failed");
13408c2ecf20Sopenharmony_ci		return -EIO;
13418c2ecf20Sopenharmony_ci	}
13428c2ecf20Sopenharmony_ci	msleep(100);
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	/* Attach frontend */
13458c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(atbm8830_attach,
13468c2ecf20Sopenharmony_ci					 &mygica_d689_atbm8830_cfg,
13478c2ecf20Sopenharmony_ci					 &d->i2c_adap);
13488c2ecf20Sopenharmony_ci	if (!adap->fe_adap[0].fe)
13498c2ecf20Sopenharmony_ci		return -EIO;
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	return 0;
13528c2ecf20Sopenharmony_ci}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci/*
13558c2ecf20Sopenharmony_ci * DViCO has shipped two devices with the same USB ID, but only one of them
13568c2ecf20Sopenharmony_ci * needs a firmware download.  Check the device class details to see if they
13578c2ecf20Sopenharmony_ci * have non-default values to decide whether the device is actually cold or
13588c2ecf20Sopenharmony_ci * not, and forget a match if it turns out we selected the wrong device.
13598c2ecf20Sopenharmony_ci */
13608c2ecf20Sopenharmony_cistatic int bluebird_fx2_identify_state(struct usb_device *udev,
13618c2ecf20Sopenharmony_ci				       const struct dvb_usb_device_properties *props,
13628c2ecf20Sopenharmony_ci				       const struct dvb_usb_device_description **desc,
13638c2ecf20Sopenharmony_ci				       int *cold)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	int wascold = *cold;
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	*cold = udev->descriptor.bDeviceClass == 0xff &&
13688c2ecf20Sopenharmony_ci		udev->descriptor.bDeviceSubClass == 0xff &&
13698c2ecf20Sopenharmony_ci		udev->descriptor.bDeviceProtocol == 0xff;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	if (*cold && !wascold)
13728c2ecf20Sopenharmony_ci		*desc = NULL;
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	return 0;
13758c2ecf20Sopenharmony_ci}
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci/*
13788c2ecf20Sopenharmony_ci * DViCO bluebird firmware needs the "warm" product ID to be patched into the
13798c2ecf20Sopenharmony_ci * firmware file before download.
13808c2ecf20Sopenharmony_ci */
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_cistatic const int dvico_firmware_id_offsets[] = { 6638, 3204 };
13838c2ecf20Sopenharmony_cistatic int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
13848c2ecf20Sopenharmony_ci						  const struct firmware *fw)
13858c2ecf20Sopenharmony_ci{
13868c2ecf20Sopenharmony_ci	int pos;
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
13898c2ecf20Sopenharmony_ci		int idoff = dvico_firmware_id_offsets[pos];
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci		if (fw->size < idoff + 4)
13928c2ecf20Sopenharmony_ci			continue;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci		if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
13958c2ecf20Sopenharmony_ci		    fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
13968c2ecf20Sopenharmony_ci			struct firmware new_fw;
13978c2ecf20Sopenharmony_ci			u8 *new_fw_data = vmalloc(fw->size);
13988c2ecf20Sopenharmony_ci			int ret;
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci			if (!new_fw_data)
14018c2ecf20Sopenharmony_ci				return -ENOMEM;
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci			memcpy(new_fw_data, fw->data, fw->size);
14048c2ecf20Sopenharmony_ci			new_fw.size = fw->size;
14058c2ecf20Sopenharmony_ci			new_fw.data = new_fw_data;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci			new_fw_data[idoff + 2] =
14088c2ecf20Sopenharmony_ci				le16_to_cpu(udev->descriptor.idProduct) + 1;
14098c2ecf20Sopenharmony_ci			new_fw_data[idoff + 3] =
14108c2ecf20Sopenharmony_ci				le16_to_cpu(udev->descriptor.idProduct) >> 8;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci			ret = usb_cypress_load_firmware(udev, &new_fw,
14138c2ecf20Sopenharmony_ci							CYPRESS_FX2);
14148c2ecf20Sopenharmony_ci			vfree(new_fw_data);
14158c2ecf20Sopenharmony_ci			return ret;
14168c2ecf20Sopenharmony_ci		}
14178c2ecf20Sopenharmony_ci	}
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	return -EINVAL;
14208c2ecf20Sopenharmony_ci}
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ciint cxusb_medion_get(struct dvb_usb_device *dvbdev,
14238c2ecf20Sopenharmony_ci		     enum cxusb_open_type open_type)
14248c2ecf20Sopenharmony_ci{
14258c2ecf20Sopenharmony_ci	struct cxusb_medion_dev *cxdev = dvbdev->priv;
14268c2ecf20Sopenharmony_ci	int ret = 0;
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	mutex_lock(&cxdev->open_lock);
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	if (WARN_ON((cxdev->open_type == CXUSB_OPEN_INIT ||
14318c2ecf20Sopenharmony_ci		     cxdev->open_type == CXUSB_OPEN_NONE) &&
14328c2ecf20Sopenharmony_ci		    cxdev->open_ctr != 0)) {
14338c2ecf20Sopenharmony_ci		ret = -EINVAL;
14348c2ecf20Sopenharmony_ci		goto ret_unlock;
14358c2ecf20Sopenharmony_ci	}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	if (cxdev->open_type == CXUSB_OPEN_INIT) {
14388c2ecf20Sopenharmony_ci		ret = -EAGAIN;
14398c2ecf20Sopenharmony_ci		goto ret_unlock;
14408c2ecf20Sopenharmony_ci	}
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	if (cxdev->open_ctr == 0) {
14438c2ecf20Sopenharmony_ci		if (cxdev->open_type != open_type) {
14448c2ecf20Sopenharmony_ci			dev_info(&dvbdev->udev->dev, "will acquire and switch to %s\n",
14458c2ecf20Sopenharmony_ci				 open_type == CXUSB_OPEN_ANALOG ?
14468c2ecf20Sopenharmony_ci				 "analog" : "digital");
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci			if (open_type == CXUSB_OPEN_ANALOG) {
14498c2ecf20Sopenharmony_ci				ret = _cxusb_power_ctrl(dvbdev, 1);
14508c2ecf20Sopenharmony_ci				if (ret != 0)
14518c2ecf20Sopenharmony_ci					dev_warn(&dvbdev->udev->dev,
14528c2ecf20Sopenharmony_ci						 "powerup for analog switch failed (%d)\n",
14538c2ecf20Sopenharmony_ci						 ret);
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci				ret = cxusb_medion_set_mode(dvbdev, false);
14568c2ecf20Sopenharmony_ci				if (ret != 0)
14578c2ecf20Sopenharmony_ci					goto ret_unlock;
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci				ret = cxusb_medion_analog_init(dvbdev);
14608c2ecf20Sopenharmony_ci				if (ret != 0)
14618c2ecf20Sopenharmony_ci					goto ret_unlock;
14628c2ecf20Sopenharmony_ci			} else { /* digital */
14638c2ecf20Sopenharmony_ci				ret = _cxusb_power_ctrl(dvbdev, 1);
14648c2ecf20Sopenharmony_ci				if (ret != 0)
14658c2ecf20Sopenharmony_ci					dev_warn(&dvbdev->udev->dev,
14668c2ecf20Sopenharmony_ci						 "powerup for digital switch failed (%d)\n",
14678c2ecf20Sopenharmony_ci						 ret);
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci				ret = cxusb_medion_set_mode(dvbdev, true);
14708c2ecf20Sopenharmony_ci				if (ret != 0)
14718c2ecf20Sopenharmony_ci					goto ret_unlock;
14728c2ecf20Sopenharmony_ci			}
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci			cxdev->open_type = open_type;
14758c2ecf20Sopenharmony_ci		} else {
14768c2ecf20Sopenharmony_ci			dev_info(&dvbdev->udev->dev, "reacquired idle %s\n",
14778c2ecf20Sopenharmony_ci				 open_type == CXUSB_OPEN_ANALOG ?
14788c2ecf20Sopenharmony_ci				 "analog" : "digital");
14798c2ecf20Sopenharmony_ci		}
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci		cxdev->open_ctr = 1;
14828c2ecf20Sopenharmony_ci	} else if (cxdev->open_type == open_type) {
14838c2ecf20Sopenharmony_ci		cxdev->open_ctr++;
14848c2ecf20Sopenharmony_ci		dev_info(&dvbdev->udev->dev, "acquired %s\n",
14858c2ecf20Sopenharmony_ci			 open_type == CXUSB_OPEN_ANALOG ? "analog" : "digital");
14868c2ecf20Sopenharmony_ci	} else {
14878c2ecf20Sopenharmony_ci		ret = -EBUSY;
14888c2ecf20Sopenharmony_ci	}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ciret_unlock:
14918c2ecf20Sopenharmony_ci	mutex_unlock(&cxdev->open_lock);
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	return ret;
14948c2ecf20Sopenharmony_ci}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_civoid cxusb_medion_put(struct dvb_usb_device *dvbdev)
14978c2ecf20Sopenharmony_ci{
14988c2ecf20Sopenharmony_ci	struct cxusb_medion_dev *cxdev = dvbdev->priv;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	mutex_lock(&cxdev->open_lock);
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	if (cxdev->open_type == CXUSB_OPEN_INIT) {
15038c2ecf20Sopenharmony_ci		WARN_ON(cxdev->open_ctr != 0);
15048c2ecf20Sopenharmony_ci		cxdev->open_type = CXUSB_OPEN_NONE;
15058c2ecf20Sopenharmony_ci		goto unlock;
15068c2ecf20Sopenharmony_ci	}
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	if (!WARN_ON(cxdev->open_ctr < 1)) {
15098c2ecf20Sopenharmony_ci		cxdev->open_ctr--;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci		dev_info(&dvbdev->udev->dev, "release %s\n",
15128c2ecf20Sopenharmony_ci			 cxdev->open_type == CXUSB_OPEN_ANALOG ?
15138c2ecf20Sopenharmony_ci			 "analog" : "digital");
15148c2ecf20Sopenharmony_ci	}
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ciunlock:
15178c2ecf20Sopenharmony_ci	mutex_unlock(&cxdev->open_lock);
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci/* DVB USB Driver stuff */
15218c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_medion_properties;
15228c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
15238c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
15248c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
15258c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
15268c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
15278c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties;
15288c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
15298c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
15308c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_aver_a868r_properties;
15318c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_d680_dmb_properties;
15328c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_mygica_d689_properties;
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_cistatic int cxusb_medion_priv_init(struct dvb_usb_device *dvbdev)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	struct cxusb_medion_dev *cxdev = dvbdev->priv;
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	cxdev->dvbdev = dvbdev;
15398c2ecf20Sopenharmony_ci	cxdev->open_type = CXUSB_OPEN_INIT;
15408c2ecf20Sopenharmony_ci	mutex_init(&cxdev->open_lock);
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci	return 0;
15438c2ecf20Sopenharmony_ci}
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_cistatic void cxusb_medion_priv_destroy(struct dvb_usb_device *dvbdev)
15468c2ecf20Sopenharmony_ci{
15478c2ecf20Sopenharmony_ci	struct cxusb_medion_dev *cxdev = dvbdev->priv;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	mutex_destroy(&cxdev->open_lock);
15508c2ecf20Sopenharmony_ci}
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_cistatic bool cxusb_medion_check_altsetting(struct usb_host_interface *as)
15538c2ecf20Sopenharmony_ci{
15548c2ecf20Sopenharmony_ci	unsigned int ctr;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	for (ctr = 0; ctr < as->desc.bNumEndpoints; ctr++) {
15578c2ecf20Sopenharmony_ci		if ((as->endpoint[ctr].desc.bEndpointAddress &
15588c2ecf20Sopenharmony_ci		     USB_ENDPOINT_NUMBER_MASK) != 2)
15598c2ecf20Sopenharmony_ci			continue;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci		if (as->endpoint[ctr].desc.bEndpointAddress & USB_DIR_IN &&
15628c2ecf20Sopenharmony_ci		    ((as->endpoint[ctr].desc.bmAttributes &
15638c2ecf20Sopenharmony_ci		      USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC))
15648c2ecf20Sopenharmony_ci			return true;
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci		break;
15678c2ecf20Sopenharmony_ci	}
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	return false;
15708c2ecf20Sopenharmony_ci}
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_cistatic bool cxusb_medion_check_intf(struct usb_interface *intf)
15738c2ecf20Sopenharmony_ci{
15748c2ecf20Sopenharmony_ci	unsigned int ctr;
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	if (intf->num_altsetting < 2) {
15778c2ecf20Sopenharmony_ci		dev_err(intf->usb_dev, "no alternate interface");
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci		return false;
15808c2ecf20Sopenharmony_ci	}
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	for (ctr = 0; ctr < intf->num_altsetting; ctr++) {
15838c2ecf20Sopenharmony_ci		if (intf->altsetting[ctr].desc.bAlternateSetting != 1)
15848c2ecf20Sopenharmony_ci			continue;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci		if (cxusb_medion_check_altsetting(&intf->altsetting[ctr]))
15878c2ecf20Sopenharmony_ci			return true;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci		break;
15908c2ecf20Sopenharmony_ci	}
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	dev_err(intf->usb_dev, "no iso interface");
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	return false;
15958c2ecf20Sopenharmony_ci}
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_cistatic int cxusb_probe(struct usb_interface *intf,
15988c2ecf20Sopenharmony_ci		       const struct usb_device_id *id)
15998c2ecf20Sopenharmony_ci{
16008c2ecf20Sopenharmony_ci	struct dvb_usb_device *dvbdev;
16018c2ecf20Sopenharmony_ci	int ret;
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	/* Medion 95700 */
16048c2ecf20Sopenharmony_ci	if (!dvb_usb_device_init(intf, &cxusb_medion_properties,
16058c2ecf20Sopenharmony_ci				 THIS_MODULE, &dvbdev, adapter_nr)) {
16068c2ecf20Sopenharmony_ci		if (!cxusb_medion_check_intf(intf)) {
16078c2ecf20Sopenharmony_ci			ret = -ENODEV;
16088c2ecf20Sopenharmony_ci			goto ret_uninit;
16098c2ecf20Sopenharmony_ci		}
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci		_cxusb_power_ctrl(dvbdev, 1);
16128c2ecf20Sopenharmony_ci		ret = cxusb_medion_set_mode(dvbdev, false);
16138c2ecf20Sopenharmony_ci		if (ret)
16148c2ecf20Sopenharmony_ci			goto ret_uninit;
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci		ret = cxusb_medion_register_analog(dvbdev);
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci		cxusb_medion_set_mode(dvbdev, true);
16198c2ecf20Sopenharmony_ci		_cxusb_power_ctrl(dvbdev, 0);
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci		if (ret != 0)
16228c2ecf20Sopenharmony_ci			goto ret_uninit;
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci		/* release device from INIT mode to normal operation */
16258c2ecf20Sopenharmony_ci		cxusb_medion_put(dvbdev);
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci		return 0;
16288c2ecf20Sopenharmony_ci	} else if (!dvb_usb_device_init(intf,
16298c2ecf20Sopenharmony_ci					&cxusb_bluebird_lgh064f_properties,
16308c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16318c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16328c2ecf20Sopenharmony_ci					&cxusb_bluebird_dee1601_properties,
16338c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16348c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16358c2ecf20Sopenharmony_ci					&cxusb_bluebird_lgz201_properties,
16368c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16378c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16388c2ecf20Sopenharmony_ci					&cxusb_bluebird_dtt7579_properties,
16398c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16408c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16418c2ecf20Sopenharmony_ci					&cxusb_bluebird_dualdig4_properties,
16428c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16438c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16448c2ecf20Sopenharmony_ci					&cxusb_bluebird_nano2_properties,
16458c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16468c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16478c2ecf20Sopenharmony_ci					&cxusb_bluebird_nano2_needsfirmware_properties,
16488c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16498c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
16508c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16518c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf,
16528c2ecf20Sopenharmony_ci					&cxusb_bluebird_dualdig4_rev2_properties,
16538c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16548c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
16558c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16568c2ecf20Sopenharmony_ci		   !dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
16578c2ecf20Sopenharmony_ci					THIS_MODULE, NULL, adapter_nr) ||
16588c2ecf20Sopenharmony_ci		   0)
16598c2ecf20Sopenharmony_ci		return 0;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	return -EINVAL;
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ciret_uninit:
16648c2ecf20Sopenharmony_ci	dvb_usb_device_exit(intf);
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci	return ret;
16678c2ecf20Sopenharmony_ci}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_cistatic void cxusb_disconnect(struct usb_interface *intf)
16708c2ecf20Sopenharmony_ci{
16718c2ecf20Sopenharmony_ci	struct dvb_usb_device *d = usb_get_intfdata(intf);
16728c2ecf20Sopenharmony_ci	struct cxusb_state *st = d->priv;
16738c2ecf20Sopenharmony_ci	struct i2c_client *client;
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	if (d->props.devices[0].warm_ids[0] == &cxusb_table[MEDION_MD95700])
16768c2ecf20Sopenharmony_ci		cxusb_medion_unregister_analog(d);
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	/* remove I2C client for tuner */
16798c2ecf20Sopenharmony_ci	client = st->i2c_client_tuner;
16808c2ecf20Sopenharmony_ci	if (client) {
16818c2ecf20Sopenharmony_ci		module_put(client->dev.driver->owner);
16828c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
16838c2ecf20Sopenharmony_ci	}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	/* remove I2C client for demodulator */
16868c2ecf20Sopenharmony_ci	client = st->i2c_client_demod;
16878c2ecf20Sopenharmony_ci	if (client) {
16888c2ecf20Sopenharmony_ci		module_put(client->dev.driver->owner);
16898c2ecf20Sopenharmony_ci		i2c_unregister_device(client);
16908c2ecf20Sopenharmony_ci	}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	dvb_usb_device_exit(intf);
16938c2ecf20Sopenharmony_ci}
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_cistatic struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = {
16968c2ecf20Sopenharmony_ci	[MEDION_MD95700] = {
16978c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700)
16988c2ecf20Sopenharmony_ci	},
16998c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_LG064F_COLD] = {
17008c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD)
17018c2ecf20Sopenharmony_ci	},
17028c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_LG064F_WARM] = {
17038c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM)
17048c2ecf20Sopenharmony_ci	},
17058c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_1_COLD] = {
17068c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD)
17078c2ecf20Sopenharmony_ci	},
17088c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_1_WARM] = {
17098c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM)
17108c2ecf20Sopenharmony_ci	},
17118c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_LGZ201_COLD] = {
17128c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD)
17138c2ecf20Sopenharmony_ci	},
17148c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_LGZ201_WARM] = {
17158c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM)
17168c2ecf20Sopenharmony_ci	},
17178c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_TH7579_COLD] = {
17188c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD)
17198c2ecf20Sopenharmony_ci	},
17208c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_TH7579_WARM] = {
17218c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM)
17228c2ecf20Sopenharmony_ci	},
17238c2ecf20Sopenharmony_ci	[DIGITALNOW_BLUEBIRD_DUAL_1_COLD] = {
17248c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO,
17258c2ecf20Sopenharmony_ci			   USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD)
17268c2ecf20Sopenharmony_ci	},
17278c2ecf20Sopenharmony_ci	[DIGITALNOW_BLUEBIRD_DUAL_1_WARM] = {
17288c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO,
17298c2ecf20Sopenharmony_ci			   USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM)
17308c2ecf20Sopenharmony_ci	},
17318c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_2_COLD] = {
17328c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD)
17338c2ecf20Sopenharmony_ci	},
17348c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_2_WARM] = {
17358c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM)
17368c2ecf20Sopenharmony_ci	},
17378c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_4] = {
17388c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4)
17398c2ecf20Sopenharmony_ci	},
17408c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DVB_T_NANO_2] = {
17418c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2)
17428c2ecf20Sopenharmony_ci	},
17438c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM] = {
17448c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO,
17458c2ecf20Sopenharmony_ci			   USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM)
17468c2ecf20Sopenharmony_ci	},
17478c2ecf20Sopenharmony_ci	[AVERMEDIA_VOLAR_A868R] = {
17488c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R)
17498c2ecf20Sopenharmony_ci	},
17508c2ecf20Sopenharmony_ci	[DVICO_BLUEBIRD_DUAL_4_REV_2] = {
17518c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2)
17528c2ecf20Sopenharmony_ci	},
17538c2ecf20Sopenharmony_ci	[CONEXANT_D680_DMB] = {
17548c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB)
17558c2ecf20Sopenharmony_ci	},
17568c2ecf20Sopenharmony_ci	[MYGICA_D689] = {
17578c2ecf20Sopenharmony_ci		USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689)
17588c2ecf20Sopenharmony_ci	},
17598c2ecf20Sopenharmony_ci	{}		/* Terminating entry */
17608c2ecf20Sopenharmony_ci};
17618c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, cxusb_table);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_medion_properties = {
17648c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	.usb_ctrl = CYPRESS_FX2,
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_medion_dev),
17698c2ecf20Sopenharmony_ci	.priv_init        = cxusb_medion_priv_init,
17708c2ecf20Sopenharmony_ci	.priv_destroy     = cxusb_medion_priv_destroy,
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	.num_adapters = 1,
17738c2ecf20Sopenharmony_ci	.adapter = {
17748c2ecf20Sopenharmony_ci		{
17758c2ecf20Sopenharmony_ci		.num_frontends = 1,
17768c2ecf20Sopenharmony_ci		.fe = {{
17778c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
17788c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_cx22702_frontend_attach,
17798c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_fmd1216me_tuner_attach,
17808c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
17818c2ecf20Sopenharmony_ci					.stream = {
17828c2ecf20Sopenharmony_ci						.type = USB_BULK,
17838c2ecf20Sopenharmony_ci				.count = 5,
17848c2ecf20Sopenharmony_ci				.endpoint = 0x02,
17858c2ecf20Sopenharmony_ci				.u = {
17868c2ecf20Sopenharmony_ci					.bulk = {
17878c2ecf20Sopenharmony_ci						.buffersize = 8192,
17888c2ecf20Sopenharmony_ci					}
17898c2ecf20Sopenharmony_ci				}
17908c2ecf20Sopenharmony_ci			},
17918c2ecf20Sopenharmony_ci		} },
17928c2ecf20Sopenharmony_ci		},
17938c2ecf20Sopenharmony_ci	},
17948c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_power_ctrl,
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	.num_device_descs = 1,
18018c2ecf20Sopenharmony_ci	.devices = {
18028c2ecf20Sopenharmony_ci		{
18038c2ecf20Sopenharmony_ci			"Medion MD95700 (MDUSBTV-HYBRID)",
18048c2ecf20Sopenharmony_ci			{ NULL },
18058c2ecf20Sopenharmony_ci			{ &cxusb_table[MEDION_MD95700], NULL },
18068c2ecf20Sopenharmony_ci		},
18078c2ecf20Sopenharmony_ci	}
18088c2ecf20Sopenharmony_ci};
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
18118c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci	.usb_ctrl          = DEVICE_SPECIFIC,
18148c2ecf20Sopenharmony_ci	.firmware          = "dvb-usb-bluebird-01.fw",
18158c2ecf20Sopenharmony_ci	.download_firmware = bluebird_patch_dvico_firmware_download,
18168c2ecf20Sopenharmony_ci	/*
18178c2ecf20Sopenharmony_ci	 * use usb alt setting 0 for EP4 transfer (dvb-t),
18188c2ecf20Sopenharmony_ci	 * use usb alt setting 7 for EP2 transfer (atsc)
18198c2ecf20Sopenharmony_ci	 */
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	.num_adapters = 1,
18248c2ecf20Sopenharmony_ci	.adapter = {
18258c2ecf20Sopenharmony_ci		{
18268c2ecf20Sopenharmony_ci		.num_frontends = 1,
18278c2ecf20Sopenharmony_ci		.fe = {{
18288c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
18298c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_lgdt3303_frontend_attach,
18308c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_lgh064f_tuner_attach,
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
18338c2ecf20Sopenharmony_ci					.stream = {
18348c2ecf20Sopenharmony_ci						.type = USB_BULK,
18358c2ecf20Sopenharmony_ci				.count = 5,
18368c2ecf20Sopenharmony_ci				.endpoint = 0x02,
18378c2ecf20Sopenharmony_ci				.u = {
18388c2ecf20Sopenharmony_ci					.bulk = {
18398c2ecf20Sopenharmony_ci						.buffersize = 8192,
18408c2ecf20Sopenharmony_ci					}
18418c2ecf20Sopenharmony_ci				}
18428c2ecf20Sopenharmony_ci			},
18438c2ecf20Sopenharmony_ci		} },
18448c2ecf20Sopenharmony_ci		},
18458c2ecf20Sopenharmony_ci	},
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_bluebird_power_ctrl,
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	.rc.core = {
18528c2ecf20Sopenharmony_ci		.rc_interval	= 100,
18538c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_PORTABLE,
18548c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
18558c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
18568c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
18578c2ecf20Sopenharmony_ci	},
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	.num_device_descs = 1,
18628c2ecf20Sopenharmony_ci	.devices = {
18638c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV5 USB Gold",
18648c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_LG064F_COLD], NULL },
18658c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_LG064F_WARM], NULL },
18668c2ecf20Sopenharmony_ci		},
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci};
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
18718c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci	.usb_ctrl          = DEVICE_SPECIFIC,
18748c2ecf20Sopenharmony_ci	.firmware          = "dvb-usb-bluebird-01.fw",
18758c2ecf20Sopenharmony_ci	.download_firmware = bluebird_patch_dvico_firmware_download,
18768c2ecf20Sopenharmony_ci	/*
18778c2ecf20Sopenharmony_ci	 * use usb alt setting 0 for EP4 transfer (dvb-t),
18788c2ecf20Sopenharmony_ci	 * use usb alt setting 7 for EP2 transfer (atsc)
18798c2ecf20Sopenharmony_ci	 */
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	.num_adapters = 1,
18848c2ecf20Sopenharmony_ci	.adapter = {
18858c2ecf20Sopenharmony_ci		{
18868c2ecf20Sopenharmony_ci		.num_frontends = 1,
18878c2ecf20Sopenharmony_ci		.fe = {{
18888c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
18898c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_dee1601_frontend_attach,
18908c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_dee1601_tuner_attach,
18918c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
18928c2ecf20Sopenharmony_ci			.stream = {
18938c2ecf20Sopenharmony_ci				.type = USB_BULK,
18948c2ecf20Sopenharmony_ci				.count = 5,
18958c2ecf20Sopenharmony_ci				.endpoint = 0x04,
18968c2ecf20Sopenharmony_ci				.u = {
18978c2ecf20Sopenharmony_ci					.bulk = {
18988c2ecf20Sopenharmony_ci						.buffersize = 8192,
18998c2ecf20Sopenharmony_ci					}
19008c2ecf20Sopenharmony_ci				}
19018c2ecf20Sopenharmony_ci			},
19028c2ecf20Sopenharmony_ci		} },
19038c2ecf20Sopenharmony_ci		},
19048c2ecf20Sopenharmony_ci	},
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_bluebird_power_ctrl,
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ci	.rc.core = {
19118c2ecf20Sopenharmony_ci		.rc_interval	= 100,
19128c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_MCE,
19138c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
19148c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
19158c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
19168c2ecf20Sopenharmony_ci	},
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	.num_device_descs = 3,
19218c2ecf20Sopenharmony_ci	.devices = {
19228c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T Dual USB",
19238c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_1_COLD], NULL },
19248c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_1_WARM], NULL },
19258c2ecf20Sopenharmony_ci		},
19268c2ecf20Sopenharmony_ci		{   "DigitalNow DVB-T Dual USB",
19278c2ecf20Sopenharmony_ci			{ &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_COLD], NULL },
19288c2ecf20Sopenharmony_ci			{ &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_WARM], NULL },
19298c2ecf20Sopenharmony_ci		},
19308c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T Dual Digital 2",
19318c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_2_COLD], NULL },
19328c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_2_WARM], NULL },
19338c2ecf20Sopenharmony_ci		},
19348c2ecf20Sopenharmony_ci	}
19358c2ecf20Sopenharmony_ci};
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
19388c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	.usb_ctrl          = DEVICE_SPECIFIC,
19418c2ecf20Sopenharmony_ci	.firmware          = "dvb-usb-bluebird-01.fw",
19428c2ecf20Sopenharmony_ci	.download_firmware = bluebird_patch_dvico_firmware_download,
19438c2ecf20Sopenharmony_ci	/*
19448c2ecf20Sopenharmony_ci	 * use usb alt setting 0 for EP4 transfer (dvb-t),
19458c2ecf20Sopenharmony_ci	 * use usb alt setting 7 for EP2 transfer (atsc)
19468c2ecf20Sopenharmony_ci	 */
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	.num_adapters = 1,
19518c2ecf20Sopenharmony_ci	.adapter = {
19528c2ecf20Sopenharmony_ci		{
19538c2ecf20Sopenharmony_ci		.num_frontends = 1,
19548c2ecf20Sopenharmony_ci		.fe = {{
19558c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
19568c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_mt352_frontend_attach,
19578c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_lgz201_tuner_attach,
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
19608c2ecf20Sopenharmony_ci			.stream = {
19618c2ecf20Sopenharmony_ci				.type = USB_BULK,
19628c2ecf20Sopenharmony_ci				.count = 5,
19638c2ecf20Sopenharmony_ci				.endpoint = 0x04,
19648c2ecf20Sopenharmony_ci				.u = {
19658c2ecf20Sopenharmony_ci					.bulk = {
19668c2ecf20Sopenharmony_ci						.buffersize = 8192,
19678c2ecf20Sopenharmony_ci					}
19688c2ecf20Sopenharmony_ci				}
19698c2ecf20Sopenharmony_ci			},
19708c2ecf20Sopenharmony_ci		} },
19718c2ecf20Sopenharmony_ci		},
19728c2ecf20Sopenharmony_ci	},
19738c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_bluebird_power_ctrl,
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
19768c2ecf20Sopenharmony_ci
19778c2ecf20Sopenharmony_ci	.rc.core = {
19788c2ecf20Sopenharmony_ci		.rc_interval	= 100,
19798c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_PORTABLE,
19808c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
19818c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
19828c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
19838c2ecf20Sopenharmony_ci	},
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
19868c2ecf20Sopenharmony_ci	.num_device_descs = 1,
19878c2ecf20Sopenharmony_ci	.devices = {
19888c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T USB (LGZ201)",
19898c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_LGZ201_COLD], NULL },
19908c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_LGZ201_WARM], NULL },
19918c2ecf20Sopenharmony_ci		},
19928c2ecf20Sopenharmony_ci	}
19938c2ecf20Sopenharmony_ci};
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
19968c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	.usb_ctrl          = DEVICE_SPECIFIC,
19998c2ecf20Sopenharmony_ci	.firmware          = "dvb-usb-bluebird-01.fw",
20008c2ecf20Sopenharmony_ci	.download_firmware = bluebird_patch_dvico_firmware_download,
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	/*
20038c2ecf20Sopenharmony_ci	 * use usb alt setting 0 for EP4 transfer (dvb-t),
20048c2ecf20Sopenharmony_ci	 * use usb alt setting 7 for EP2 transfer (atsc)
20058c2ecf20Sopenharmony_ci	 */
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	.num_adapters = 1,
20108c2ecf20Sopenharmony_ci	.adapter = {
20118c2ecf20Sopenharmony_ci		{
20128c2ecf20Sopenharmony_ci		.num_frontends = 1,
20138c2ecf20Sopenharmony_ci		.fe = {{
20148c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
20158c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_mt352_frontend_attach,
20168c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_dtt7579_tuner_attach,
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
20198c2ecf20Sopenharmony_ci			.stream = {
20208c2ecf20Sopenharmony_ci				.type = USB_BULK,
20218c2ecf20Sopenharmony_ci				.count = 5,
20228c2ecf20Sopenharmony_ci				.endpoint = 0x04,
20238c2ecf20Sopenharmony_ci				.u = {
20248c2ecf20Sopenharmony_ci					.bulk = {
20258c2ecf20Sopenharmony_ci						.buffersize = 8192,
20268c2ecf20Sopenharmony_ci					}
20278c2ecf20Sopenharmony_ci				}
20288c2ecf20Sopenharmony_ci			},
20298c2ecf20Sopenharmony_ci		} },
20308c2ecf20Sopenharmony_ci		},
20318c2ecf20Sopenharmony_ci	},
20328c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_bluebird_power_ctrl,
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	.rc.core = {
20378c2ecf20Sopenharmony_ci		.rc_interval	= 100,
20388c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_PORTABLE,
20398c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
20408c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
20418c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
20428c2ecf20Sopenharmony_ci	},
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	.num_device_descs = 1,
20478c2ecf20Sopenharmony_ci	.devices = {
20488c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T USB (TH7579)",
20498c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_TH7579_COLD], NULL },
20508c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_TH7579_WARM], NULL },
20518c2ecf20Sopenharmony_ci		},
20528c2ecf20Sopenharmony_ci	}
20538c2ecf20Sopenharmony_ci};
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
20568c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	.num_adapters = 1,
20638c2ecf20Sopenharmony_ci	.adapter = {
20648c2ecf20Sopenharmony_ci		{
20658c2ecf20Sopenharmony_ci		.num_frontends = 1,
20668c2ecf20Sopenharmony_ci		.fe = {{
20678c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
20688c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_dualdig4_frontend_attach,
20698c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
20708c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
20718c2ecf20Sopenharmony_ci			.stream = {
20728c2ecf20Sopenharmony_ci				.type = USB_BULK,
20738c2ecf20Sopenharmony_ci				.count = 5,
20748c2ecf20Sopenharmony_ci				.endpoint = 0x02,
20758c2ecf20Sopenharmony_ci				.u = {
20768c2ecf20Sopenharmony_ci					.bulk = {
20778c2ecf20Sopenharmony_ci						.buffersize = 8192,
20788c2ecf20Sopenharmony_ci					}
20798c2ecf20Sopenharmony_ci				}
20808c2ecf20Sopenharmony_ci			},
20818c2ecf20Sopenharmony_ci		} },
20828c2ecf20Sopenharmony_ci		},
20838c2ecf20Sopenharmony_ci	},
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_power_ctrl,
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
20908c2ecf20Sopenharmony_ci
20918c2ecf20Sopenharmony_ci	.rc.core = {
20928c2ecf20Sopenharmony_ci		.rc_interval	= 100,
20938c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_MCE,
20948c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
20958c2ecf20Sopenharmony_ci		.rc_query	= cxusb_bluebird2_rc_query,
20968c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
20978c2ecf20Sopenharmony_ci	},
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	.num_device_descs = 1,
21008c2ecf20Sopenharmony_ci	.devices = {
21018c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T Dual Digital 4",
21028c2ecf20Sopenharmony_ci			{ NULL },
21038c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_4], NULL },
21048c2ecf20Sopenharmony_ci		},
21058c2ecf20Sopenharmony_ci	}
21068c2ecf20Sopenharmony_ci};
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
21098c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
21128c2ecf20Sopenharmony_ci	.identify_state   = bluebird_fx2_identify_state,
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	.num_adapters = 1,
21178c2ecf20Sopenharmony_ci	.adapter = {
21188c2ecf20Sopenharmony_ci		{
21198c2ecf20Sopenharmony_ci		.num_frontends = 1,
21208c2ecf20Sopenharmony_ci		.fe = {{
21218c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
21228c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_nano2_frontend_attach,
21238c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
21248c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
21258c2ecf20Sopenharmony_ci			.stream = {
21268c2ecf20Sopenharmony_ci				.type = USB_BULK,
21278c2ecf20Sopenharmony_ci				.count = 5,
21288c2ecf20Sopenharmony_ci				.endpoint = 0x02,
21298c2ecf20Sopenharmony_ci				.u = {
21308c2ecf20Sopenharmony_ci					.bulk = {
21318c2ecf20Sopenharmony_ci						.buffersize = 8192,
21328c2ecf20Sopenharmony_ci					}
21338c2ecf20Sopenharmony_ci				}
21348c2ecf20Sopenharmony_ci			},
21358c2ecf20Sopenharmony_ci		} },
21368c2ecf20Sopenharmony_ci		},
21378c2ecf20Sopenharmony_ci	},
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_nano2_power_ctrl,
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci	.rc.core = {
21468c2ecf20Sopenharmony_ci		.rc_interval	= 100,
21478c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_PORTABLE,
21488c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
21498c2ecf20Sopenharmony_ci		.rc_query       = cxusb_bluebird2_rc_query,
21508c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
21518c2ecf20Sopenharmony_ci	},
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci	.num_device_descs = 1,
21548c2ecf20Sopenharmony_ci	.devices = {
21558c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T NANO2",
21568c2ecf20Sopenharmony_ci			{ NULL },
21578c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL },
21588c2ecf20Sopenharmony_ci		},
21598c2ecf20Sopenharmony_ci	}
21608c2ecf20Sopenharmony_ci};
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties
21638c2ecf20Sopenharmony_cicxusb_bluebird_nano2_needsfirmware_properties = {
21648c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
21658c2ecf20Sopenharmony_ci
21668c2ecf20Sopenharmony_ci	.usb_ctrl          = DEVICE_SPECIFIC,
21678c2ecf20Sopenharmony_ci	.firmware          = "dvb-usb-bluebird-02.fw",
21688c2ecf20Sopenharmony_ci	.download_firmware = bluebird_patch_dvico_firmware_download,
21698c2ecf20Sopenharmony_ci	.identify_state    = bluebird_fx2_identify_state,
21708c2ecf20Sopenharmony_ci
21718c2ecf20Sopenharmony_ci	.size_of_priv      = sizeof(struct cxusb_state),
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci	.num_adapters = 1,
21748c2ecf20Sopenharmony_ci	.adapter = {
21758c2ecf20Sopenharmony_ci		{
21768c2ecf20Sopenharmony_ci		.num_frontends = 1,
21778c2ecf20Sopenharmony_ci		.fe = {{
21788c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_streaming_ctrl,
21798c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_nano2_frontend_attach,
21808c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
21818c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
21828c2ecf20Sopenharmony_ci			.stream = {
21838c2ecf20Sopenharmony_ci				.type = USB_BULK,
21848c2ecf20Sopenharmony_ci				.count = 5,
21858c2ecf20Sopenharmony_ci				.endpoint = 0x02,
21868c2ecf20Sopenharmony_ci				.u = {
21878c2ecf20Sopenharmony_ci					.bulk = {
21888c2ecf20Sopenharmony_ci						.buffersize = 8192,
21898c2ecf20Sopenharmony_ci					}
21908c2ecf20Sopenharmony_ci				}
21918c2ecf20Sopenharmony_ci			},
21928c2ecf20Sopenharmony_ci		} },
21938c2ecf20Sopenharmony_ci		},
21948c2ecf20Sopenharmony_ci	},
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_nano2_power_ctrl,
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_ci	.rc.core = {
22038c2ecf20Sopenharmony_ci		.rc_interval	= 100,
22048c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_PORTABLE,
22058c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
22068c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
22078c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
22088c2ecf20Sopenharmony_ci	},
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	.num_device_descs = 1,
22118c2ecf20Sopenharmony_ci	.devices = { {
22128c2ecf20Sopenharmony_ci			"DViCO FusionHDTV DVB-T NANO2 w/o firmware",
22138c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL },
22148c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM],
22158c2ecf20Sopenharmony_ci			  NULL },
22168c2ecf20Sopenharmony_ci		},
22178c2ecf20Sopenharmony_ci	}
22188c2ecf20Sopenharmony_ci};
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
22218c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
22248c2ecf20Sopenharmony_ci
22258c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	.num_adapters = 1,
22288c2ecf20Sopenharmony_ci	.adapter = {
22298c2ecf20Sopenharmony_ci		{
22308c2ecf20Sopenharmony_ci		.num_frontends = 1,
22318c2ecf20Sopenharmony_ci		.fe = {{
22328c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_aver_streaming_ctrl,
22338c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_aver_lgdt3303_frontend_attach,
22348c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_mxl5003s_tuner_attach,
22358c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
22368c2ecf20Sopenharmony_ci			.stream = {
22378c2ecf20Sopenharmony_ci				.type = USB_BULK,
22388c2ecf20Sopenharmony_ci				.count = 5,
22398c2ecf20Sopenharmony_ci				.endpoint = 0x04,
22408c2ecf20Sopenharmony_ci				.u = {
22418c2ecf20Sopenharmony_ci					.bulk = {
22428c2ecf20Sopenharmony_ci						.buffersize = 8192,
22438c2ecf20Sopenharmony_ci					}
22448c2ecf20Sopenharmony_ci				}
22458c2ecf20Sopenharmony_ci			},
22468c2ecf20Sopenharmony_ci		} },
22478c2ecf20Sopenharmony_ci		},
22488c2ecf20Sopenharmony_ci	},
22498c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_aver_power_ctrl,
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci	.num_device_descs = 1,
22568c2ecf20Sopenharmony_ci	.devices = {
22578c2ecf20Sopenharmony_ci		{   "AVerMedia AVerTVHD Volar (A868R)",
22588c2ecf20Sopenharmony_ci			{ NULL },
22598c2ecf20Sopenharmony_ci			{ &cxusb_table[AVERMEDIA_VOLAR_A868R], NULL },
22608c2ecf20Sopenharmony_ci		},
22618c2ecf20Sopenharmony_ci	}
22628c2ecf20Sopenharmony_ci};
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_cistatic
22658c2ecf20Sopenharmony_cistruct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
22668c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci	.num_adapters = 1,
22738c2ecf20Sopenharmony_ci	.adapter = {
22748c2ecf20Sopenharmony_ci		{
22758c2ecf20Sopenharmony_ci		.size_of_priv    = sizeof(struct dib0700_adapter_state),
22768c2ecf20Sopenharmony_ci		.num_frontends = 1,
22778c2ecf20Sopenharmony_ci		.fe = {{
22788c2ecf20Sopenharmony_ci			.streaming_ctrl  = cxusb_streaming_ctrl,
22798c2ecf20Sopenharmony_ci			.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
22808c2ecf20Sopenharmony_ci			.tuner_attach    = cxusb_dualdig4_rev2_tuner_attach,
22818c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
22828c2ecf20Sopenharmony_ci			.stream = {
22838c2ecf20Sopenharmony_ci				.type = USB_BULK,
22848c2ecf20Sopenharmony_ci				.count = 7,
22858c2ecf20Sopenharmony_ci				.endpoint = 0x02,
22868c2ecf20Sopenharmony_ci				.u = {
22878c2ecf20Sopenharmony_ci					.bulk = {
22888c2ecf20Sopenharmony_ci						.buffersize = 4096,
22898c2ecf20Sopenharmony_ci					}
22908c2ecf20Sopenharmony_ci				}
22918c2ecf20Sopenharmony_ci			},
22928c2ecf20Sopenharmony_ci		} },
22938c2ecf20Sopenharmony_ci		},
22948c2ecf20Sopenharmony_ci	},
22958c2ecf20Sopenharmony_ci
22968c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_bluebird_power_ctrl,
22978c2ecf20Sopenharmony_ci
22988c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci	.rc.core = {
23038c2ecf20Sopenharmony_ci		.rc_interval	= 100,
23048c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_DVICO_MCE,
23058c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
23068c2ecf20Sopenharmony_ci		.rc_query	= cxusb_rc_query,
23078c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_NEC,
23088c2ecf20Sopenharmony_ci	},
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	.num_device_descs = 1,
23118c2ecf20Sopenharmony_ci	.devices = {
23128c2ecf20Sopenharmony_ci		{   "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
23138c2ecf20Sopenharmony_ci			{ NULL },
23148c2ecf20Sopenharmony_ci			{ &cxusb_table[DVICO_BLUEBIRD_DUAL_4_REV_2], NULL },
23158c2ecf20Sopenharmony_ci		},
23168c2ecf20Sopenharmony_ci	}
23178c2ecf20Sopenharmony_ci};
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
23208c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
23258c2ecf20Sopenharmony_ci
23268c2ecf20Sopenharmony_ci	.num_adapters = 1,
23278c2ecf20Sopenharmony_ci	.adapter = {
23288c2ecf20Sopenharmony_ci		{
23298c2ecf20Sopenharmony_ci		.num_frontends = 1,
23308c2ecf20Sopenharmony_ci		.fe = {{
23318c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
23328c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_d680_dmb_frontend_attach,
23338c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_d680_dmb_tuner_attach,
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
23368c2ecf20Sopenharmony_ci			.stream = {
23378c2ecf20Sopenharmony_ci				.type = USB_BULK,
23388c2ecf20Sopenharmony_ci				.count = 5,
23398c2ecf20Sopenharmony_ci				.endpoint = 0x02,
23408c2ecf20Sopenharmony_ci				.u = {
23418c2ecf20Sopenharmony_ci					.bulk = {
23428c2ecf20Sopenharmony_ci						.buffersize = 8192,
23438c2ecf20Sopenharmony_ci					}
23448c2ecf20Sopenharmony_ci				}
23458c2ecf20Sopenharmony_ci			},
23468c2ecf20Sopenharmony_ci		} },
23478c2ecf20Sopenharmony_ci		},
23488c2ecf20Sopenharmony_ci	},
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_d680_dmb_power_ctrl,
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
23538c2ecf20Sopenharmony_ci
23548c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	.rc.core = {
23578c2ecf20Sopenharmony_ci		.rc_interval	= 100,
23588c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_TOTAL_MEDIA_IN_HAND_02,
23598c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
23608c2ecf20Sopenharmony_ci		.rc_query       = cxusb_d680_dmb_rc_query,
23618c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_UNKNOWN,
23628c2ecf20Sopenharmony_ci	},
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	.num_device_descs = 1,
23658c2ecf20Sopenharmony_ci	.devices = {
23668c2ecf20Sopenharmony_ci		{
23678c2ecf20Sopenharmony_ci			"Conexant DMB-TH Stick",
23688c2ecf20Sopenharmony_ci			{ NULL },
23698c2ecf20Sopenharmony_ci			{ &cxusb_table[CONEXANT_D680_DMB], NULL },
23708c2ecf20Sopenharmony_ci		},
23718c2ecf20Sopenharmony_ci	}
23728c2ecf20Sopenharmony_ci};
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
23758c2ecf20Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci	.usb_ctrl         = CYPRESS_FX2,
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	.size_of_priv     = sizeof(struct cxusb_state),
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci	.num_adapters = 1,
23828c2ecf20Sopenharmony_ci	.adapter = {
23838c2ecf20Sopenharmony_ci		{
23848c2ecf20Sopenharmony_ci		.num_frontends = 1,
23858c2ecf20Sopenharmony_ci		.fe = {{
23868c2ecf20Sopenharmony_ci			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
23878c2ecf20Sopenharmony_ci			.frontend_attach  = cxusb_mygica_d689_frontend_attach,
23888c2ecf20Sopenharmony_ci			.tuner_attach     = cxusb_mygica_d689_tuner_attach,
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
23918c2ecf20Sopenharmony_ci			.stream = {
23928c2ecf20Sopenharmony_ci				.type = USB_BULK,
23938c2ecf20Sopenharmony_ci				.count = 5,
23948c2ecf20Sopenharmony_ci				.endpoint = 0x02,
23958c2ecf20Sopenharmony_ci				.u = {
23968c2ecf20Sopenharmony_ci					.bulk = {
23978c2ecf20Sopenharmony_ci						.buffersize = 8192,
23988c2ecf20Sopenharmony_ci					}
23998c2ecf20Sopenharmony_ci				}
24008c2ecf20Sopenharmony_ci			},
24018c2ecf20Sopenharmony_ci		} },
24028c2ecf20Sopenharmony_ci		},
24038c2ecf20Sopenharmony_ci	},
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	.power_ctrl       = cxusb_d680_dmb_power_ctrl,
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci	.i2c_algo         = &cxusb_i2c_algo,
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci	.rc.core = {
24128c2ecf20Sopenharmony_ci		.rc_interval	= 100,
24138c2ecf20Sopenharmony_ci		.rc_codes	= RC_MAP_D680_DMB,
24148c2ecf20Sopenharmony_ci		.module_name	= KBUILD_MODNAME,
24158c2ecf20Sopenharmony_ci		.rc_query       = cxusb_d680_dmb_rc_query,
24168c2ecf20Sopenharmony_ci		.allowed_protos = RC_PROTO_BIT_UNKNOWN,
24178c2ecf20Sopenharmony_ci	},
24188c2ecf20Sopenharmony_ci
24198c2ecf20Sopenharmony_ci	.num_device_descs = 1,
24208c2ecf20Sopenharmony_ci	.devices = {
24218c2ecf20Sopenharmony_ci		{
24228c2ecf20Sopenharmony_ci			"Mygica D689 DMB-TH",
24238c2ecf20Sopenharmony_ci			{ NULL },
24248c2ecf20Sopenharmony_ci			{ &cxusb_table[MYGICA_D689], NULL },
24258c2ecf20Sopenharmony_ci		},
24268c2ecf20Sopenharmony_ci	}
24278c2ecf20Sopenharmony_ci};
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_cistatic struct usb_driver cxusb_driver = {
24308c2ecf20Sopenharmony_ci	.name		= "dvb_usb_cxusb",
24318c2ecf20Sopenharmony_ci	.probe		= cxusb_probe,
24328c2ecf20Sopenharmony_ci	.disconnect     = cxusb_disconnect,
24338c2ecf20Sopenharmony_ci	.id_table	= cxusb_table,
24348c2ecf20Sopenharmony_ci};
24358c2ecf20Sopenharmony_ci
24368c2ecf20Sopenharmony_cimodule_usb_driver(cxusb_driver);
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
24398c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
24408c2ecf20Sopenharmony_ciMODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
24418c2ecf20Sopenharmony_ciMODULE_AUTHOR("Maciej S. Szmigiero <mail@maciej.szmigiero.name>");
24428c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
24438c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
2444