diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
30 files changed, 454 insertions, 253 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 524533d3eb29..0e4944b2b0f4 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -156,3 +156,11 @@ config DVB_USB_DVBSKY select DVB_SP2 if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the USB receivers from DVBSky. + +config DVB_USB_ZD1301 + tristate "ZyDAS ZD1301" + depends on DVB_USB_V2 + select DVB_ZD1301_DEMOD if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the ZyDAS ZD1301 DVB USB receiver. diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile index f10d4df0eae5..969f68e55265 100644 --- a/drivers/media/usb/dvb-usb-v2/Makefile +++ b/drivers/media/usb/dvb-usb-v2/Makefile @@ -40,6 +40,9 @@ obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o dvb-usb-dvbsky-objs := dvbsky.o obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o +dvb-usb-zd1301-objs := zd1301.o +obj-$(CONFIG_DVB_USB_ZD1301) += zd1301.o + ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/tuners diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index 29011dfabb11..caa1e6101f58 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -15,10 +15,6 @@ * 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. - * */ #include "af9015.h" diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h index 1db1bb0d57bc..2dd9231a8ece 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.h +++ b/drivers/media/usb/dvb-usb-v2/af9015.h @@ -15,10 +15,6 @@ * 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. - * */ #ifndef AF9015_H diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index c673726d9b70..4df9486e19b9 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -335,14 +335,12 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || - (msg[0].addr == state->af9033_i2c_addr[1]) || - (state->chip_type == 0x9135)) { + (msg[0].addr == state->af9033_i2c_addr[1])) { /* demod access via firmware interface */ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | msg[0].buf[2]; - if (msg[0].addr == state->af9033_i2c_addr[1] || - msg[0].addr == (state->af9033_i2c_addr[1] >> 1)) + if (msg[0].addr == state->af9033_i2c_addr[1]) reg |= 0x100000; ret = af9035_rd_regs(d, reg, &msg[1].buf[0], @@ -396,14 +394,12 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; } else if ((msg[0].addr == state->af9033_i2c_addr[0]) || - (msg[0].addr == state->af9033_i2c_addr[1]) || - (state->chip_type == 0x9135)) { + (msg[0].addr == state->af9033_i2c_addr[1])) { /* demod access via firmware interface */ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | msg[0].buf[2]; - if (msg[0].addr == state->af9033_i2c_addr[1] || - msg[0].addr == (state->af9033_i2c_addr[1] >> 1)) + if (msg[0].addr == state->af9033_i2c_addr[1]) reg |= 0x100000; ret = af9035_wr_regs(d, reg, &msg[0].buf[3], @@ -496,7 +492,8 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) { struct state *state = d_to_priv(d); struct usb_interface *intf = d->intf; - int ret, ts_mode_invalid; + int ret, i, ts_mode_invalid; + unsigned int utmp, eeprom_addr; u8 tmp; u8 wbuf[1] = { 1 }; u8 rbuf[4]; @@ -518,25 +515,48 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) state->prechip_version, state->chip_version, state->chip_type); if (state->chip_type == 0x9135) { - if (state->chip_version == 0x02) + if (state->chip_version == 0x02) { *name = AF9035_FIRMWARE_IT9135_V2; - else + utmp = 0x00461d; + } else { *name = AF9035_FIRMWARE_IT9135_V1; - state->eeprom_addr = EEPROM_BASE_IT9135; + utmp = 0x00461b; + } + + /* Check if eeprom exists */ + ret = af9035_rd_reg(d, utmp, &tmp); + if (ret < 0) + goto err; + + if (tmp == 0x00) { + dev_dbg(&intf->dev, "no eeprom\n"); + state->no_eeprom = true; + goto check_firmware_status; + } + + eeprom_addr = EEPROM_BASE_IT9135; } else if (state->chip_type == 0x9306) { *name = AF9035_FIRMWARE_IT9303; - state->eeprom_addr = EEPROM_BASE_IT9135; + state->no_eeprom = true; + goto check_firmware_status; } else { *name = AF9035_FIRMWARE_AF9035; - state->eeprom_addr = EEPROM_BASE_AF9035; + eeprom_addr = EEPROM_BASE_AF9035; + } + + /* Read and store eeprom */ + for (i = 0; i < 256; i += 32) { + ret = af9035_rd_regs(d, eeprom_addr + i, &state->eeprom[i], 32); + if (ret < 0) + goto err; } + dev_dbg(&intf->dev, "eeprom dump:\n"); + for (i = 0; i < 256; i += 16) + dev_dbg(&intf->dev, "%*ph\n", 16, &state->eeprom[i]); /* check for dual tuner mode */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); - if (ret < 0) - goto err; - + tmp = state->eeprom[EEPROM_TS_MODE]; ts_mode_invalid = 0; switch (tmp) { case 0: @@ -560,7 +580,7 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) if (ts_mode_invalid) dev_info(&intf->dev, "ts mode=%d not supported, defaulting to single tuner mode!", tmp); - +check_firmware_status: ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; @@ -750,15 +770,11 @@ static int af9035_download_firmware(struct dvb_usb_device *d, goto err; /* tell the slave I2C address */ - ret = af9035_rd_reg(d, - state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR, - &tmp); - if (ret < 0) - goto err; + tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; - /* use default I2C address if eeprom has no address set */ + /* Use default I2C address if eeprom has no address set */ if (!tmp) - tmp = 0x3a; + tmp = 0x1d << 1; /* 8-bit format used by chip */ if ((state->chip_type == 0x9135) || (state->chip_type == 0x9306)) { @@ -819,11 +835,11 @@ static int af9035_read_config(struct dvb_usb_device *d) struct state *state = d_to_priv(d); int ret, i; u8 tmp; - u16 tmp16, addr; + u16 tmp16; - /* demod I2C "address" */ - state->af9033_i2c_addr[0] = 0x38; - state->af9033_i2c_addr[1] = 0x3a; + /* Demod I2C address */ + state->af9033_i2c_addr[0] = 0x1c; + state->af9033_i2c_addr[1] = 0x1d; 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; @@ -837,20 +853,16 @@ static int af9035_read_config(struct dvb_usb_device *d) if (state->chip_version == 0x02) { state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60; - tmp16 = 0x00461d; /* eeprom memory mapped location */ } else { state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38; - tmp16 = 0x00461b; /* eeprom memory mapped location */ } - /* check if eeprom exists */ - ret = af9035_rd_reg(d, tmp16, &tmp); - if (ret < 0) - goto err; + if (state->no_eeprom) { + /* Remote controller to NEC polling by default */ + state->ir_mode = 0x05; + state->ir_type = 0x00; - if (tmp == 0x00) { - dev_dbg(&intf->dev, "no eeprom\n"); goto skip_eeprom; } } else if (state->chip_type == 0x9306) { @@ -861,29 +873,25 @@ static int af9035_read_config(struct dvb_usb_device *d) return 0; } + /* Remote controller */ + state->ir_mode = state->eeprom[EEPROM_IR_MODE]; + state->ir_type = state->eeprom[EEPROM_IR_TYPE]; if (state->dual_mode) { - /* read 2nd demodulator I2C address */ - ret = af9035_rd_reg(d, - state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR, - &tmp); - if (ret < 0) - goto err; - + /* Read 2nd demodulator I2C address. 8-bit format on eeprom */ + tmp = state->eeprom[EEPROM_2ND_DEMOD_ADDR]; if (tmp) - state->af9033_i2c_addr[1] = tmp; + state->af9033_i2c_addr[1] = tmp >> 1; - dev_dbg(&intf->dev, "2nd demod I2C addr=%02x\n", tmp); + dev_dbg(&intf->dev, "2nd demod I2C addr=%02x\n", + state->af9033_i2c_addr[1]); } - addr = state->eeprom_addr; - for (i = 0; i < state->dual_mode + 1; i++) { - /* tuner */ - ret = af9035_rd_reg(d, addr + EEPROM_1_TUNER_ID, &tmp); - if (ret < 0) - goto err; + unsigned int eeprom_offset = 0; + /* tuner */ + tmp = state->eeprom[EEPROM_1_TUNER_ID + eeprom_offset]; dev_dbg(&intf->dev, "[%d]tuner=%02x\n", i, tmp); /* tuner sanity check */ @@ -956,21 +964,13 @@ static int af9035_read_config(struct dvb_usb_device *d) } /* tuner IF frequency */ - ret = af9035_rd_reg(d, addr + EEPROM_1_IF_L, &tmp); - if (ret < 0) - goto err; - - tmp16 = tmp; - - ret = af9035_rd_reg(d, addr + EEPROM_1_IF_H, &tmp); - if (ret < 0) - goto err; - + tmp = state->eeprom[EEPROM_1_IF_L + eeprom_offset]; + tmp16 = tmp << 0; + tmp = state->eeprom[EEPROM_1_IF_H + eeprom_offset]; tmp16 |= tmp << 8; - dev_dbg(&intf->dev, "[%d]IF=%d\n", i, tmp16); - addr += 0x10; /* shift for the 2nd tuner params */ + eeprom_offset += 0x10; /* shift for the 2nd tuner params */ } skip_eeprom: @@ -1247,30 +1247,11 @@ static int af9035_frontend_detach(struct dvb_usb_adapter *adap) struct state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); struct usb_interface *intf = d->intf; - int demod2; dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); - /* - * For dual tuner devices we have to resolve 2nd demod client, as there - * is two different kind of tuner drivers; one is using I2C binding - * and the other is using DVB attach/detach binding. - */ - switch (state->af9033_config[adap->id].tuner) { - case AF9033_TUNER_IT9135_38: - case AF9033_TUNER_IT9135_51: - case AF9033_TUNER_IT9135_52: - case AF9033_TUNER_IT9135_60: - case AF9033_TUNER_IT9135_61: - case AF9033_TUNER_IT9135_62: - demod2 = 2; - break; - default: - demod2 = 1; - } - if (adap->id == 1) { - if (state->i2c_client[demod2]) + if (state->i2c_client[1]) af9035_del_i2c_dev(d); } else if (adap->id == 0) { if (state->i2c_client[0]) @@ -1510,50 +1491,58 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) case AF9033_TUNER_IT9135_38: case AF9033_TUNER_IT9135_51: case AF9033_TUNER_IT9135_52: - { - struct it913x_config it913x_config = { - .fe = adap->fe[0], - .chip_ver = 1, - }; - - if (state->dual_mode) { - if (adap->id == 0) - it913x_config.role = IT913X_ROLE_DUAL_MASTER; - else - it913x_config.role = IT913X_ROLE_DUAL_SLAVE; - } - - ret = af9035_add_i2c_dev(d, "it913x", - state->af9033_i2c_addr[adap->id] >> 1, - &it913x_config, &d->i2c_adap); - if (ret) - goto err; - - fe = adap->fe[0]; - break; - } case AF9033_TUNER_IT9135_60: case AF9033_TUNER_IT9135_61: case AF9033_TUNER_IT9135_62: { - struct it913x_config it913x_config = { + struct platform_device *pdev; + const char *name; + struct it913x_platform_data it913x_pdata = { + .regmap = state->af9033_config[adap->id].regmap, .fe = adap->fe[0], - .chip_ver = 2, }; + switch (state->af9033_config[adap->id].tuner) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + name = "it9133ax-tuner"; + break; + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + name = "it9133bx-tuner"; + break; + default: + ret = -ENODEV; + goto err; + } + if (state->dual_mode) { if (adap->id == 0) - it913x_config.role = IT913X_ROLE_DUAL_MASTER; + it913x_pdata.role = IT913X_ROLE_DUAL_MASTER; else - it913x_config.role = IT913X_ROLE_DUAL_SLAVE; + it913x_pdata.role = IT913X_ROLE_DUAL_SLAVE; + } else { + it913x_pdata.role = IT913X_ROLE_SINGLE; } - ret = af9035_add_i2c_dev(d, "it913x", - state->af9033_i2c_addr[adap->id] >> 1, - &it913x_config, &d->i2c_adap); - if (ret) + request_module("%s", "it913x"); + pdev = platform_device_register_data(&d->intf->dev, name, + PLATFORM_DEVID_AUTO, + &it913x_pdata, + sizeof(it913x_pdata)); + if (IS_ERR(pdev) || !pdev->dev.driver) { + ret = -ENODEV; + goto err; + } + if (!try_module_get(pdev->dev.driver->owner)) { + platform_device_unregister(pdev); + ret = -ENODEV; goto err; + } + state->platform_device_tuner[adap->id] = pdev; fe = adap->fe[0]; break; } @@ -1675,12 +1664,6 @@ static int af9035_tuner_detach(struct dvb_usb_adapter *adap) switch (state->af9033_config[adap->id].tuner) { case AF9033_TUNER_TUA9001: case AF9033_TUNER_FC2580: - case AF9033_TUNER_IT9135_38: - case AF9033_TUNER_IT9135_51: - case AF9033_TUNER_IT9135_52: - case AF9033_TUNER_IT9135_60: - case AF9033_TUNER_IT9135_61: - case AF9033_TUNER_IT9135_62: if (adap->id == 1) { if (state->i2c_client[3]) af9035_del_i2c_dev(d); @@ -1688,6 +1671,23 @@ static int af9035_tuner_detach(struct dvb_usb_adapter *adap) if (state->i2c_client[1]) af9035_del_i2c_dev(d); } + break; + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + { + struct platform_device *pdev; + + pdev = state->platform_device_tuner[adap->id]; + if (pdev) { + module_put(pdev->dev.driver->owner); + platform_device_unregister(pdev); + } + break; + } } return 0; @@ -1872,25 +1872,13 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { struct state *state = d_to_priv(d); struct usb_interface *intf = d->intf; - int ret; - u8 tmp; - - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_MODE, &tmp); - if (ret < 0) - goto err; - dev_dbg(&intf->dev, "ir_mode=%02x\n", tmp); + dev_dbg(&intf->dev, "ir_mode=%02x ir_type=%02x\n", + state->ir_mode, state->ir_type); /* don't activate rc if in HID mode or if not available */ - if (tmp == 5) { - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_TYPE, - &tmp); - if (ret < 0) - goto err; - - dev_dbg(&intf->dev, "ir_type=%02x\n", tmp); - - switch (tmp) { + if (state->ir_mode == 0x05) { + switch (state->ir_type) { case 0: /* NEC */ default: rc->allowed_protos = RC_BIT_NEC | RC_BIT_NECX | @@ -1910,11 +1898,6 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) } return 0; - -err: - dev_dbg(&intf->dev, "failed=%d\n", ret); - - return ret; } #else #define af9035_get_rc_config NULL diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 1f83c9218ad0..a76e6bf0ab1e 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -22,6 +22,7 @@ #ifndef AF9035_H #define AF9035_H +#include <linux/platform_device.h> #include "dvb_usb.h" #include "af9033.h" #include "tua9001.h" @@ -61,15 +62,19 @@ struct state { u8 prechip_version; u8 chip_version; u16 chip_type; + u8 eeprom[256]; + bool no_eeprom; + u8 ir_mode; + u8 ir_type; u8 dual_mode:1; u8 no_read:1; - u16 eeprom_addr; u8 af9033_i2c_addr[2]; struct af9033_config af9033_config[2]; struct af9033_ops ops; #define AF9035_I2C_CLIENT_MAX 4 struct i2c_client *i2c_client[AF9035_I2C_CLIENT_MAX]; struct i2c_adapter *i2c_adapter_demod; + struct platform_device *platform_device_tuner[2]; }; static const u32 clock_lut_af9035[] = { diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index ae917c042a52..6795c0c609b1 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c @@ -13,10 +13,6 @@ * 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. - * * TODO: * - add smart card reader support for Conditional Access (CA) * diff --git a/drivers/media/usb/dvb-usb-v2/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h index 3ca2bca4ebaf..393e2fce2aed 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.h +++ b/drivers/media/usb/dvb-usb-v2/anysee.h @@ -13,10 +13,6 @@ * 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. - * * TODO: * - add smart card reader support for Conditional Access (CA) * diff --git a/drivers/media/usb/dvb-usb-v2/au6610.c b/drivers/media/usb/dvb-usb-v2/au6610.c index ae6a671b7fd5..6ee01cb64ca5 100644 --- a/drivers/media/usb/dvb-usb-v2/au6610.c +++ b/drivers/media/usb/dvb-usb-v2/au6610.c @@ -12,10 +12,6 @@ * 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. */ #include "au6610.h" diff --git a/drivers/media/usb/dvb-usb-v2/au6610.h b/drivers/media/usb/dvb-usb-v2/au6610.h index ea337bfc00b1..aacfcc6fa0f5 100644 --- a/drivers/media/usb/dvb-usb-v2/au6610.h +++ b/drivers/media/usb/dvb-usb-v2/au6610.h @@ -12,10 +12,6 @@ * 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. */ #ifndef AU6610_H diff --git a/drivers/media/usb/dvb-usb-v2/ce6230.c b/drivers/media/usb/dvb-usb-v2/ce6230.c index f67b14bc32e3..e596031a708d 100644 --- a/drivers/media/usb/dvb-usb-v2/ce6230.c +++ b/drivers/media/usb/dvb-usb-v2/ce6230.c @@ -13,10 +13,6 @@ * 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. - * */ #include "ce6230.h" diff --git a/drivers/media/usb/dvb-usb-v2/ce6230.h b/drivers/media/usb/dvb-usb-v2/ce6230.h index 299e57e3390b..b25b3b938e49 100644 --- a/drivers/media/usb/dvb-usb-v2/ce6230.h +++ b/drivers/media/usb/dvb-usb-v2/ce6230.h @@ -13,10 +13,6 @@ * 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. - * */ #ifndef CE6230_H 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 a8e6624fbe83..955fb0d07507 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -147,7 +147,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) if (!d->rc.map_name) return 0; - dev = rc_allocate_device(); + dev = rc_allocate_device(d->rc.driver_type); if (!dev) { ret = -ENOMEM; goto err; @@ -162,7 +162,6 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) /* TODO: likely RC-core should took const char * */ dev->driver_name = (char *) d->props->driver_name; dev->map_name = d->rc.map_name; - dev->driver_type = d->rc.driver_type; dev->allowed_protocols = d->rc.allowed_protos; dev->change_protocol = d->rc.change_protocol; dev->priv = d; @@ -1013,8 +1012,8 @@ EXPORT_SYMBOL(dvb_usbv2_probe); void dvb_usbv2_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); - const char *name = d->name; - struct device dev = d->udev->dev; + const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL); + const char *drvname = d->name; dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, intf->cur_altsetting->desc.bInterfaceNumber); @@ -1024,8 +1023,9 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) dvb_usbv2_exit(d); - dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", - KBUILD_MODNAME, name); + pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n", + KBUILD_MODNAME, drvname, devname); + kfree(devname); } EXPORT_SYMBOL(dvb_usbv2_disconnect); diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 0636eac37bbb..5730760e4e93 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -12,10 +12,6 @@ * 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. */ #include "dvb_usb.h" diff --git a/drivers/media/usb/dvb-usb-v2/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c index 0c2b377704ff..1db8aeef3655 100644 --- a/drivers/media/usb/dvb-usb-v2/ec168.c +++ b/drivers/media/usb/dvb-usb-v2/ec168.c @@ -13,10 +13,6 @@ * 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. - * */ #include "ec168.h" diff --git a/drivers/media/usb/dvb-usb-v2/ec168.h b/drivers/media/usb/dvb-usb-v2/ec168.h index 615a6569421f..704955bcaa10 100644 --- a/drivers/media/usb/dvb-usb-v2/ec168.h +++ b/drivers/media/usb/dvb-usb-v2/ec168.h @@ -13,10 +13,6 @@ * 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. - * */ #ifndef EC168_H diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 5fea02672685..924adfdb660d 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -48,10 +48,6 @@ * 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 * @@ -99,9 +95,7 @@ static int dvb_usb_lme2510_debug; } while (0) #define deb_info(level, args...) lme_debug(dvb_usb_lme2510_debug, level, args) #define debug_data_snipet(level, name, p) \ - deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \ - *p, *(p+1), *(p+2), *(p+3), *(p+4), \ - *(p+5), *(p+6), *(p+7)); + deb_info(level, name" (%8phN)", p); #define info(args...) pr_info(DVB_USB_LOG_PREFIX": "args) module_param_named(debug, dvb_usb_lme2510_debug, int, 0644); @@ -315,7 +309,7 @@ static void lme2510_int_response(struct urb *lme_urb) { struct dvb_usb_adapter *adap = lme_urb->context; struct lme2510_state *st = adap_to_priv(adap); - static u8 *ibuf, *rbuf; + u8 *ibuf, *rbuf; int i = 0, offset; u32 key; u8 signal_lock = 0; @@ -1002,8 +996,9 @@ static int lme_name(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *st = adap_to_priv(adap); const char *desc = d->name; - char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", - " SHARP:BS2F7HZ0194", " RS2000"}; + static const char * const fe_name[] = { + "", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", + " SHARP:BS2F7HZ0194", " RS2000"}; char *name = adap->fe[0]->ops.info.name; strlcpy(name, desc, 128); @@ -1124,7 +1119,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *st = adap_to_priv(adap); - char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; + static const char * const tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; int ret = 0; switch (st->tuner_config) { @@ -1178,10 +1173,7 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff) mutex_lock(&d->i2c_mutex); - if (onoff) - ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); - else - ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); + ret = lme2510_usb_talk(d, onoff ? lnb_on : lnb_off, len, rbuf, rlen); st->i2c_talk_onoff = 1; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index 639e156e0c1b..f0ed37da73d4 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -12,10 +12,6 @@ * 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. */ #include "mxl111sf-demod.h" diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h index e6eae9d88e9f..9cb4972ce7a3 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h @@ -12,10 +12,6 @@ * 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. */ #ifndef __MXL111SF_DEMOD_H__ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c index 2180c13a6dcc..c66861c9342b 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c @@ -12,10 +12,6 @@ * 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. */ #include "mxl111sf-gpio.h" diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h index 16fa4d4daf88..af2c7bc8f301 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h @@ -12,10 +12,6 @@ * 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. */ #ifndef _DVB_USB_MXL111SF_GPIO_H_ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index 6427137a09ef..ffb49c28b15a 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -12,10 +12,6 @@ * 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. */ #include "mxl111sf-i2c.h" diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h index c486fe02f018..28877c7a8175 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h @@ -12,10 +12,6 @@ * 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. */ #ifndef _DVB_USB_MXL111SF_I2C_H_ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c index 5b0191178f9f..ffb6e7c72f57 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c @@ -12,10 +12,6 @@ * 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. */ #include "mxl111sf-phy.h" diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h index 25aa4a1ea755..0a61e8a56584 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h @@ -12,10 +12,6 @@ * 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. */ #ifndef _DVB_USB_MXL111SF_PHY_H_ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h index 1f4bfbcdbabb..ad3f806dcc7a 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h @@ -12,10 +12,6 @@ * 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. */ #ifndef _DVB_USB_MXL111SF_REG_H_ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index f84bef6034dc..240d736bf1bb 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -12,10 +12,6 @@ * 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. */ #include "mxl111sf-tuner.h" diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index e96d9a444ed1..11ea07a73271 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -12,10 +12,6 @@ * 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. */ #ifndef __MXL111SF_TUNER_H__ diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index c583c638e468..e16ca07acf1d 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1778,7 +1778,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, /* load empty to enable rc */ if (!rc->map_name) rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_BIT_ALL; + rc->allowed_protos = RC_BIT_ALL_IR_DECODER; rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 200; diff --git a/drivers/media/usb/dvb-usb-v2/zd1301.c b/drivers/media/usb/dvb-usb-v2/zd1301.c new file mode 100644 index 000000000000..d1eb4b7bc051 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/zd1301.c @@ -0,0 +1,298 @@ +/* + * ZyDAS ZD1301 driver (USB interface) + * + * Copyright (C) 2015 Antti Palosaari <crope@iki.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#include "dvb_usb.h" +#include "zd1301_demod.h" +#include "mt2060.h" +#include <linux/i2c.h> +#include <linux/platform_device.h> + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +struct zd1301_dev { + #define BUF_LEN 8 + u8 buf[BUF_LEN]; /* bulk USB control message */ + struct zd1301_demod_platform_data demod_pdata; + struct mt2060_platform_data mt2060_pdata; + struct platform_device *platform_device_demod; + struct i2c_client *i2c_client_tuner; +}; + +static int zd1301_ctrl_msg(struct dvb_usb_device *d, const u8 *wbuf, + unsigned int wlen, u8 *rbuf, unsigned int rlen) +{ + struct zd1301_dev *dev = d_to_priv(d); + struct usb_interface *intf = d->intf; + int ret, actual_length; + + mutex_lock(&d->usb_mutex); + + memcpy(&dev->buf, wbuf, wlen); + + dev_dbg(&intf->dev, ">>> %*ph\n", wlen, dev->buf); + + ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, 0x04), dev->buf, + wlen, &actual_length, 1000); + if (ret) { + dev_err(&intf->dev, "1st usb_bulk_msg() failed %d\n", ret); + goto err_mutex_unlock; + } + + if (rlen) { + ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 0x83), + dev->buf, rlen, &actual_length, 1000); + if (ret) { + dev_err(&intf->dev, + "2nd usb_bulk_msg() failed %d\n", ret); + goto err_mutex_unlock; + } + + dev_dbg(&intf->dev, "<<< %*ph\n", actual_length, dev->buf); + + if (actual_length != rlen) { + /* + * Chip replies often with 3 byte len stub. On that case + * we have to query new reply. + */ + dev_dbg(&intf->dev, "repeating reply message\n"); + + ret = usb_bulk_msg(d->udev, + usb_rcvbulkpipe(d->udev, 0x83), + dev->buf, rlen, &actual_length, + 1000); + if (ret) { + dev_err(&intf->dev, + "3rd usb_bulk_msg() failed %d\n", ret); + goto err_mutex_unlock; + } + + dev_dbg(&intf->dev, + "<<< %*ph\n", actual_length, dev->buf); + } + + memcpy(rbuf, dev->buf, rlen); + } + +err_mutex_unlock: + mutex_unlock(&d->usb_mutex); + return ret; +} + +static int zd1301_demod_wreg(void *reg_priv, u16 reg, u8 val) +{ + struct dvb_usb_device *d = reg_priv; + struct usb_interface *intf = d->intf; + int ret; + u8 buf[7] = {0x07, 0x00, 0x03, 0x01, + (reg >> 0) & 0xff, (reg >> 8) & 0xff, val}; + + ret = zd1301_ctrl_msg(d, buf, 7, NULL, 0); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); + return ret; +} + +static int zd1301_demod_rreg(void *reg_priv, u16 reg, u8 *val) +{ + struct dvb_usb_device *d = reg_priv; + struct usb_interface *intf = d->intf; + int ret; + u8 buf[7] = {0x07, 0x00, 0x04, 0x01, + (reg >> 0) & 0xff, (reg >> 8) & 0xff, 0}; + + ret = zd1301_ctrl_msg(d, buf, 7, buf, 7); + if (ret) + goto err; + + *val = buf[6]; + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); + return ret; +} + +static int zd1301_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct zd1301_dev *dev = adap_to_priv(adap); + struct usb_interface *intf = d->intf; + struct platform_device *pdev; + struct i2c_client *client; + struct i2c_board_info board_info; + struct i2c_adapter *adapter; + struct dvb_frontend *frontend; + int ret; + + dev_dbg(&intf->dev, "\n"); + + /* Add platform demod */ + dev->demod_pdata.reg_priv = d; + dev->demod_pdata.reg_read = zd1301_demod_rreg; + dev->demod_pdata.reg_write = zd1301_demod_wreg; + request_module("%s", "zd1301_demod"); + pdev = platform_device_register_data(&intf->dev, + "zd1301_demod", + PLATFORM_DEVID_AUTO, + &dev->demod_pdata, + sizeof(dev->demod_pdata)); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + goto err; + } + if (!pdev->dev.driver) { + ret = -ENODEV; + goto err; + } + if (!try_module_get(pdev->dev.driver->owner)) { + ret = -ENODEV; + goto err_platform_device_unregister; + } + + adapter = zd1301_demod_get_i2c_adapter(pdev); + frontend = zd1301_demod_get_dvb_frontend(pdev); + if (!adapter || !frontend) { + ret = -ENODEV; + goto err_module_put_demod; + } + + /* Add I2C tuner */ + dev->mt2060_pdata.i2c_write_max = 9; + dev->mt2060_pdata.dvb_frontend = frontend; + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "mt2060", I2C_NAME_SIZE); + board_info.addr = 0x60; + board_info.platform_data = &dev->mt2060_pdata; + request_module("%s", "mt2060"); + client = i2c_new_device(adapter, &board_info); + if (!client || !client->dev.driver) { + ret = -ENODEV; + goto err_module_put_demod; + } + if (!try_module_get(client->dev.driver->owner)) { + ret = -ENODEV; + goto err_i2c_unregister_device; + } + + dev->platform_device_demod = pdev; + dev->i2c_client_tuner = client; + adap->fe[0] = frontend; + + return 0; +err_i2c_unregister_device: + i2c_unregister_device(client); +err_module_put_demod: + module_put(pdev->dev.driver->owner); +err_platform_device_unregister: + platform_device_unregister(pdev); +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); + return ret; +} + +static int zd1301_frontend_detach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct zd1301_dev *dev = d_to_priv(d); + struct usb_interface *intf = d->intf; + struct platform_device *pdev; + struct i2c_client *client; + + dev_dbg(&intf->dev, "\n"); + + client = dev->i2c_client_tuner; + pdev = dev->platform_device_demod; + + /* Remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + /* Remove platform demod */ + if (pdev) { + module_put(pdev->dev.driver->owner); + platform_device_unregister(pdev); + } + + return 0; +} + +static int zd1301_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct dvb_usb_device *d = fe_to_d(fe); + struct usb_interface *intf = d->intf; + int ret; + u8 buf[3] = {0x03, 0x00, onoff ? 0x07 : 0x08}; + + dev_dbg(&intf->dev, "onoff=%d\n", onoff); + + ret = zd1301_ctrl_msg(d, buf, 3, NULL, 0); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&intf->dev, "failed=%d\n", ret); + return ret; +} + +static const struct dvb_usb_device_properties zd1301_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct zd1301_dev), + + .frontend_attach = zd1301_frontend_attach, + .frontend_detach = zd1301_frontend_detach, + .streaming_ctrl = zd1301_streaming_ctrl, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_BULK(0x81, 6, 21 * 188), + }, + }, +}; + +static const struct usb_device_id zd1301_id_table[] = { + {DVB_USB_DEVICE(USB_VID_ZYDAS, 0x13a1, &zd1301_props, + "ZyDAS ZD1301 reference design", NULL)}, + {} +}; +MODULE_DEVICE_TABLE(usb, zd1301_id_table); + +/* Usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver zd1301_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = zd1301_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, +}; +module_usb_driver(zd1301_usb_driver); + +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("ZyDAS ZD1301 driver"); +MODULE_LICENSE("GPL"); |