diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
33 files changed, 1641 insertions, 1796 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 834bfecbed7..037e519bbaa 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -1,6 +1,6 @@ config DVB_USB_V2 tristate "Support for various USB DVB devices v2" - depends on DVB_CORE && USB && I2C && RC_CORE + depends on DVB_CORE && USB && I2C && (RC_CORE || RC_CORE=n) help By enabling this you will be able to choose the various supported USB1.1 and USB2.0 DVB devices. @@ -13,10 +13,6 @@ config DVB_USB_V2 Say Y if you own a USB DVB device. -config DVB_USB_CYPRESS_FIRMWARE - tristate "Cypress firmware helper routines" - depends on DVB_USB_V2 - config DVB_USB_AF9015 tristate "Afatech AF9015 DVB-T USB2.0 support" depends on DVB_USB_V2 @@ -41,6 +37,7 @@ config DVB_USB_AF9035 select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_IT913X if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the Afatech AF9035 based DVB USB receiver. @@ -72,7 +69,7 @@ config DVB_USB_AU6610 config DVB_USB_AZ6007 tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" depends on DVB_USB_V2 - select DVB_USB_CYPRESS_FIRMWARE + select CYPRESS_FIRMWARE select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT help @@ -103,16 +100,10 @@ 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 + depends on RC_CORE select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT @@ -120,6 +111,7 @@ config DVB_USB_LME2510 select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 @@ -134,7 +126,7 @@ config DVB_USB_MXL111SF config DVB_USB_RTL28XXU tristate "Realtek RTL28xxU DVB USB support" - depends on DVB_USB_V2 && EXPERIMENTAL + depends on DVB_USB_V2 && I2C_MUX select DVB_RTL2830 select DVB_RTL2832 select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT @@ -144,6 +136,7 @@ config DVB_USB_RTL28XXU select MEDIA_TUNER_FC0013 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_E4000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_R820T if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the Realtek RTL28xxU DVB USB receiver. diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile index b76f58e6c64..bc38f03394c 100644 --- a/drivers/media/usb/dvb-usb-v2/Makefile +++ b/drivers/media/usb/dvb-usb-v2/Makefile @@ -1,9 +1,6 @@ dvb_usb_v2-objs := dvb_usb_core.o dvb_usb_urb.o usb_urb.o obj-$(CONFIG_DVB_USB_V2) += dvb_usb_v2.o -dvb_usb_cypress_firmware-objs := cypress_firmware.o -obj-$(CONFIG_DVB_USB_CYPRESS_FIRMWARE) += dvb_usb_cypress_firmware.o - dvb-usb-af9015-objs := af9015.o obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o @@ -25,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 @@ -46,4 +40,4 @@ obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o 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 diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index 3d7526e28d4..da47d2392f2 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -30,22 +30,22 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) { -#define BUF_LEN 63 #define REQ_HDR_LEN 8 /* send header size */ #define ACK_HDR_LEN 2 /* rece header size */ struct af9015_state *state = d_to_priv(d); int ret, wlen, rlen; - u8 buf[BUF_LEN]; u8 write = 1; - buf[0] = req->cmd; - buf[1] = state->seq++; - buf[2] = req->i2c_addr; - buf[3] = req->addr >> 8; - buf[4] = req->addr & 0xff; - buf[5] = req->mbox; - buf[6] = req->addr_len; - buf[7] = req->data_len; + mutex_lock(&d->usb_mutex); + + state->buf[0] = req->cmd; + state->buf[1] = state->seq++; + state->buf[2] = req->i2c_addr; + state->buf[3] = req->addr >> 8; + state->buf[4] = req->addr & 0xff; + state->buf[5] = req->mbox; + state->buf[6] = req->addr_len; + state->buf[7] = req->data_len; switch (req->cmd) { case GET_CONFIG: @@ -55,14 +55,14 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) break; case READ_I2C: write = 0; - buf[2] |= 0x01; /* set I2C direction */ + state->buf[2] |= 0x01; /* set I2C direction */ case WRITE_I2C: - buf[0] = READ_WRITE_I2C; + state->buf[0] = READ_WRITE_I2C; break; case WRITE_MEMORY: if (((req->addr & 0xff00) == 0xff00) || ((req->addr & 0xff00) == 0xae00)) - buf[0] = WRITE_VIRTUAL_MEMORY; + state->buf[0] = WRITE_VIRTUAL_MEMORY; case WRITE_VIRTUAL_MEMORY: case COPY_FIRMWARE: case DOWNLOAD_FIRMWARE: @@ -90,7 +90,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) rlen = ACK_HDR_LEN; if (write) { wlen += req->data_len; - memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); + memcpy(&state->buf[REQ_HDR_LEN], req->data, req->data_len); } else { rlen += req->data_len; } @@ -99,22 +99,25 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) rlen = 0; - ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); + ret = dvb_usbv2_generic_rw_locked(d, + state->buf, wlen, state->buf, rlen); if (ret) goto error; /* check status */ - if (rlen && buf[1]) { + if (rlen && state->buf[1]) { dev_err(&d->udev->dev, "%s: command failed=%d\n", - KBUILD_MODNAME, buf[1]); + KBUILD_MODNAME, state->buf[1]); ret = -EIO; goto error; } /* read request, copy returned data to return buf */ if (!write) - memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); + memcpy(req->data, &state->buf[ACK_HDR_LEN], req->data_len); error: + mutex_unlock(&d->usb_mutex); + return ret; } @@ -394,12 +397,13 @@ error: return ret; } +#define AF9015_EEPROM_SIZE 256 + /* hash (and dump) eeprom */ static int af9015_eeprom_hash(struct dvb_usb_device *d) { struct af9015_state *state = d_to_priv(d); int ret, i; - static const unsigned int AF9015_EEPROM_SIZE = 256; u8 buf[AF9015_EEPROM_SIZE]; struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL}; @@ -1156,6 +1160,7 @@ error: return ret; } +#if IS_ENABLED(CONFIG_RC_CORE) struct af9015_rc_setup { unsigned int id; char *rc_codes; @@ -1306,12 +1311,52 @@ static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) if (!rc->map_name) rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_TYPE_NEC; + rc->allowed_protos = RC_BIT_NEC; rc->query = af9015_rc_query; rc->interval = 500; return 0; } +#else + #define af9015_get_rc_config NULL +#endif + +static int af9015_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + char manufacturer[sizeof("ITE Technologies, Inc.")]; + + memset(manufacturer, 0, sizeof(manufacturer)); + usb_string(udev, udev->descriptor.iManufacturer, + manufacturer, sizeof(manufacturer)); + /* + * There is two devices having same ID but different chipset. One uses + * AF9015 and the other IT9135 chipset. Only difference seen on lsusb + * is iManufacturer string. + * + * idVendor 0x0ccd TerraTec Electronic GmbH + * idProduct 0x0099 + * bcdDevice 2.00 + * iManufacturer 1 Afatech + * iProduct 2 DVB-T 2 + * + * idVendor 0x0ccd TerraTec Electronic GmbH + * idProduct 0x0099 + * bcdDevice 2.00 + * iManufacturer 1 ITE Technologies, Inc. + * iProduct 2 DVB-T TV Stick + */ + if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && + (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { + if (!strcmp("ITE Technologies, Inc.", manufacturer)) { + dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); + return -ENODEV; + } + } + + return dvb_usbv2_probe(intf, id); +} /* interface 0 is used by DVB-T receiver and interface 1 is for remote controller (HID) */ @@ -1421,6 +1466,7 @@ static const struct usb_device_id af9015_id_table[] = { &af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC, &af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) }, + /* XXX: that same ID [0ccd:0099] is used by af9035 driver too */ { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, &af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) }, { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T, @@ -1437,7 +1483,7 @@ MODULE_DEVICE_TABLE(usb, af9015_id_table); static struct usb_driver af9015_usb_driver = { .name = KBUILD_MODNAME, .id_table = af9015_id_table, - .probe = dvb_usbv2_probe, + .probe = af9015_probe, .disconnect = dvb_usbv2_disconnect, .suspend = dvb_usbv2_suspend, .resume = dvb_usbv2_resume, diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h index 533637dedd2..3a6f3ad1ead 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.h +++ b/drivers/media/usb/dvb-usb-v2/af9015.h @@ -115,7 +115,9 @@ enum af9015_ir_mode { AF9015_IR_MODE_POLLING, /* just guess */ }; +#define BUF_LEN 63 struct af9015_state { + u8 buf[BUF_LEN]; /* bulk USB control message */ u8 ir_mode; u8 rc_repeat; u32 rc_keycode; diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index ea27eaff4e3..7b9b75f6077 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -21,6 +21,9 @@ #include "af9035.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static u16 af9035_checksum(const u8 *buf, size_t len) @@ -41,88 +44,100 @@ static u16 af9035_checksum(const u8 *buf, size_t len) static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) { -#define BUF_LEN 64 #define REQ_HDR_LEN 4 /* send header size */ #define ACK_HDR_LEN 3 /* rece header size */ #define CHECKSUM_LEN 2 #define USB_TIMEOUT 2000 struct state *state = d_to_priv(d); int ret, wlen, rlen; - u8 buf[BUF_LEN]; u16 checksum, tmp_checksum; + mutex_lock(&d->usb_mutex); + /* buffer overflow check */ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", - __func__, req->wlen, req->rlen); - return -EINVAL; + KBUILD_MODNAME, req->wlen, req->rlen); + ret = -EINVAL; + goto exit; } - buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; - buf[1] = req->mbox; - buf[2] = req->cmd; - buf[3] = state->seq++; - memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen); + state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; + state->buf[1] = req->mbox; + state->buf[2] = req->cmd; + state->buf[3] = state->seq++; + memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen); wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; /* calc and add checksum */ - checksum = af9035_checksum(buf, buf[0] - 1); - buf[buf[0] - 1] = (checksum >> 8); - buf[buf[0] - 0] = (checksum & 0xff); + checksum = af9035_checksum(state->buf, state->buf[0] - 1); + state->buf[state->buf[0] - 1] = (checksum >> 8); + state->buf[state->buf[0] - 0] = (checksum & 0xff); /* no ack for these packets */ if (req->cmd == CMD_FW_DL) rlen = 0; - ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); + ret = dvb_usbv2_generic_rw_locked(d, + state->buf, wlen, state->buf, rlen); if (ret) - goto err; + goto exit; /* no ack for those packets */ if (req->cmd == CMD_FW_DL) goto exit; /* verify checksum */ - checksum = af9035_checksum(buf, rlen - 2); - tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1]; + checksum = af9035_checksum(state->buf, rlen - 2); + tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; if (tmp_checksum != checksum) { - dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \ - "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd, - tmp_checksum, checksum); + dev_err(&d->udev->dev, + "%s: command=%02x checksum mismatch (%04x != %04x)\n", + KBUILD_MODNAME, req->cmd, tmp_checksum, + checksum); ret = -EIO; - goto err; + goto exit; } /* check status */ - if (buf[2]) { + if (state->buf[2]) { + /* fw returns status 1 when IR code was not received */ + if (req->cmd == CMD_IR_GET || state->buf[2] == 1) { + ret = 1; + goto exit; + } + dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n", - __func__, req->cmd, buf[2]); + __func__, req->cmd, state->buf[2]); ret = -EIO; - goto err; + goto exit; } /* read request, copy returned data to return buf */ if (req->rlen) - memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); - + memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen); exit: - return 0; - -err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); - + mutex_unlock(&d->usb_mutex); + if (ret < 0) + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } /* write multiple registers */ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) { - u8 wbuf[6 + len]; + u8 wbuf[MAX_XFER_SIZE]; u8 mbox = (reg >> 16) & 0xff; - struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; + struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL }; + + if (6 + len > sizeof(wbuf)) { + dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, len); + return -EOPNOTSUPP; + } wbuf[0] = len; wbuf[1] = 2; @@ -209,17 +224,31 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, if (msg[0].len > 40 || msg[1].len > 40) { /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; - } else if (msg[0].addr == state->af9033_config[0].i2c_addr) { - /* integrated demod */ + } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || + (msg[0].addr == state->af9033_config[1].i2c_addr)) { + /* 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_config[1].i2c_addr) + reg |= 0x100000; + ret = af9035_rd_regs(d, reg, &msg[1].buf[0], msg[1].len); } else { /* I2C */ - u8 buf[5 + msg[0].len]; - struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + u8 buf[MAX_XFER_SIZE]; + struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len, buf, msg[1].len, msg[1].buf }; + + if (5 + msg[0].len > sizeof(buf)) { + dev_warn(&d->udev->dev, + "%s: i2c xfer: len=%d is too big!\n", + KBUILD_MODNAME, msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } + req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[1].len; buf[1] = msg[0].addr << 1; buf[2] = 0x00; /* reg addr len */ @@ -232,17 +261,31 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, if (msg[0].len > 40) { /* TODO: correct limits > 40 */ ret = -EOPNOTSUPP; - } else if (msg[0].addr == state->af9033_config[0].i2c_addr) { - /* integrated demod */ + } else if ((msg[0].addr == state->af9033_config[0].i2c_addr) || + (msg[0].addr == state->af9033_config[1].i2c_addr)) { + /* 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_config[1].i2c_addr) + reg |= 0x100000; + ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3); } else { /* I2C */ - u8 buf[5 + msg[0].len]; - struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, - 0, NULL }; + u8 buf[MAX_XFER_SIZE]; + struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len, + buf, 0, NULL }; + + if (5 + msg[0].len > sizeof(buf)) { + dev_warn(&d->udev->dev, + "%s: i2c xfer: len=%d is too big!\n", + KBUILD_MODNAME, msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } + req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[0].len; buf[1] = msg[0].addr << 1; buf[2] = 0x00; /* reg addr len */ @@ -251,15 +294,34 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, memcpy(&buf[5], msg[0].buf, msg[0].len); ret = af9035_ctrl_msg(d, &req); } + } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { + if (msg[0].len > 40) { + /* TODO: correct limits > 40 */ + ret = -EOPNOTSUPP; + } else { + /* I2C */ + u8 buf[5]; + struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + buf, msg[0].len, msg[0].buf }; + req.mbox |= ((msg[0].addr & 0x80) >> 3); + buf[0] = msg[0].len; + buf[1] = msg[0].addr << 1; + buf[2] = 0x00; /* reg addr len */ + buf[3] = 0x00; /* reg addr MSB */ + buf[4] = 0x00; /* reg addr LSB */ + ret = af9035_ctrl_msg(d, &req); + } } else { /* - * We support only two kind of I2C transactions: - * 1) 1 x read + 1 x write + * We support only three kind of I2C transactions: + * 1) 1 x read + 1 x write (repeated start) * 2) 1 x write + * 3) 1 x read */ ret = -EOPNOTSUPP; } +unlock: mutex_unlock(&d->i2c_mutex); if (ret < 0) @@ -280,12 +342,40 @@ static struct i2c_algorithm af9035_i2c_algo = { static int af9035_identify_state(struct dvb_usb_device *d, const char **name) { + struct state *state = d_to_priv(d); int ret; u8 wbuf[1] = { 1 }; u8 rbuf[4]; struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, sizeof(rbuf), rbuf }; + ret = af9035_rd_regs(d, 0x1222, rbuf, 3); + if (ret < 0) + goto err; + + state->chip_version = rbuf[0]; + state->chip_type = rbuf[2] << 8 | rbuf[1] << 0; + + ret = af9035_rd_reg(d, 0x384f, &state->prechip_version); + if (ret < 0) + goto err; + + dev_info(&d->udev->dev, + "%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n", + KBUILD_MODNAME, state->prechip_version, + state->chip_version, state->chip_type); + + if (state->chip_type == 0x9135) { + if (state->chip_version == 0x02) + *name = AF9035_FIRMWARE_IT9135_V2; + else + *name = AF9035_FIRMWARE_IT9135_V1; + state->eeprom_addr = EEPROM_BASE_IT9135; + } else { + *name = AF9035_FIRMWARE_AF9035; + state->eeprom_addr = EEPROM_BASE_AF9035; + } + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; @@ -304,15 +394,13 @@ err: return ret; } -static int af9035_download_firmware(struct dvb_usb_device *d, +static int af9035_download_firmware_old(struct dvb_usb_device *d, const struct firmware *fw) { int ret, i, j, len; u8 wbuf[1]; - u8 rbuf[4]; struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; - struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; u8 hdr_core; u16 hdr_addr, hdr_data_len, hdr_checksum; #define MAX_DATA 58 @@ -339,9 +427,10 @@ static int af9035_download_firmware(struct dvb_usb_device *d, hdr_checksum = fw->data[fw->size - i + 5] << 8; hdr_checksum |= fw->data[fw->size - i + 6] << 0; - dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ - "checksum=%04x\n", __func__, hdr_core, hdr_addr, - hdr_data_len, hdr_checksum); + dev_dbg(&d->udev->dev, + "%s: core=%d addr=%04x data_len=%d checksum=%04x\n", + __func__, hdr_core, hdr_addr, hdr_data_len, + hdr_checksum); if (((hdr_core != 1) && (hdr_core != 2)) || (hdr_data_len > i)) { @@ -380,27 +469,9 @@ static int af9035_download_firmware(struct dvb_usb_device *d, __func__, fw->size - i); } - /* firmware loaded, request boot */ - req.cmd = CMD_FW_BOOT; - ret = af9035_ctrl_msg(d, &req); - if (ret < 0) - goto err; - - /* ensure firmware starts */ - wbuf[0] = 1; - ret = af9035_ctrl_msg(d, &req_fw_ver); - if (ret < 0) - goto err; - - if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { - dev_err(&d->udev->dev, "%s: firmware did not run\n", - KBUILD_MODNAME); - ret = -ENODEV; - goto err; - } - - dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", - KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); + /* print warn if firmware is bad, continue and see what happens */ + if (i) + dev_warn(&d->udev->dev, "%s: bad firmware\n", KBUILD_MODNAME); return 0; @@ -410,15 +481,11 @@ err: return ret; } -static int af9035_download_firmware_it9135(struct dvb_usb_device *d, +static int af9035_download_firmware_new(struct dvb_usb_device *d, const struct firmware *fw) { int ret, i, i_prev; - u8 wbuf[1]; - u8 rbuf[4]; - struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; - struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; #define HDR_SIZE 7 /* @@ -433,7 +500,6 @@ static int af9035_download_firmware_it9135(struct dvb_usb_device *d, * 5: addr LSB * 6: count of data bytes ? */ - for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { if (i == fw->size || (fw->data[i + 0] == 0x03 && @@ -452,6 +518,90 @@ static int af9035_download_firmware_it9135(struct dvb_usb_device *d, } } + return 0; + +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_download_firmware(struct dvb_usb_device *d, + const struct firmware *fw) +{ + struct state *state = d_to_priv(d); + int ret; + u8 wbuf[1]; + u8 rbuf[4]; + u8 tmp; + struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* + * In case of dual tuner configuration we need to do some extra + * initialization in order to download firmware to slave demod too, + * which is done by master demod. + * Master feeds also clock and controls power via GPIO. + */ + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); + if (ret < 0) + goto err; + + if (tmp == 1 || tmp == 3) { + /* configure gpioh1, reset & power slave demod */ + ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01); + if (ret < 0) + goto err; + + usleep_range(10000, 50000); + + ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01); + if (ret < 0) + 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; + + /* 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) + goto err; + } else { + ret = af9035_wr_reg(d, 0x00417f, tmp); + if (ret < 0) + goto err; + + /* enable clock out */ + ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01); + if (ret < 0) + goto err; + } + } + + if (fw->data[0] == 0x01) + ret = af9035_download_firmware_old(d, fw); + else + ret = af9035_download_firmware_new(d, fw); + if (ret < 0) + goto err; + /* firmware loaded, request boot */ req.cmd = CMD_FW_BOOT; ret = af9035_ctrl_msg(d, &req); @@ -485,51 +635,160 @@ err: static int af9035_read_config(struct dvb_usb_device *d) { struct state *state = d_to_priv(d); - int ret, i, eeprom_shift = 0; + int ret, i; u8 tmp; - u16 tmp16; + u16 tmp16, addr; + + /* 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; + state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; + + /* eeprom memory mapped location */ + if (state->chip_type == 0x9135) { + 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; + } else { + state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38; + state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38; + tmp16 = 0x00461b; + } + + /* check if eeprom exists */ + ret = af9035_rd_reg(d, tmp16, &tmp); + if (ret < 0) + goto err; + + if (tmp == 0x00) { + dev_dbg(&d->udev->dev, "%s: no eeprom\n", __func__); + goto skip_eeprom; + } + } /* check if there is dual tuners */ - ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); if (ret < 0) goto err; - state->dual_mode = tmp; - dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", - __func__, state->dual_mode); + if (tmp == 1 || tmp == 3) + state->dual_mode = true; + + dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, + tmp, state->dual_mode); + + 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; + + if (tmp) + state->af9033_config[1].i2c_addr = tmp; + + dev_dbg(&d->udev->dev, "%s: 2nd demod I2C addr=%02x\n", + __func__, tmp); + } + + addr = state->eeprom_addr; for (i = 0; i < state->dual_mode + 1; i++) { /* tuner */ - ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); + ret = af9035_rd_reg(d, addr + EEPROM_1_TUNER_ID, &tmp); if (ret < 0) goto err; - state->af9033_config[i].tuner = tmp; dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", __func__, i, tmp); - switch (tmp) { + /* tuner sanity check */ + if (state->chip_type == 0x9135) { + if (state->chip_version == 0x02) { + /* IT9135 BX (v2) */ + switch (tmp) { + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + state->af9033_config[i].tuner = tmp; + break; + } + } else { + /* IT9135 AX (v1) */ + switch (tmp) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + state->af9033_config[i].tuner = tmp; + break; + } + } + } else { + /* AF9035 */ + state->af9033_config[i].tuner = tmp; + } + + if (state->af9033_config[i].tuner != tmp) { + dev_info(&d->udev->dev, + "%s: [%d] overriding tuner from %02x to %02x\n", + KBUILD_MODNAME, i, tmp, + state->af9033_config[i].tuner); + } + + switch (state->af9033_config[i].tuner) { case AF9033_TUNER_TUA9001: case AF9033_TUNER_FC0011: case AF9033_TUNER_MXL5007T: case AF9033_TUNER_TDA18218: case AF9033_TUNER_FC2580: + case AF9033_TUNER_FC0012: state->af9033_config[i].spec_inv = 1; 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: + break; default: - dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \ - "supported, please report!", + dev_warn(&d->udev->dev, + "%s: tuner id=%02x not supported, please report!", KBUILD_MODNAME, tmp); } + /* disable dual mode if driver does not support it */ + if (i == 1) + switch (state->af9033_config[i].tuner) { + case AF9033_TUNER_FC0012: + 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: + case AF9033_TUNER_MXL5007T: + break; + default: + state->dual_mode = false; + dev_info(&d->udev->dev, + "%s: driver does not support 2nd tuner and will disable it", + KBUILD_MODNAME); + } + /* tuner IF frequency */ - ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); + ret = af9035_rd_reg(d, addr + EEPROM_1_IF_L, &tmp); if (ret < 0) goto err; tmp16 = tmp; - ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); + ret = af9035_rd_reg(d, addr + EEPROM_1_IF_H, &tmp); if (ret < 0) goto err; @@ -537,9 +796,10 @@ static int af9035_read_config(struct dvb_usb_device *d) dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16); - eeprom_shift = 0x10; /* shift for the 2nd tuner params */ + addr += 0x10; /* shift for the 2nd tuner params */ } +skip_eeprom: /* get demod clock */ ret = af9035_rd_reg(d, 0x00d800, &tmp); if (ret < 0) @@ -547,34 +807,12 @@ static int af9035_read_config(struct dvb_usb_device *d) tmp = (tmp >> 0) & 0x0f; - for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) - state->af9033_config[i].clock = clock_lut[tmp]; - - return 0; - -err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); - - return ret; -} - -static int af9035_read_config_it9135(struct dvb_usb_device *d) -{ - struct state *state = d_to_priv(d); - int ret, i; - u8 tmp; - - state->dual_mode = false; - - /* get demod clock */ - ret = af9035_rd_reg(d, 0x00d800, &tmp); - if (ret < 0) - goto err; - - tmp = (tmp >> 0) & 0x0f; - - for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) - state->af9033_config[i].clock = clock_lut_it9135[tmp]; + for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) { + if (state->chip_type == 0x9135) + state->af9033_config[i].clock = clock_lut_it9135[tmp]; + else + state->af9033_config[i].clock = clock_lut_af9035[tmp]; + } return 0; @@ -730,11 +968,18 @@ static int af9035_frontend_callback(void *adapter_priv, int component, return 0; } +static int af9035_get_adapter_count(struct dvb_usb_device *d) +{ + struct state *state = d_to_priv(d); + return state->dual_mode + 1; +} + static int af9035_frontend_attach(struct dvb_usb_adapter *adap) { struct state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); if (!state->af9033_config[adap->id].tuner) { /* unsupported tuner */ @@ -742,24 +987,9 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap) goto err; } - if (adap->id == 0) { - state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; - state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; - - ret = af9035_wr_reg(d, 0x00417f, - state->af9033_config[1].i2c_addr); - if (ret < 0) - goto err; - - ret = af9035_wr_reg(d, 0x00d81a, - state->dual_mode); - if (ret < 0) - goto err; - } - /* attach demodulator */ - adap->fe[0] = dvb_attach(af9033_attach, - &state->af9033_config[adap->id], &d->i2c_adap); + adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id], + &d->i2c_adap, &state->ops); if (adap->fe[0] == NULL) { ret = -ENODEV; goto err; @@ -785,13 +1015,22 @@ static const struct fc0011_config af9035_fc0011_config = { .i2c_address = 0x60, }; -static struct mxl5007t_config af9035_mxl5007t_config = { - .xtal_freq_hz = MxL_XTAL_24_MHZ, - .if_freq_hz = MxL_IF_4_57_MHZ, - .invert_if = 0, - .loop_thru_enable = 0, - .clk_out_enable = 0, - .clk_out_amp = MxL_CLKOUT_AMP_0_94V, +static struct mxl5007t_config af9035_mxl5007t_config[] = { + { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, + .invert_if = 0, + .loop_thru_enable = 0, + .clk_out_enable = 0, + .clk_out_amp = MxL_CLKOUT_AMP_0_94V, + }, { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, + .invert_if = 0, + .loop_thru_enable = 1, + .clk_out_enable = 1, + .clk_out_amp = MxL_CLKOUT_AMP_0_94V, + } }; static struct tda18218_config af9035_tda18218_config = { @@ -804,12 +1043,34 @@ static const struct fc2580_config af9035_fc2580_config = { .clock = 16384000, }; +static const struct fc0012_config af9035_fc0012_config[] = { + { + .i2c_address = 0x63, + .xtal_freq = FC_XTAL_36_MHZ, + .dual_master = true, + .loop_through = true, + .clock_out = true, + }, { + .i2c_address = 0x63 | 0x80, /* I2C bus select hack */ + .xtal_freq = FC_XTAL_36_MHZ, + .dual_master = true, + } +}; + static int af9035_tuner_attach(struct dvb_usb_adapter *adap) { struct state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); int ret; struct dvb_frontend *fe; + struct i2c_msg msg[1]; + u8 tuner_addr; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* + * XXX: Hack used in that function: we abuse unused I2C address bit [7] + * to carry info about used I2C bus for dual tuner configuration. + */ switch (state->af9033_config[adap->id].tuner) { case AF9033_TUNER_TUA9001: @@ -842,46 +1103,59 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) &d->i2c_adap, &af9035_fc0011_config); break; case AF9033_TUNER_MXL5007T: - ret = af9035_wr_reg(d, 0x00d8e0, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8e1, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8df, 0); - if (ret < 0) - goto err; + if (adap->id == 0) { + ret = af9035_wr_reg(d, 0x00d8e0, 1); + if (ret < 0) + goto err; - msleep(30); + ret = af9035_wr_reg(d, 0x00d8e1, 1); + if (ret < 0) + goto err; - ret = af9035_wr_reg(d, 0x00d8df, 1); - if (ret < 0) - goto err; + ret = af9035_wr_reg(d, 0x00d8df, 0); + if (ret < 0) + goto err; - msleep(300); + msleep(30); - ret = af9035_wr_reg(d, 0x00d8c0, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8c1, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8bf, 0); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8b4, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8b5, 1); - if (ret < 0) - goto err; - ret = af9035_wr_reg(d, 0x00d8b3, 1); - if (ret < 0) - goto err; + ret = af9035_wr_reg(d, 0x00d8df, 1); + if (ret < 0) + goto err; + + msleep(300); + + ret = af9035_wr_reg(d, 0x00d8c0, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0x00d8c1, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0x00d8bf, 0); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0x00d8b4, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0x00d8b5, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0x00d8b3, 1); + if (ret < 0) + goto err; + + tuner_addr = 0x60; + } else { + tuner_addr = 0x60 | 0x80; /* I2C bus hack */ + } /* attach tuner */ - fe = dvb_attach(mxl5007t_attach, adap->fe[0], - &d->i2c_adap, 0x60, &af9035_mxl5007t_config); + fe = dvb_attach(mxl5007t_attach, adap->fe[0], &d->i2c_adap, + tuner_addr, &af9035_mxl5007t_config[adap->id]); break; case AF9033_TUNER_TDA18218: /* attach tuner */ @@ -907,6 +1181,57 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap, &af9035_fc2580_config); break; + case AF9033_TUNER_FC0012: + /* + * AF9035 gpiot2 = FC0012 enable + * XXX: there seems to be something on gpioh8 too, but on my + * my test I didn't find any difference. + */ + + if (adap->id == 0) { + /* configure gpiot2 as output and high */ + ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); + if (ret < 0) + goto err; + } else { + /* + * FIXME: That belongs for the FC0012 driver. + * Write 02 to FC0012 master tuner register 0d directly + * in order to make slave tuner working. + */ + msg[0].addr = 0x63; + msg[0].flags = 0; + msg[0].len = 2; + msg[0].buf = "\x0d\x02"; + ret = i2c_transfer(&d->i2c_adap, msg, 1); + if (ret < 0) + goto err; + } + + usleep_range(10000, 50000); + + fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap, + &af9035_fc0012_config[adap->id]); + 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: + /* attach tuner */ + fe = dvb_attach(it913x_attach, adap->fe[0], &d->i2c_adap, + state->af9033_config[adap->id].i2c_addr, + state->af9033_config[0].tuner); + break; default: fe = NULL; } @@ -928,8 +1253,8 @@ static int af9035_init(struct dvb_usb_device *d) { struct state *state = d_to_priv(d); int ret, i; - u16 frame_size = 87 * 188 / 4; - u8 packet_size = 512 / 4; + u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4; + u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4; struct reg_val_mask tab[] = { { 0x80f99d, 0x01, 0x01 }, { 0x80f9a4, 0x01, 0x01 }, @@ -945,15 +1270,15 @@ static int af9035_init(struct dvb_usb_device *d) { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, { 0x00dd0d, packet_size, 0xff }, - { 0x80f9a3, 0x00, 0x01 }, - { 0x80f9cd, 0x00, 0x01 }, + { 0x80f9a3, state->dual_mode, 0x01 }, + { 0x80f9cd, state->dual_mode, 0x01 }, { 0x80f99d, 0x00, 0x01 }, { 0x80f9a4, 0x00, 0x01 }, }; - dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ - "packet_size=%02x\n", __func__, - d->udev->speed, frame_size, packet_size); + dev_dbg(&d->udev->dev, + "%s: USB speed=%d frame_size=%04x packet_size=%02x\n", + __func__, d->udev->speed, frame_size, packet_size); /* init endpoints */ for (i = 0; i < ARRAY_SIZE(tab); i++) { @@ -971,42 +1296,52 @@ err: return ret; } +#if IS_ENABLED(CONFIG_RC_CORE) static int af9035_rc_query(struct dvb_usb_device *d) { - unsigned int key; - unsigned char b[4]; int ret; - struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; + u32 key; + u8 buf[4]; + struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf }; ret = af9035_ctrl_msg(d, &req); - if (ret < 0) + if (ret == 1) + return 0; + else if (ret < 0) goto err; - if ((b[2] + b[3]) == 0xff) { - if ((b[0] + b[1]) == 0xff) { - /* NEC */ - key = b[0] << 8 | b[2]; + if ((buf[2] + buf[3]) == 0xff) { + if ((buf[0] + buf[1]) == 0xff) { + /* NEC standard 16bit */ + key = buf[0] << 8 | buf[2]; } else { - /* ext. NEC */ - key = b[0] << 16 | b[1] << 8 | b[2]; + /* NEC extended 24bit */ + key = buf[0] << 16 | buf[1] << 8 | buf[2]; } } else { - key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; + /* NEC full code 32bit */ + key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; } + dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf); + rc_keydown(d->rc_dev, key, 0); -err: - /* ignore errors */ return 0; + +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + + return ret; } static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { + struct state *state = d_to_priv(d); int ret; u8 tmp; - ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_MODE, &tmp); if (ret < 0) goto err; @@ -1014,7 +1349,8 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) /* don't activate rc if in HID mode or if not available */ if (tmp == 5) { - ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_TYPE, + &tmp); if (ret < 0) goto err; @@ -1023,10 +1359,10 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) switch (tmp) { case 0: /* NEC */ default: - rc->allowed_protos = RC_TYPE_NEC; + rc->allowed_protos = RC_BIT_NEC; break; case 1: /* RC6 */ - rc->allowed_protos = RC_TYPE_RC6; + rc->allowed_protos = RC_BIT_RC6_MCE; break; } @@ -1045,6 +1381,73 @@ err: return ret; } +#else + #define af9035_get_rc_config NULL +#endif + +static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, + struct usb_data_stream_properties *stream) +{ + struct dvb_usb_device *d = fe_to_d(fe); + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); + + if (d->udev->speed == USB_SPEED_FULL) + stream->u.bulk.buffersize = 5 * 188; + + return 0; +} + +static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct state *state = adap_to_priv(adap); + + 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 state *state = adap_to_priv(adap); + + return state->ops.pid_filter(adap->fe[0], index, pid, onoff); +} + +static int af9035_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + char manufacturer[sizeof("Afatech")]; + + memset(manufacturer, 0, sizeof(manufacturer)); + usb_string(udev, udev->descriptor.iManufacturer, + manufacturer, sizeof(manufacturer)); + /* + * There is two devices having same ID but different chipset. One uses + * AF9015 and the other IT9135 chipset. Only difference seen on lsusb + * is iManufacturer string. + * + * idVendor 0x0ccd TerraTec Electronic GmbH + * idProduct 0x0099 + * bcdDevice 2.00 + * iManufacturer 1 Afatech + * iProduct 2 DVB-T 2 + * + * idVendor 0x0ccd TerraTec Electronic GmbH + * idProduct 0x0099 + * bcdDevice 2.00 + * iManufacturer 1 ITE Technologies, Inc. + * iProduct 2 DVB-T TV Stick + */ + if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && + (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { + if (!strcmp("Afatech", manufacturer)) { + dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); + return -ENODEV; + } + } + + return dvb_usbv2_probe(intf, id); +} /* interface 0 is used by DVB-T receiver and interface 1 is for remote controller (HID) */ @@ -1058,7 +1461,6 @@ static const struct dvb_usb_device_properties af9035_props = { .generic_bulk_ctrl_endpoint_response = 0x81, .identify_state = af9035_identify_state, - .firmware = AF9035_FIRMWARE_AF9035, .download_firmware = af9035_download_firmware, .i2c_algo = &af9035_i2c_algo, @@ -1067,48 +1469,34 @@ static const struct dvb_usb_device_properties af9035_props = { .tuner_attach = af9035_tuner_attach, .init = af9035_init, .get_rc_config = af9035_get_rc_config, + .get_stream_config = af9035_get_stream_config, - .num_adapters = 1, + .get_adapter_count = af9035_get_adapter_count, .adapter = { { - .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), - }, { - .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), - }, - }, -}; + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, -static const struct dvb_usb_device_properties it9135_props = { - .driver_name = KBUILD_MODNAME, - .owner = THIS_MODULE, - .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct state), - - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - - .identify_state = af9035_identify_state, - .firmware = AF9035_FIRMWARE_IT9135, - .download_firmware = af9035_download_firmware_it9135, + .pid_filter_count = 32, + .pid_filter_ctrl = af9035_pid_filter_ctrl, + .pid_filter = af9035_pid_filter, - .i2c_algo = &af9035_i2c_algo, - .read_config = af9035_read_config_it9135, - .frontend_attach = af9035_frontend_attach, - .tuner_attach = af9035_tuner_attach, - .init = af9035_init, - .get_rc_config = af9035_get_rc_config, - - .num_adapters = 1, - .adapter = { - { .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), }, }, }; static const struct usb_device_id af9035_id_table[] = { + /* AF9035 devices */ { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, &af9035_props, "Afatech AF9035 reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, @@ -1133,6 +1521,40 @@ static const struct usb_device_id af9035_id_table[] = { &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, &af9035_props, "Asus U3100Mini Plus", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, + &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, + /* IT9135 devices */ + { 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) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, + &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, + &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, af9035_id_table); @@ -1140,7 +1562,7 @@ MODULE_DEVICE_TABLE(usb, af9035_id_table); static struct usb_driver af9035_usb_driver = { .name = KBUILD_MODNAME, .id_table = af9035_id_table, - .probe = dvb_usbv2_probe, + .probe = af9035_probe, .disconnect = dvb_usbv2_disconnect, .suspend = dvb_usbv2_suspend, .resume = dvb_usbv2_resume, @@ -1155,4 +1577,5 @@ MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("Afatech AF9035 driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); -MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135); +MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1); +MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2); diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 75ef1ec13fb..c21902fdd4c 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -26,9 +26,11 @@ #include "af9033.h" #include "tua9001.h" #include "fc0011.h" +#include "fc0012.h" #include "mxl5007t.h" #include "tda18218.h" #include "fc2580.h" +#include "tuner_it913x.h" struct reg_val { u32 reg; @@ -51,13 +53,20 @@ struct usb_req { }; struct state { +#define BUF_LEN 64 + u8 buf[BUF_LEN]; u8 seq; /* packet sequence number */ - bool dual_mode; - + u8 prechip_version; + u8 chip_version; + u16 chip_type; + u8 dual_mode:1; + u16 eeprom_addr; struct af9033_config af9033_config[2]; + + struct af9033_ops ops; }; -u32 clock_lut[] = { +static const u32 clock_lut_af9035[] = { 20480000, /* FPGA */ 16384000, /* 16.38 MHz */ 20480000, /* 20.48 MHz */ @@ -72,7 +81,7 @@ u32 clock_lut[] = { 12000000, /* 12.00 MHz */ }; -u32 clock_lut_it9135[] = { +static const u32 clock_lut_it9135[] = { 12000000, /* 12.00 MHz */ 20480000, /* 20.48 MHz */ 36000000, /* 36.00 MHz */ @@ -86,18 +95,36 @@ u32 clock_lut_it9135[] = { }; #define AF9035_FIRMWARE_AF9035 "dvb-usb-af9035-02.fw" -#define AF9035_FIRMWARE_IT9135 "dvb-usb-it9135-01.fw" +#define AF9035_FIRMWARE_IT9135_V1 "dvb-usb-it9135-01.fw" +#define AF9035_FIRMWARE_IT9135_V2 "dvb-usb-it9135-02.fw" + +/* + * eeprom is memory mapped as read only. Writing that memory mapped address + * will not corrupt eeprom. + * + * TS mode: + * 0 TS + * 1 DCA + PIP + * 3 PIP + * n DCA + * + * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. + */ + +#define EEPROM_BASE_AF9035 0x42fd +#define EEPROM_BASE_IT9135 0x499c +#define EEPROM_SHIFT 0x10 -/* EEPROM locations */ -#define EEPROM_IR_MODE 0x430d -#define EEPROM_DUAL_MODE 0x4326 -#define EEPROM_IR_TYPE 0x4329 -#define EEPROM_1_IFFREQ_L 0x432d -#define EEPROM_1_IFFREQ_H 0x432e -#define EEPROM_1_TUNER_ID 0x4331 -#define EEPROM_2_IFFREQ_L 0x433d -#define EEPROM_2_IFFREQ_H 0x433e -#define EEPROM_2_TUNER_ID 0x4341 +#define EEPROM_IR_MODE 0x10 +#define EEPROM_TS_MODE 0x29 +#define EEPROM_2ND_DEMOD_ADDR 0x2a +#define EEPROM_IR_TYPE 0x2c +#define EEPROM_1_IF_L 0x30 +#define EEPROM_1_IF_H 0x31 +#define EEPROM_1_TUNER_ID 0x34 +#define EEPROM_2_IF_L 0x40 +#define EEPROM_2_IF_H 0x41 +#define EEPROM_2_TUNER_ID 0x44 /* USB commands */ #define CMD_MEM_RD 0x00 diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index ec540140c81..eeab79bdd2a 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c @@ -45,25 +45,24 @@ #include "cxd2820r.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static DEFINE_MUTEX(anysee_usb_mutex); -static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, - u8 *rbuf, u8 rlen) +static int anysee_ctrl_msg(struct dvb_usb_device *d, + u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d_to_priv(d); int act_len, ret, i; - u8 buf[64]; - memcpy(&buf[0], sbuf, slen); - buf[60] = state->seq++; + mutex_lock(&d->usb_mutex); - mutex_lock(&anysee_usb_mutex); + memcpy(&state->buf[0], sbuf, slen); + state->buf[60] = state->seq++; - dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, buf); + dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, state->buf); /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ - ret = dvb_usbv2_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf)); + ret = dvb_usbv2_generic_rw_locked(d, state->buf, sizeof(state->buf), + state->buf, sizeof(state->buf)); if (ret) goto error_unlock; @@ -82,20 +81,19 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, for (i = 0; i < 3; i++) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, - d->props->generic_bulk_ctrl_endpoint), buf, sizeof(buf), - &act_len, 2000); - + d->props->generic_bulk_ctrl_endpoint), + state->buf, sizeof(state->buf), &act_len, 2000); if (ret) { - dev_dbg(&d->udev->dev, "%s: recv bulk message " \ - "failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, + "%s: recv bulk message failed=%d\n", + __func__, ret); } else { dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__, - rlen, buf); - - if (buf[63] != 0x4f) - dev_dbg(&d->udev->dev, "%s: cmd failed\n", - __func__); + rlen, state->buf); + if (state->buf[63] != 0x4f) + dev_dbg(&d->udev->dev, + "%s: cmd failed\n", __func__); break; } } @@ -109,11 +107,10 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, /* read request, copy returned data to return buf */ if (rbuf && rlen) - memcpy(rbuf, buf, rlen); + memcpy(rbuf, state->buf, rlen); error_unlock: - mutex_unlock(&anysee_usb_mutex); - + mutex_unlock(&d->usb_mutex); return ret; } @@ -445,6 +442,7 @@ static struct cxd2820r_config anysee_cxd2820r_config = { * IOD[0] ZL10353 1=enabled * IOE[0] tuner 0=enabled * tuner is behind ZL10353 I2C-gate + * tuner is behind TDA10023 I2C-gate * * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" * PCB: 508TC (rev0.6) @@ -638,7 +636,7 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) { struct anysee_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); - int ret; + int ret = 0; u8 tmp; struct i2c_msg msg[2] = { { @@ -884,9 +882,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) if (!adap->fe[0]) { /* we have no frontend :-( */ ret = -ENODEV; - dev_err(&d->udev->dev, "%s: Unsupported Anysee version. " \ - "Please report the " \ - "<linux-media@vger.kernel.org>.\n", + dev_err(&d->udev->dev, + "%s: Unsupported Anysee version. Please report to <linux-media@vger.kernel.org>.\n", KBUILD_MODNAME); } error: @@ -960,7 +957,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) if (fe && adap->fe[1]) { /* attach tuner for 2nd FE */ - fe = dvb_attach(dvb_pll_attach, adap->fe[0], + fe = dvb_attach(dvb_pll_attach, adap->fe[1], (0xc0 >> 1), &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); } @@ -1019,6 +1016,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) return ret; } +#if IS_ENABLED(CONFIG_RC_CORE) static int anysee_rc_query(struct dvb_usb_device *d) { u8 buf[] = {CMD_GET_IR_CODE}; @@ -1048,12 +1046,15 @@ static int anysee_rc_query(struct dvb_usb_device *d) static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - rc->allowed_protos = RC_TYPE_NEC; + rc->allowed_protos = RC_BIT_NEC; rc->query = anysee_rc_query; rc->interval = 250; /* windows driver uses 500ms */ return 0; } +#else + #define anysee_get_rc_config NULL +#endif static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot, int addr) @@ -1170,7 +1171,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, struct dvb_usb_device *d = ci->data; struct anysee_state *state = d_to_priv(d); int ret; - u8 tmp; + u8 tmp = 0; ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40); if (ret) diff --git a/drivers/media/usb/dvb-usb-v2/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h index c1a4273f14f..8f426d9fc6e 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.h +++ b/drivers/media/usb/dvb-usb-v2/anysee.h @@ -52,8 +52,9 @@ enum cmd { }; struct anysee_state { - u8 hw; /* PCB ID */ + u8 buf[64]; u8 seq; + u8 hw; /* PCB ID */ u8 fe_id:1; /* frondend ID */ u8 has_ci:1; u8 ci_attached:1; diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 54f1221d930..c3c4b98733b 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. * @@ -68,6 +68,19 @@ static struct drxk_config terratec_h7_drxk = { .microcode_name = "dvb-usb-terratec-h7-drxk.fw", }; +static struct drxk_config cablestar_hdci_drxk = { + .adr = 0x29, + .parallel_ts = true, + .dynamic_clk = true, + .single_master = true, + .enable_merr_cfg = true, + .no_i2c_bridge = false, + .chunk_size = 64, + .mpeg_out_clk_strength = 0x02, + .qam_demod_parameter_count = 2, + .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw", +}; + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct az6007_device_state *st = fe_to_priv(fe); @@ -189,6 +202,7 @@ static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff) return az6007_write(d, 0xbc, onoff, 0, NULL, 0); } +#if IS_ENABLED(CONFIG_RC_CORE) /* remote control stuff (does not work with my box) */ static int az6007_rc_query(struct dvb_usb_device *d) { @@ -215,6 +229,20 @@ static int az6007_rc_query(struct dvb_usb_device *d) return 0; } +static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) +{ + pr_debug("Getting az6007 Remote Control properties\n"); + + rc->allowed_protos = RC_BIT_NEC; + rc->query = az6007_rc_query; + rc->interval = 400; + + return 0; +} +#else + #define az6007_get_rc_config NULL +#endif + static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) @@ -615,6 +643,27 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) return 0; } +static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct az6007_device_state *st = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); + + pr_debug("attaching demod drxk\n"); + + adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk, + &d->i2c_adap); + if (!adap->fe[0]) + return -EINVAL; + + adap->fe[0]->sec_priv = adap; + st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; + adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; + + az6007_ci_init(adap); + + return 0; +} + static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); @@ -822,23 +871,12 @@ static void az6007_usb_disconnect(struct usb_interface *intf) dvb_usbv2_disconnect(intf); } -static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) -{ - pr_debug("Getting az6007 Remote Control properties\n"); - - rc->allowed_protos = RC_TYPE_NEC; - rc->query = az6007_rc_query; - rc->interval = 400; - - return 0; -} - static int az6007_download_firmware(struct dvb_usb_device *d, const struct firmware *fw) { pr_debug("Loading az6007 firmware\n"); - return usbv2_cypress_load_firmware(d->udev, fw, CYPRESS_FX2); + return cypress_load_firmware(d->udev, fw, CYPRESS_FX2); } /* DVB USB Driver stuff */ @@ -864,6 +902,29 @@ static struct dvb_usb_device_properties az6007_props = { } }; +static struct dvb_usb_device_properties az6007_cablestar_hdci_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .firmware = AZ6007_FIRMWARE, + + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct az6007_device_state), + .i2c_algo = &az6007_i2c_algo, + .tuner_attach = az6007_tuner_attach, + .frontend_attach = az6007_cablestar_hdci_frontend_attach, + .streaming_ctrl = az6007_streaming_ctrl, +/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */ + .get_rc_config = NULL, + .read_mac_address = az6007_read_mac_addr, + .download_firmware = az6007_download_firmware, + .identify_state = az6007_identify_state, + .power_ctrl = az6007_power_ctrl, + .num_adapters = 1, + .adapter = { + { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } + } +}; + static struct usb_device_id az6007_usb_table[] = { {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, @@ -871,6 +932,8 @@ static struct usb_device_id az6007_usb_table[] = { &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, + {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI, + &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)}, {0}, }; @@ -912,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/cypress_firmware.c b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c deleted file mode 100644 index 211df549f26..00000000000 --- a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c +++ /dev/null @@ -1,134 +0,0 @@ -/* cypress_firmware.c is part of the DVB USB library. - * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) - * see dvb-usb-init.c for copyright information. - * - * This file contains functions for downloading the firmware to Cypress FX 1 - * and 2 based devices. - * - */ - -#include "dvb_usb.h" -#include "cypress_firmware.h" - -struct usb_cypress_controller { - u8 id; - const char *name; /* name of the usb controller */ - u16 cs_reg; /* needs to be restarted, - * when the firmware has been downloaded */ -}; - -static const struct usb_cypress_controller cypress[] = { - { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 }, - { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 }, - { .id = CYPRESS_FX2, .name = "Cypress FX2", .cs_reg = 0xe600 }, -}; - -/* - * load a firmware packet to the device - */ -static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data, - u8 len) -{ - dvb_usb_dbg_usb_control_msg(udev, - 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len); - - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); -} - -int usbv2_cypress_load_firmware(struct usb_device *udev, - const struct firmware *fw, int type) -{ - struct hexline *hx; - int ret, pos = 0; - - hx = kmalloc(sizeof(struct hexline), GFP_KERNEL); - if (!hx) { - dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME); - return -ENOMEM; - } - - /* stop the CPU */ - hx->data[0] = 1; - ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); - if (ret != 1) { - dev_err(&udev->dev, "%s: CPU stop failed=%d\n", - KBUILD_MODNAME, ret); - ret = -EIO; - goto err_kfree; - } - - /* write firmware to memory */ - for (;;) { - ret = dvb_usbv2_get_hexline(fw, hx, &pos); - if (ret < 0) - goto err_kfree; - else if (ret == 0) - break; - - ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len); - if (ret < 0) { - goto err_kfree; - } else if (ret != hx->len) { - dev_err(&udev->dev, "%s: error while transferring " \ - "firmware (transferred size=%d, " \ - "block size=%d)\n", - KBUILD_MODNAME, ret, hx->len); - ret = -EIO; - goto err_kfree; - } - } - - /* start the CPU */ - hx->data[0] = 0; - ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); - if (ret != 1) { - dev_err(&udev->dev, "%s: CPU start failed=%d\n", - KBUILD_MODNAME, ret); - ret = -EIO; - goto err_kfree; - } - - ret = 0; -err_kfree: - kfree(hx); - return ret; -} -EXPORT_SYMBOL(usbv2_cypress_load_firmware); - -int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx, - int *pos) -{ - u8 *b = (u8 *) &fw->data[*pos]; - int data_offs = 4; - - if (*pos >= fw->size) - return 0; - - memset(hx, 0, sizeof(struct hexline)); - hx->len = b[0]; - - if ((*pos + hx->len + 4) >= fw->size) - return -EINVAL; - - hx->addr = b[1] | (b[2] << 8); - hx->type = b[3]; - - if (hx->type == 0x04) { - /* b[4] and b[5] are the Extended linear address record data - * field */ - hx->addr |= (b[4] << 24) | (b[5] << 16); - } - - memcpy(hx->data, &b[data_offs], hx->len); - hx->chk = b[hx->len + data_offs]; - *pos += hx->len + 5; - - return *pos; -} -EXPORT_SYMBOL(dvb_usbv2_get_hexline); - -MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Cypress firmware download"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.h b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h deleted file mode 100644 index 80085fd4132..00000000000 --- a/drivers/media/usb/dvb-usb-v2/cypress_firmware.h +++ /dev/null @@ -1,31 +0,0 @@ -/* cypress_firmware.h is part of the DVB USB library. - * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) - * see dvb-usb-init.c for copyright information. - * - * This file contains functions for downloading the firmware to Cypress FX 1 - * and 2 based devices. - * - */ - -#ifndef CYPRESS_FIRMWARE_H -#define CYPRESS_FIRMWARE_H - -#define CYPRESS_AN2135 0 -#define CYPRESS_AN2235 1 -#define CYPRESS_FX2 2 - -/* commonly used firmware download types and function */ -struct hexline { - u8 len; - u32 addr; - u8 type; - u8 data[255]; - u8 chk; -}; -extern int usbv2_cypress_load_firmware(struct usb_device *, - const struct firmware *, int); -extern int dvb_usbv2_get_hexline(const struct firmware *, - struct hexline *, int *); - -#endif diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index bae16a1189d..124b4baa7e9 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -137,10 +137,10 @@ struct dvb_usb_driver_info { struct dvb_usb_rc { const char *map_name; u64 allowed_protos; - int (*change_protocol)(struct rc_dev *dev, u64 rc_type); + int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*query) (struct dvb_usb_device *d); unsigned int interval; - const enum rc_driver_type driver_type; + enum rc_driver_type driver_type; bool bulk_mode; }; @@ -329,13 +329,16 @@ struct dvb_usb_adapter { u8 feed_count; u8 max_feed_count; s8 active_fe; +#define ADAP_INIT 0 +#define ADAP_SLEEP 1 +#define ADAP_STREAMING 2 + unsigned long state_bits; /* dvb */ struct dvb_adapter dvb_adap; struct dmxdev dmxdev; struct dvb_demux demux; struct dvb_net dvb_net; - struct mutex sync_mutex; struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP]; int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *); @@ -347,10 +350,9 @@ struct dvb_usb_adapter { * @props: device properties * @name: device name * @rc_map: name of rc codes table + * @rc_polling_active: set when RC polling is active * @udev: pointer to the device's struct usb_device - * @intf: pointer to the device's usb interface * @rc: remote controller configuration - * @probe_work: work to defer .probe() * @powered: indicated whether the device is power or not * @usb_mutex: mutex for usb control messages * @i2c_mutex: mutex for i2c-transfers @@ -364,12 +366,9 @@ struct dvb_usb_device { const struct dvb_usb_device_properties *props; const char *name; const char *rc_map; - + bool rc_polling_active; struct usb_device *udev; - struct usb_interface *intf; struct dvb_usb_rc rc; - struct work_struct probe_work; - pid_t work_pid; int powered; /* locking */ @@ -399,5 +398,9 @@ extern int dvb_usbv2_reset_resume(struct usb_interface *); /* the generic read/write method for device control */ extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); extern int dvb_usbv2_generic_write(struct dvb_usb_device *, u8 *, u16); +/* caller must hold lock when locked versions are called */ +extern int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *, + u8 *, u16, u8 *, u16); +extern int dvb_usbv2_generic_write_locked(struct dvb_usb_device *, u8 *, u16); #endif 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 9859d2a2449..e3558061893 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -28,10 +28,11 @@ MODULE_PARM_DESC(disable_rc_polling, static int dvb_usb_force_pid_filter_usage; module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); -MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \ - "PID filter, if any (default: 0)"); +MODULE_PARM_DESC(force_pid_filter_usage, + "force all DVB USB devices to use a PID filter, if any (default: 0)"); -static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name) +static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, + const char *name) { int ret; const struct firmware *fw; @@ -44,10 +45,9 @@ static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *nam ret = request_firmware(&fw, name, &d->udev->dev); if (ret < 0) { - dev_err(&d->udev->dev, "%s: Did not find the firmware file "\ - "'%s'. Please see linux/Documentation/dvb/ " \ - "for more details on firmware-problems. " \ - "Status %d\n", KBUILD_MODNAME, name, ret); + dev_err(&d->udev->dev, + "%s: Did not find the firmware file '%s'. Please see linux/Documentation/dvb/ for more details on firmware-problems. Status %d\n", + KBUILD_MODNAME, name, ret); goto err; } @@ -102,6 +102,7 @@ static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d) return 0; } +#if IS_ENABLED(CONFIG_RC_CORE) static void dvb_usb_read_remote_control(struct work_struct *work) { struct dvb_usb_device *d = container_of(work, @@ -112,13 +113,16 @@ static void dvb_usb_read_remote_control(struct work_struct *work) * When the parameter has been set to 1 via sysfs while the * driver was running, or when bulk mode is enabled after IR init. */ - if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode) + if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode) { + d->rc_polling_active = false; return; + } ret = d->rc.query(d); if (ret < 0) { dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n", KBUILD_MODNAME, ret); + d->rc_polling_active = false; return; /* stop polling */ } @@ -160,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; @@ -177,11 +181,12 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) /* initialize a work queue for handling polling */ INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); - dev_info(&d->udev->dev, "%s: schedule remote query interval " \ - "to %d msecs\n", KBUILD_MODNAME, - d->rc.interval); + dev_info(&d->udev->dev, + "%s: schedule remote query interval to %d msecs\n", + KBUILD_MODNAME, d->rc.interval); schedule_delayed_work(&d->rc_query_work, msecs_to_jiffies(d->rc.interval)); + d->rc_polling_active = true; } return 0; @@ -202,6 +207,10 @@ static int dvb_usbv2_remote_exit(struct dvb_usb_device *d) return 0; } +#else + #define dvb_usbv2_remote_init(args...) 0 + #define dvb_usbv2_remote_exit(args...) +#endif static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buf, size_t len) @@ -224,7 +233,7 @@ static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf, dvb_dmx_swfilter_raw(&adap->demux, buf, len); } -int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) { dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, adap->id); @@ -236,7 +245,7 @@ int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) return usb_urb_initv2(&adap->stream, &adap->props->stream); } -int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) { dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, adap->id); @@ -244,132 +253,162 @@ int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) return usb_urb_exitv2(&adap->stream); } -static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, - int count) +static int wait_schedule(void *ptr) +{ + schedule(); + + return 0; +} + +static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; struct dvb_usb_device *d = adap_to_d(adap); - int ret; - dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \ - "setting pid [%s]: %04x (%04d) at index %d '%s'\n", + int ret = 0; + struct usb_data_stream_properties stream_props; + dev_dbg(&d->udev->dev, + "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", __func__, adap->id, adap->active_fe, dvbdmxfeed->type, adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, - dvbdmxfeed->pid, dvbdmxfeed->index, - (count == 1) ? "on" : "off"); + dvbdmxfeed->pid, dvbdmxfeed->index); + + /* wait init is done */ + wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule, + TASK_UNINTERRUPTIBLE); if (adap->active_fe == -1) return -EINVAL; - adap->feed_count += count; - - /* stop feeding if it is last pid */ - if (adap->feed_count == 0) { - dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__); - - if (d->props->streaming_ctrl) { - ret = d->props->streaming_ctrl( - adap->fe[adap->active_fe], 0); - if (ret < 0) { - dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ - "failed=%d\n", KBUILD_MODNAME, - ret); - usb_urb_killv2(&adap->stream); - goto err_mutex_unlock; - } - } - usb_urb_killv2(&adap->stream); - mutex_unlock(&adap->sync_mutex); - } + /* skip feed setup if we are already feeding */ + if (adap->feed_count++ > 0) + goto skip_feed_start; - /* activate the pid on the device pid filter */ - if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && - adap->pid_filtering && - adap->props->pid_filter) - ret = adap->props->pid_filter(adap, dvbdmxfeed->index, - dvbdmxfeed->pid, (count == 1) ? 1 : 0); - if (ret < 0) - dev_err(&d->udev->dev, "%s: pid_filter() " \ - "failed=%d\n", KBUILD_MODNAME, - ret); - - /* start feeding if it is first pid */ - if (adap->feed_count == 1 && count == 1) { - struct usb_data_stream_properties stream_props; - mutex_lock(&adap->sync_mutex); - dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__); - - /* resolve input and output streaming paramters */ - if (d->props->get_stream_config) { - memcpy(&stream_props, &adap->props->stream, + /* set 'streaming' status bit */ + set_bit(ADAP_STREAMING, &adap->state_bits); + + /* resolve input and output streaming parameters */ + if (d->props->get_stream_config) { + memcpy(&stream_props, &adap->props->stream, sizeof(struct usb_data_stream_properties)); - ret = d->props->get_stream_config( - adap->fe[adap->active_fe], - &adap->ts_type, &stream_props); - if (ret < 0) - goto err_mutex_unlock; - } else { - stream_props = adap->props->stream; - } + ret = d->props->get_stream_config(adap->fe[adap->active_fe], + &adap->ts_type, &stream_props); + if (ret) + dev_err(&d->udev->dev, + "%s: get_stream_config() failed=%d\n", + KBUILD_MODNAME, ret); + } else { + stream_props = adap->props->stream; + } - switch (adap->ts_type) { - case DVB_USB_FE_TS_TYPE_204: - adap->stream.complete = dvb_usb_data_complete_204; - break; - case DVB_USB_FE_TS_TYPE_RAW: - adap->stream.complete = dvb_usb_data_complete_raw; - break; - case DVB_USB_FE_TS_TYPE_188: - default: - adap->stream.complete = dvb_usb_data_complete; - break; - } + switch (adap->ts_type) { + case DVB_USB_FE_TS_TYPE_204: + adap->stream.complete = dvb_usb_data_complete_204; + break; + case DVB_USB_FE_TS_TYPE_RAW: + adap->stream.complete = dvb_usb_data_complete_raw; + break; + case DVB_USB_FE_TS_TYPE_188: + default: + adap->stream.complete = dvb_usb_data_complete; + break; + } - usb_urb_submitv2(&adap->stream, &stream_props); - - if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && - adap->props->caps & - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && - adap->props->pid_filter_ctrl) { - ret = adap->props->pid_filter_ctrl(adap, - adap->pid_filtering); - if (ret < 0) { - dev_err(&d->udev->dev, "%s: " \ - "pid_filter_ctrl() failed=%d\n", - KBUILD_MODNAME, ret); - goto err_mutex_unlock; - } - } + /* submit USB streaming packets */ + usb_urb_submitv2(&adap->stream, &stream_props); - if (d->props->streaming_ctrl) { - ret = d->props->streaming_ctrl( - adap->fe[adap->active_fe], 1); - if (ret < 0) { - dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ - "failed=%d\n", KBUILD_MODNAME, - ret); - goto err_mutex_unlock; - } - } + /* enable HW PID filter */ + if (adap->pid_filtering && adap->props->pid_filter_ctrl) { + ret = adap->props->pid_filter_ctrl(adap, 1); + if (ret) + dev_err(&d->udev->dev, + "%s: pid_filter_ctrl() failed=%d\n", + KBUILD_MODNAME, ret); } - return 0; -err_mutex_unlock: - mutex_unlock(&adap->sync_mutex); - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} + /* ask device to start streaming */ + if (d->props->streaming_ctrl) { + ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1); + if (ret) + dev_err(&d->udev->dev, + "%s: streaming_ctrl() failed=%d\n", + KBUILD_MODNAME, ret); + } +skip_feed_start: -static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - return dvb_usb_ctrl_feed(dvbdmxfeed, 1); + /* add PID to device HW PID filter */ + if (adap->pid_filtering && adap->props->pid_filter) { + ret = adap->props->pid_filter(adap, dvbdmxfeed->index, + dvbdmxfeed->pid, 1); + if (ret) + dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", + KBUILD_MODNAME, ret); + } + + if (ret) + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; } static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - return dvb_usb_ctrl_feed(dvbdmxfeed, -1); + struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; + struct dvb_usb_device *d = adap_to_d(adap); + int ret = 0; + dev_dbg(&d->udev->dev, + "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", + __func__, adap->id, adap->active_fe, dvbdmxfeed->type, + adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, + dvbdmxfeed->pid, dvbdmxfeed->index); + + if (adap->active_fe == -1) + return -EINVAL; + + /* remove PID from device HW PID filter */ + if (adap->pid_filtering && adap->props->pid_filter) { + ret = adap->props->pid_filter(adap, dvbdmxfeed->index, + dvbdmxfeed->pid, 0); + if (ret) + dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", + KBUILD_MODNAME, ret); + } + + /* we cannot stop streaming until last PID is removed */ + if (--adap->feed_count > 0) + goto skip_feed_stop; + + /* ask device to stop streaming */ + if (d->props->streaming_ctrl) { + ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 0); + if (ret) + dev_err(&d->udev->dev, + "%s: streaming_ctrl() failed=%d\n", + KBUILD_MODNAME, ret); + } + + /* disable HW PID filter */ + if (adap->pid_filtering && adap->props->pid_filter_ctrl) { + ret = adap->props->pid_filter_ctrl(adap, 0); + if (ret) + dev_err(&d->udev->dev, + "%s: pid_filter_ctrl() failed=%d\n", + KBUILD_MODNAME, ret); + } + + /* kill USB streaming packets */ + usb_urb_killv2(&adap->stream); + + /* clear 'streaming' status bit */ + clear_bit(ADAP_STREAMING, &adap->state_bits); + smp_mb__after_atomic(); + wake_up_bit(&adap->state_bits, ADAP_STREAMING); +skip_feed_stop: + + if (ret) + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; } -int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) { int ret; struct dvb_usb_device *d = adap_to_d(adap); @@ -427,8 +466,6 @@ int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) goto err_dvb_net_init; } - mutex_init(&adap->sync_mutex); - return 0; err_dvb_net_init: dvb_dmxdev_release(&adap->dmxdev); @@ -441,7 +478,7 @@ err_dvb_register_adapter: return ret; } -int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) { dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, adap->id); @@ -457,7 +494,7 @@ int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) return 0; } -int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) +static int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; @@ -492,7 +529,7 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) if (!adap->suspend_resume_active) { adap->active_fe = fe->id; - mutex_lock(&adap->sync_mutex); + set_bit(ADAP_INIT, &adap->state_bits); } ret = dvb_usbv2_device_power_ctrl(d, 1); @@ -511,8 +548,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe) goto err; } err: - if (!adap->suspend_resume_active) - mutex_unlock(&adap->sync_mutex); + if (!adap->suspend_resume_active) { + clear_bit(ADAP_INIT, &adap->state_bits); + smp_mb__after_atomic(); + wake_up_bit(&adap->state_bits, ADAP_INIT); + } dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); return ret; @@ -526,8 +566,11 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, fe->id); - if (!adap->suspend_resume_active) - mutex_lock(&adap->sync_mutex); + if (!adap->suspend_resume_active) { + set_bit(ADAP_SLEEP, &adap->state_bits); + wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule, + TASK_UNINTERRUPTIBLE); + } if (adap->fe_sleep[fe->id]) { ret = adap->fe_sleep[fe->id](fe); @@ -547,14 +590,16 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe) err: if (!adap->suspend_resume_active) { adap->active_fe = -1; - mutex_unlock(&adap->sync_mutex); + clear_bit(ADAP_SLEEP, &adap->state_bits); + smp_mb__after_atomic(); + wake_up_bit(&adap->state_bits, ADAP_SLEEP); } dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); return ret; } -int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) { int ret, i, count_registered = 0; struct dvb_usb_device *d = adap_to_d(adap); @@ -566,8 +611,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) if (d->props->frontend_attach) { ret = d->props->frontend_attach(adap); if (ret < 0) { - dev_dbg(&d->udev->dev, "%s: frontend_attach() " \ - "failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, + "%s: frontend_attach() failed=%d\n", + __func__, ret); goto err_dvb_frontend_detach; } } else { @@ -587,8 +633,9 @@ int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); if (ret < 0) { - dev_err(&d->udev->dev, "%s: frontend%d registration " \ - "failed\n", KBUILD_MODNAME, i); + dev_err(&d->udev->dev, + "%s: frontend%d registration failed\n", + KBUILD_MODNAME, i); goto err_dvb_unregister_frontend; } @@ -623,7 +670,7 @@ err: return ret; } -int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) +static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) { int i; dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, @@ -662,33 +709,33 @@ static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) /* speed - when running at FULL speed we need a HW PID filter */ if (d->udev->speed == USB_SPEED_FULL && !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { - dev_err(&d->udev->dev, "%s: this USB2.0 device " \ - "cannot be run on a USB1.1 port (it " \ - "lacks a hardware PID filter)\n", + dev_err(&d->udev->dev, + "%s: this USB2.0 device cannot be run on a USB1.1 port (it lacks a hardware PID filter)\n", KBUILD_MODNAME); ret = -ENODEV; goto err; } else if ((d->udev->speed == USB_SPEED_FULL && adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { - dev_info(&d->udev->dev, "%s: will use the device's " \ - "hardware PID filter " \ - "(table count: %d)\n", KBUILD_MODNAME, + dev_info(&d->udev->dev, + "%s: will use the device's hardware PID filter (table count: %d)\n", + KBUILD_MODNAME, adap->props->pid_filter_count); adap->pid_filtering = 1; adap->max_feed_count = adap->props->pid_filter_count; } else { - dev_info(&d->udev->dev, "%s: will pass the complete " \ - "MPEG2 transport stream to the " \ - "software demuxer\n", KBUILD_MODNAME); + dev_info(&d->udev->dev, + "%s: will pass the complete MPEG2 transport stream to the software demuxer\n", + KBUILD_MODNAME); adap->pid_filtering = 0; adap->max_feed_count = 255; } if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { - dev_info(&d->udev->dev, "%s: PID filter enabled by " \ - "module option\n", KBUILD_MODNAME); + dev_info(&d->udev->dev, + "%s: PID filter enabled by module option\n", + KBUILD_MODNAME); adap->pid_filtering = 1; adap->max_feed_count = adap->props->pid_filter_count; } @@ -786,20 +833,44 @@ err: return ret; } -/* - * udev, which is used for the firmware downloading, requires we cannot - * block during module_init(). module_init() calls USB probe() which - * is this routine. Due to that we delay actual operation using workqueue - * and return always success here. - */ -static void dvb_usbv2_init_work(struct work_struct *work) +int dvb_usbv2_probe(struct usb_interface *intf, + const struct usb_device_id *id) { int ret; - struct dvb_usb_device *d = - container_of(work, struct dvb_usb_device, probe_work); + struct dvb_usb_device *d; + struct usb_device *udev = interface_to_usbdev(intf); + struct dvb_usb_driver_info *driver_info = + (struct dvb_usb_driver_info *) id->driver_info; + + dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + if (!id->driver_info) { + dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); + ret = -ENODEV; + goto err; + } - d->work_pid = current->pid; - dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); + d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); + if (!d) { + dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + ret = -ENOMEM; + goto err; + } + + d->name = driver_info->name; + d->rc_map = driver_info->rc_map; + d->udev = udev; + d->props = driver_info->props; + + if (intf->cur_altsetting->desc.bInterfaceNumber != + d->props->bInterfaceNumber) { + ret = -ENODEV; + goto err_free_all; + } + + mutex_init(&d->usb_mutex); + mutex_init(&d->i2c_mutex); if (d->props->size_of_priv) { d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); @@ -807,7 +878,7 @@ static void dvb_usbv2_init_work(struct work_struct *work) dev_err(&d->udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); ret = -ENOMEM; - goto err_usb_driver_release_interface; + goto err_free_all; } } @@ -817,8 +888,9 @@ static void dvb_usbv2_init_work(struct work_struct *work) if (ret == 0) { ; } else if (ret == COLD) { - dev_info(&d->udev->dev, "%s: found a '%s' in cold " \ - "state\n", KBUILD_MODNAME, d->name); + dev_info(&d->udev->dev, + "%s: found a '%s' in cold state\n", + KBUILD_MODNAME, d->name); if (!name) name = d->props->firmware; @@ -836,20 +908,12 @@ static void dvb_usbv2_init_work(struct work_struct *work) * device. As 'new' device is warm we should * never go here again. */ - return; + goto exit; } else { - /* - * Unexpected error. We must unregister driver - * manually from the device, because device is - * already register by returning from probe() - * with success. usb_driver_release_interface() - * finally calls disconnect() in order to free - * resources. - */ - goto err_usb_driver_release_interface; + goto err_free_all; } } else { - goto err_usb_driver_release_interface; + goto err_free_all; } } @@ -858,72 +922,17 @@ static void dvb_usbv2_init_work(struct work_struct *work) ret = dvb_usbv2_init(d); if (ret < 0) - goto err_usb_driver_release_interface; + goto err_free_all; - dev_info(&d->udev->dev, "%s: '%s' successfully initialized and " \ - "connected\n", KBUILD_MODNAME, d->name); - - return; -err_usb_driver_release_interface: - dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n", - KBUILD_MODNAME, d->name, ret); - usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), - d->intf); - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); - return; -} - -int dvb_usbv2_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret; - struct dvb_usb_device *d; - struct usb_device *udev = interface_to_usbdev(intf); - struct dvb_usb_driver_info *driver_info = - (struct dvb_usb_driver_info *) id->driver_info; - - dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - - if (!id->driver_info) { - dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); - ret = -ENODEV; - goto err; - } - - d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); - if (!d) { - dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); - ret = -ENOMEM; - goto err; - } - - d->name = driver_info->name; - d->rc_map = driver_info->rc_map; - d->udev = udev; - d->intf = intf; - d->props = driver_info->props; - - if (d->intf->cur_altsetting->desc.bInterfaceNumber != - d->props->bInterfaceNumber) { - ret = -ENODEV; - goto err_kfree; - } - - mutex_init(&d->usb_mutex); - mutex_init(&d->i2c_mutex); - INIT_WORK(&d->probe_work, dvb_usbv2_init_work); + dev_info(&d->udev->dev, + "%s: '%s' successfully initialized and connected\n", + KBUILD_MODNAME, d->name); +exit: usb_set_intfdata(intf, d); - ret = schedule_work(&d->probe_work); - if (ret < 0) { - dev_err(&d->udev->dev, "%s: schedule_work() failed\n", - KBUILD_MODNAME); - goto err_kfree; - } return 0; -err_kfree: - kfree(d); +err_free_all: + dvb_usbv2_exit(d); err: dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); return ret; @@ -935,12 +944,8 @@ 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; - dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, - current->pid, d->work_pid); - - /* ensure initialization work is finished until release resources */ - if (d->work_pid != current->pid) - cancel_work_sync(&d->probe_work); + dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); if (d->props->exit) d->props->exit(d); @@ -960,7 +965,7 @@ int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) dev_dbg(&d->udev->dev, "%s:\n", __func__); /* stop remote controller poll */ - if (d->rc.query && !d->rc.bulk_mode) + if (d->rc_polling_active) cancel_delayed_work_sync(&d->rc_query_work); for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { @@ -1007,7 +1012,7 @@ static int dvb_usbv2_resume_common(struct dvb_usb_device *d) } /* start remote controller poll */ - if (d->rc.query && !d->rc.bulk_mode) + if (d->rc_polling_active) schedule_delayed_work(&d->rc_query_work, msecs_to_jiffies(d->rc.interval)); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c index 0431beed0ef..33ff97e708e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -21,8 +21,8 @@ #include "dvb_usb_common.h" -int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, - u16 rlen) +static int dvb_usb_v2_generic_io(struct dvb_usb_device *d, + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { int ret, actual_length; @@ -32,10 +32,6 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, return -EINVAL; } - ret = mutex_lock_interruptible(&d->usb_mutex); - if (ret < 0) - return ret; - dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf); ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, @@ -58,20 +54,51 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, d->props->generic_bulk_ctrl_endpoint_response), rbuf, rlen, &actual_length, 2000); if (ret) - dev_err(&d->udev->dev, "%s: 2nd usb_bulk_msg() " \ - "failed=%d\n", KBUILD_MODNAME, ret); + dev_err(&d->udev->dev, + "%s: 2nd usb_bulk_msg() failed=%d\n", + KBUILD_MODNAME, ret); dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__, actual_length, rbuf); } + return ret; +} + +int dvb_usbv2_generic_rw(struct dvb_usb_device *d, + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) +{ + int ret; + + mutex_lock(&d->usb_mutex); + ret = dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen); mutex_unlock(&d->usb_mutex); + return ret; } EXPORT_SYMBOL(dvb_usbv2_generic_rw); int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) { - return dvb_usbv2_generic_rw(d, buf, len, NULL, 0); + int ret; + + mutex_lock(&d->usb_mutex); + ret = dvb_usb_v2_generic_io(d, buf, len, NULL, 0); + mutex_unlock(&d->usb_mutex); + + return ret; } EXPORT_SYMBOL(dvb_usbv2_generic_write); + +int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *d, + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) +{ + return dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen); +} +EXPORT_SYMBOL(dvb_usbv2_generic_rw_locked); + +int dvb_usbv2_generic_write_locked(struct dvb_usb_device *d, u8 *buf, u16 len) +{ + return dvb_usb_v2_generic_io(d, buf, len, NULL, 0); +} +EXPORT_SYMBOL(dvb_usbv2_generic_write_locked); diff --git a/drivers/media/usb/dvb-usb-v2/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c index 5c68f3918bc..0c2b377704f 100644 --- a/drivers/media/usb/dvb-usb-v2/ec168.c +++ b/drivers/media/usb/dvb-usb-v2/ec168.c @@ -170,7 +170,7 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], error: mutex_unlock(&d->i2c_mutex); - return i; + return ret; } static u32 ec168_i2c_func(struct i2c_adapter *adapter) 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 695f9106bc5..00000000000 --- a/drivers/media/usb/dvb-usb-v2/it913x.c +++ /dev/null @@ -1,799 +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); - - 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 */ -#define IT913X_POLL 250 -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; -} - -/* 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->stream.buf_size / 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); - 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]) { - 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_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_TYPE_NEC; - rc->query = it913x_rc_query; - rc->interval = 250; - - return 0; -} - -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) }, - {} /* 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.32"); -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/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index c41d9d9ec7b..f674dc024d0 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -81,6 +81,7 @@ #include "dvb-pll.h" #include "z0194a.h" #include "m88rs2000.h" +#include "ts2020.h" #define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw"; @@ -626,8 +627,8 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], gate = 5; for (i = 0; i < num; i++) { - read_o = 1 & (msg[i].flags & I2C_M_RD); - read = i+1 < num && (msg[i+1].flags & I2C_M_RD); + read_o = msg[i].flags & I2C_M_RD; + read = i + 1 < num && msg[i + 1].flags & I2C_M_RD; read |= read_o; gate = (msg[i].addr == st->i2c_tuner_addr) ? (read) ? st->i2c_tuner_gate_r @@ -640,7 +641,8 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], else obuf[1] = msg[i].len + read + 1; - obuf[2] = msg[i].addr; + obuf[2] = msg[i].addr << 1; + if (read) { if (read_o) len = 3; @@ -799,7 +801,7 @@ static const char fw_c_rs2000[] = LME2510_C_RS2000; static const char fw_lg[] = LME2510_LG; static const char fw_s0194[] = LME2510_S0194; -const char *lme_firmware_switch(struct dvb_usb_device *d, int cold) +static const char *lme_firmware_switch(struct dvb_usb_device *d, int cold) { struct lme2510_state *st = d->priv; struct usb_device *udev = d->udev; @@ -894,27 +896,27 @@ static int lme2510_kill_urb(struct usb_data_stream *stream) } static struct tda10086_config tda10086_config = { - .demod_address = 0x1c, + .demod_address = 0x0e, .invert = 0, .diseqc_tone = 1, .xtal_freq = TDA10086_XTAL_16M, }; static struct stv0288_config lme_config = { - .demod_address = 0xd0, + .demod_address = 0x68, .min_delay_ms = 15, .inittab = s7395_inittab, }; static struct ix2505v_config lme_tuner = { - .tuner_address = 0xc0, + .tuner_address = 0x60, .min_delay_ms = 100, .tuner_gain = 0x0, .tuner_chargepump = 0x3, }; static struct stv0299_config sharp_z0194_config = { - .demod_address = 0xd0, + .demod_address = 0x68, .inittab = sharp_z0194a_inittab, .mclk = 88000000UL, .invert = 0, @@ -943,11 +945,15 @@ static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, } static struct m88rs2000_config m88rs2000_config = { - .demod_addr = 0xd0, - .tuner_addr = 0xc0, + .demod_addr = 0x68, .set_ts_params = dm04_rs2000_set_ts_param, }; +static struct ts2020_config ts2020_config = { + .tuner_address = 0x60, + .clk_out_div = 7, +}; + static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { @@ -1049,7 +1055,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) info("TUN Found Frontend TDA10086"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 4; - st->i2c_tuner_addr = 0xc0; + st->i2c_tuner_addr = 0x60; st->tuner_config = TUNER_LG; if (st->dvb_usb_lme2510_firmware != TUNER_LG) { st->dvb_usb_lme2510_firmware = TUNER_LG; @@ -1065,7 +1071,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) info("FE Found Stv0299"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 5; - st->i2c_tuner_addr = 0xc0; + st->i2c_tuner_addr = 0x60; st->tuner_config = TUNER_S0194; if (st->dvb_usb_lme2510_firmware != TUNER_S0194) { st->dvb_usb_lme2510_firmware = TUNER_S0194; @@ -1082,7 +1088,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) info("FE Found Stv0288"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 5; - st->i2c_tuner_addr = 0xc0; + st->i2c_tuner_addr = 0x60; st->tuner_config = TUNER_S7395; if (st->dvb_usb_lme2510_firmware != TUNER_S7395) { st->dvb_usb_lme2510_firmware = TUNER_S7395; @@ -1097,9 +1103,11 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) if (adap->fe[0]) { info("FE Found M88RS2000"); + dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config, + &d->i2c_adap); st->i2c_tuner_gate_w = 5; st->i2c_tuner_gate_r = 5; - st->i2c_tuner_addr = 0xc0; + st->i2c_tuner_addr = 0x60; st->tuner_config = TUNER_RS2000; st->fe_set_voltage = adap->fe[0]->ops.set_voltage; @@ -1144,7 +1152,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) switch (st->tuner_config) { case TUNER_LG: - if (dvb_attach(tda826x_attach, adap->fe[0], 0xc0, + if (dvb_attach(tda826x_attach, adap->fe[0], 0x60, &d->i2c_adap, 1)) ret = st->tuner_config; break; @@ -1154,7 +1162,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) ret = st->tuner_config; break; case TUNER_S0194: - if (dvb_attach(dvb_pll_attach , adap->fe[0], 0xc0, + if (dvb_attach(dvb_pll_attach , adap->fe[0], 0x60, &d->i2c_adap, DVB_PLL_OPERA1)) ret = st->tuner_config; break; @@ -1217,7 +1225,7 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) usb_reset_configuration(d->udev); usb_set_interface(d->udev, - d->intf->cur_altsetting->desc.bInterfaceNumber, 1); + d->props->bInterfaceNumber, 1); st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; @@ -1233,10 +1241,13 @@ static int lme2510_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); - struct dvb_usb_device *d = adap_to_d(adap); + struct dvb_usb_device *d; if (adap == NULL) return 0; + + d = adap_to_d(adap); + /* Turn PID filter on the fly by module option */ if (pid_filter == 2) { adap->pid_filtering = 1; @@ -1253,7 +1264,7 @@ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, static int lme2510_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - rc->allowed_protos = RC_TYPE_NEC; + rc->allowed_protos = RC_BIT_NEC; return 0; } @@ -1291,8 +1302,7 @@ static void lme2510_exit(struct dvb_usb_device *d) if (d != NULL) { usb_buffer = lme2510_exit_int(d); - if (usb_buffer != NULL) - kfree(usb_buffer); + kfree(usb_buffer); } } diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index d83df4bb72d..0a98d04c53e 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -1,7 +1,7 @@ /* * mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 @@ -601,7 +601,7 @@ struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, EXPORT_SYMBOL_GPL(mxl111sf_demod_attach); MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver"); -MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); +MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h index 432706ae527..2d4530f5be5 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h @@ -1,7 +1,7 @@ /* * mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 @@ -21,6 +21,7 @@ #ifndef __MXL111SF_DEMOD_H__ #define __MXL111SF_DEMOD_H__ +#include <linux/kconfig.h> #include "dvb_frontend.h" #include "mxl111sf.h" @@ -31,8 +32,7 @@ struct mxl111sf_demod_config { struct mxl111sf_reg_ctrl_info *ctrl_reg_info); }; -#if defined(CONFIG_DVB_USB_MXL111SF) || \ - (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, struct mxl111sf_demod_config *cfg); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c index e4121cb8f5e..a619410adde 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c @@ -1,7 +1,7 @@ /* * mxl111sf-gpio.c - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h index 0220f54299a..b85a5772d77 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h @@ -1,7 +1,7 @@ /* * mxl111sf-gpio.h - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index 34434557ef6..a101d06eb14 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -1,7 +1,7 @@ /* * mxl111sf-i2c.c - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h index a57a45ffb9e..465762145ad 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h @@ -1,7 +1,7 @@ /* * mxl111sf-i2c.h - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c index b741b3a7a32..f6b348024be 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c @@ -1,7 +1,7 @@ /* * mxl111sf-phy.c - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h index f0756071d34..0643738de7d 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h @@ -1,7 +1,7 @@ /* * mxl111sf-phy.h - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h index 17831b0fb9d..89bf115e927 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h @@ -1,7 +1,7 @@ /* * mxl111sf-reg.h - driver for the MaxLinear MXL111SF * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index ef4c65fcbb7..a8d2c705367 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -1,7 +1,7 @@ /* * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 @@ -31,8 +31,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); if (mxl111sf_tuner_debug) \ mxl_printk(KERN_DEBUG, fmt, ##arg) -#define err pr_err - /* ------------------------------------------------------------------------ */ struct mxl111sf_tuner_state { @@ -113,7 +111,7 @@ static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq, filt_bw = 63; break; default: - err("%s: invalid bandwidth setting!", __func__); + pr_err("%s: invalid bandwidth setting!", __func__); return NULL; } @@ -304,12 +302,12 @@ static int mxl111sf_tuner_set_params(struct dvb_frontend *fe) bw = 8; break; default: - err("%s: bandwidth not set!", __func__); + pr_err("%s: bandwidth not set!", __func__); return -EINVAL; } break; default: - err("%s: modulation type not supported!", __func__); + pr_err("%s: modulation type not supported!", __func__); return -EINVAL; } ret = mxl1x1sf_tune_rf(fe, c->frequency, bw); @@ -514,7 +512,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach); MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver"); -MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); +MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index ff333960b18..2046db22519 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -1,7 +1,7 @@ /* * mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner * - * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> + * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> * * 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 @@ -21,8 +21,8 @@ #ifndef __MXL111SF_TUNER_H__ #define __MXL111SF_TUNER_H__ +#include <linux/kconfig.h> #include "dvb_frontend.h" - #include "mxl111sf.h" enum mxl_if_freq { @@ -60,8 +60,7 @@ struct mxl111sf_tuner_config { /* ------------------------------------------------------------------------ */ -#if defined(CONFIG_DVB_USB_MXL111SF) || \ - (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, struct mxl111sf_state *mxl_state, @@ -69,7 +68,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, #else static inline struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state + struct mxl111sf_state *mxl_state, struct mxl111sf_tuner_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index efdcb15358f..c7304fa8ab7 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) + * Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org) * * 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 @@ -23,6 +23,9 @@ #include "lgdt3305.h" #include "lg2160.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + int dvb_usb_mxl111sf_debug; module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level " @@ -52,20 +55,19 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -#define deb_info pr_debug -#define deb_reg pr_debug -#define deb_adv pr_debug -#define err pr_err -#define info pr_info - int mxl111sf_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int wo = (rbuf == NULL || rlen == 0); /* write-only */ int ret; - u8 sndbuf[1+wlen]; + u8 sndbuf[MAX_XFER_SIZE]; + + if (1 + wlen > sizeof(sndbuf)) { + pr_warn("%s: len=%d is too big!\n", __func__, wlen); + return -EOPNOTSUPP; + } - deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); + pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); memset(sndbuf, 0, 1+wlen); @@ -98,12 +100,12 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) if (buf[0] == addr) *data = buf[1]; else { - err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", + pr_err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", addr, buf[0], buf[1]); ret = -EINVAL; } - deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); + pr_debug("R: (0x%02x, 0x%02x)\n", addr, buf[1]); fail: return ret; } @@ -113,11 +115,11 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) u8 buf[] = { addr, data }; int ret; - deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); + pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) - err("error writing reg: 0x%02x, val: 0x%02x", addr, data); + pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; } @@ -134,7 +136,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state, #if 1 /* dont know why this usually errors out on the first try */ if (mxl_fail(ret)) - err("error writing addr: 0x%02x, mask: 0x%02x, " + pr_err("error writing addr: 0x%02x, mask: 0x%02x, " "data: 0x%02x, retrying...", addr, mask, data); ret = mxl111sf_read_reg(state, addr, &val); @@ -167,7 +169,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, ctrl_reg_info[i].mask, ctrl_reg_info[i].data); if (mxl_fail(ret)) { - err("failed on reg #%d (0x%02x)", i, + pr_err("failed on reg #%d (0x%02x)", i, ctrl_reg_info[i].addr); break; } @@ -225,7 +227,7 @@ static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) mxl_rev = "UNKNOWN REVISION"; break; } - info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); + pr_info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); fail: return ret; } @@ -239,7 +241,7 @@ fail: " on first probe attempt"); \ ___ret = mxl1x1sf_get_chip_info(state); \ if (mxl_fail(___ret)) \ - err("failed to get chip info during probe"); \ + pr_err("failed to get chip info during probe"); \ else \ mxl_debug("probe needed a retry " \ "in order to succeed."); \ @@ -264,20 +266,20 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); mutex_lock(&state->fe_lock); state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); err = mxl1x1sf_soft_reset(state); mxl_fail(err); @@ -320,13 +322,13 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; @@ -344,7 +346,7 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -368,7 +370,7 @@ static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -394,7 +396,7 @@ static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -424,7 +426,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -432,7 +434,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; adap_state->gpio_mode = state->gpio_mode; @@ -495,7 +497,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -503,7 +505,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -580,7 +582,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -588,7 +590,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -667,7 +669,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -675,7 +677,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -742,7 +744,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -750,7 +752,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; adap_state->gpio_mode = state->gpio_mode; @@ -802,7 +804,7 @@ static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, } #define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ - err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ + pr_err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ __func__, __LINE__, \ (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ pwr0, pwr1, pwr2, pwr3) @@ -868,7 +870,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) struct mxl111sf_state *state = adap_to_priv(adap); int i; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); for (i = 0; i < state->num_frontends; i++) { if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state, @@ -902,7 +904,7 @@ static int mxl111sf_init(struct dvb_usb_device *d) ret = get_chip_info(state); if (mxl_fail(ret)) - err("failed to get chip info during probe"); + pr_err("failed to get chip info during probe"); mutex_init(&state->fe_lock); @@ -950,7 +952,7 @@ static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -970,7 +972,7 @@ static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -990,7 +992,7 @@ static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_attach_demod(adap, 0); if (ret < 0) @@ -1006,7 +1008,7 @@ static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint) { - deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint); + pr_debug("%s: endpoint=%d size=8192\n", __func__, endpoint); stream->type = USB_BULK; stream->count = 5; stream->endpoint = endpoint; @@ -1016,7 +1018,7 @@ static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *strea static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream, u8 endpoint, int framesperurb, int framesize) { - deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint, + pr_debug("%s: endpoint=%d size=%d\n", __func__, endpoint, framesperurb * framesize); stream->type = USB_ISOC; stream->count = 5; @@ -1035,7 +1037,7 @@ static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *strea static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1076,7 +1078,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = { static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1117,7 +1119,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = { static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_RAW; if (dvb_usb_mxl111sf_isoc) @@ -1158,7 +1160,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = { static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1184,7 +1186,7 @@ static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1228,7 +1230,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1260,7 +1262,7 @@ static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1306,7 +1308,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = { static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1332,7 +1334,7 @@ static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep4_streaming_ctrl(fe, onoff); @@ -1419,7 +1421,7 @@ static struct usb_driver mxl111sf_usb_driver = { module_usb_driver(mxl111sf_usb_driver); -MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); +MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 9816de86e48..8516c011b7c 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) + * Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org) * * 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 diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index adabba8d28b..a676e445284 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -33,7 +33,50 @@ #include "e4000.h" #include "fc2580.h" #include "tua9001.h" +#include "r820t.h" +/* + * RTL2832_SDR module is in staging. That logic is added in order to avoid any + * hard dependency to drivers/staging/ directory as we want compile mainline + * driver even whole staging directory is missing. + */ +#include <media/v4l2-subdev.h> + +#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR) +struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct rtl2832_config *cfg, + struct v4l2_subdev *sd); +#else +static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct rtl2832_config *cfg, + struct v4l2_subdev *sd) +{ + return NULL; +} +#endif + +#ifdef CONFIG_MEDIA_ATTACH +#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } \ + __r; \ +}) + +#else +#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) + +#endif + +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) @@ -375,6 +418,8 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; + struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf}; + struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf}; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -479,6 +524,23 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) goto found; } + /* check R820T ID register; reg=00 val=69 */ + ret = rtl28xxu_ctrl_msg(d, &req_r820t); + if (ret == 0 && buf[0] == 0x69) { + priv->tuner = TUNER_RTL2832_R820T; + priv->tuner_name = "R820T"; + goto found; + } + + /* check R828D ID register; reg=00 val=69 */ + ret = rtl28xxu_ctrl_msg(d, &req_r828d); + if (ret == 0 && buf[0] == 0x69) { + priv->tuner = TUNER_RTL2832_R828D; + priv->tuner_name = "R828D"; + goto found; + } + + found: dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); @@ -493,7 +555,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, @@ -504,7 +566,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, @@ -514,7 +576,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, @@ -528,7 +590,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__); @@ -563,32 +625,36 @@ 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 const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { + .i2c_addr = 0x10, + .xtal = 28800000, + .tuner = TUNER_RTL2832_R820T, +}; + static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { @@ -707,7 +773,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__); @@ -728,6 +794,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) case TUNER_RTL2832_E4000: rtl2832_config = &rtl28xxu_rtl2832_e4000_config; break; + case TUNER_RTL2832_R820T: + case TUNER_RTL2832_R828D: + rtl2832_config = &rtl28xxu_rtl2832_r820t_config; + break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", KBUILD_MODNAME, priv->tuner_name); @@ -742,6 +812,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; @@ -821,11 +894,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, @@ -835,25 +903,51 @@ static struct tua9001_config rtl2832u_tua9001_config = { .i2c_addr = 0x60, }; +static const struct fc0012_config rtl2832u_fc0012_config = { + .i2c_address = 0x63, /* 0xc6 >> 1 */ + .xtal_freq = FC_XTAL_28_8_MHZ, +}; + +static const struct r820t_config rtl2832u_r820t_config = { + .i2c_addr = 0x1a, + .xtal = 28800000, + .max_i2c_msg_len = 2, + .rafael_chip = CHIP_R820T, +}; + +static const struct r820t_config rtl2832u_r828d_config = { + .i2c_addr = 0x3a, + .xtal = 16000000, + .max_i2c_msg_len = 2, + .rafael_chip = CHIP_R828D, +}; + 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], - &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + &d->i2c_adap, &rtl2832u_fc0012_config); /* since fc0012 includs reading the signal strength delegate * 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_sdr(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], @@ -862,10 +956,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_sdr(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_sdr(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, @@ -884,13 +1011,45 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap, &rtl2832u_tua9001_config); break; + case TUNER_RTL2832_R820T: + fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, + &rtl2832u_r820t_config); + + /* 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_sdr(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 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01); + if (ret) + goto err; + + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); + if (ret) + goto err; + + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); + if (ret) + goto err; + + fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, + &rtl2832u_r828d_config); + + /* Use tuner to get the signal strength */ + adap->fe[0]->ops.read_signal_strength = + 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; } @@ -935,6 +1094,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; @@ -1002,67 +1177,34 @@ err: static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - u8 val; dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); if (onoff) { - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - val |= 0x08; - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); - if (ret) - goto err; - - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); + /* GPIO3=1, GPIO4=0 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); if (ret) goto err; - /* demod control */ - /* PLL enable */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); + /* suspend? */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); if (ret) goto err; - /* bit 7 to 1 */ - val |= 0x80; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* enable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); if (ret) goto err; - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val |= 0x20; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable reset */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); if (ret) goto err; mdelay(5); - /*enable ADC_Q and ADC_I */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val |= 0x48; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* enable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48); if (ret) goto err; @@ -1075,36 +1217,18 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; } else { - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val |= 0x0c; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); + /* GPIO4=1 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); if (ret) goto err; - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - val |= 0x10; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + /* disable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48); if (ret) goto err; - /* demod control */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val &= 0x37; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); if (ret) goto err; @@ -1120,7 +1244,7 @@ err: return ret; } - +#if IS_ENABLED(CONFIG_RC_CORE) static int rtl2831u_rc_query(struct dvb_usb_device *d) { int ret, i; @@ -1197,7 +1321,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_TYPE_NEC; + rc->allowed_protos = RC_BIT_NEC; rc->query = rtl2831u_rc_query; rc->interval = 400; @@ -1206,35 +1330,44 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, static int rtl2832u_rc_query(struct dvb_usb_device *d) { - int ret, i; + int ret, i, len; struct rtl28xxu_priv *priv = d->priv; + struct ir_raw_event ev; u8 buf[128]; - int len; - struct rtl28xxu_reg_val rc_nec_tab[] = { - { IR_RX_CTRL, 0x20 }, - { IR_RX_BUF_CTRL, 0x80 }, - { IR_RX_IF, 0xff }, - { IR_RX_IE, 0xff }, - { IR_MAX_DURATION0, 0xd0 }, - { IR_MAX_DURATION1, 0x07 }, - { IR_IDLE_LEN0, 0xc0 }, - { IR_IDLE_LEN1, 0x00 }, - { IR_GLITCH_LEN, 0x03 }, - { IR_RX_CLK, 0x09 }, - { IR_RX_CFG, 0x1c }, - { IR_MAX_H_TOL_LEN, 0x1e }, - { IR_MAX_L_TOL_LEN, 0x1e }, - { IR_RX_CTRL, 0x80 }, + static const struct rtl28xxu_reg_val_mask refresh_tab[] = { + {IR_RX_IF, 0x03, 0xff}, + {IR_RX_BUF_CTRL, 0x80, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, }; /* init remote controller */ if (!priv->rc_active) { - for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, - rc_nec_tab[i].val); + static const struct rtl28xxu_reg_val_mask init_tab[] = { + {SYS_DEMOD_CTL1, 0x00, 0x04}, + {SYS_DEMOD_CTL1, 0x00, 0x08}, + {USB_CTRL, 0x20, 0x20}, + {SYS_GPIO_DIR, 0x00, 0x08}, + {SYS_GPIO_OUT_EN, 0x08, 0x08}, + {SYS_GPIO_OUT_VAL, 0x08, 0x08}, + {IR_MAX_DURATION0, 0xd0, 0xff}, + {IR_MAX_DURATION1, 0x07, 0xff}, + {IR_IDLE_LEN0, 0xc0, 0xff}, + {IR_IDLE_LEN1, 0x00, 0xff}, + {IR_GLITCH_LEN, 0x03, 0xff}, + {IR_RX_CLK, 0x09, 0xff}, + {IR_RX_CFG, 0x1c, 0xff}, + {IR_MAX_H_TOL_LEN, 0x1e, 0xff}, + {IR_MAX_L_TOL_LEN, 0x1e, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, + }; + + for (i = 0; i < ARRAY_SIZE(init_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, + init_tab[i].val, init_tab[i].mask); if (ret) goto err; } + priv->rc_active = true; } @@ -1250,14 +1383,32 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; len = buf[0]; + + /* read raw code from hw */ ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + if (ret) + goto err; - /* TODO: pass raw IR to Kernel IR decoder */ + /* let hw receive new code */ + for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, + refresh_tab[i].val, refresh_tab[i].mask); + if (ret) + goto err; + } - ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03); - ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); - ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); + /* pass data to Kernel IR decoder */ + init_ir_raw_event(&ev); + for (i = 0; i < len; i++) { + ev.pulse = buf[i] >> 7; + ev.duration = 50800 * (buf[i] & 0x7f); + ir_raw_event_store_with_filter(d->rc_dev, &ev); + } + + /* 'flush' ir_raw_event_store_with_filter() */ + ir_raw_event_set_idle(d->rc_dev, true); + ir_raw_event_handle(d->rc_dev); exit: return ret; err: @@ -1268,13 +1419,24 @@ err: static int rtl2832u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_TYPE_NEC; + /* 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; + rc->allowed_protos = RC_BIT_ALL; + rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 400; return 0; } +#else +#define rtl2831u_get_rc_config NULL +#define rtl2832u_get_rc_config NULL +#endif static const struct dvb_usb_device_properties rtl2831u_props = { .driver_name = KBUILD_MODNAME, @@ -1310,6 +1472,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, @@ -1321,6 +1484,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, @@ -1328,24 +1492,61 @@ 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, &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, - &rtl2832u_props, "Terratec Cinergy T Stick Black", NULL) }, + &rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, - &rtl2832u_props, "NOXON DAB/DAB+ USB dongle", NULL) }, + &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, &rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680, &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID, + &rtl2832u_props, "Leadtek Winfast DTV Dongle Mini D", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, + { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102, + &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7, + &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd3a8, + &rtl2832u_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393, + &rtl2832u_props, "GIGABYTE U7300", NULL) }, + { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104, + &rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) }, + { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, + &rtl2832u_props, "Compro VideoMate U620F", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, + &rtl2832u_props, "MaxMedia HU394-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, + &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) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd395, + &rtl2832u_props, "Peak DVB-T USB", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U, + &rtl2832u_props, "Sveon STV20", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27, + &rtl2832u_props, "Sveon STV27", NULL) }, + + /* RTL2832P devices: */ + { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, + &rtl2832u_props, "Astrometa DVB-T2", 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 2f3af2d3b6c..a26cab10f38 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 { @@ -82,6 +84,8 @@ enum rtl28xxu_tuner { TUNER_RTL2832_E4000, TUNER_RTL2832_TDA18272, TUNER_RTL2832_FC0013, + TUNER_RTL2832_R820T, + TUNER_RTL2832_R828D, }; struct rtl28xxu_req { @@ -96,6 +100,12 @@ struct rtl28xxu_reg_val { u8 val; }; +struct rtl28xxu_reg_val_mask { + u16 reg; + u8 val; + u8 mask; +}; + /* * memory map * diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c index 5989b659037..ca8f3c2b108 100644 --- a/drivers/media/usb/dvb-usb-v2/usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -22,8 +22,8 @@ static void usb_urb_complete(struct urb *urb) int i; u8 *b; - dev_dbg_ratelimited(&stream->udev->dev, "%s: %s urb completed " \ - "status=%d length=%d/%d pack_num=%d errors=%d\n", + dev_dbg_ratelimited(&stream->udev->dev, + "%s: %s urb completed status=%d length=%d/%d pack_num=%d errors=%d\n", __func__, ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", urb->status, urb->actual_length, urb->transfer_buffer_length, @@ -49,8 +49,8 @@ static void usb_urb_complete(struct urb *urb) case PIPE_ISOCHRONOUS: for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status != 0) - dev_dbg(&stream->udev->dev, "%s: iso frame " \ - "descriptor has an error=%d\n", + dev_dbg(&stream->udev->dev, + "%s: iso frame descriptor has an error=%d\n", __func__, urb->iso_frame_desc[i].status); else if (urb->iso_frame_desc[i].actual_length > 0) @@ -67,8 +67,9 @@ static void usb_urb_complete(struct urb *urb) stream->complete(stream, b, urb->actual_length); break; default: - dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \ - "completition handler\n", KBUILD_MODNAME); + dev_err(&stream->udev->dev, + "%s: unknown endpoint type in completition handler\n", + KBUILD_MODNAME); return; } usb_submit_urb(urb, GFP_ATOMIC); @@ -101,8 +102,8 @@ int usb_urb_submitv2(struct usb_data_stream *stream, dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i); ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC); if (ret) { - dev_err(&stream->udev->dev, "%s: could not submit " \ - "urb no. %d - get them all back\n", + dev_err(&stream->udev->dev, + "%s: could not submit urb no. %d - get them all back\n", KBUILD_MODNAME, i); usb_urb_killv2(stream); return ret; @@ -112,7 +113,7 @@ int usb_urb_submitv2(struct usb_data_stream *stream, return 0; } -int usb_urb_free_urbs(struct usb_data_stream *stream) +static int usb_urb_free_urbs(struct usb_data_stream *stream) { int i; @@ -205,7 +206,7 @@ static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream) return 0; } -int usb_free_stream_buffers(struct usb_data_stream *stream) +static int usb_free_stream_buffers(struct usb_data_stream *stream) { if (stream->state & USB_STATE_URB_BUF) { while (stream->buf_num) { @@ -223,14 +224,15 @@ int usb_free_stream_buffers(struct usb_data_stream *stream) return 0; } -int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, - unsigned long size) +static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, + unsigned long size) { stream->buf_num = 0; stream->buf_size = size; - dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \ - "streaming\n", __func__, num * size); + dev_dbg(&stream->udev->dev, + "%s: all in all I will use %lu bytes for streaming\n", + __func__, num * size); for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { stream->buf_list[stream->buf_num] = usb_alloc_coherent( @@ -274,8 +276,8 @@ int usb_urb_reconfig(struct usb_data_stream *stream, } if (stream->buf_num < props->count || stream->buf_size < buf_size) { - dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \ - "allocated buffers are too small\n", + dev_err(&stream->udev->dev, + "%s: cannot reconfigure as allocated buffers are too small\n", KBUILD_MODNAME); return -EINVAL; } @@ -321,8 +323,9 @@ int usb_urb_initv2(struct usb_data_stream *stream, memcpy(&stream->props, props, sizeof(*props)); if (!stream->complete) { - dev_err(&stream->udev->dev, "%s: there is no data callback - " \ - "this doesn't make sense\n", KBUILD_MODNAME); + dev_err(&stream->udev->dev, + "%s: there is no data callback - this doesn't make sense\n", + KBUILD_MODNAME); return -EINVAL; } @@ -343,8 +346,9 @@ int usb_urb_initv2(struct usb_data_stream *stream, return usb_urb_alloc_isoc_urbs(stream); default: - dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \ - "transfer\n", KBUILD_MODNAME); + dev_err(&stream->udev->dev, + "%s: unknown urb-type for data transfer\n", + KBUILD_MODNAME); return -EINVAL; } } |
