summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/dvb-usb
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/dvb/dvb-usb')
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig2
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700.h4
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_core.c115
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_devices.c179
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h5
5 files changed, 299 insertions, 6 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index aee3b5dd6..5880f2d45 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -72,9 +72,11 @@ config DVB_USB_DIB0700
select DVB_DIB7000P
select DVB_DIB7000M
select DVB_DIB3000MC
+ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
select DVB_TUNER_DIB0070
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700.h b/linux/drivers/media/dvb/dvb-usb/dib0700.h
index 66d4dc6ba..739193943 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700.h
@@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug;
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
#define REQUEST_SET_RC 0x11
+#define REQUEST_NEW_I2C_READ 0x12
+#define REQUEST_NEW_I2C_WRITE 0x13
#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
@@ -39,6 +41,8 @@ struct dib0700_state {
u8 rc_toggle;
u8 rc_counter;
u8 is_dib7000pc;
+ u8 fw_use_new_i2c_api;
+ u8 disable_streaming_master_mode;
};
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
index a2162fda5..3c7bdef28 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
}
/*
- * I2C master xfer function
+ * I2C master xfer function (supported in 1.20 firmware)
*/
-static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
+static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ /* The new i2c firmware messages are more reliable and in particular
+ properly support i2c read calls not preceded by a write */
+
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */
+ uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
+ uint8_t en_start = 0;
+ uint8_t en_stop = 0;
+ uint8_t buf[255]; /* TBV: malloc ? */
+ int result, i;
+
+ /* Ensure nobody else hits the i2c bus while we're sending our
+ sequence of messages, (such as the remote control thread) */
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ for (i = 0; i < num; i++) {
+ if (i == 0) {
+ /* First message in the transaction */
+ en_start = 1;
+ } else if (!(msg[i].flags & I2C_M_NOSTART)) {
+ /* Device supports repeated-start */
+ en_start = 1;
+ } else {
+ /* Not the first packet and device doesn't support
+ repeated start */
+ en_start = 0;
+ }
+ if (i == (num - 1)) {
+ /* Last message in the transaction */
+ en_stop = 1;
+ }
+
+ if (msg[i].flags & I2C_M_RD) {
+ /* Read request */
+ u16 index, value;
+ uint8_t i2c_dest;
+
+ i2c_dest = (msg[i].addr << 1);
+ value = ((en_start << 7) | (en_stop << 6) |
+ (msg[i].len & 0x3F)) << 8 | i2c_dest;
+ /* I2C ctrl + FE bus; */
+ index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+
+ result = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev, 0),
+ REQUEST_NEW_I2C_READ,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value, index, msg[i].buf,
+ msg[i].len,
+ USB_CTRL_GET_TIMEOUT);
+ if (result < 0) {
+ err("i2c read error (status = %d)\n", result);
+ break;
+ }
+ } else {
+ /* Write request */
+ buf[0] = REQUEST_NEW_I2C_WRITE;
+ buf[1] = (msg[i].addr << 1);
+ buf[2] = (en_start << 7) | (en_stop << 6) |
+ (msg[i].len & 0x3F);
+ /* I2C ctrl + FE bus; */
+ buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+ /* The Actual i2c payload */
+ memcpy(&buf[4], msg[i].buf, msg[i].len);
+
+ result = usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev, 0),
+ REQUEST_NEW_I2C_WRITE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ 0, 0, buf, msg[i].len + 4,
+ USB_CTRL_GET_TIMEOUT);
+ if (result < 0) {
+ err("i2c write error (status = %d)\n", result);
+ break;
+ }
+ }
+ }
+ mutex_unlock(&d->i2c_mutex);
+ return i;
+}
+
+/*
+ * I2C master xfer function (pre-1.20 firmware)
+ */
+static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+ struct i2c_msg *msg, int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i,len;
@@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num
return i;
}
+static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct dib0700_state *st = d->priv;
+
+ if (st->fw_use_new_i2c_api == 1) {
+ /* User running at least fw 1.20 */
+ return dib0700_i2c_xfer_new(adap, msg, num);
+ } else {
+ /* Use legacy calls */
+ return dib0700_i2c_xfer_legacy(adap, msg, num);
+ }
+}
+
static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
@@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
b[0] = REQUEST_ENABLE_VIDEO;
b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
- b[2] = (0x01 << 4); /* Master mode */
+
+ if (st->disable_streaming_master_mode == 1)
+ b[2] = 0x00;
+ else
+ b[2] = (0x01 << 4); /* Master mode */
+
b[3] = 0x00;
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 88925c9ba..8b74e13a6 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -14,6 +14,8 @@
#include "mt2060.h"
#include "mt2266.h"
#include "tuner-xc2028.h"
+#include "xc5000.h"
+#include "s5h1411.h"
#include "dib0070.h"
static int force_lna_activation;
@@ -679,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
{ 0x01, 0x7d, KEY_VOLUMEDOWN },
{ 0x02, 0x42, KEY_CHANNELUP },
{ 0x00, 0x7d, KEY_CHANNELDOWN },
+
+ /* Key codes for Nova-TD "credit card" remote control. */
+ { 0x1d, 0x00, KEY_0 },
+ { 0x1d, 0x01, KEY_1 },
+ { 0x1d, 0x02, KEY_2 },
+ { 0x1d, 0x03, KEY_3 },
+ { 0x1d, 0x04, KEY_4 },
+ { 0x1d, 0x05, KEY_5 },
+ { 0x1d, 0x06, KEY_6 },
+ { 0x1d, 0x07, KEY_7 },
+ { 0x1d, 0x08, KEY_8 },
+ { 0x1d, 0x09, KEY_9 },
+ { 0x1d, 0x0a, KEY_TEXT },
+ { 0x1d, 0x0d, KEY_MENU },
+ { 0x1d, 0x0f, KEY_MUTE },
+ { 0x1d, 0x10, KEY_VOLUMEUP },
+ { 0x1d, 0x11, KEY_VOLUMEDOWN },
+ { 0x1d, 0x12, KEY_CHANNEL },
+ { 0x1d, 0x14, KEY_UP },
+ { 0x1d, 0x15, KEY_DOWN },
+ { 0x1d, 0x16, KEY_LEFT },
+ { 0x1d, 0x17, KEY_RIGHT },
+ { 0x1d, 0x1c, KEY_TV },
+ { 0x1d, 0x1e, KEY_NEXT },
+ { 0x1d, 0x1f, KEY_BACK },
+ { 0x1d, 0x20, KEY_CHANNELUP },
+ { 0x1d, 0x21, KEY_CHANNELDOWN },
+ { 0x1d, 0x24, KEY_LAST },
+ { 0x1d, 0x25, KEY_OK },
+ { 0x1d, 0x30, KEY_PAUSE },
+ { 0x1d, 0x32, KEY_REWIND },
+ { 0x1d, 0x34, KEY_FASTFORWARD },
+ { 0x1d, 0x35, KEY_PLAY },
+ { 0x1d, 0x36, KEY_STOP },
+ { 0x1d, 0x37, KEY_RECORD },
+ { 0x1d, 0x3b, KEY_GOTO },
+ { 0x1d, 0x3d, KEY_POWER },
};
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@@ -1080,6 +1119,89 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe == NULL ? -ENODEV : 0;
}
+/* S5H1411 */
+static struct s5h1411_config pinnacle_801e_config = {
+ .output_mode = S5H1411_PARALLEL_OUTPUT,
+ .gpio = S5H1411_GPIO_OFF,
+ .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+ .qam_if = S5H1411_IF_44000,
+ .vsb_if = S5H1411_IF_44000,
+ .inversion = S5H1411_INVERSION_OFF,
+ .status_mode = S5H1411_DEMODLOCKING
+};
+
+/* Pinnacle PCTV HD Pro 801e GPIOs map:
+ GPIO0 - currently unknown
+ GPIO1 - xc5000 tuner reset
+ GPIO2 - CX25843 sleep
+ GPIO3 - currently unknown
+ GPIO4 - currently unknown
+ GPIO6 - currently unknown
+ GPIO7 - currently unknown
+ GPIO9 - currently unknown
+ GPIO10 - CX25843 reset
+ */
+static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_state *st = adap->dev->priv;
+
+ /* Make use of the new i2c functions from FW 1.20 */
+ st->fw_use_new_i2c_api = 1;
+
+ /* The s5h1411 requires the dib0700 to not be in master mode */
+ st->disable_streaming_master_mode = 1;
+
+ /* All msleep values taken from Windows USB trace */
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(400);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ msleep(60);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(30);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0);
+ msleep(30);
+
+ /* Put the CX25843 to sleep for now since we're in digital mode */
+ dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
+
+ /* GPIOs are initialized, do the attach */
+ adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+ &adap->dev->i2c_adap);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+int dib0700_xc5000_tuner_callback(void *priv, int command, int arg)
+{
+ struct dvb_usb_adapter *adap = priv;
+
+ /* Reset the tuner */
+ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
+ msleep(330); /* from Windows USB trace */
+ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
+ msleep(330); /* from Windows USB trace */
+
+ return 0;
+}
+
+static struct xc5000_config s5h1411_xc5000_tunerconfig = {
+ .i2c_address = 0x64,
+ .if_khz = 5380,
+ .tuner_callback = dib0700_xc5000_tuner_callback
+};
+
+static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+ &s5h1411_xc5000_tunerconfig, adap)
+ == NULL ? -ENODEV : 0;
+}
+
/* DVB-USB and USB stuff follows */
struct usb_device_id dib0700_usb_id_table[] = {
/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
@@ -1121,6 +1243,11 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
/* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) },
+ { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) },
+ { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) },
+ { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) },
+/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1128,7 +1255,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
.usb_ctrl = DEVICE_SPECIFIC, \
- .firmware = "dvb-usb-dib0700-1.10.fw", \
+ .firmware = "dvb-usb-dib0700-1.20.fw", \
.download_firmware = dib0700_download_firmware, \
.no_reconnect = 1, \
.size_of_priv = sizeof(struct dib0700_state), \
@@ -1295,7 +1422,12 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[31], NULL },
{ NULL },
}
- }
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
@@ -1410,7 +1542,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 3,
+ .num_device_descs = 5,
.devices = {
{ "Terratec Cinergy HT USB XE",
{ &dib0700_usb_id_table[27], NULL },
@@ -1424,6 +1556,47 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[32], NULL },
{ NULL },
},
+ { "Gigabyte U8000-RH",
+ { &dib0700_usb_id_table[37], NULL },
+ { NULL },
+ },
+ { "YUAN High-Tech STK7700PH",
+ { &dib0700_usb_id_table[38], NULL },
+ { NULL },
+ },
+ { "Asus My Cinema-U3000Hybrid",
+ { &dib0700_usb_id_table[39], NULL },
+ { NULL },
+ },
+ },
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .frontend_attach = s5h1411_frontend_attach,
+ .tuner_attach = xc5000_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+ .size_of_priv = sizeof(struct
+ dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "Pinnacle PCTV HD Pro USB Stick",
+ { &dib0700_usb_id_table[40], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV HD USB Stick",
+ { &dib0700_usb_id_table[41], NULL },
+ { NULL },
+ },
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 7ae262e08..dfaf1d257 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -171,6 +171,8 @@
#define USB_PID_PINNACLE_PCTV71E 0x022b
#define USB_PID_PINNACLE_PCTV72E 0x0236
#define USB_PID_PINNACLE_PCTV73E 0x0237
+#define USB_PID_PINNACLE_PCTV801E 0x023a
+#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
@@ -221,9 +223,12 @@
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
#define USB_PID_GIGABYTE_U7000 0x7001
+#define USB_PID_GIGABYTE_U8000 0x7002
#define USB_PID_ASUS_U3000 0x171f
+#define USB_PID_ASUS_U3000H 0x1736
#define USB_PID_ASUS_U3100 0x173f
#define USB_PID_YUAN_EC372S 0x1edc
+#define USB_PID_YUAN_STK7700PH 0x1f08
#define USB_PID_DW2102 0x2102
#define USB_PID_XTENSIONS_XD_380 0x0381
#define USB_PID_TELESTAR_STARSTICK_2 0x8000