diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.c | 102 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/az6007.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/it913x.c | 828 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 123 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 2 |
9 files changed, 152 insertions, 924 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 2059d0c86ad3..037e519bbaa2 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -100,13 +100,6 @@ config DVB_USB_GL861 Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. -config DVB_USB_IT913X - tristate "ITE IT913X DVB-T USB2.0 support" - depends on DVB_USB_V2 - select DVB_IT913X_FE - help - Say Y here to support the ITE IT913X DVB-T USB2.0 - config DVB_USB_LME2510 tristate "LME DM04/QQBOX DVB-S USB2.0 support" depends on DVB_USB_V2 @@ -133,7 +126,7 @@ config DVB_USB_MXL111SF config DVB_USB_RTL28XXU tristate "Realtek RTL28xxU DVB USB support" - depends on DVB_USB_V2 + depends on DVB_USB_V2 && I2C_MUX select DVB_RTL2830 select DVB_RTL2832 select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile index 2c06714b9ef0..7407b8338ccf 100644 --- a/drivers/media/usb/dvb-usb-v2/Makefile +++ b/drivers/media/usb/dvb-usb-v2/Makefile @@ -22,9 +22,6 @@ obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o dvb-usb-ec168-objs := ec168.o obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o -dvb-usb-it913x-objs := it913x.o -obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o - dvb-usb-lmedm04-objs := lmedm04.o obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o @@ -44,3 +41,4 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/tuners ccflags-y += -I$(srctree)/drivers/media/common +ccflags-y += -I$(srctree)/drivers/staging/media/rtl2832u_sdr diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 8ede8ea762e6..021e4d35e4d7 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -575,6 +575,10 @@ static int af9035_download_firmware(struct dvb_usb_device *d, if (ret < 0) goto err; + /* use default I2C address if eeprom has no address set */ + if (!tmp) + tmp = 0x3a; + if (state->chip_type == 0x9135) { ret = af9035_wr_reg(d, 0x004bfb, tmp); if (ret < 0) @@ -637,6 +641,7 @@ static int af9035_read_config(struct dvb_usb_device *d) /* demod I2C "address" */ state->af9033_config[0].i2c_addr = 0x38; + state->af9033_config[1].i2c_addr = 0x3a; state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; @@ -684,7 +689,9 @@ static int af9035_read_config(struct dvb_usb_device *d) if (ret < 0) goto err; - state->af9033_config[1].i2c_addr = tmp; + if (tmp) + state->af9033_config[1].i2c_addr = tmp; + dev_dbg(&d->udev->dev, "%s: 2nd demod I2C addr=%02x\n", __func__, tmp); } @@ -938,12 +945,7 @@ static int af9035_frontend_callback(void *adapter_priv, int component, static int af9035_get_adapter_count(struct dvb_usb_device *d) { struct state *state = d_to_priv(d); - - /* disable 2nd adapter as we don't have PID filters implemented */ - if (d->udev->speed == USB_SPEED_FULL) - return 1; - else - return state->dual_mode + 1; + return state->dual_mode + 1; } static int af9035_frontend_attach(struct dvb_usb_adapter *adap) @@ -961,7 +963,7 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap) /* attach demodulator */ adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], - &d->i2c_adap); + &d->i2c_adap, &state->ops); if (adap->fe[0] == NULL) { ret = -ENODEV; goto err; @@ -1369,58 +1371,19 @@ static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, return 0; } -/* - * FIXME: PID filter is property of demodulator and should be moved to the - * correct driver. Also we support only adapter #0 PID filter and will - * disable adapter #1 if USB1.1 is used. - */ static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - struct dvb_usb_device *d = adap_to_d(adap); - int ret; - - dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); - - ret = af9035_wr_reg_mask(d, 0x80f993, onoff, 0x01); - if (ret < 0) - goto err; - - return 0; - -err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + struct state *state = adap_to_priv(adap); - return ret; + return state->ops.pid_filter_ctrl(adap->fe[0], onoff); } static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { - struct dvb_usb_device *d = adap_to_d(adap); - int ret; - u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; - - dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", - __func__, index, pid, onoff); - - ret = af9035_wr_regs(d, 0x80f996, wbuf, 2); - if (ret < 0) - goto err; - - ret = af9035_wr_reg(d, 0x80f994, onoff); - if (ret < 0) - goto err; - - ret = af9035_wr_reg(d, 0x80f995, index); - if (ret < 0) - goto err; - - return 0; - -err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + struct state *state = adap_to_priv(adap); - return ret; + return state->ops.pid_filter(adap->fe[0], index, pid, onoff); } static int af9035_probe(struct usb_interface *intf, @@ -1494,6 +1457,13 @@ static const struct dvb_usb_device_properties af9035_props = { .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), }, { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter_ctrl = af9035_pid_filter_ctrl, + .pid_filter = af9035_pid_filter, + .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), }, }, @@ -1528,12 +1498,30 @@ static const struct usb_device_id af9035_id_table[] = { { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, /* IT9135 devices */ -#if 0 - { DVB_USB_DEVICE(0x048d, 0x9135, - &af9035_props, "IT9135 reference design", NULL) }, - { DVB_USB_DEVICE(0x048d, 0x9006, - &af9035_props, "IT9135 reference design", NULL) }, -#endif + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, + &af9035_props, "ITE 9135 Generic", RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, + &af9035_props, "ITE 9135(9005) Generic", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, + &af9035_props, "ITE 9135(9006) Generic", RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835, + &af9035_props, "Avermedia A835B(1835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835, + &af9035_props, "Avermedia A835B(2835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835, + &af9035_props, "Avermedia A835B(3835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, + &af9035_props, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335, + &af9035_props, "Avermedia H335", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, + &af9035_props, "Kworld UB499-2T T09", RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, + &af9035_props, "Sveon STV22 Dual DVB-T HDTV", + RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, + &af9035_props, "Digital Dual TV Receiver CTVDIGDUAL_V2", + RC_MAP_IT913X_V1) }, /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index a1c68d829b8c..c21902fdd4c4 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -62,6 +62,8 @@ struct state { u8 dual_mode:1; u16 eeprom_addr; struct af9033_config af9033_config[2]; + + struct af9033_ops ops; }; static const u32 clock_lut_af9035[] = { diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index c1051c347744..c3c4b98733bf 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -7,7 +7,7 @@ * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz * The original driver's license is GPL, as declared with MODULE_LICENSE() * - * Copyright (c) 2010-2012 Mauro Carvalho Chehab <mchehab@redhat.com> + * Copyright (c) 2010-2012 Mauro Carvalho Chehab * Driver modified by in order to work with upstream drxk driver, and * tons of bugs got fixed, and converted to use dvb-usb-v2. * @@ -975,7 +975,7 @@ static struct usb_driver az6007_usb_driver = { module_usb_driver(az6007_usb_driver); MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); MODULE_VERSION("2.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 8a054d66e708..de02db802ace 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) dev->driver_name = (char *) d->props->driver_name; dev->map_name = d->rc.map_name; dev->driver_type = d->rc.driver_type; - dev->allowed_protos = d->rc.allowed_protos; + rc_set_allowed_protocols(dev, d->rc.allowed_protos); dev->change_protocol = d->rc.change_protocol; dev->priv = d; diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c deleted file mode 100644 index fe95a586dd5d..000000000000 --- a/drivers/media/usb/dvb-usb-v2/it913x.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * DVB USB compliant linux driver for ITE IT9135 and IT9137 - * - * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com) - * IT9135 (C) ITE Tech Inc. - * IT9137 (C) ITE Tech Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * see Documentation/dvb/README.dvb-usb for more information - * see Documentation/dvb/it9137.txt for firmware information - * - */ -#define DVB_USB_LOG_PREFIX "it913x" - -#include <linux/usb.h> -#include <linux/usb/input.h> -#include <media/rc-core.h> - -#include "dvb_usb.h" -#include "it913x-fe.h" - -/* debug */ -static int dvb_usb_it913x_debug; -#define it_debug(var, level, args...) \ - do { if ((var & level)) pr_debug(DVB_USB_LOG_PREFIX": " args); \ -} while (0) -#define deb_info(level, args...) it_debug(dvb_usb_it913x_debug, level, args) -#define info(args...) pr_info(DVB_USB_LOG_PREFIX": " args) - -module_param_named(debug, dvb_usb_it913x_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); - -static int dvb_usb_it913x_firmware; -module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); -MODULE_PARM_DESC(firmware, "set firmware 0=auto "\ - "1=IT9137 2=IT9135 V1 3=IT9135 V2"); -#define FW_IT9137 "dvb-usb-it9137-01.fw" -#define FW_IT9135_V1 "dvb-usb-it9135-01.fw" -#define FW_IT9135_V2 "dvb-usb-it9135-02.fw" - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -struct it913x_state { - struct ite_config it913x_config; - u8 pid_filter_onoff; - bool proprietary_ir; - int cmd_counter; -}; - -static u16 check_sum(u8 *p, u8 len) -{ - u16 sum = 0; - u8 i = 1; - while (i < len) - sum += (i++ & 1) ? (*p++) << 8 : *p++; - return ~sum; -} - -static int it913x_io(struct dvb_usb_device *d, u8 mode, u8 pro, - u8 cmd, u32 reg, u8 addr, u8 *data, u8 len) -{ - struct it913x_state *st = d->priv; - int ret = 0, i, buf_size = 1; - u8 *buff; - u8 rlen; - u16 chk_sum; - - buff = kzalloc(256, GFP_KERNEL); - if (!buff) { - info("USB Buffer Failed"); - return -ENOMEM; - } - - buff[buf_size++] = pro; - buff[buf_size++] = cmd; - buff[buf_size++] = st->cmd_counter; - - switch (mode) { - case READ_LONG: - case WRITE_LONG: - buff[buf_size++] = len; - buff[buf_size++] = 2; - buff[buf_size++] = (reg >> 24); - buff[buf_size++] = (reg >> 16) & 0xff; - buff[buf_size++] = (reg >> 8) & 0xff; - buff[buf_size++] = reg & 0xff; - break; - case READ_SHORT: - buff[buf_size++] = addr; - break; - case WRITE_SHORT: - buff[buf_size++] = len; - buff[buf_size++] = addr; - buff[buf_size++] = (reg >> 8) & 0xff; - buff[buf_size++] = reg & 0xff; - break; - case READ_DATA: - case WRITE_DATA: - break; - case WRITE_CMD: - mode = 7; - break; - default: - kfree(buff); - return -EINVAL; - } - - if (mode & 1) { - for (i = 0; i < len ; i++) - buff[buf_size++] = data[i]; - } - chk_sum = check_sum(&buff[1], buf_size); - - buff[buf_size++] = chk_sum >> 8; - buff[0] = buf_size; - buff[buf_size++] = (chk_sum & 0xff); - - ret = dvb_usbv2_generic_rw(d, buff, buf_size, buff, (mode & 1) ? - 5 : len + 5); - if (ret < 0) - goto error; - - rlen = (mode & 0x1) ? 0x1 : len; - - if (mode & 1) - ret = buff[2]; - else - memcpy(data, &buff[3], rlen); - - st->cmd_counter++; - -error: kfree(buff); - - return ret; -} - -static int it913x_wr_reg(struct dvb_usb_device *d, u8 pro, u32 reg , u8 data) -{ - int ret; - u8 b[1]; - b[0] = data; - ret = it913x_io(d, WRITE_LONG, pro, - CMD_DEMOD_WRITE, reg, 0, b, sizeof(b)); - - return ret; -} - -static int it913x_read_reg(struct dvb_usb_device *d, u32 reg) -{ - int ret; - u8 data[1]; - - ret = it913x_io(d, READ_LONG, DEV_0, - CMD_DEMOD_READ, reg, 0, &data[0], sizeof(data)); - - return (ret < 0) ? ret : data[0]; -} - -static int it913x_query(struct dvb_usb_device *d, u8 pro) -{ - struct it913x_state *st = d->priv; - int ret, i; - u8 data[4]; - u8 ver; - - for (i = 0; i < 5; i++) { - ret = it913x_io(d, READ_LONG, pro, CMD_DEMOD_READ, - 0x1222, 0, &data[0], 3); - ver = data[0]; - if (ver > 0 && ver < 3) - break; - msleep(100); - } - - if (ver < 1 || ver > 2) { - info("Failed to identify chip version applying 1"); - st->it913x_config.chip_ver = 0x1; - st->it913x_config.chip_type = 0x9135; - return 0; - } - - st->it913x_config.chip_ver = ver; - st->it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; - - info("Chip Version=%02x Chip Type=%04x", st->it913x_config.chip_ver, - st->it913x_config.chip_type); - - ret = it913x_io(d, READ_SHORT, pro, - CMD_QUERYINFO, 0, 0x1, &data[0], 4); - - st->it913x_config.firmware = (data[0] << 24) | (data[1] << 16) | - (data[2] << 8) | data[3]; - - return ret; -} - -static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct dvb_usb_device *d = adap_to_d(adap); - struct it913x_state *st = adap_to_priv(adap); - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - mutex_lock(&d->i2c_mutex); - - deb_info(1, "PID_C (%02x)", onoff); - - st->pid_filter_onoff = adap->pid_filtering; - ret = it913x_wr_reg(d, pro, PID_EN, st->pid_filter_onoff); - - mutex_unlock(&d->i2c_mutex); - return ret; -} - -static int it913x_pid_filter(struct dvb_usb_adapter *adap, - int index, u16 pid, int onoff) -{ - struct dvb_usb_device *d = adap_to_d(adap); - struct it913x_state *st = adap_to_priv(adap); - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - mutex_lock(&d->i2c_mutex); - - deb_info(1, "PID_F (%02x)", onoff); - - ret = it913x_wr_reg(d, pro, PID_LSB, (u8)(pid & 0xff)); - - ret |= it913x_wr_reg(d, pro, PID_MSB, (u8)(pid >> 8)); - - ret |= it913x_wr_reg(d, pro, PID_INX_EN, (u8)onoff); - - ret |= it913x_wr_reg(d, pro, PID_INX, (u8)(index & 0x1f)); - - if (d->udev->speed == USB_SPEED_HIGH && pid == 0x2000) { - ret |= it913x_wr_reg(d , pro, PID_EN, !onoff); - st->pid_filter_onoff = !onoff; - } else - st->pid_filter_onoff = - adap->pid_filtering; - - mutex_unlock(&d->i2c_mutex); - return 0; -} - - -static int it913x_return_status(struct dvb_usb_device *d) -{ - struct it913x_state *st = d->priv; - int ret = it913x_query(d, DEV_0); - if (st->it913x_config.firmware > 0) - info("Firmware Version %d", st->it913x_config.firmware); - - return ret; -} - -static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - static u8 data[256]; - int ret; - u32 reg; - u8 pro; - - mutex_lock(&d->i2c_mutex); - - deb_info(2, "num of messages %d address %02x", num, msg[0].addr); - - pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0; - pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0; - memcpy(data, msg[0].buf, msg[0].len); - reg = (data[0] << 24) + (data[1] << 16) + - (data[2] << 8) + data[3]; - if (num == 2) { - ret = it913x_io(d, READ_LONG, pro, - CMD_DEMOD_READ, reg, 0, data, msg[1].len); - memcpy(msg[1].buf, data, msg[1].len); - } else - ret = it913x_io(d, WRITE_LONG, pro, CMD_DEMOD_WRITE, - reg, 0, &data[4], msg[0].len - 4); - - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static u32 it913x_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static struct i2c_algorithm it913x_i2c_algo = { - .master_xfer = it913x_i2c_xfer, - .functionality = it913x_i2c_func, -}; - -/* Callbacks for DVB USB */ -#if IS_ENABLED(CONFIG_RC_CORE) -static int it913x_rc_query(struct dvb_usb_device *d) -{ - u8 ibuf[4]; - int ret; - u32 key; - /* Avoid conflict with frontends*/ - mutex_lock(&d->i2c_mutex); - - ret = it913x_io(d, READ_LONG, PRO_LINK, CMD_IR_GET, - 0, 0, &ibuf[0], sizeof(ibuf)); - - if ((ibuf[2] + ibuf[3]) == 0xff) { - key = ibuf[2]; - key += ibuf[0] << 16; - key += ibuf[1] << 8; - deb_info(1, "NEC Extended Key =%08x", key); - if (d->rc_dev != NULL) - rc_keydown(d->rc_dev, key, 0); - } - - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) -{ - struct it913x_state *st = d->priv; - - if (st->proprietary_ir == false) { - rc->map_name = NULL; - return 0; - } - - rc->allowed_protos = RC_BIT_NEC; - rc->query = it913x_rc_query; - rc->interval = 250; - - return 0; -} -#else - #define it913x_get_rc_config NULL -#endif - -/* Firmware sets raw */ -static const char fw_it9135_v1[] = FW_IT9135_V1; -static const char fw_it9135_v2[] = FW_IT9135_V2; -static const char fw_it9137[] = FW_IT9137; - -static void ite_get_firmware_name(struct dvb_usb_device *d, - const char **name) -{ - struct it913x_state *st = d->priv; - int sw; - /* auto switch */ - if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_KWORLD_2) - sw = IT9137_FW; - else if (st->it913x_config.chip_ver == 1) - sw = IT9135_V1_FW; - else - sw = IT9135_V2_FW; - - /* force switch */ - if (dvb_usb_it913x_firmware != IT9135_AUTO) - sw = dvb_usb_it913x_firmware; - - switch (sw) { - case IT9135_V1_FW: - st->it913x_config.firmware_ver = 1; - st->it913x_config.adc_x2 = 1; - st->it913x_config.read_slevel = false; - *name = fw_it9135_v1; - break; - case IT9135_V2_FW: - st->it913x_config.firmware_ver = 1; - st->it913x_config.adc_x2 = 1; - st->it913x_config.read_slevel = false; - *name = fw_it9135_v2; - switch (st->it913x_config.tuner_id_0) { - case IT9135_61: - case IT9135_62: - break; - default: - info("Unknown tuner ID applying default 0x60"); - case IT9135_60: - st->it913x_config.tuner_id_0 = IT9135_60; - } - break; - case IT9137_FW: - default: - st->it913x_config.firmware_ver = 0; - st->it913x_config.adc_x2 = 0; - st->it913x_config.read_slevel = true; - *name = fw_it9137; - } - - return; -} - -#define TS_MPEG_PKT_SIZE 188 -#define EP_LOW 21 -#define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) -#define EP_HIGH 348 -#define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) - -static int it913x_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, - struct usb_data_stream_properties *stream) -{ - struct dvb_usb_adapter *adap = fe_to_adap(fe); - if (adap->pid_filtering) - stream->u.bulk.buffersize = TS_BUFFER_SIZE_PID; - else - stream->u.bulk.buffersize = TS_BUFFER_SIZE_MAX; - - return 0; -} - -static int it913x_select_config(struct dvb_usb_device *d) -{ - struct it913x_state *st = d->priv; - int ret, reg; - - ret = it913x_return_status(d); - if (ret < 0) - return ret; - - if (st->it913x_config.chip_ver == 0x02 - && st->it913x_config.chip_type == 0x9135) - reg = it913x_read_reg(d, 0x461d); - else - reg = it913x_read_reg(d, 0x461b); - - if (reg < 0) - return reg; - - if (reg == 0) { - st->it913x_config.dual_mode = 0; - st->it913x_config.tuner_id_0 = IT9135_38; - st->proprietary_ir = true; - } else { - /* TS mode */ - reg = it913x_read_reg(d, 0x49c5); - if (reg < 0) - return reg; - st->it913x_config.dual_mode = reg; - - /* IR mode type */ - reg = it913x_read_reg(d, 0x49ac); - if (reg < 0) - return reg; - if (reg == 5) { - info("Remote propriety (raw) mode"); - st->proprietary_ir = true; - } else if (reg == 1) { - info("Remote HID mode NOT SUPPORTED"); - st->proprietary_ir = false; - } - - /* Tuner_id */ - reg = it913x_read_reg(d, 0x49d0); - if (reg < 0) - return reg; - st->it913x_config.tuner_id_0 = reg; - } - - info("Dual mode=%x Tuner Type=%x", st->it913x_config.dual_mode, - st->it913x_config.tuner_id_0); - - return ret; -} - -static int it913x_streaming_ctrl(struct dvb_frontend *fe, int onoff) -{ - struct dvb_usb_adapter *adap = fe_to_adap(fe); - struct dvb_usb_device *d = adap_to_d(adap); - struct it913x_state *st = fe_to_priv(fe); - int ret = 0; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - deb_info(1, "STM (%02x)", onoff); - - if (!onoff) { - mutex_lock(&d->i2c_mutex); - - ret = it913x_wr_reg(d, pro, PID_RST, 0x1); - - mutex_unlock(&d->i2c_mutex); - st->pid_filter_onoff = - adap->pid_filtering; - - } - - return ret; -} - -static int it913x_identify_state(struct dvb_usb_device *d, const char **name) -{ - struct it913x_state *st = d->priv; - int ret; - u8 reg; - - /* Read and select config */ - ret = it913x_select_config(d); - if (ret < 0) - return ret; - - ite_get_firmware_name(d, name); - - if (st->it913x_config.firmware > 0) - return WARM; - - if (st->it913x_config.dual_mode) { - st->it913x_config.tuner_id_1 = it913x_read_reg(d, 0x49e0); - ret = it913x_wr_reg(d, DEV_0, GPIOH1_EN, 0x1); - ret |= it913x_wr_reg(d, DEV_0, GPIOH1_ON, 0x1); - ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); - msleep(50); - ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x0); - msleep(50); - reg = it913x_read_reg(d, GPIOH1_O); - if (reg == 0) { - ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); - ret |= it913x_return_status(d); - if (ret != 0) - ret = it913x_wr_reg(d, DEV_0, - GPIOH1_O, 0x0); - } - } - - reg = it913x_read_reg(d, IO_MUX_POWER_CLK); - - if (st->it913x_config.dual_mode) { - ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, CHIP2_I2C_ADDR); - if (st->it913x_config.firmware_ver == 1) - ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x1); - else - ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x1); - } else { - ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, 0x0); - if (st->it913x_config.firmware_ver == 1) - ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x0); - else - ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x0); - } - - ret |= it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); - - return (ret < 0) ? ret : COLD; -} - -static int it913x_download_firmware(struct dvb_usb_device *d, - const struct firmware *fw) -{ - struct it913x_state *st = d->priv; - int ret = 0, i = 0, pos = 0; - u8 packet_size, min_pkt; - u8 *fw_data; - - ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); - - info("FRM Starting Firmware Download"); - - /* Multi firmware loader */ - /* This uses scatter write firmware headers */ - /* The firmware must start with 03 XX 00 */ - /* and be the extact firmware length */ - - if (st->it913x_config.chip_ver == 2) - min_pkt = 0x11; - else - min_pkt = 0x19; - - while (i <= fw->size) { - if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0)) - || (i == fw->size)) { - packet_size = i - pos; - if ((packet_size > min_pkt) || (i == fw->size)) { - fw_data = (u8 *)(fw->data + pos); - pos += packet_size; - if (packet_size > 0) { - ret = it913x_io(d, WRITE_DATA, - DEV_0, CMD_SCATTER_WRITE, 0, - 0, fw_data, packet_size); - if (ret < 0) - break; - } - udelay(1000); - } - } - i++; - } - - if (ret < 0) - info("FRM Firmware Download Failed (%d)" , ret); - else - info("FRM Firmware Download Completed - Resetting Device"); - - msleep(30); - - ret = it913x_io(d, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); - if (ret < 0) - info("FRM Device not responding to reboot"); - - ret = it913x_return_status(d); - if (st->it913x_config.firmware == 0) { - info("FRM Failed to reboot device"); - return -ENODEV; - } - - msleep(30); - - ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_400); - - msleep(30); - - /* Tuner function */ - if (st->it913x_config.dual_mode) - ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0xa0); - else - ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0x68); - - if ((st->it913x_config.chip_ver == 1) && - (st->it913x_config.chip_type == 0x9135)) { - ret |= it913x_wr_reg(d, DEV_0, PADODPU, 0x0); - ret |= it913x_wr_reg(d, DEV_0, AGC_O_D, 0x0); - if (st->it913x_config.dual_mode) { - ret |= it913x_wr_reg(d, DEV_1, PADODPU, 0x0); - ret |= it913x_wr_reg(d, DEV_1, AGC_O_D, 0x0); - } - } - - return (ret < 0) ? -ENODEV : 0; -} - -static int it913x_name(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap_to_d(adap); - const char *desc = d->name; - char *fe_name[] = {"_1", "_2", "_3", "_4"}; - char *name = adap->fe[0]->ops.info.name; - - strlcpy(name, desc, 128); - strlcat(name, fe_name[adap->id], 128); - - return 0; -} - -static int it913x_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap_to_d(adap); - struct it913x_state *st = d->priv; - int ret = 0; - u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); - u16 ep_size = (adap->pid_filtering) ? TS_BUFFER_SIZE_PID / 4 : - TS_BUFFER_SIZE_MAX / 4; - u8 pkt_size = 0x80; - - if (d->udev->speed != USB_SPEED_HIGH) - pkt_size = 0x10; - - st->it913x_config.adf = it913x_read_reg(d, IO_MUX_POWER_CLK); - - adap->fe[0] = dvb_attach(it913x_fe_attach, - &d->i2c_adap, adap_addr, &st->it913x_config); - - if (adap->id == 0 && adap->fe[0]) { - it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x1); - it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1); - it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f); - it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b); - if (st->proprietary_ir == false) /* Enable endpoint 3 */ - it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x3f); - else - it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f); - it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB, - ep_size & 0xff); - it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8); - ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size); - } else if (adap->id == 1 && adap->fe[0]) { - if (st->proprietary_ir == false) - it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x7f); - else - it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f); - it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB, - ep_size & 0xff); - it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8); - it913x_wr_reg(d, DEV_0, EP5_MAX_PKT, pkt_size); - it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_EN, 0x1); - it913x_wr_reg(d, DEV_1_DMOD, MP2IF_SERIAL, 0x1); - it913x_wr_reg(d, DEV_1, TOP_HOSTB_SER_MODE, 0x1); - it913x_wr_reg(d, DEV_0_DMOD, TSIS_ENABLE, 0x1); - it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x0); - it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x0); - it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0); - it913x_wr_reg(d, DEV_0_DMOD, MP2IF_STOP_EN, 0x1); - it913x_wr_reg(d, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0); - ret = it913x_wr_reg(d, DEV_1_DMOD, MP2IF_STOP_EN, 0x0); - } else - return -ENODEV; - - ret |= it913x_name(adap); - - return ret; -} - -/* DVB USB Driver */ -static int it913x_get_adapter_count(struct dvb_usb_device *d) -{ - struct it913x_state *st = d->priv; - if (st->it913x_config.dual_mode) - return 2; - return 1; -} - -static struct dvb_usb_device_properties it913x_properties = { - .driver_name = KBUILD_MODNAME, - .owner = THIS_MODULE, - .bInterfaceNumber = 0, - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - - .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct it913x_state), - - .identify_state = it913x_identify_state, - .i2c_algo = &it913x_i2c_algo, - - .download_firmware = it913x_download_firmware, - - .frontend_attach = it913x_frontend_attach, - .get_rc_config = it913x_get_rc_config, - .get_stream_config = it913x_get_stream_config, - .get_adapter_count = it913x_get_adapter_count, - .streaming_ctrl = it913x_streaming_ctrl, - - - .adapter = { - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .pid_filter_count = 32, - .pid_filter = it913x_pid_filter, - .pid_filter_ctrl = it913x_pid_filter_ctrl, - .stream = - DVB_USB_STREAM_BULK(0x84, 10, TS_BUFFER_SIZE_MAX), - }, - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .pid_filter_count = 32, - .pid_filter = it913x_pid_filter, - .pid_filter_ctrl = it913x_pid_filter_ctrl, - .stream = - DVB_USB_STREAM_BULK(0x85, 10, TS_BUFFER_SIZE_MAX), - } - } -}; - -static const struct usb_device_id it913x_id_table[] = { - { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, - &it913x_properties, "Kworld UB499-2T T09(IT9137)", - RC_MAP_IT913X_V1) }, - { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, - &it913x_properties, "ITE 9135 Generic", - RC_MAP_IT913X_V1) }, - { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, - &it913x_properties, "Sveon STV22 Dual DVB-T HDTV(IT9137)", - RC_MAP_IT913X_V1) }, - { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, - &it913x_properties, "ITE 9135(9005) Generic", - RC_MAP_IT913X_V2) }, - { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, - &it913x_properties, "ITE 9135(9006) Generic", - RC_MAP_IT913X_V1) }, - { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_1835, - &it913x_properties, "Avermedia A835B(1835)", - RC_MAP_IT913X_V2) }, - { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_2835, - &it913x_properties, "Avermedia A835B(2835)", - RC_MAP_IT913X_V2) }, - { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_3835, - &it913x_properties, "Avermedia A835B(3835)", - RC_MAP_IT913X_V2) }, - { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, - &it913x_properties, "Avermedia A835B(4835)", - RC_MAP_IT913X_V2) }, - { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, - &it913x_properties, "Digital Dual TV Receiver CTVDIGDUAL_V2", - RC_MAP_IT913X_V1) }, - { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_H335, - &it913x_properties, "Avermedia H335", - RC_MAP_IT913X_V2) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, it913x_id_table); - -static struct usb_driver it913x_driver = { - .name = KBUILD_MODNAME, - .probe = dvb_usbv2_probe, - .disconnect = dvb_usbv2_disconnect, - .suspend = dvb_usbv2_suspend, - .resume = dvb_usbv2_resume, - .id_table = it913x_id_table, -}; - -module_usb_driver(it913x_driver); - -MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); -MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.33"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FW_IT9135_V1); -MODULE_FIRMWARE(FW_IT9135_V2); -MODULE_FIRMWARE(FW_IT9137); - diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index fda5c64ba0e8..c83c16cece01 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -24,6 +24,7 @@ #include "rtl2830.h" #include "rtl2832.h" +#include "rtl2832_sdr.h" #include "qt1010.h" #include "mt2060.h" @@ -35,6 +36,9 @@ #include "tua9001.h" #include "r820t.h" +static int rtl28xxu_disable_rc; +module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644); +MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) @@ -513,7 +517,7 @@ err: return ret; } -static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { +static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, .ts_mode = 0, @@ -524,7 +528,7 @@ static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { }; -static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { +static const struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, .ts_mode = 0, @@ -534,7 +538,7 @@ static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { .agc_targ_val = 0x2d, }; -static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { +static const struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, .ts_mode = 0, @@ -548,7 +552,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2830_config *rtl2830_config; + const struct rtl2830_config *rtl2830_config; int ret; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -583,33 +587,31 @@ err: return ret; } -static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { +static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, - .if_dvbt = 0, .tuner = TUNER_RTL2832_FC0012 }; -static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { +static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, - .if_dvbt = 0, .tuner = TUNER_RTL2832_FC0013 }; -static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { +static const struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, .tuner = TUNER_RTL2832_TUA9001, }; -static struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { +static const struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, .tuner = TUNER_RTL2832_E4000, }; -static struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { +static const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { .i2c_addr = 0x10, .xtal = 28800000, .tuner = TUNER_RTL2832_R820T, @@ -733,7 +735,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_config *rtl2832_config; + const struct rtl2832_config *rtl2832_config; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -772,6 +774,9 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) goto err; } + /* RTL2832 I2C repeater */ + priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]); + /* set fe callback */ adap->fe[0]->callback = rtl2832u_frontend_callback; @@ -851,11 +856,6 @@ err: return ret; } -static const struct e4000_config rtl2832u_e4000_config = { - .i2c_addr = 0x64, - .clock = 28800000, -}; - static const struct fc2580_config rtl2832u_fc2580_config = { .i2c_addr = 0x56, .clock = 16384000, @@ -889,10 +889,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct dvb_frontend *fe; + struct dvb_frontend *fe = NULL; + struct i2c_board_info info; + struct i2c_client *client; dev_dbg(&d->udev->dev, "%s:\n", __func__); + memset(&info, 0, sizeof(struct i2c_board_info)); + switch (priv->tuner) { case TUNER_RTL2832_FC0012: fe = dvb_attach(fc0012_attach, adap->fe[0], @@ -902,7 +906,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) * that to the tuner driver */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - return 0; + + /* attach SDR */ + dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + &rtl28xxu_rtl2832_fc0012_config, NULL); break; case TUNER_RTL2832_FC0013: fe = dvb_attach(fc0013_attach, adap->fe[0], @@ -911,10 +918,43 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* fc0013 also supports signal strength reading */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - return 0; - case TUNER_RTL2832_E4000: - fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap, - &rtl2832u_e4000_config); + + /* attach SDR */ + dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + &rtl28xxu_rtl2832_fc0013_config, NULL); + break; + case TUNER_RTL2832_E4000: { + struct v4l2_subdev *sd; + struct i2c_adapter *i2c_adap_internal = + rtl2832_get_private_i2c_adapter(adap->fe[0]); + struct e4000_config e4000_config = { + .fe = adap->fe[0], + .clock = 28800000, + }; + + strlcpy(info.type, "e4000", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &e4000_config; + + request_module(info.type); + client = i2c_new_device(priv->demod_i2c_adapter, &info); + if (client == NULL || client->dev.driver == NULL) + break; + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + break; + } + + priv->client = client; + sd = i2c_get_clientdata(client); + i2c_set_adapdata(i2c_adap_internal, d); + + /* attach SDR */ + dvb_attach(rtl2832_sdr_attach, adap->fe[0], + i2c_adap_internal, + &rtl28xxu_rtl2832_e4000_config, sd); + } break; case TUNER_RTL2832_FC2580: fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap, @@ -940,6 +980,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* Use tuner to get the signal strength */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; + + /* attach SDR */ + dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + &rtl28xxu_rtl2832_r820t_config, NULL); break; case TUNER_RTL2832_R828D: /* power off mn88472 demod on GPIO0 */ @@ -963,12 +1007,11 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[0]->ops.tuner_ops.get_rf_strength; break; default: - fe = NULL; dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, priv->tuner); } - if (fe == NULL) { + if (fe == NULL && priv->client == NULL) { ret = -ENODEV; goto err; } @@ -1013,6 +1056,22 @@ err: return ret; } +static void rtl28xxu_exit(struct dvb_usb_device *d) +{ + struct rtl28xxu_priv *priv = d->priv; + struct i2c_client *client = priv->client; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + return; +} + static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; @@ -1322,6 +1381,10 @@ err: static int rtl2832u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { + /* disable IR interrupts in order to avoid SDR sample loss */ + if (rtl28xxu_disable_rc) + return rtl28xx_wr_reg(d, IR_RX_IE, 0x00); + /* load empty to enable rc */ if (!rc->map_name) rc->map_name = RC_MAP_EMPTY; @@ -1371,6 +1434,7 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .frontend_attach = rtl2832u_frontend_attach, .tuner_attach = rtl2832u_tuner_attach, .init = rtl28xxu_init, + .exit = rtl28xxu_exit, .get_rc_config = rtl2832u_get_rc_config, .num_adapters = 1, @@ -1382,6 +1446,7 @@ static const struct dvb_usb_device_properties rtl2832u_props = { }; static const struct usb_device_id rtl28xxu_id_table[] = { + /* RTL2831U devices: */ { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, &rtl2831u_props, "Realtek RTL2831U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT, @@ -1389,6 +1454,7 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2, &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, + /* RTL2832U devices: */ { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832, &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, @@ -1401,6 +1467,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl2832u_props, "TerraTec NOXON DAB Stick", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2, &rtl2832u_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV3, + &rtl2832u_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0, &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101, @@ -1429,9 +1497,14 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, + { DVB_USB_DEVICE(USB_VID_KYE, 0x707f, + &rtl2832u_props, "Genius TVGo DVB-T03", NULL) }, + /* RTL2832P devices: */ { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, &rtl2832u_props, "Astrometa DVB-T2", NULL) }, + { DVB_USB_DEVICE(USB_VID_KYE, 0x707f, + &rtl2832u_props, "Genius TVGo DVB-T03", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 2142bcb41b41..a26cab10f382 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -55,7 +55,9 @@ struct rtl28xxu_priv { u8 tuner; char *tuner_name; u8 page; /* integrated demod active register page */ + struct i2c_adapter *demod_i2c_adapter; bool rc_active; + struct i2c_client *client; }; enum rtl28xxu_chip_id { |