162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* DVB USB compliant linux driver for Conexant USB reference design. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * The Conexant reference design I saw on their website was only for analogue 562306a36Sopenharmony_ci * capturing (using the cx25842). The box I took to write this driver (reverse 662306a36Sopenharmony_ci * engineered) is the one labeled Medion MD95700. In addition to the cx25842 762306a36Sopenharmony_ci * for analogue capturing it also has a cx22702 DVB-T demodulator on the main 862306a36Sopenharmony_ci * board. Besides it has a atiremote (X10) and a USB2.0 hub onboard. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Maybe it is a little bit premature to call this driver cxusb, but I assume 1162306a36Sopenharmony_ci * the USB protocol is identical or at least inherited from the reference 1262306a36Sopenharmony_ci * design, so it can be reused for the "analogue-only" device (if it will 1362306a36Sopenharmony_ci * appear at all). 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) 1762306a36Sopenharmony_ci * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) 1862306a36Sopenharmony_ci * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au) 1962306a36Sopenharmony_ci * Copyright (C) 2011, 2017 Maciej S. Szmigiero (mail@maciej.szmigiero.name) 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci#include <media/tuner.h> 2462306a36Sopenharmony_ci#include <linux/delay.h> 2562306a36Sopenharmony_ci#include <linux/device.h> 2662306a36Sopenharmony_ci#include <linux/kernel.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci#include <linux/string.h> 2962306a36Sopenharmony_ci#include <linux/vmalloc.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include "cxusb.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "cx22702.h" 3462306a36Sopenharmony_ci#include "lgdt330x.h" 3562306a36Sopenharmony_ci#include "mt352.h" 3662306a36Sopenharmony_ci#include "mt352_priv.h" 3762306a36Sopenharmony_ci#include "zl10353.h" 3862306a36Sopenharmony_ci#include "xc2028.h" 3962306a36Sopenharmony_ci#include "tuner-simple.h" 4062306a36Sopenharmony_ci#include "mxl5005s.h" 4162306a36Sopenharmony_ci#include "max2165.h" 4262306a36Sopenharmony_ci#include "dib7000p.h" 4362306a36Sopenharmony_ci#include "dib0070.h" 4462306a36Sopenharmony_ci#include "lgs8gxx.h" 4562306a36Sopenharmony_ci#include "atbm8830.h" 4662306a36Sopenharmony_ci#include "si2168.h" 4762306a36Sopenharmony_ci#include "si2157.h" 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* debug */ 5062306a36Sopenharmony_ciint dvb_usb_cxusb_debug; 5162306a36Sopenharmony_cimodule_param_named(debug, dvb_usb_cxusb_debug, int, 0644); 5262306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (see cxusb.h)." 5362306a36Sopenharmony_ci DVB_USB_DEBUG_STATUS); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cienum cxusb_table_index { 5862306a36Sopenharmony_ci MEDION_MD95700, 5962306a36Sopenharmony_ci DVICO_BLUEBIRD_LG064F_COLD, 6062306a36Sopenharmony_ci DVICO_BLUEBIRD_LG064F_WARM, 6162306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_1_COLD, 6262306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_1_WARM, 6362306a36Sopenharmony_ci DVICO_BLUEBIRD_LGZ201_COLD, 6462306a36Sopenharmony_ci DVICO_BLUEBIRD_LGZ201_WARM, 6562306a36Sopenharmony_ci DVICO_BLUEBIRD_TH7579_COLD, 6662306a36Sopenharmony_ci DVICO_BLUEBIRD_TH7579_WARM, 6762306a36Sopenharmony_ci DIGITALNOW_BLUEBIRD_DUAL_1_COLD, 6862306a36Sopenharmony_ci DIGITALNOW_BLUEBIRD_DUAL_1_WARM, 6962306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_2_COLD, 7062306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_2_WARM, 7162306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_4, 7262306a36Sopenharmony_ci DVICO_BLUEBIRD_DVB_T_NANO_2, 7362306a36Sopenharmony_ci DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM, 7462306a36Sopenharmony_ci AVERMEDIA_VOLAR_A868R, 7562306a36Sopenharmony_ci DVICO_BLUEBIRD_DUAL_4_REV_2, 7662306a36Sopenharmony_ci CONEXANT_D680_DMB, 7762306a36Sopenharmony_ci MYGICA_D689, 7862306a36Sopenharmony_ci NR__cxusb_table_index 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic struct usb_device_id cxusb_table[]; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciint cxusb_ctrl_msg(struct dvb_usb_device *d, 8462306a36Sopenharmony_ci u8 cmd, const u8 *wbuf, int wlen, u8 *rbuf, int rlen) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci struct cxusb_state *st = d->priv; 8762306a36Sopenharmony_ci int ret; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (1 + wlen > MAX_XFER_SIZE) { 9062306a36Sopenharmony_ci warn("i2c wr: len=%d is too big!\n", wlen); 9162306a36Sopenharmony_ci return -EOPNOTSUPP; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (rlen > MAX_XFER_SIZE) { 9562306a36Sopenharmony_ci warn("i2c rd: len=%d is too big!\n", rlen); 9662306a36Sopenharmony_ci return -EOPNOTSUPP; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci mutex_lock(&d->data_mutex); 10062306a36Sopenharmony_ci st->data[0] = cmd; 10162306a36Sopenharmony_ci memcpy(&st->data[1], wbuf, wlen); 10262306a36Sopenharmony_ci ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, st->data, rlen, 0); 10362306a36Sopenharmony_ci if (!ret && rbuf && rlen) 10462306a36Sopenharmony_ci memcpy(rbuf, st->data, rlen); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci mutex_unlock(&d->data_mutex); 10762306a36Sopenharmony_ci return ret; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* GPIO */ 11162306a36Sopenharmony_cistatic void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct cxusb_state *st = d->priv; 11462306a36Sopenharmony_ci u8 o[2], i; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (st->gpio_write_state[GPIO_TUNER] == onoff && 11762306a36Sopenharmony_ci !st->gpio_write_refresh[GPIO_TUNER]) 11862306a36Sopenharmony_ci return; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci o[0] = GPIO_TUNER; 12162306a36Sopenharmony_ci o[1] = onoff; 12262306a36Sopenharmony_ci cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (i != 0x01) 12562306a36Sopenharmony_ci dev_info(&d->udev->dev, "gpio_write failed.\n"); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci st->gpio_write_state[GPIO_TUNER] = onoff; 12862306a36Sopenharmony_ci st->gpio_write_refresh[GPIO_TUNER] = false; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask, 13262306a36Sopenharmony_ci u8 newval) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci u8 o[2], gpio_state; 13562306a36Sopenharmony_ci int rc; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci o[0] = 0xff & ~changemask; /* mask of bits to keep */ 13862306a36Sopenharmony_ci o[1] = newval & changemask; /* new values for bits */ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1); 14162306a36Sopenharmony_ci if (rc < 0 || (gpio_state & changemask) != (newval & changemask)) 14262306a36Sopenharmony_ci dev_info(&d->udev->dev, "bluebird_gpio_write failed.\n"); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return rc < 0 ? rc : gpio_state; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin); 15062306a36Sopenharmony_ci msleep(5); 15162306a36Sopenharmony_ci cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void cxusb_nano2_led(struct dvb_usb_device *d, int onoff) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, 16062306a36Sopenharmony_ci u8 addr, int onoff) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci u8 o[2] = {addr, onoff}; 16362306a36Sopenharmony_ci u8 i; 16462306a36Sopenharmony_ci int rc; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (rc < 0) 16962306a36Sopenharmony_ci return rc; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (i == 0x01) 17262306a36Sopenharmony_ci return 0; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci dev_info(&d->udev->dev, "gpio_write failed.\n"); 17562306a36Sopenharmony_ci return -EIO; 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* I2C */ 17962306a36Sopenharmony_cistatic int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], 18062306a36Sopenharmony_ci int num) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct dvb_usb_device *d = i2c_get_adapdata(adap); 18362306a36Sopenharmony_ci int ret; 18462306a36Sopenharmony_ci int i; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 18762306a36Sopenharmony_ci return -EAGAIN; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci for (i = 0; i < num; i++) { 19062306a36Sopenharmony_ci if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_MEDION) 19162306a36Sopenharmony_ci switch (msg[i].addr) { 19262306a36Sopenharmony_ci case 0x63: 19362306a36Sopenharmony_ci cxusb_gpio_tuner(d, 0); 19462306a36Sopenharmony_ci break; 19562306a36Sopenharmony_ci default: 19662306a36Sopenharmony_ci cxusb_gpio_tuner(d, 1); 19762306a36Sopenharmony_ci break; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if (msg[i].flags & I2C_M_RD) { 20162306a36Sopenharmony_ci /* read only */ 20262306a36Sopenharmony_ci u8 obuf[3], ibuf[MAX_XFER_SIZE]; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (1 + msg[i].len > sizeof(ibuf)) { 20562306a36Sopenharmony_ci warn("i2c rd: len=%d is too big!\n", 20662306a36Sopenharmony_ci msg[i].len); 20762306a36Sopenharmony_ci ret = -EOPNOTSUPP; 20862306a36Sopenharmony_ci goto unlock; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci obuf[0] = 0; 21162306a36Sopenharmony_ci obuf[1] = msg[i].len; 21262306a36Sopenharmony_ci obuf[2] = msg[i].addr; 21362306a36Sopenharmony_ci if (cxusb_ctrl_msg(d, CMD_I2C_READ, 21462306a36Sopenharmony_ci obuf, 3, 21562306a36Sopenharmony_ci ibuf, 1 + msg[i].len) < 0) { 21662306a36Sopenharmony_ci warn("i2c read failed"); 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci memcpy(msg[i].buf, &ibuf[1], msg[i].len); 22062306a36Sopenharmony_ci } else if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD) && 22162306a36Sopenharmony_ci msg[i].addr == msg[i + 1].addr) { 22262306a36Sopenharmony_ci /* write to then read from same address */ 22362306a36Sopenharmony_ci u8 obuf[MAX_XFER_SIZE], ibuf[MAX_XFER_SIZE]; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (3 + msg[i].len > sizeof(obuf)) { 22662306a36Sopenharmony_ci warn("i2c wr: len=%d is too big!\n", 22762306a36Sopenharmony_ci msg[i].len); 22862306a36Sopenharmony_ci ret = -EOPNOTSUPP; 22962306a36Sopenharmony_ci goto unlock; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci if (1 + msg[i + 1].len > sizeof(ibuf)) { 23262306a36Sopenharmony_ci warn("i2c rd: len=%d is too big!\n", 23362306a36Sopenharmony_ci msg[i + 1].len); 23462306a36Sopenharmony_ci ret = -EOPNOTSUPP; 23562306a36Sopenharmony_ci goto unlock; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci obuf[0] = msg[i].len; 23862306a36Sopenharmony_ci obuf[1] = msg[i + 1].len; 23962306a36Sopenharmony_ci obuf[2] = msg[i].addr; 24062306a36Sopenharmony_ci memcpy(&obuf[3], msg[i].buf, msg[i].len); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (cxusb_ctrl_msg(d, CMD_I2C_READ, 24362306a36Sopenharmony_ci obuf, 3 + msg[i].len, 24462306a36Sopenharmony_ci ibuf, 1 + msg[i + 1].len) < 0) 24562306a36Sopenharmony_ci break; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (ibuf[0] != 0x08) 24862306a36Sopenharmony_ci dev_info(&d->udev->dev, "i2c read may have failed\n"); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci memcpy(msg[i + 1].buf, &ibuf[1], msg[i + 1].len); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci i++; 25362306a36Sopenharmony_ci } else { 25462306a36Sopenharmony_ci /* write only */ 25562306a36Sopenharmony_ci u8 obuf[MAX_XFER_SIZE], ibuf; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (2 + msg[i].len > sizeof(obuf)) { 25862306a36Sopenharmony_ci warn("i2c wr: len=%d is too big!\n", 25962306a36Sopenharmony_ci msg[i].len); 26062306a36Sopenharmony_ci ret = -EOPNOTSUPP; 26162306a36Sopenharmony_ci goto unlock; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci obuf[0] = msg[i].addr; 26462306a36Sopenharmony_ci obuf[1] = msg[i].len; 26562306a36Sopenharmony_ci memcpy(&obuf[2], msg[i].buf, msg[i].len); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, 26862306a36Sopenharmony_ci 2 + msg[i].len, &ibuf, 1) < 0) 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci if (ibuf != 0x08) 27162306a36Sopenharmony_ci dev_info(&d->udev->dev, "i2c write may have failed\n"); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (i == num) 27662306a36Sopenharmony_ci ret = num; 27762306a36Sopenharmony_ci else 27862306a36Sopenharmony_ci ret = -EREMOTEIO; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ciunlock: 28162306a36Sopenharmony_ci mutex_unlock(&d->i2c_mutex); 28262306a36Sopenharmony_ci return ret; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic u32 cxusb_i2c_func(struct i2c_adapter *adapter) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic struct i2c_algorithm cxusb_i2c_algo = { 29162306a36Sopenharmony_ci .master_xfer = cxusb_i2c_xfer, 29262306a36Sopenharmony_ci .functionality = cxusb_i2c_func, 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int _cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci u8 b = 0; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci dev_info(&d->udev->dev, "setting power %s\n", onoff ? "ON" : "OFF"); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (onoff) 30262306a36Sopenharmony_ci return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); 30362306a36Sopenharmony_ci else 30462306a36Sopenharmony_ci return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci bool is_medion = d->props.devices[0].warm_ids[0] == &cxusb_table[MEDION_MD95700]; 31062306a36Sopenharmony_ci int ret; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (is_medion && !onoff) { 31362306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = d->priv; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci mutex_lock(&cxdev->open_lock); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if (cxdev->open_type == CXUSB_OPEN_ANALOG) { 31862306a36Sopenharmony_ci dev_info(&d->udev->dev, "preventing DVB core from setting power OFF while we are in analog mode\n"); 31962306a36Sopenharmony_ci ret = -EBUSY; 32062306a36Sopenharmony_ci goto ret_unlock; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci ret = _cxusb_power_ctrl(d, onoff); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ciret_unlock: 32762306a36Sopenharmony_ci if (is_medion && !onoff) { 32862306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = d->priv; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci mutex_unlock(&cxdev->open_lock); 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return ret; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci int ret; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!onoff) 34162306a36Sopenharmony_ci return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0); 34262306a36Sopenharmony_ci if (d->state == DVB_USB_STATE_INIT && 34362306a36Sopenharmony_ci usb_set_interface(d->udev, 0, 0) < 0) 34462306a36Sopenharmony_ci err("set interface failed"); 34562306a36Sopenharmony_ci do { 34662306a36Sopenharmony_ci /* Nothing */ 34762306a36Sopenharmony_ci } while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && 34862306a36Sopenharmony_ci !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) && 34962306a36Sopenharmony_ci !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (!ret) { 35262306a36Sopenharmony_ci /* 35362306a36Sopenharmony_ci * FIXME: We don't know why, but we need to configure the 35462306a36Sopenharmony_ci * lgdt3303 with the register settings below on resume 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci int i; 35762306a36Sopenharmony_ci u8 buf; 35862306a36Sopenharmony_ci static const u8 bufs[] = { 35962306a36Sopenharmony_ci 0x0e, 0x2, 0x00, 0x7f, 36062306a36Sopenharmony_ci 0x0e, 0x2, 0x02, 0xfe, 36162306a36Sopenharmony_ci 0x0e, 0x2, 0x02, 0x01, 36262306a36Sopenharmony_ci 0x0e, 0x2, 0x00, 0x03, 36362306a36Sopenharmony_ci 0x0e, 0x2, 0x0d, 0x40, 36462306a36Sopenharmony_ci 0x0e, 0x2, 0x0e, 0x87, 36562306a36Sopenharmony_ci 0x0e, 0x2, 0x0f, 0x8e, 36662306a36Sopenharmony_ci 0x0e, 0x2, 0x10, 0x01, 36762306a36Sopenharmony_ci 0x0e, 0x2, 0x14, 0xd7, 36862306a36Sopenharmony_ci 0x0e, 0x2, 0x47, 0x88, 36962306a36Sopenharmony_ci }; 37062306a36Sopenharmony_ci msleep(20); 37162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bufs); i += 4 / sizeof(u8)) { 37262306a36Sopenharmony_ci ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE, 37362306a36Sopenharmony_ci bufs + i, 4, &buf, 1); 37462306a36Sopenharmony_ci if (ret) 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci if (buf != 0x8) 37762306a36Sopenharmony_ci return -EREMOTEIO; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci return ret; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci u8 b = 0; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (onoff) 38862306a36Sopenharmony_ci return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); 38962306a36Sopenharmony_ci else 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci int rc = 0; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci rc = cxusb_power_ctrl(d, onoff); 39862306a36Sopenharmony_ci if (!onoff) 39962306a36Sopenharmony_ci cxusb_nano2_led(d, 0); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return rc; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci int ret; 40762306a36Sopenharmony_ci u8 b; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ret = cxusb_power_ctrl(d, onoff); 41062306a36Sopenharmony_ci if (!onoff) 41162306a36Sopenharmony_ci return ret; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci msleep(128); 41462306a36Sopenharmony_ci cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1); 41562306a36Sopenharmony_ci msleep(100); 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct dvb_usb_device *dvbdev = adap->dev; 42262306a36Sopenharmony_ci bool is_medion = dvbdev->props.devices[0].warm_ids[0] == 42362306a36Sopenharmony_ci &cxusb_table[MEDION_MD95700]; 42462306a36Sopenharmony_ci u8 buf[2] = { 0x03, 0x00 }; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (is_medion && onoff) { 42762306a36Sopenharmony_ci int ret; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci ret = cxusb_medion_get(dvbdev, CXUSB_OPEN_DIGITAL); 43062306a36Sopenharmony_ci if (ret != 0) 43162306a36Sopenharmony_ci return ret; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (onoff) 43562306a36Sopenharmony_ci cxusb_ctrl_msg(dvbdev, CMD_STREAMING_ON, buf, 2, NULL, 0); 43662306a36Sopenharmony_ci else 43762306a36Sopenharmony_ci cxusb_ctrl_msg(dvbdev, CMD_STREAMING_OFF, NULL, 0, NULL, 0); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (is_medion && !onoff) 44062306a36Sopenharmony_ci cxusb_medion_put(dvbdev); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return 0; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci if (onoff) 44862306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0); 44962306a36Sopenharmony_ci else 45062306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF, 45162306a36Sopenharmony_ci NULL, 0, NULL, 0); 45262306a36Sopenharmony_ci return 0; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci int ep = d->props.generic_bulk_ctrl_endpoint; 45862306a36Sopenharmony_ci const int timeout = 100; 45962306a36Sopenharmony_ci const int junk_len = 32; 46062306a36Sopenharmony_ci u8 *junk; 46162306a36Sopenharmony_ci int rd_count; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* Discard remaining data in video pipe */ 46462306a36Sopenharmony_ci junk = kmalloc(junk_len, GFP_KERNEL); 46562306a36Sopenharmony_ci if (!junk) 46662306a36Sopenharmony_ci return; 46762306a36Sopenharmony_ci while (1) { 46862306a36Sopenharmony_ci if (usb_bulk_msg(d->udev, 46962306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, ep), 47062306a36Sopenharmony_ci junk, junk_len, &rd_count, timeout) < 0) 47162306a36Sopenharmony_ci break; 47262306a36Sopenharmony_ci if (!rd_count) 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci kfree(junk); 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream; 48162306a36Sopenharmony_ci const int timeout = 100; 48262306a36Sopenharmony_ci const int junk_len = p->u.bulk.buffersize; 48362306a36Sopenharmony_ci u8 *junk; 48462306a36Sopenharmony_ci int rd_count; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* Discard remaining data in video pipe */ 48762306a36Sopenharmony_ci junk = kmalloc(junk_len, GFP_KERNEL); 48862306a36Sopenharmony_ci if (!junk) 48962306a36Sopenharmony_ci return; 49062306a36Sopenharmony_ci while (1) { 49162306a36Sopenharmony_ci if (usb_bulk_msg(d->udev, 49262306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, p->endpoint), 49362306a36Sopenharmony_ci junk, junk_len, &rd_count, timeout) < 0) 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci if (!rd_count) 49662306a36Sopenharmony_ci break; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci kfree(junk); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int cxusb_d680_dmb_streaming_ctrl(struct dvb_usb_adapter *adap, 50262306a36Sopenharmony_ci int onoff) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci if (onoff) { 50562306a36Sopenharmony_ci u8 buf[2] = { 0x03, 0x00 }; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci cxusb_d680_dmb_drain_video(adap->dev); 50862306a36Sopenharmony_ci return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, 50962306a36Sopenharmony_ci buf, sizeof(buf), NULL, 0); 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci int ret = cxusb_ctrl_msg(adap->dev, 51262306a36Sopenharmony_ci CMD_STREAMING_OFF, NULL, 0, NULL, 0); 51362306a36Sopenharmony_ci return ret; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic int cxusb_rc_query(struct dvb_usb_device *d) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci u8 ircode[4]; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0) 52262306a36Sopenharmony_ci return 0; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (ircode[2] || ircode[3]) 52562306a36Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_NEC, 52662306a36Sopenharmony_ci RC_SCANCODE_NEC(~ircode[2] & 0xff, ircode[3]), 0); 52762306a36Sopenharmony_ci return 0; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic int cxusb_bluebird2_rc_query(struct dvb_usb_device *d) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci u8 ircode[4]; 53362306a36Sopenharmony_ci struct i2c_msg msg = { 53462306a36Sopenharmony_ci .addr = 0x6b, 53562306a36Sopenharmony_ci .flags = I2C_M_RD, 53662306a36Sopenharmony_ci .buf = ircode, 53762306a36Sopenharmony_ci .len = 4 53862306a36Sopenharmony_ci }; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1) 54162306a36Sopenharmony_ci return 0; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (ircode[1] || ircode[2]) 54462306a36Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_NEC, 54562306a36Sopenharmony_ci RC_SCANCODE_NEC(~ircode[1] & 0xff, ircode[2]), 0); 54662306a36Sopenharmony_ci return 0; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci u8 ircode[2]; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) 55462306a36Sopenharmony_ci return 0; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (ircode[0] || ircode[1]) 55762306a36Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_UNKNOWN, 55862306a36Sopenharmony_ci RC_SCANCODE_RC5(ircode[0], ircode[1]), 0); 55962306a36Sopenharmony_ci return 0; 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic int cxusb_dee1601_demod_init(struct dvb_frontend *fe) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x28 }; 56562306a36Sopenharmony_ci static u8 reset[] = { RESET, 0x80 }; 56662306a36Sopenharmony_ci static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 56762306a36Sopenharmony_ci static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0x20 }; 56862306a36Sopenharmony_ci static u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; 56962306a36Sopenharmony_ci static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 57262306a36Sopenharmony_ci udelay(200); 57362306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 57462306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 57762306a36Sopenharmony_ci mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); 57862306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci return 0; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic int cxusb_mt352_demod_init(struct dvb_frontend *fe) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci /* used in both lgz201 and th7579 */ 58662306a36Sopenharmony_ci static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x29 }; 58762306a36Sopenharmony_ci static u8 reset[] = { RESET, 0x80 }; 58862306a36Sopenharmony_ci static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 58962306a36Sopenharmony_ci static u8 agc_cfg[] = { AGC_TARGET, 0x24, 0x20 }; 59062306a36Sopenharmony_ci static u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; 59162306a36Sopenharmony_ci static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 59462306a36Sopenharmony_ci udelay(200); 59562306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 59662306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 59962306a36Sopenharmony_ci mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); 60062306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 60162306a36Sopenharmony_ci return 0; 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic struct cx22702_config cxusb_cx22702_config = { 60562306a36Sopenharmony_ci .demod_address = 0x63, 60662306a36Sopenharmony_ci .output_mode = CX22702_PARALLEL_OUTPUT, 60762306a36Sopenharmony_ci}; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic struct lgdt330x_config cxusb_lgdt3303_config = { 61062306a36Sopenharmony_ci .demod_chip = LGDT3303, 61162306a36Sopenharmony_ci}; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic struct lgdt330x_config cxusb_aver_lgdt3303_config = { 61462306a36Sopenharmony_ci .demod_chip = LGDT3303, 61562306a36Sopenharmony_ci .clock_polarity_flip = 2, 61662306a36Sopenharmony_ci}; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic struct mt352_config cxusb_dee1601_config = { 61962306a36Sopenharmony_ci .demod_address = 0x0f, 62062306a36Sopenharmony_ci .demod_init = cxusb_dee1601_demod_init, 62162306a36Sopenharmony_ci}; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_dee1601_config = { 62462306a36Sopenharmony_ci .demod_address = 0x0f, 62562306a36Sopenharmony_ci .parallel_ts = 1, 62662306a36Sopenharmony_ci}; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic struct mt352_config cxusb_mt352_config = { 62962306a36Sopenharmony_ci /* used in both lgz201 and th7579 */ 63062306a36Sopenharmony_ci .demod_address = 0x0f, 63162306a36Sopenharmony_ci .demod_init = cxusb_mt352_demod_init, 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_xc3028_config = { 63562306a36Sopenharmony_ci .demod_address = 0x0f, 63662306a36Sopenharmony_ci .if2 = 45600, 63762306a36Sopenharmony_ci .no_tuner = 1, 63862306a36Sopenharmony_ci .parallel_ts = 1, 63962306a36Sopenharmony_ci}; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = { 64262306a36Sopenharmony_ci .demod_address = 0x0f, 64362306a36Sopenharmony_ci .if2 = 45600, 64462306a36Sopenharmony_ci .no_tuner = 1, 64562306a36Sopenharmony_ci .parallel_ts = 1, 64662306a36Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 64762306a36Sopenharmony_ci}; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic struct mt352_config cxusb_mt352_xc3028_config = { 65062306a36Sopenharmony_ci .demod_address = 0x0f, 65162306a36Sopenharmony_ci .if2 = 4560, 65262306a36Sopenharmony_ci .no_tuner = 1, 65362306a36Sopenharmony_ci .demod_init = cxusb_mt352_demod_init, 65462306a36Sopenharmony_ci}; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci/* FIXME: needs tweaking */ 65762306a36Sopenharmony_cistatic struct mxl5005s_config aver_a868r_tuner = { 65862306a36Sopenharmony_ci .i2c_address = 0x63, 65962306a36Sopenharmony_ci .if_freq = 6000000UL, 66062306a36Sopenharmony_ci .xtal_freq = CRYSTAL_FREQ_16000000HZ, 66162306a36Sopenharmony_ci .agc_mode = MXL_SINGLE_AGC, 66262306a36Sopenharmony_ci .tracking_filter = MXL_TF_C, 66362306a36Sopenharmony_ci .rssi_enable = MXL_RSSI_ENABLE, 66462306a36Sopenharmony_ci .cap_select = MXL_CAP_SEL_ENABLE, 66562306a36Sopenharmony_ci .div_out = MXL_DIV_OUT_4, 66662306a36Sopenharmony_ci .clock_out = MXL_CLOCK_OUT_DISABLE, 66762306a36Sopenharmony_ci .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, 66862306a36Sopenharmony_ci .top = MXL5005S_TOP_25P2, 66962306a36Sopenharmony_ci .mod_mode = MXL_DIGITAL_MODE, 67062306a36Sopenharmony_ci .if_mode = MXL_ZERO_IF, 67162306a36Sopenharmony_ci .AgcMasterByte = 0x00, 67262306a36Sopenharmony_ci}; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci/* FIXME: needs tweaking */ 67562306a36Sopenharmony_cistatic struct mxl5005s_config d680_dmb_tuner = { 67662306a36Sopenharmony_ci .i2c_address = 0x63, 67762306a36Sopenharmony_ci .if_freq = 36125000UL, 67862306a36Sopenharmony_ci .xtal_freq = CRYSTAL_FREQ_16000000HZ, 67962306a36Sopenharmony_ci .agc_mode = MXL_SINGLE_AGC, 68062306a36Sopenharmony_ci .tracking_filter = MXL_TF_C, 68162306a36Sopenharmony_ci .rssi_enable = MXL_RSSI_ENABLE, 68262306a36Sopenharmony_ci .cap_select = MXL_CAP_SEL_ENABLE, 68362306a36Sopenharmony_ci .div_out = MXL_DIV_OUT_4, 68462306a36Sopenharmony_ci .clock_out = MXL_CLOCK_OUT_DISABLE, 68562306a36Sopenharmony_ci .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, 68662306a36Sopenharmony_ci .top = MXL5005S_TOP_25P2, 68762306a36Sopenharmony_ci .mod_mode = MXL_DIGITAL_MODE, 68862306a36Sopenharmony_ci .if_mode = MXL_ZERO_IF, 68962306a36Sopenharmony_ci .AgcMasterByte = 0x00, 69062306a36Sopenharmony_ci}; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic struct max2165_config mygica_d689_max2165_cfg = { 69362306a36Sopenharmony_ci .i2c_address = 0x60, 69462306a36Sopenharmony_ci .osc_clk = 20 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci/* Callbacks for DVB USB */ 69862306a36Sopenharmony_cistatic int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci struct dvb_usb_device *dvbdev = adap->dev; 70162306a36Sopenharmony_ci bool is_medion = dvbdev->props.devices[0].warm_ids[0] == 70262306a36Sopenharmony_ci &cxusb_table[MEDION_MD95700]; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe, 70562306a36Sopenharmony_ci &dvbdev->i2c_adap, 0x61, 70662306a36Sopenharmony_ci TUNER_PHILIPS_FMD1216ME_MK3); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (is_medion && adap->fe_adap[0].fe) 70962306a36Sopenharmony_ci /* 71062306a36Sopenharmony_ci * make sure that DVB core won't put to sleep (reset, really) 71162306a36Sopenharmony_ci * tuner when we might be open in analog mode 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_ci adap->fe_adap[0].fe->ops.tuner_ops.sleep = NULL; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci return 0; 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_cistatic int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, 72162306a36Sopenharmony_ci NULL, DVB_PLL_THOMSON_DTT7579); 72262306a36Sopenharmony_ci return 0; 72362306a36Sopenharmony_ci} 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_cistatic int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) 72662306a36Sopenharmony_ci{ 72762306a36Sopenharmony_ci dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, 72862306a36Sopenharmony_ci NULL, DVB_PLL_LG_Z201); 72962306a36Sopenharmony_ci return 0; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, 73562306a36Sopenharmony_ci NULL, DVB_PLL_THOMSON_DTT7579); 73662306a36Sopenharmony_ci return 0; 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_cistatic int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe, 74262306a36Sopenharmony_ci &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic int dvico_bluebird_xc2028_callback(void *ptr, int component, 74762306a36Sopenharmony_ci int command, int arg) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci struct dvb_usb_adapter *adap = ptr; 75062306a36Sopenharmony_ci struct dvb_usb_device *d = adap->dev; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci switch (command) { 75362306a36Sopenharmony_ci case XC2028_TUNER_RESET: 75462306a36Sopenharmony_ci dev_info(&d->udev->dev, "XC2028_TUNER_RESET %d\n", arg); 75562306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(d, 0x01, 1); 75662306a36Sopenharmony_ci break; 75762306a36Sopenharmony_ci case XC2028_RESET_CLK: 75862306a36Sopenharmony_ci dev_info(&d->udev->dev, "XC2028_RESET_CLK %d\n", arg); 75962306a36Sopenharmony_ci break; 76062306a36Sopenharmony_ci case XC2028_I2C_FLUSH: 76162306a36Sopenharmony_ci break; 76262306a36Sopenharmony_ci default: 76362306a36Sopenharmony_ci dev_info(&d->udev->dev, "unknown command %d, arg %d\n", 76462306a36Sopenharmony_ci command, arg); 76562306a36Sopenharmony_ci return -EINVAL; 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci return 0; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct dvb_frontend *fe; 77462306a36Sopenharmony_ci struct xc2028_config cfg = { 77562306a36Sopenharmony_ci .i2c_adap = &adap->dev->i2c_adap, 77662306a36Sopenharmony_ci .i2c_addr = 0x61, 77762306a36Sopenharmony_ci }; 77862306a36Sopenharmony_ci static struct xc2028_ctrl ctl = { 77962306a36Sopenharmony_ci .fname = XC2028_DEFAULT_FIRMWARE, 78062306a36Sopenharmony_ci .max_len = 64, 78162306a36Sopenharmony_ci .demod = XC3028_FE_ZARLINK456, 78262306a36Sopenharmony_ci }; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci /* FIXME: generalize & move to common area */ 78562306a36Sopenharmony_ci adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg); 78862306a36Sopenharmony_ci if (!fe || !fe->ops.tuner_ops.set_config) 78962306a36Sopenharmony_ci return -EIO; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci fe->ops.tuner_ops.set_config(fe, &ctl); 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci return 0; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, 79962306a36Sopenharmony_ci &adap->dev->i2c_adap, &aver_a868r_tuner); 80062306a36Sopenharmony_ci return 0; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct dvb_frontend *fe; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, 80862306a36Sopenharmony_ci &adap->dev->i2c_adap, &d680_dmb_tuner); 80962306a36Sopenharmony_ci return (!fe) ? -EIO : 0; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci struct dvb_frontend *fe; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe, 81762306a36Sopenharmony_ci &adap->dev->i2c_adap, &mygica_d689_max2165_cfg); 81862306a36Sopenharmony_ci return (!fe) ? -EIO : 0; 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistatic int cxusb_medion_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci struct dvb_usb_adapter *adap = fe->dvb->priv; 82462306a36Sopenharmony_ci struct dvb_usb_device *dvbdev = adap->dev; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci if (acquire) 82762306a36Sopenharmony_ci return cxusb_medion_get(dvbdev, CXUSB_OPEN_DIGITAL); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci cxusb_medion_put(dvbdev); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic int cxusb_medion_set_mode(struct dvb_usb_device *dvbdev, bool digital) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci struct cxusb_state *st = dvbdev->priv; 83762306a36Sopenharmony_ci int ret; 83862306a36Sopenharmony_ci u8 b; 83962306a36Sopenharmony_ci unsigned int i; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci /* 84262306a36Sopenharmony_ci * switching mode while doing an I2C transaction often causes 84362306a36Sopenharmony_ci * the device to crash 84462306a36Sopenharmony_ci */ 84562306a36Sopenharmony_ci mutex_lock(&dvbdev->i2c_mutex); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (digital) { 84862306a36Sopenharmony_ci ret = usb_set_interface(dvbdev->udev, 0, 6); 84962306a36Sopenharmony_ci if (ret != 0) { 85062306a36Sopenharmony_ci dev_err(&dvbdev->udev->dev, 85162306a36Sopenharmony_ci "digital interface selection failed (%d)\n", 85262306a36Sopenharmony_ci ret); 85362306a36Sopenharmony_ci goto ret_unlock; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci } else { 85662306a36Sopenharmony_ci ret = usb_set_interface(dvbdev->udev, 0, 1); 85762306a36Sopenharmony_ci if (ret != 0) { 85862306a36Sopenharmony_ci dev_err(&dvbdev->udev->dev, 85962306a36Sopenharmony_ci "analog interface selection failed (%d)\n", 86062306a36Sopenharmony_ci ret); 86162306a36Sopenharmony_ci goto ret_unlock; 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* pipes need to be cleared after setting interface */ 86662306a36Sopenharmony_ci ret = usb_clear_halt(dvbdev->udev, usb_rcvbulkpipe(dvbdev->udev, 1)); 86762306a36Sopenharmony_ci if (ret != 0) 86862306a36Sopenharmony_ci dev_warn(&dvbdev->udev->dev, 86962306a36Sopenharmony_ci "clear halt on IN pipe failed (%d)\n", 87062306a36Sopenharmony_ci ret); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci ret = usb_clear_halt(dvbdev->udev, usb_sndbulkpipe(dvbdev->udev, 1)); 87362306a36Sopenharmony_ci if (ret != 0) 87462306a36Sopenharmony_ci dev_warn(&dvbdev->udev->dev, 87562306a36Sopenharmony_ci "clear halt on OUT pipe failed (%d)\n", 87662306a36Sopenharmony_ci ret); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci ret = cxusb_ctrl_msg(dvbdev, digital ? CMD_DIGITAL : CMD_ANALOG, 87962306a36Sopenharmony_ci NULL, 0, &b, 1); 88062306a36Sopenharmony_ci if (ret != 0) { 88162306a36Sopenharmony_ci dev_err(&dvbdev->udev->dev, "mode switch failed (%d)\n", 88262306a36Sopenharmony_ci ret); 88362306a36Sopenharmony_ci goto ret_unlock; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci /* mode switch seems to reset GPIO states */ 88762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(st->gpio_write_refresh); i++) 88862306a36Sopenharmony_ci st->gpio_write_refresh[i] = true; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ciret_unlock: 89162306a36Sopenharmony_ci mutex_unlock(&dvbdev->i2c_mutex); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci return ret; 89462306a36Sopenharmony_ci} 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_cistatic int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct dvb_usb_device *dvbdev = adap->dev; 89962306a36Sopenharmony_ci bool is_medion = dvbdev->props.devices[0].warm_ids[0] == 90062306a36Sopenharmony_ci &cxusb_table[MEDION_MD95700]; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (is_medion) { 90362306a36Sopenharmony_ci int ret; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci ret = cxusb_medion_set_mode(dvbdev, true); 90662306a36Sopenharmony_ci if (ret) 90762306a36Sopenharmony_ci return ret; 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, 91162306a36Sopenharmony_ci &dvbdev->i2c_adap); 91262306a36Sopenharmony_ci if (!adap->fe_adap[0].fe) 91362306a36Sopenharmony_ci return -EIO; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci if (is_medion) 91662306a36Sopenharmony_ci adap->fe_adap[0].fe->ops.ts_bus_ctrl = 91762306a36Sopenharmony_ci cxusb_medion_fe_ts_bus_ctrl; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci return 0; 92062306a36Sopenharmony_ci} 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_cistatic int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 7) < 0) 92562306a36Sopenharmony_ci err("set interface failed"); 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, 93062306a36Sopenharmony_ci &cxusb_lgdt3303_config, 93162306a36Sopenharmony_ci 0x0e, 93262306a36Sopenharmony_ci &adap->dev->i2c_adap); 93362306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 93462306a36Sopenharmony_ci return 0; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci return -EIO; 93762306a36Sopenharmony_ci} 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_cistatic int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, 94262306a36Sopenharmony_ci &cxusb_aver_lgdt3303_config, 94362306a36Sopenharmony_ci 0x0e, 94462306a36Sopenharmony_ci &adap->dev->i2c_adap); 94562306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 94662306a36Sopenharmony_ci return 0; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return -EIO; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci /* used in both lgz201 and th7579 */ 95462306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 0) < 0) 95562306a36Sopenharmony_ci err("set interface failed"); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config, 96062306a36Sopenharmony_ci &adap->dev->i2c_adap); 96162306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 96262306a36Sopenharmony_ci return 0; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci return -EIO; 96562306a36Sopenharmony_ci} 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_cistatic int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) 96862306a36Sopenharmony_ci{ 96962306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 0) < 0) 97062306a36Sopenharmony_ci err("set interface failed"); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, 97562306a36Sopenharmony_ci &adap->dev->i2c_adap); 97662306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 97762306a36Sopenharmony_ci return 0; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(zl10353_attach, 98062306a36Sopenharmony_ci &cxusb_zl10353_dee1601_config, 98162306a36Sopenharmony_ci &adap->dev->i2c_adap); 98262306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 98362306a36Sopenharmony_ci return 0; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci return -EIO; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_cistatic int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci u8 ircode[4]; 99162306a36Sopenharmony_ci int i; 99262306a36Sopenharmony_ci struct i2c_msg msg = { 99362306a36Sopenharmony_ci .addr = 0x6b, 99462306a36Sopenharmony_ci .flags = I2C_M_RD, 99562306a36Sopenharmony_ci .buf = ircode, 99662306a36Sopenharmony_ci .len = 4 99762306a36Sopenharmony_ci }; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 1) < 0) 100062306a36Sopenharmony_ci err("set interface failed"); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* reset the tuner and demodulator */ 100562306a36Sopenharmony_ci cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0); 100662306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1); 100762306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci adap->fe_adap[0].fe = 101062306a36Sopenharmony_ci dvb_attach(zl10353_attach, 101162306a36Sopenharmony_ci &cxusb_zl10353_xc3028_config_no_i2c_gate, 101262306a36Sopenharmony_ci &adap->dev->i2c_adap); 101362306a36Sopenharmony_ci if (!adap->fe_adap[0].fe) 101462306a36Sopenharmony_ci return -EIO; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci /* try to determine if there is no IR decoder on the I2C bus */ 101762306a36Sopenharmony_ci for (i = 0; adap->dev->props.rc.core.rc_codes && i < 5; i++) { 101862306a36Sopenharmony_ci msleep(20); 101962306a36Sopenharmony_ci if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1) 102062306a36Sopenharmony_ci goto no_IR; 102162306a36Sopenharmony_ci if (ircode[0] == 0 && ircode[1] == 0) 102262306a36Sopenharmony_ci continue; 102362306a36Sopenharmony_ci if (ircode[2] + ircode[3] != 0xff) { 102462306a36Sopenharmony_cino_IR: 102562306a36Sopenharmony_ci adap->dev->props.rc.core.rc_codes = NULL; 102662306a36Sopenharmony_ci info("No IR receiver detected on this device."); 102762306a36Sopenharmony_ci break; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci } 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci return 0; 103262306a36Sopenharmony_ci} 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cistatic struct dibx000_agc_config dib7070_agc_config = { 103562306a36Sopenharmony_ci .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* 103862306a36Sopenharmony_ci * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, 103962306a36Sopenharmony_ci * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, 104062306a36Sopenharmony_ci * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 104162306a36Sopenharmony_ci */ 104262306a36Sopenharmony_ci .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | 104362306a36Sopenharmony_ci (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), 104462306a36Sopenharmony_ci .inv_gain = 600, 104562306a36Sopenharmony_ci .time_stabiliz = 10, 104662306a36Sopenharmony_ci .alpha_level = 0, 104762306a36Sopenharmony_ci .thlock = 118, 104862306a36Sopenharmony_ci .wbd_inv = 0, 104962306a36Sopenharmony_ci .wbd_ref = 3530, 105062306a36Sopenharmony_ci .wbd_sel = 1, 105162306a36Sopenharmony_ci .wbd_alpha = 5, 105262306a36Sopenharmony_ci .agc1_max = 65535, 105362306a36Sopenharmony_ci .agc1_min = 0, 105462306a36Sopenharmony_ci .agc2_max = 65535, 105562306a36Sopenharmony_ci .agc2_min = 0, 105662306a36Sopenharmony_ci .agc1_pt1 = 0, 105762306a36Sopenharmony_ci .agc1_pt2 = 40, 105862306a36Sopenharmony_ci .agc1_pt3 = 183, 105962306a36Sopenharmony_ci .agc1_slope1 = 206, 106062306a36Sopenharmony_ci .agc1_slope2 = 255, 106162306a36Sopenharmony_ci .agc2_pt1 = 72, 106262306a36Sopenharmony_ci .agc2_pt2 = 152, 106362306a36Sopenharmony_ci .agc2_slope1 = 88, 106462306a36Sopenharmony_ci .agc2_slope2 = 90, 106562306a36Sopenharmony_ci .alpha_mant = 17, 106662306a36Sopenharmony_ci .alpha_exp = 27, 106762306a36Sopenharmony_ci .beta_mant = 23, 106862306a36Sopenharmony_ci .beta_exp = 51, 106962306a36Sopenharmony_ci .perform_agc_softsplit = 0, 107062306a36Sopenharmony_ci}; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { 107362306a36Sopenharmony_ci .internal = 60000, 107462306a36Sopenharmony_ci .sampling = 15000, 107562306a36Sopenharmony_ci .pll_prediv = 1, 107662306a36Sopenharmony_ci .pll_ratio = 20, 107762306a36Sopenharmony_ci .pll_range = 3, 107862306a36Sopenharmony_ci .pll_reset = 1, 107962306a36Sopenharmony_ci .pll_bypass = 0, 108062306a36Sopenharmony_ci .enable_refdiv = 0, 108162306a36Sopenharmony_ci .bypclk_div = 0, 108262306a36Sopenharmony_ci .IO_CLK_en_core = 1, 108362306a36Sopenharmony_ci .ADClkSrc = 1, 108462306a36Sopenharmony_ci .modulo = 2, 108562306a36Sopenharmony_ci /* refsel, sel, freq_15k */ 108662306a36Sopenharmony_ci .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0), 108762306a36Sopenharmony_ci .ifreq = (0 << 25) | 0, 108862306a36Sopenharmony_ci .timf = 20452225, 108962306a36Sopenharmony_ci .xtal_hz = 12000000, 109062306a36Sopenharmony_ci}; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_cistatic struct dib7000p_config cxusb_dualdig4_rev2_config = { 109362306a36Sopenharmony_ci .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, 109462306a36Sopenharmony_ci .output_mpeg2_in_188_bytes = 1, 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci .agc_config_count = 1, 109762306a36Sopenharmony_ci .agc = &dib7070_agc_config, 109862306a36Sopenharmony_ci .bw = &dib7070_bw_config_12_mhz, 109962306a36Sopenharmony_ci .tuner_is_baseband = 1, 110062306a36Sopenharmony_ci .spur_protect = 1, 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci .gpio_dir = 0xfcef, 110362306a36Sopenharmony_ci .gpio_val = 0x0110, 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci .hostbus_diversity = 1, 110862306a36Sopenharmony_ci}; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_cistruct dib0700_adapter_state { 111162306a36Sopenharmony_ci int (*set_param_save)(struct dvb_frontend *fe); 111262306a36Sopenharmony_ci struct dib7000p_ops dib7000p_ops; 111362306a36Sopenharmony_ci}; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_cistatic int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) 111662306a36Sopenharmony_ci{ 111762306a36Sopenharmony_ci struct dib0700_adapter_state *state = adap->priv; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 1) < 0) 112062306a36Sopenharmony_ci err("set interface failed"); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) 112762306a36Sopenharmony_ci return -ENODEV; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 113062306a36Sopenharmony_ci &cxusb_dualdig4_rev2_config) < 0) { 113162306a36Sopenharmony_ci pr_warn("Unable to enumerate dib7000p\n"); 113262306a36Sopenharmony_ci return -ENODEV; 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 113662306a36Sopenharmony_ci 0x80, 113762306a36Sopenharmony_ci &cxusb_dualdig4_rev2_config); 113862306a36Sopenharmony_ci if (!adap->fe_adap[0].fe) 113962306a36Sopenharmony_ci return -EIO; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return 0; 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_cistatic int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) 114562306a36Sopenharmony_ci{ 114662306a36Sopenharmony_ci struct dvb_usb_adapter *adap = fe->dvb->priv; 114762306a36Sopenharmony_ci struct dib0700_adapter_state *state = adap->priv; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff); 115062306a36Sopenharmony_ci} 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_cistatic int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) 115362306a36Sopenharmony_ci{ 115462306a36Sopenharmony_ci return 0; 115562306a36Sopenharmony_ci} 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_cistatic struct dib0070_config dib7070p_dib0070_config = { 115862306a36Sopenharmony_ci .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, 115962306a36Sopenharmony_ci .reset = dib7070_tuner_reset, 116062306a36Sopenharmony_ci .sleep = dib7070_tuner_sleep, 116162306a36Sopenharmony_ci .clock_khz = 12000, 116262306a36Sopenharmony_ci}; 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_cistatic int dib7070_set_param_override(struct dvb_frontend *fe) 116562306a36Sopenharmony_ci{ 116662306a36Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 116762306a36Sopenharmony_ci struct dvb_usb_adapter *adap = fe->dvb->priv; 116862306a36Sopenharmony_ci struct dib0700_adapter_state *state = adap->priv; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci u16 offset; 117162306a36Sopenharmony_ci u8 band = BAND_OF_FREQUENCY(p->frequency / 1000); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci switch (band) { 117462306a36Sopenharmony_ci case BAND_VHF: 117562306a36Sopenharmony_ci offset = 950; 117662306a36Sopenharmony_ci break; 117762306a36Sopenharmony_ci default: 117862306a36Sopenharmony_ci case BAND_UHF: 117962306a36Sopenharmony_ci offset = 550; 118062306a36Sopenharmony_ci break; 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci return state->set_param_save(fe); 118662306a36Sopenharmony_ci} 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_cistatic int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) 118962306a36Sopenharmony_ci{ 119062306a36Sopenharmony_ci struct dib0700_adapter_state *st = adap->priv; 119162306a36Sopenharmony_ci struct i2c_adapter *tun_i2c; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci /* 119462306a36Sopenharmony_ci * No need to call dvb7000p_attach here, as it was called 119562306a36Sopenharmony_ci * already, as frontend_attach method is called first, and 119662306a36Sopenharmony_ci * tuner_attach is only called on success. 119762306a36Sopenharmony_ci */ 119862306a36Sopenharmony_ci tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, 119962306a36Sopenharmony_ci DIBX000_I2C_INTERFACE_TUNER, 1); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, 120262306a36Sopenharmony_ci &dib7070p_dib0070_config) == NULL) 120362306a36Sopenharmony_ci return -ENODEV; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; 120662306a36Sopenharmony_ci adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override; 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_cistatic int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) 121162306a36Sopenharmony_ci{ 121262306a36Sopenharmony_ci if (usb_set_interface(adap->dev->udev, 0, 1) < 0) 121362306a36Sopenharmony_ci err("set interface failed"); 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* reset the tuner and demodulator */ 121862306a36Sopenharmony_ci cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0); 121962306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1); 122062306a36Sopenharmony_ci cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(zl10353_attach, 122362306a36Sopenharmony_ci &cxusb_zl10353_xc3028_config, 122462306a36Sopenharmony_ci &adap->dev->i2c_adap); 122562306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 122662306a36Sopenharmony_ci return 0; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(mt352_attach, 122962306a36Sopenharmony_ci &cxusb_mt352_xc3028_config, 123062306a36Sopenharmony_ci &adap->dev->i2c_adap); 123162306a36Sopenharmony_ci if (adap->fe_adap[0].fe) 123262306a36Sopenharmony_ci return 0; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci return -EIO; 123562306a36Sopenharmony_ci} 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_cistatic struct lgs8gxx_config d680_lgs8gl5_cfg = { 123862306a36Sopenharmony_ci .prod = LGS8GXX_PROD_LGS8GL5, 123962306a36Sopenharmony_ci .demod_address = 0x19, 124062306a36Sopenharmony_ci .serial_ts = 0, 124162306a36Sopenharmony_ci .ts_clk_pol = 0, 124262306a36Sopenharmony_ci .ts_clk_gated = 1, 124362306a36Sopenharmony_ci .if_clk_freq = 30400, /* 30.4 MHz */ 124462306a36Sopenharmony_ci .if_freq = 5725, /* 5.725 MHz */ 124562306a36Sopenharmony_ci .if_neg_center = 0, 124662306a36Sopenharmony_ci .ext_adc = 0, 124762306a36Sopenharmony_ci .adc_signed = 0, 124862306a36Sopenharmony_ci .if_neg_edge = 0, 124962306a36Sopenharmony_ci}; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_cistatic int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) 125262306a36Sopenharmony_ci{ 125362306a36Sopenharmony_ci struct dvb_usb_device *d = adap->dev; 125462306a36Sopenharmony_ci int n; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci /* Select required USB configuration */ 125762306a36Sopenharmony_ci if (usb_set_interface(d->udev, 0, 0) < 0) 125862306a36Sopenharmony_ci err("set interface failed"); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci /* Unblock all USB pipes */ 126162306a36Sopenharmony_ci usb_clear_halt(d->udev, 126262306a36Sopenharmony_ci usb_sndbulkpipe(d->udev, 126362306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint)); 126462306a36Sopenharmony_ci usb_clear_halt(d->udev, 126562306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, 126662306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint)); 126762306a36Sopenharmony_ci usb_clear_halt(d->udev, 126862306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, 126962306a36Sopenharmony_ci d->props.adapter[0].fe[0].stream.endpoint)); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* Drain USB pipes to avoid hang after reboot */ 127262306a36Sopenharmony_ci for (n = 0; n < 5; n++) { 127362306a36Sopenharmony_ci cxusb_d680_dmb_drain_message(d); 127462306a36Sopenharmony_ci cxusb_d680_dmb_drain_video(d); 127562306a36Sopenharmony_ci msleep(200); 127662306a36Sopenharmony_ci } 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci /* Reset the tuner */ 127962306a36Sopenharmony_ci if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { 128062306a36Sopenharmony_ci err("clear tuner gpio failed"); 128162306a36Sopenharmony_ci return -EIO; 128262306a36Sopenharmony_ci } 128362306a36Sopenharmony_ci msleep(100); 128462306a36Sopenharmony_ci if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { 128562306a36Sopenharmony_ci err("set tuner gpio failed"); 128662306a36Sopenharmony_ci return -EIO; 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci msleep(100); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci /* Attach frontend */ 129162306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, 129262306a36Sopenharmony_ci &d680_lgs8gl5_cfg, &d->i2c_adap); 129362306a36Sopenharmony_ci if (!adap->fe_adap[0].fe) 129462306a36Sopenharmony_ci return -EIO; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci return 0; 129762306a36Sopenharmony_ci} 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_cistatic struct atbm8830_config mygica_d689_atbm8830_cfg = { 130062306a36Sopenharmony_ci .prod = ATBM8830_PROD_8830, 130162306a36Sopenharmony_ci .demod_address = 0x40, 130262306a36Sopenharmony_ci .serial_ts = 0, 130362306a36Sopenharmony_ci .ts_sampling_edge = 1, 130462306a36Sopenharmony_ci .ts_clk_gated = 0, 130562306a36Sopenharmony_ci .osc_clk_freq = 30400, /* in kHz */ 130662306a36Sopenharmony_ci .if_freq = 0, /* zero IF */ 130762306a36Sopenharmony_ci .zif_swap_iq = 1, 130862306a36Sopenharmony_ci .agc_min = 0x2E, 130962306a36Sopenharmony_ci .agc_max = 0x90, 131062306a36Sopenharmony_ci .agc_hold_loop = 0, 131162306a36Sopenharmony_ci}; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_cistatic int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) 131462306a36Sopenharmony_ci{ 131562306a36Sopenharmony_ci struct dvb_usb_device *d = adap->dev; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* Select required USB configuration */ 131862306a36Sopenharmony_ci if (usb_set_interface(d->udev, 0, 0) < 0) 131962306a36Sopenharmony_ci err("set interface failed"); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci /* Unblock all USB pipes */ 132262306a36Sopenharmony_ci usb_clear_halt(d->udev, 132362306a36Sopenharmony_ci usb_sndbulkpipe(d->udev, 132462306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint)); 132562306a36Sopenharmony_ci usb_clear_halt(d->udev, 132662306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, 132762306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint)); 132862306a36Sopenharmony_ci usb_clear_halt(d->udev, 132962306a36Sopenharmony_ci usb_rcvbulkpipe(d->udev, 133062306a36Sopenharmony_ci d->props.adapter[0].fe[0].stream.endpoint)); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci /* Reset the tuner */ 133362306a36Sopenharmony_ci if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { 133462306a36Sopenharmony_ci err("clear tuner gpio failed"); 133562306a36Sopenharmony_ci return -EIO; 133662306a36Sopenharmony_ci } 133762306a36Sopenharmony_ci msleep(100); 133862306a36Sopenharmony_ci if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { 133962306a36Sopenharmony_ci err("set tuner gpio failed"); 134062306a36Sopenharmony_ci return -EIO; 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci msleep(100); 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci /* Attach frontend */ 134562306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, 134662306a36Sopenharmony_ci &mygica_d689_atbm8830_cfg, 134762306a36Sopenharmony_ci &d->i2c_adap); 134862306a36Sopenharmony_ci if (!adap->fe_adap[0].fe) 134962306a36Sopenharmony_ci return -EIO; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci return 0; 135262306a36Sopenharmony_ci} 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci/* 135562306a36Sopenharmony_ci * DViCO has shipped two devices with the same USB ID, but only one of them 135662306a36Sopenharmony_ci * needs a firmware download. Check the device class details to see if they 135762306a36Sopenharmony_ci * have non-default values to decide whether the device is actually cold or 135862306a36Sopenharmony_ci * not, and forget a match if it turns out we selected the wrong device. 135962306a36Sopenharmony_ci */ 136062306a36Sopenharmony_cistatic int bluebird_fx2_identify_state(struct usb_device *udev, 136162306a36Sopenharmony_ci const struct dvb_usb_device_properties *props, 136262306a36Sopenharmony_ci const struct dvb_usb_device_description **desc, 136362306a36Sopenharmony_ci int *cold) 136462306a36Sopenharmony_ci{ 136562306a36Sopenharmony_ci int wascold = *cold; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci *cold = udev->descriptor.bDeviceClass == 0xff && 136862306a36Sopenharmony_ci udev->descriptor.bDeviceSubClass == 0xff && 136962306a36Sopenharmony_ci udev->descriptor.bDeviceProtocol == 0xff; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci if (*cold && !wascold) 137262306a36Sopenharmony_ci *desc = NULL; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci return 0; 137562306a36Sopenharmony_ci} 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci/* 137862306a36Sopenharmony_ci * DViCO bluebird firmware needs the "warm" product ID to be patched into the 137962306a36Sopenharmony_ci * firmware file before download. 138062306a36Sopenharmony_ci */ 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_cistatic const int dvico_firmware_id_offsets[] = { 6638, 3204 }; 138362306a36Sopenharmony_cistatic int bluebird_patch_dvico_firmware_download(struct usb_device *udev, 138462306a36Sopenharmony_ci const struct firmware *fw) 138562306a36Sopenharmony_ci{ 138662306a36Sopenharmony_ci int pos; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) { 138962306a36Sopenharmony_ci int idoff = dvico_firmware_id_offsets[pos]; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci if (fw->size < idoff + 4) 139262306a36Sopenharmony_ci continue; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci if (fw->data[idoff] == (USB_VID_DVICO & 0xff) && 139562306a36Sopenharmony_ci fw->data[idoff + 1] == USB_VID_DVICO >> 8) { 139662306a36Sopenharmony_ci struct firmware new_fw; 139762306a36Sopenharmony_ci u8 *new_fw_data = vmalloc(fw->size); 139862306a36Sopenharmony_ci int ret; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci if (!new_fw_data) 140162306a36Sopenharmony_ci return -ENOMEM; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci memcpy(new_fw_data, fw->data, fw->size); 140462306a36Sopenharmony_ci new_fw.size = fw->size; 140562306a36Sopenharmony_ci new_fw.data = new_fw_data; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci new_fw_data[idoff + 2] = 140862306a36Sopenharmony_ci le16_to_cpu(udev->descriptor.idProduct) + 1; 140962306a36Sopenharmony_ci new_fw_data[idoff + 3] = 141062306a36Sopenharmony_ci le16_to_cpu(udev->descriptor.idProduct) >> 8; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci ret = usb_cypress_load_firmware(udev, &new_fw, 141362306a36Sopenharmony_ci CYPRESS_FX2); 141462306a36Sopenharmony_ci vfree(new_fw_data); 141562306a36Sopenharmony_ci return ret; 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci } 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci return -EINVAL; 142062306a36Sopenharmony_ci} 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ciint cxusb_medion_get(struct dvb_usb_device *dvbdev, 142362306a36Sopenharmony_ci enum cxusb_open_type open_type) 142462306a36Sopenharmony_ci{ 142562306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = dvbdev->priv; 142662306a36Sopenharmony_ci int ret = 0; 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci mutex_lock(&cxdev->open_lock); 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci if (WARN_ON((cxdev->open_type == CXUSB_OPEN_INIT || 143162306a36Sopenharmony_ci cxdev->open_type == CXUSB_OPEN_NONE) && 143262306a36Sopenharmony_ci cxdev->open_ctr != 0)) { 143362306a36Sopenharmony_ci ret = -EINVAL; 143462306a36Sopenharmony_ci goto ret_unlock; 143562306a36Sopenharmony_ci } 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci if (cxdev->open_type == CXUSB_OPEN_INIT) { 143862306a36Sopenharmony_ci ret = -EAGAIN; 143962306a36Sopenharmony_ci goto ret_unlock; 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci if (cxdev->open_ctr == 0) { 144362306a36Sopenharmony_ci if (cxdev->open_type != open_type) { 144462306a36Sopenharmony_ci dev_info(&dvbdev->udev->dev, "will acquire and switch to %s\n", 144562306a36Sopenharmony_ci open_type == CXUSB_OPEN_ANALOG ? 144662306a36Sopenharmony_ci "analog" : "digital"); 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci if (open_type == CXUSB_OPEN_ANALOG) { 144962306a36Sopenharmony_ci ret = _cxusb_power_ctrl(dvbdev, 1); 145062306a36Sopenharmony_ci if (ret != 0) 145162306a36Sopenharmony_ci dev_warn(&dvbdev->udev->dev, 145262306a36Sopenharmony_ci "powerup for analog switch failed (%d)\n", 145362306a36Sopenharmony_ci ret); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci ret = cxusb_medion_set_mode(dvbdev, false); 145662306a36Sopenharmony_ci if (ret != 0) 145762306a36Sopenharmony_ci goto ret_unlock; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci ret = cxusb_medion_analog_init(dvbdev); 146062306a36Sopenharmony_ci if (ret != 0) 146162306a36Sopenharmony_ci goto ret_unlock; 146262306a36Sopenharmony_ci } else { /* digital */ 146362306a36Sopenharmony_ci ret = _cxusb_power_ctrl(dvbdev, 1); 146462306a36Sopenharmony_ci if (ret != 0) 146562306a36Sopenharmony_ci dev_warn(&dvbdev->udev->dev, 146662306a36Sopenharmony_ci "powerup for digital switch failed (%d)\n", 146762306a36Sopenharmony_ci ret); 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci ret = cxusb_medion_set_mode(dvbdev, true); 147062306a36Sopenharmony_ci if (ret != 0) 147162306a36Sopenharmony_ci goto ret_unlock; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci cxdev->open_type = open_type; 147562306a36Sopenharmony_ci } else { 147662306a36Sopenharmony_ci dev_info(&dvbdev->udev->dev, "reacquired idle %s\n", 147762306a36Sopenharmony_ci open_type == CXUSB_OPEN_ANALOG ? 147862306a36Sopenharmony_ci "analog" : "digital"); 147962306a36Sopenharmony_ci } 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci cxdev->open_ctr = 1; 148262306a36Sopenharmony_ci } else if (cxdev->open_type == open_type) { 148362306a36Sopenharmony_ci cxdev->open_ctr++; 148462306a36Sopenharmony_ci dev_info(&dvbdev->udev->dev, "acquired %s\n", 148562306a36Sopenharmony_ci open_type == CXUSB_OPEN_ANALOG ? "analog" : "digital"); 148662306a36Sopenharmony_ci } else { 148762306a36Sopenharmony_ci ret = -EBUSY; 148862306a36Sopenharmony_ci } 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ciret_unlock: 149162306a36Sopenharmony_ci mutex_unlock(&cxdev->open_lock); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci return ret; 149462306a36Sopenharmony_ci} 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_civoid cxusb_medion_put(struct dvb_usb_device *dvbdev) 149762306a36Sopenharmony_ci{ 149862306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = dvbdev->priv; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci mutex_lock(&cxdev->open_lock); 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci if (cxdev->open_type == CXUSB_OPEN_INIT) { 150362306a36Sopenharmony_ci WARN_ON(cxdev->open_ctr != 0); 150462306a36Sopenharmony_ci cxdev->open_type = CXUSB_OPEN_NONE; 150562306a36Sopenharmony_ci goto unlock; 150662306a36Sopenharmony_ci } 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci if (!WARN_ON(cxdev->open_ctr < 1)) { 150962306a36Sopenharmony_ci cxdev->open_ctr--; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci dev_info(&dvbdev->udev->dev, "release %s\n", 151262306a36Sopenharmony_ci cxdev->open_type == CXUSB_OPEN_ANALOG ? 151362306a36Sopenharmony_ci "analog" : "digital"); 151462306a36Sopenharmony_ci } 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ciunlock: 151762306a36Sopenharmony_ci mutex_unlock(&cxdev->open_lock); 151862306a36Sopenharmony_ci} 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci/* DVB USB Driver stuff */ 152162306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_medion_properties; 152262306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties; 152362306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; 152462306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; 152562306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; 152662306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; 152762306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; 152862306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; 152962306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; 153062306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_aver_a868r_properties; 153162306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_d680_dmb_properties; 153262306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_mygica_d689_properties; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_cistatic int cxusb_medion_priv_init(struct dvb_usb_device *dvbdev) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = dvbdev->priv; 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci cxdev->dvbdev = dvbdev; 153962306a36Sopenharmony_ci cxdev->open_type = CXUSB_OPEN_INIT; 154062306a36Sopenharmony_ci mutex_init(&cxdev->open_lock); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci return 0; 154362306a36Sopenharmony_ci} 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_cistatic void cxusb_medion_priv_destroy(struct dvb_usb_device *dvbdev) 154662306a36Sopenharmony_ci{ 154762306a36Sopenharmony_ci struct cxusb_medion_dev *cxdev = dvbdev->priv; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci mutex_destroy(&cxdev->open_lock); 155062306a36Sopenharmony_ci} 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_cistatic bool cxusb_medion_check_altsetting(struct usb_host_interface *as) 155362306a36Sopenharmony_ci{ 155462306a36Sopenharmony_ci unsigned int ctr; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci for (ctr = 0; ctr < as->desc.bNumEndpoints; ctr++) { 155762306a36Sopenharmony_ci if ((as->endpoint[ctr].desc.bEndpointAddress & 155862306a36Sopenharmony_ci USB_ENDPOINT_NUMBER_MASK) != 2) 155962306a36Sopenharmony_ci continue; 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci if (as->endpoint[ctr].desc.bEndpointAddress & USB_DIR_IN && 156262306a36Sopenharmony_ci ((as->endpoint[ctr].desc.bmAttributes & 156362306a36Sopenharmony_ci USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) 156462306a36Sopenharmony_ci return true; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci break; 156762306a36Sopenharmony_ci } 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci return false; 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_cistatic bool cxusb_medion_check_intf(struct usb_interface *intf) 157362306a36Sopenharmony_ci{ 157462306a36Sopenharmony_ci unsigned int ctr; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci if (intf->num_altsetting < 2) { 157762306a36Sopenharmony_ci dev_err(intf->usb_dev, "no alternate interface"); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci return false; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci for (ctr = 0; ctr < intf->num_altsetting; ctr++) { 158362306a36Sopenharmony_ci if (intf->altsetting[ctr].desc.bAlternateSetting != 1) 158462306a36Sopenharmony_ci continue; 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci if (cxusb_medion_check_altsetting(&intf->altsetting[ctr])) 158762306a36Sopenharmony_ci return true; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci break; 159062306a36Sopenharmony_ci } 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci dev_err(intf->usb_dev, "no iso interface"); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci return false; 159562306a36Sopenharmony_ci} 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_cistatic int cxusb_probe(struct usb_interface *intf, 159862306a36Sopenharmony_ci const struct usb_device_id *id) 159962306a36Sopenharmony_ci{ 160062306a36Sopenharmony_ci struct dvb_usb_device *dvbdev; 160162306a36Sopenharmony_ci int ret; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci /* Medion 95700 */ 160462306a36Sopenharmony_ci if (!dvb_usb_device_init(intf, &cxusb_medion_properties, 160562306a36Sopenharmony_ci THIS_MODULE, &dvbdev, adapter_nr)) { 160662306a36Sopenharmony_ci if (!cxusb_medion_check_intf(intf)) { 160762306a36Sopenharmony_ci ret = -ENODEV; 160862306a36Sopenharmony_ci goto ret_uninit; 160962306a36Sopenharmony_ci } 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci _cxusb_power_ctrl(dvbdev, 1); 161262306a36Sopenharmony_ci ret = cxusb_medion_set_mode(dvbdev, false); 161362306a36Sopenharmony_ci if (ret) 161462306a36Sopenharmony_ci goto ret_uninit; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci ret = cxusb_medion_register_analog(dvbdev); 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci cxusb_medion_set_mode(dvbdev, true); 161962306a36Sopenharmony_ci _cxusb_power_ctrl(dvbdev, 0); 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci if (ret != 0) 162262306a36Sopenharmony_ci goto ret_uninit; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci /* release device from INIT mode to normal operation */ 162562306a36Sopenharmony_ci cxusb_medion_put(dvbdev); 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci return 0; 162862306a36Sopenharmony_ci } else if (!dvb_usb_device_init(intf, 162962306a36Sopenharmony_ci &cxusb_bluebird_lgh064f_properties, 163062306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 163162306a36Sopenharmony_ci !dvb_usb_device_init(intf, 163262306a36Sopenharmony_ci &cxusb_bluebird_dee1601_properties, 163362306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 163462306a36Sopenharmony_ci !dvb_usb_device_init(intf, 163562306a36Sopenharmony_ci &cxusb_bluebird_lgz201_properties, 163662306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 163762306a36Sopenharmony_ci !dvb_usb_device_init(intf, 163862306a36Sopenharmony_ci &cxusb_bluebird_dtt7579_properties, 163962306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 164062306a36Sopenharmony_ci !dvb_usb_device_init(intf, 164162306a36Sopenharmony_ci &cxusb_bluebird_dualdig4_properties, 164262306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 164362306a36Sopenharmony_ci !dvb_usb_device_init(intf, 164462306a36Sopenharmony_ci &cxusb_bluebird_nano2_properties, 164562306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 164662306a36Sopenharmony_ci !dvb_usb_device_init(intf, 164762306a36Sopenharmony_ci &cxusb_bluebird_nano2_needsfirmware_properties, 164862306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 164962306a36Sopenharmony_ci !dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, 165062306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 165162306a36Sopenharmony_ci !dvb_usb_device_init(intf, 165262306a36Sopenharmony_ci &cxusb_bluebird_dualdig4_rev2_properties, 165362306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 165462306a36Sopenharmony_ci !dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, 165562306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 165662306a36Sopenharmony_ci !dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, 165762306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr) || 165862306a36Sopenharmony_ci 0) 165962306a36Sopenharmony_ci return 0; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci return -EINVAL; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ciret_uninit: 166462306a36Sopenharmony_ci dvb_usb_device_exit(intf); 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci return ret; 166762306a36Sopenharmony_ci} 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_cistatic void cxusb_disconnect(struct usb_interface *intf) 167062306a36Sopenharmony_ci{ 167162306a36Sopenharmony_ci struct dvb_usb_device *d = usb_get_intfdata(intf); 167262306a36Sopenharmony_ci struct cxusb_state *st = d->priv; 167362306a36Sopenharmony_ci struct i2c_client *client; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci if (d->props.devices[0].warm_ids[0] == &cxusb_table[MEDION_MD95700]) 167662306a36Sopenharmony_ci cxusb_medion_unregister_analog(d); 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci /* remove I2C client for tuner */ 167962306a36Sopenharmony_ci client = st->i2c_client_tuner; 168062306a36Sopenharmony_ci if (client) { 168162306a36Sopenharmony_ci module_put(client->dev.driver->owner); 168262306a36Sopenharmony_ci i2c_unregister_device(client); 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci /* remove I2C client for demodulator */ 168662306a36Sopenharmony_ci client = st->i2c_client_demod; 168762306a36Sopenharmony_ci if (client) { 168862306a36Sopenharmony_ci module_put(client->dev.driver->owner); 168962306a36Sopenharmony_ci i2c_unregister_device(client); 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci dvb_usb_device_exit(intf); 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_cistatic struct usb_device_id cxusb_table[] = { 169662306a36Sopenharmony_ci DVB_USB_DEV(MEDION, MEDION_MD95700), 169762306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_LG064F_COLD), 169862306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_LG064F_WARM), 169962306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_1_COLD), 170062306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_1_WARM), 170162306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_LGZ201_COLD), 170262306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_LGZ201_WARM), 170362306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_TH7579_COLD), 170462306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_TH7579_WARM), 170562306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DIGITALNOW_BLUEBIRD_DUAL_1_COLD), 170662306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DIGITALNOW_BLUEBIRD_DUAL_1_WARM), 170762306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_2_COLD), 170862306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_2_WARM), 170962306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_4), 171062306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DVB_T_NANO_2), 171162306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM), 171262306a36Sopenharmony_ci DVB_USB_DEV(AVERMEDIA, AVERMEDIA_VOLAR_A868R), 171362306a36Sopenharmony_ci DVB_USB_DEV(DVICO, DVICO_BLUEBIRD_DUAL_4_REV_2), 171462306a36Sopenharmony_ci DVB_USB_DEV(CONEXANT, CONEXANT_D680_DMB), 171562306a36Sopenharmony_ci DVB_USB_DEV(CONEXANT, MYGICA_D689), 171662306a36Sopenharmony_ci { } 171762306a36Sopenharmony_ci}; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, cxusb_table); 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_medion_properties = { 172262306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_medion_dev), 172762306a36Sopenharmony_ci .priv_init = cxusb_medion_priv_init, 172862306a36Sopenharmony_ci .priv_destroy = cxusb_medion_priv_destroy, 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci .num_adapters = 1, 173162306a36Sopenharmony_ci .adapter = { 173262306a36Sopenharmony_ci { 173362306a36Sopenharmony_ci .num_frontends = 1, 173462306a36Sopenharmony_ci .fe = {{ 173562306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 173662306a36Sopenharmony_ci .frontend_attach = cxusb_cx22702_frontend_attach, 173762306a36Sopenharmony_ci .tuner_attach = cxusb_fmd1216me_tuner_attach, 173862306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 173962306a36Sopenharmony_ci .stream = { 174062306a36Sopenharmony_ci .type = USB_BULK, 174162306a36Sopenharmony_ci .count = 5, 174262306a36Sopenharmony_ci .endpoint = 0x02, 174362306a36Sopenharmony_ci .u = { 174462306a36Sopenharmony_ci .bulk = { 174562306a36Sopenharmony_ci .buffersize = 8192, 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci }, 174962306a36Sopenharmony_ci } }, 175062306a36Sopenharmony_ci }, 175162306a36Sopenharmony_ci }, 175262306a36Sopenharmony_ci .power_ctrl = cxusb_power_ctrl, 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci .num_device_descs = 1, 175962306a36Sopenharmony_ci .devices = { 176062306a36Sopenharmony_ci { 176162306a36Sopenharmony_ci "Medion MD95700 (MDUSBTV-HYBRID)", 176262306a36Sopenharmony_ci { NULL }, 176362306a36Sopenharmony_ci { &cxusb_table[MEDION_MD95700], NULL }, 176462306a36Sopenharmony_ci }, 176562306a36Sopenharmony_ci } 176662306a36Sopenharmony_ci}; 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { 176962306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci .usb_ctrl = DEVICE_SPECIFIC, 177262306a36Sopenharmony_ci .firmware = "dvb-usb-bluebird-01.fw", 177362306a36Sopenharmony_ci .download_firmware = bluebird_patch_dvico_firmware_download, 177462306a36Sopenharmony_ci /* 177562306a36Sopenharmony_ci * use usb alt setting 0 for EP4 transfer (dvb-t), 177662306a36Sopenharmony_ci * use usb alt setting 7 for EP2 transfer (atsc) 177762306a36Sopenharmony_ci */ 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci .num_adapters = 1, 178262306a36Sopenharmony_ci .adapter = { 178362306a36Sopenharmony_ci { 178462306a36Sopenharmony_ci .num_frontends = 1, 178562306a36Sopenharmony_ci .fe = {{ 178662306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 178762306a36Sopenharmony_ci .frontend_attach = cxusb_lgdt3303_frontend_attach, 178862306a36Sopenharmony_ci .tuner_attach = cxusb_lgh064f_tuner_attach, 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 179162306a36Sopenharmony_ci .stream = { 179262306a36Sopenharmony_ci .type = USB_BULK, 179362306a36Sopenharmony_ci .count = 5, 179462306a36Sopenharmony_ci .endpoint = 0x02, 179562306a36Sopenharmony_ci .u = { 179662306a36Sopenharmony_ci .bulk = { 179762306a36Sopenharmony_ci .buffersize = 8192, 179862306a36Sopenharmony_ci } 179962306a36Sopenharmony_ci } 180062306a36Sopenharmony_ci }, 180162306a36Sopenharmony_ci } }, 180262306a36Sopenharmony_ci }, 180362306a36Sopenharmony_ci }, 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci .power_ctrl = cxusb_bluebird_power_ctrl, 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci .rc.core = { 181062306a36Sopenharmony_ci .rc_interval = 100, 181162306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_PORTABLE, 181262306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 181362306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 181462306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 181562306a36Sopenharmony_ci }, 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci .num_device_descs = 1, 182062306a36Sopenharmony_ci .devices = { 182162306a36Sopenharmony_ci { "DViCO FusionHDTV5 USB Gold", 182262306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_LG064F_COLD], NULL }, 182362306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_LG064F_WARM], NULL }, 182462306a36Sopenharmony_ci }, 182562306a36Sopenharmony_ci } 182662306a36Sopenharmony_ci}; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { 182962306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci .usb_ctrl = DEVICE_SPECIFIC, 183262306a36Sopenharmony_ci .firmware = "dvb-usb-bluebird-01.fw", 183362306a36Sopenharmony_ci .download_firmware = bluebird_patch_dvico_firmware_download, 183462306a36Sopenharmony_ci /* 183562306a36Sopenharmony_ci * use usb alt setting 0 for EP4 transfer (dvb-t), 183662306a36Sopenharmony_ci * use usb alt setting 7 for EP2 transfer (atsc) 183762306a36Sopenharmony_ci */ 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci .num_adapters = 1, 184262306a36Sopenharmony_ci .adapter = { 184362306a36Sopenharmony_ci { 184462306a36Sopenharmony_ci .num_frontends = 1, 184562306a36Sopenharmony_ci .fe = {{ 184662306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 184762306a36Sopenharmony_ci .frontend_attach = cxusb_dee1601_frontend_attach, 184862306a36Sopenharmony_ci .tuner_attach = cxusb_dee1601_tuner_attach, 184962306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 185062306a36Sopenharmony_ci .stream = { 185162306a36Sopenharmony_ci .type = USB_BULK, 185262306a36Sopenharmony_ci .count = 5, 185362306a36Sopenharmony_ci .endpoint = 0x04, 185462306a36Sopenharmony_ci .u = { 185562306a36Sopenharmony_ci .bulk = { 185662306a36Sopenharmony_ci .buffersize = 8192, 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci }, 186062306a36Sopenharmony_ci } }, 186162306a36Sopenharmony_ci }, 186262306a36Sopenharmony_ci }, 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci .power_ctrl = cxusb_bluebird_power_ctrl, 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci .rc.core = { 186962306a36Sopenharmony_ci .rc_interval = 100, 187062306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_MCE, 187162306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 187262306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 187362306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 187462306a36Sopenharmony_ci }, 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci .num_device_descs = 3, 187962306a36Sopenharmony_ci .devices = { 188062306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T Dual USB", 188162306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_1_COLD], NULL }, 188262306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_1_WARM], NULL }, 188362306a36Sopenharmony_ci }, 188462306a36Sopenharmony_ci { "DigitalNow DVB-T Dual USB", 188562306a36Sopenharmony_ci { &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_COLD], NULL }, 188662306a36Sopenharmony_ci { &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_WARM], NULL }, 188762306a36Sopenharmony_ci }, 188862306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T Dual Digital 2", 188962306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_2_COLD], NULL }, 189062306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_2_WARM], NULL }, 189162306a36Sopenharmony_ci }, 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci}; 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { 189662306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci .usb_ctrl = DEVICE_SPECIFIC, 189962306a36Sopenharmony_ci .firmware = "dvb-usb-bluebird-01.fw", 190062306a36Sopenharmony_ci .download_firmware = bluebird_patch_dvico_firmware_download, 190162306a36Sopenharmony_ci /* 190262306a36Sopenharmony_ci * use usb alt setting 0 for EP4 transfer (dvb-t), 190362306a36Sopenharmony_ci * use usb alt setting 7 for EP2 transfer (atsc) 190462306a36Sopenharmony_ci */ 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci .num_adapters = 1, 190962306a36Sopenharmony_ci .adapter = { 191062306a36Sopenharmony_ci { 191162306a36Sopenharmony_ci .num_frontends = 1, 191262306a36Sopenharmony_ci .fe = {{ 191362306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 191462306a36Sopenharmony_ci .frontend_attach = cxusb_mt352_frontend_attach, 191562306a36Sopenharmony_ci .tuner_attach = cxusb_lgz201_tuner_attach, 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 191862306a36Sopenharmony_ci .stream = { 191962306a36Sopenharmony_ci .type = USB_BULK, 192062306a36Sopenharmony_ci .count = 5, 192162306a36Sopenharmony_ci .endpoint = 0x04, 192262306a36Sopenharmony_ci .u = { 192362306a36Sopenharmony_ci .bulk = { 192462306a36Sopenharmony_ci .buffersize = 8192, 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci } 192762306a36Sopenharmony_ci }, 192862306a36Sopenharmony_ci } }, 192962306a36Sopenharmony_ci }, 193062306a36Sopenharmony_ci }, 193162306a36Sopenharmony_ci .power_ctrl = cxusb_bluebird_power_ctrl, 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci .rc.core = { 193662306a36Sopenharmony_ci .rc_interval = 100, 193762306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_PORTABLE, 193862306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 193962306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 194062306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 194162306a36Sopenharmony_ci }, 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 194462306a36Sopenharmony_ci .num_device_descs = 1, 194562306a36Sopenharmony_ci .devices = { 194662306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T USB (LGZ201)", 194762306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_LGZ201_COLD], NULL }, 194862306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_LGZ201_WARM], NULL }, 194962306a36Sopenharmony_ci }, 195062306a36Sopenharmony_ci } 195162306a36Sopenharmony_ci}; 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { 195462306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci .usb_ctrl = DEVICE_SPECIFIC, 195762306a36Sopenharmony_ci .firmware = "dvb-usb-bluebird-01.fw", 195862306a36Sopenharmony_ci .download_firmware = bluebird_patch_dvico_firmware_download, 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci /* 196162306a36Sopenharmony_ci * use usb alt setting 0 for EP4 transfer (dvb-t), 196262306a36Sopenharmony_ci * use usb alt setting 7 for EP2 transfer (atsc) 196362306a36Sopenharmony_ci */ 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci .num_adapters = 1, 196862306a36Sopenharmony_ci .adapter = { 196962306a36Sopenharmony_ci { 197062306a36Sopenharmony_ci .num_frontends = 1, 197162306a36Sopenharmony_ci .fe = {{ 197262306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 197362306a36Sopenharmony_ci .frontend_attach = cxusb_mt352_frontend_attach, 197462306a36Sopenharmony_ci .tuner_attach = cxusb_dtt7579_tuner_attach, 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 197762306a36Sopenharmony_ci .stream = { 197862306a36Sopenharmony_ci .type = USB_BULK, 197962306a36Sopenharmony_ci .count = 5, 198062306a36Sopenharmony_ci .endpoint = 0x04, 198162306a36Sopenharmony_ci .u = { 198262306a36Sopenharmony_ci .bulk = { 198362306a36Sopenharmony_ci .buffersize = 8192, 198462306a36Sopenharmony_ci } 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci }, 198762306a36Sopenharmony_ci } }, 198862306a36Sopenharmony_ci }, 198962306a36Sopenharmony_ci }, 199062306a36Sopenharmony_ci .power_ctrl = cxusb_bluebird_power_ctrl, 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci .rc.core = { 199562306a36Sopenharmony_ci .rc_interval = 100, 199662306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_PORTABLE, 199762306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 199862306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 199962306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 200062306a36Sopenharmony_ci }, 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci .num_device_descs = 1, 200562306a36Sopenharmony_ci .devices = { 200662306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T USB (TH7579)", 200762306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_TH7579_COLD], NULL }, 200862306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_TH7579_WARM], NULL }, 200962306a36Sopenharmony_ci }, 201062306a36Sopenharmony_ci } 201162306a36Sopenharmony_ci}; 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { 201462306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci .num_adapters = 1, 202162306a36Sopenharmony_ci .adapter = { 202262306a36Sopenharmony_ci { 202362306a36Sopenharmony_ci .num_frontends = 1, 202462306a36Sopenharmony_ci .fe = {{ 202562306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 202662306a36Sopenharmony_ci .frontend_attach = cxusb_dualdig4_frontend_attach, 202762306a36Sopenharmony_ci .tuner_attach = cxusb_dvico_xc3028_tuner_attach, 202862306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 202962306a36Sopenharmony_ci .stream = { 203062306a36Sopenharmony_ci .type = USB_BULK, 203162306a36Sopenharmony_ci .count = 5, 203262306a36Sopenharmony_ci .endpoint = 0x02, 203362306a36Sopenharmony_ci .u = { 203462306a36Sopenharmony_ci .bulk = { 203562306a36Sopenharmony_ci .buffersize = 8192, 203662306a36Sopenharmony_ci } 203762306a36Sopenharmony_ci } 203862306a36Sopenharmony_ci }, 203962306a36Sopenharmony_ci } }, 204062306a36Sopenharmony_ci }, 204162306a36Sopenharmony_ci }, 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci .power_ctrl = cxusb_power_ctrl, 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci .rc.core = { 205062306a36Sopenharmony_ci .rc_interval = 100, 205162306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_MCE, 205262306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 205362306a36Sopenharmony_ci .rc_query = cxusb_bluebird2_rc_query, 205462306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 205562306a36Sopenharmony_ci }, 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci .num_device_descs = 1, 205862306a36Sopenharmony_ci .devices = { 205962306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T Dual Digital 4", 206062306a36Sopenharmony_ci { NULL }, 206162306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_4], NULL }, 206262306a36Sopenharmony_ci }, 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci}; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = { 206762306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 207062306a36Sopenharmony_ci .identify_state = bluebird_fx2_identify_state, 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci .num_adapters = 1, 207562306a36Sopenharmony_ci .adapter = { 207662306a36Sopenharmony_ci { 207762306a36Sopenharmony_ci .num_frontends = 1, 207862306a36Sopenharmony_ci .fe = {{ 207962306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 208062306a36Sopenharmony_ci .frontend_attach = cxusb_nano2_frontend_attach, 208162306a36Sopenharmony_ci .tuner_attach = cxusb_dvico_xc3028_tuner_attach, 208262306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 208362306a36Sopenharmony_ci .stream = { 208462306a36Sopenharmony_ci .type = USB_BULK, 208562306a36Sopenharmony_ci .count = 5, 208662306a36Sopenharmony_ci .endpoint = 0x02, 208762306a36Sopenharmony_ci .u = { 208862306a36Sopenharmony_ci .bulk = { 208962306a36Sopenharmony_ci .buffersize = 8192, 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci } 209262306a36Sopenharmony_ci }, 209362306a36Sopenharmony_ci } }, 209462306a36Sopenharmony_ci }, 209562306a36Sopenharmony_ci }, 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci .power_ctrl = cxusb_nano2_power_ctrl, 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci .rc.core = { 210462306a36Sopenharmony_ci .rc_interval = 100, 210562306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_PORTABLE, 210662306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 210762306a36Sopenharmony_ci .rc_query = cxusb_bluebird2_rc_query, 210862306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 210962306a36Sopenharmony_ci }, 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci .num_device_descs = 1, 211262306a36Sopenharmony_ci .devices = { 211362306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T NANO2", 211462306a36Sopenharmony_ci { NULL }, 211562306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL }, 211662306a36Sopenharmony_ci }, 211762306a36Sopenharmony_ci } 211862306a36Sopenharmony_ci}; 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_cistatic struct dvb_usb_device_properties 212162306a36Sopenharmony_cicxusb_bluebird_nano2_needsfirmware_properties = { 212262306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci .usb_ctrl = DEVICE_SPECIFIC, 212562306a36Sopenharmony_ci .firmware = "dvb-usb-bluebird-02.fw", 212662306a36Sopenharmony_ci .download_firmware = bluebird_patch_dvico_firmware_download, 212762306a36Sopenharmony_ci .identify_state = bluebird_fx2_identify_state, 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci .num_adapters = 1, 213262306a36Sopenharmony_ci .adapter = { 213362306a36Sopenharmony_ci { 213462306a36Sopenharmony_ci .num_frontends = 1, 213562306a36Sopenharmony_ci .fe = {{ 213662306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 213762306a36Sopenharmony_ci .frontend_attach = cxusb_nano2_frontend_attach, 213862306a36Sopenharmony_ci .tuner_attach = cxusb_dvico_xc3028_tuner_attach, 213962306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 214062306a36Sopenharmony_ci .stream = { 214162306a36Sopenharmony_ci .type = USB_BULK, 214262306a36Sopenharmony_ci .count = 5, 214362306a36Sopenharmony_ci .endpoint = 0x02, 214462306a36Sopenharmony_ci .u = { 214562306a36Sopenharmony_ci .bulk = { 214662306a36Sopenharmony_ci .buffersize = 8192, 214762306a36Sopenharmony_ci } 214862306a36Sopenharmony_ci } 214962306a36Sopenharmony_ci }, 215062306a36Sopenharmony_ci } }, 215162306a36Sopenharmony_ci }, 215262306a36Sopenharmony_ci }, 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci .power_ctrl = cxusb_nano2_power_ctrl, 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci .rc.core = { 216162306a36Sopenharmony_ci .rc_interval = 100, 216262306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_PORTABLE, 216362306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 216462306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 216562306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 216662306a36Sopenharmony_ci }, 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci .num_device_descs = 1, 216962306a36Sopenharmony_ci .devices = { { 217062306a36Sopenharmony_ci "DViCO FusionHDTV DVB-T NANO2 w/o firmware", 217162306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL }, 217262306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM], 217362306a36Sopenharmony_ci NULL }, 217462306a36Sopenharmony_ci }, 217562306a36Sopenharmony_ci } 217662306a36Sopenharmony_ci}; 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_aver_a868r_properties = { 217962306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci .num_adapters = 1, 218662306a36Sopenharmony_ci .adapter = { 218762306a36Sopenharmony_ci { 218862306a36Sopenharmony_ci .num_frontends = 1, 218962306a36Sopenharmony_ci .fe = {{ 219062306a36Sopenharmony_ci .streaming_ctrl = cxusb_aver_streaming_ctrl, 219162306a36Sopenharmony_ci .frontend_attach = cxusb_aver_lgdt3303_frontend_attach, 219262306a36Sopenharmony_ci .tuner_attach = cxusb_mxl5003s_tuner_attach, 219362306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 219462306a36Sopenharmony_ci .stream = { 219562306a36Sopenharmony_ci .type = USB_BULK, 219662306a36Sopenharmony_ci .count = 5, 219762306a36Sopenharmony_ci .endpoint = 0x04, 219862306a36Sopenharmony_ci .u = { 219962306a36Sopenharmony_ci .bulk = { 220062306a36Sopenharmony_ci .buffersize = 8192, 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci } 220362306a36Sopenharmony_ci }, 220462306a36Sopenharmony_ci } }, 220562306a36Sopenharmony_ci }, 220662306a36Sopenharmony_ci }, 220762306a36Sopenharmony_ci .power_ctrl = cxusb_aver_power_ctrl, 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci .num_device_descs = 1, 221462306a36Sopenharmony_ci .devices = { 221562306a36Sopenharmony_ci { "AVerMedia AVerTVHD Volar (A868R)", 221662306a36Sopenharmony_ci { NULL }, 221762306a36Sopenharmony_ci { &cxusb_table[AVERMEDIA_VOLAR_A868R], NULL }, 221862306a36Sopenharmony_ci }, 221962306a36Sopenharmony_ci } 222062306a36Sopenharmony_ci}; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_cistatic 222362306a36Sopenharmony_cistruct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { 222462306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci .num_adapters = 1, 223162306a36Sopenharmony_ci .adapter = { 223262306a36Sopenharmony_ci { 223362306a36Sopenharmony_ci .size_of_priv = sizeof(struct dib0700_adapter_state), 223462306a36Sopenharmony_ci .num_frontends = 1, 223562306a36Sopenharmony_ci .fe = {{ 223662306a36Sopenharmony_ci .streaming_ctrl = cxusb_streaming_ctrl, 223762306a36Sopenharmony_ci .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, 223862306a36Sopenharmony_ci .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, 223962306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 224062306a36Sopenharmony_ci .stream = { 224162306a36Sopenharmony_ci .type = USB_BULK, 224262306a36Sopenharmony_ci .count = 7, 224362306a36Sopenharmony_ci .endpoint = 0x02, 224462306a36Sopenharmony_ci .u = { 224562306a36Sopenharmony_ci .bulk = { 224662306a36Sopenharmony_ci .buffersize = 4096, 224762306a36Sopenharmony_ci } 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci }, 225062306a36Sopenharmony_ci } }, 225162306a36Sopenharmony_ci }, 225262306a36Sopenharmony_ci }, 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci .power_ctrl = cxusb_bluebird_power_ctrl, 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci .rc.core = { 226162306a36Sopenharmony_ci .rc_interval = 100, 226262306a36Sopenharmony_ci .rc_codes = RC_MAP_DVICO_MCE, 226362306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 226462306a36Sopenharmony_ci .rc_query = cxusb_rc_query, 226562306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 226662306a36Sopenharmony_ci }, 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci .num_device_descs = 1, 226962306a36Sopenharmony_ci .devices = { 227062306a36Sopenharmony_ci { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)", 227162306a36Sopenharmony_ci { NULL }, 227262306a36Sopenharmony_ci { &cxusb_table[DVICO_BLUEBIRD_DUAL_4_REV_2], NULL }, 227362306a36Sopenharmony_ci }, 227462306a36Sopenharmony_ci } 227562306a36Sopenharmony_ci}; 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_d680_dmb_properties = { 227862306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci .num_adapters = 1, 228562306a36Sopenharmony_ci .adapter = { 228662306a36Sopenharmony_ci { 228762306a36Sopenharmony_ci .num_frontends = 1, 228862306a36Sopenharmony_ci .fe = {{ 228962306a36Sopenharmony_ci .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, 229062306a36Sopenharmony_ci .frontend_attach = cxusb_d680_dmb_frontend_attach, 229162306a36Sopenharmony_ci .tuner_attach = cxusb_d680_dmb_tuner_attach, 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 229462306a36Sopenharmony_ci .stream = { 229562306a36Sopenharmony_ci .type = USB_BULK, 229662306a36Sopenharmony_ci .count = 5, 229762306a36Sopenharmony_ci .endpoint = 0x02, 229862306a36Sopenharmony_ci .u = { 229962306a36Sopenharmony_ci .bulk = { 230062306a36Sopenharmony_ci .buffersize = 8192, 230162306a36Sopenharmony_ci } 230262306a36Sopenharmony_ci } 230362306a36Sopenharmony_ci }, 230462306a36Sopenharmony_ci } }, 230562306a36Sopenharmony_ci }, 230662306a36Sopenharmony_ci }, 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci .power_ctrl = cxusb_d680_dmb_power_ctrl, 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci .rc.core = { 231562306a36Sopenharmony_ci .rc_interval = 100, 231662306a36Sopenharmony_ci .rc_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02, 231762306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 231862306a36Sopenharmony_ci .rc_query = cxusb_d680_dmb_rc_query, 231962306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_UNKNOWN, 232062306a36Sopenharmony_ci }, 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci .num_device_descs = 1, 232362306a36Sopenharmony_ci .devices = { 232462306a36Sopenharmony_ci { 232562306a36Sopenharmony_ci "Conexant DMB-TH Stick", 232662306a36Sopenharmony_ci { NULL }, 232762306a36Sopenharmony_ci { &cxusb_table[CONEXANT_D680_DMB], NULL }, 232862306a36Sopenharmony_ci }, 232962306a36Sopenharmony_ci } 233062306a36Sopenharmony_ci}; 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_cistatic struct dvb_usb_device_properties cxusb_mygica_d689_properties = { 233362306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci .size_of_priv = sizeof(struct cxusb_state), 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci .num_adapters = 1, 234062306a36Sopenharmony_ci .adapter = { 234162306a36Sopenharmony_ci { 234262306a36Sopenharmony_ci .num_frontends = 1, 234362306a36Sopenharmony_ci .fe = {{ 234462306a36Sopenharmony_ci .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, 234562306a36Sopenharmony_ci .frontend_attach = cxusb_mygica_d689_frontend_attach, 234662306a36Sopenharmony_ci .tuner_attach = cxusb_mygica_d689_tuner_attach, 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 234962306a36Sopenharmony_ci .stream = { 235062306a36Sopenharmony_ci .type = USB_BULK, 235162306a36Sopenharmony_ci .count = 5, 235262306a36Sopenharmony_ci .endpoint = 0x02, 235362306a36Sopenharmony_ci .u = { 235462306a36Sopenharmony_ci .bulk = { 235562306a36Sopenharmony_ci .buffersize = 8192, 235662306a36Sopenharmony_ci } 235762306a36Sopenharmony_ci } 235862306a36Sopenharmony_ci }, 235962306a36Sopenharmony_ci } }, 236062306a36Sopenharmony_ci }, 236162306a36Sopenharmony_ci }, 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci .power_ctrl = cxusb_d680_dmb_power_ctrl, 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci .i2c_algo = &cxusb_i2c_algo, 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci .rc.core = { 237062306a36Sopenharmony_ci .rc_interval = 100, 237162306a36Sopenharmony_ci .rc_codes = RC_MAP_D680_DMB, 237262306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 237362306a36Sopenharmony_ci .rc_query = cxusb_d680_dmb_rc_query, 237462306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_UNKNOWN, 237562306a36Sopenharmony_ci }, 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci .num_device_descs = 1, 237862306a36Sopenharmony_ci .devices = { 237962306a36Sopenharmony_ci { 238062306a36Sopenharmony_ci "Mygica D689 DMB-TH", 238162306a36Sopenharmony_ci { NULL }, 238262306a36Sopenharmony_ci { &cxusb_table[MYGICA_D689], NULL }, 238362306a36Sopenharmony_ci }, 238462306a36Sopenharmony_ci } 238562306a36Sopenharmony_ci}; 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_cistatic struct usb_driver cxusb_driver = { 238862306a36Sopenharmony_ci .name = "dvb_usb_cxusb", 238962306a36Sopenharmony_ci .probe = cxusb_probe, 239062306a36Sopenharmony_ci .disconnect = cxusb_disconnect, 239162306a36Sopenharmony_ci .id_table = cxusb_table, 239262306a36Sopenharmony_ci}; 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_cimodule_usb_driver(cxusb_driver); 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 239762306a36Sopenharmony_ciMODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); 239862306a36Sopenharmony_ciMODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); 239962306a36Sopenharmony_ciMODULE_AUTHOR("Maciej S. Szmigiero <mail@maciej.szmigiero.name>"); 240062306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); 240162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2402