From c42b43fa9cd9391ce0d3ffd9cb575ba219868aaa Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Wed, 24 Jun 2015 18:54:36 +0300 Subject: [PATCH] linux: add patch for Hauppauge HVR-2205/2215/2255 support This patch adds support for the Hauppauge HVR-2205/2255 PCIe dual tuners. These are backported from kernel 4.2, so the patch is unnecessary after we move on from kernel 4.1. --- ...inux-229-hauppauge-hvr-2205-and-2255.patch | 618 ++++++++++++++++++ 1 file changed, 618 insertions(+) create mode 100644 packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch diff --git a/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch b/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch new file mode 100644 index 0000000000..f625401e07 --- /dev/null +++ b/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch @@ -0,0 +1,618 @@ +diff -urN a/drivers/media/pci/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c +--- a/drivers/media/pci/saa7164/saa7164-cards.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-cards.c 2015-06-24 18:39:26.842373718 +0300 +@@ -30,6 +30,7 @@ + * attached I2C devices, so we can simplify the virtual i2c mechansms + * and keep the -i2c.c implementation clean. + */ ++#define REGLEN_0bit 0 + #define REGLEN_8bit 1 + #define REGLEN_16bit 2 + +@@ -499,6 +500,144 @@ + .i2c_reg_len = REGLEN_8bit, + } }, + }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2255proto] = { ++ .name = "Hauppauge WinTV-HVR2255(proto)", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x27, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xb2 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x24, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x26, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0x1c >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2255] = { ++ .name = "Hauppauge WinTV-HVR2255", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x28, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xb2 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x25, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x27, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0x1c >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2205] = { ++ .name = "Hauppauge WinTV-HVR2205", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x28, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "SI2168-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xc8 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x25, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x27, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "SI2168-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xcc >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, + }; + const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards); + +@@ -546,6 +685,21 @@ + .subvendor = 0x0070, + .subdevice = 0x8953, + .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5, ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf111, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255, ++ /* Prototype card left here for documenation purposes. ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255proto, ++ */ ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf123, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205, ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf120, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205, + }, + }; + const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids); +@@ -594,12 +748,26 @@ + case SAA7164_BOARD_HAUPPAUGE_HVR2250: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: + /* ++ HVR2200 / HVR2250 + GPIO 2: s5h1411 / tda10048-1 demod reset + GPIO 3: s5h1411 / tda10048-2 demod reset + GPIO 7: IRBlaster Zilog reset + */ + ++ /* HVR2255 ++ * GPIO 2: lgdg3306-1 demod reset ++ * GPIO 3: lgdt3306-2 demod reset ++ */ ++ ++ /* HVR2205 ++ * GPIO 2: si2168-1 demod reset ++ * GPIO 3: si2168-2 demod reset ++ */ ++ + /* Reset parts by going in and out of reset */ + saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2); + saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3); +@@ -647,6 +815,21 @@ + /* WinTV-HVR2200 (PCIe, Retail, half-height) + * DVB-T (TDA18271/TDA10048) and basic analog, no IR */ + break; ++ case 151009: ++ /* First production board rev B2I6 */ ++ /* WinTV-HVR2205 (PCIe, Retail, full-height bracket) ++ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */ ++ break; ++ case 151609: ++ /* First production board rev B2I6 */ ++ /* WinTV-HVR2205 (PCIe, Retail, half-height bracket) ++ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */ ++ break; ++ case 151061: ++ /* First production board rev B1I6 */ ++ /* WinTV-HVR2255 (PCIe, Retail, full-height bracket) ++ * ATSC/QAM (SI2157/LGDT3306) and basic analog, FM */ ++ break; + default: + printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n", + dev->name, tv.model); +@@ -676,6 +859,9 @@ + case SAA7164_BOARD_HAUPPAUGE_HVR2250: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: + hauppauge_eeprom(dev, &eeprom[0]); + break; + } +diff -urN a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c +--- a/drivers/media/pci/saa7164/saa7164-dvb.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-dvb.c 2015-06-24 18:42:30.090377859 +0300 +@@ -24,6 +24,9 @@ + #include "tda10048.h" + #include "tda18271.h" + #include "s5h1411.h" ++#include "si2157.h" ++#include "si2168.h" ++#include "lgdt3306a.h" + + #define DRIVER_NAME "saa7164" + +@@ -82,6 +85,64 @@ + .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, + }; + ++static struct lgdt3306a_config hauppauge_hvr2255a_config = { ++ .i2c_addr = 0xb2 >> 1, ++ .qam_if_khz = 4000, ++ .vsb_if_khz = 3250, ++ .deny_i2c_rptr = 1, /* Disabled */ ++ .spectral_inversion = 0, /* Disabled */ ++ .mpeg_mode = LGDT3306A_MPEG_SERIAL, ++ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, ++ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, ++ .xtalMHz = 25, /* 24 or 25 */ ++}; ++ ++static struct lgdt3306a_config hauppauge_hvr2255b_config = { ++ .i2c_addr = 0x1c >> 1, ++ .qam_if_khz = 4000, ++ .vsb_if_khz = 3250, ++ .deny_i2c_rptr = 1, /* Disabled */ ++ .spectral_inversion = 0, /* Disabled */ ++ .mpeg_mode = LGDT3306A_MPEG_SERIAL, ++ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, ++ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, ++ .xtalMHz = 25, /* 24 or 25 */ ++}; ++ ++static struct si2157_config hauppauge_hvr2255_tuner_config = { ++ .inversion = 1, ++}; ++ ++static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter, ++ struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg) ++{ ++ struct i2c_board_info bi; ++ struct i2c_client *tuner; ++ ++ cfg->fe = fe; ++ ++ memset(&bi, 0, sizeof(bi)); ++ ++ strlcpy(bi.type, "si2157", I2C_NAME_SIZE); ++ bi.platform_data = cfg; ++ bi.addr = addr8bit >> 1; ++ ++ request_module(bi.type); ++ ++ tuner = i2c_new_device(adapter, &bi); ++ if (tuner == NULL || tuner->dev.driver == NULL) ++ return -ENODEV; ++ ++ if (!try_module_get(tuner->dev.driver->owner)) { ++ i2c_unregister_device(tuner); ++ return -ENODEV; ++ } ++ ++ port->i2c_client_tuner = tuner; ++ ++ return 0; ++} ++ + static int saa7164_dvb_stop_port(struct saa7164_port *port) + { + struct saa7164_dev *dev = port->dev; +@@ -242,14 +303,16 @@ + if (!demux->dmx.frontend) + return -EINVAL; + +- mutex_lock(&dvb->lock); +- if (dvb->feeding++ == 0) { +- /* Start transport */ +- ret = saa7164_dvb_start_port(port); +- } +- mutex_unlock(&dvb->lock); +- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", +- __func__, port->nr, dvb->feeding); ++ if (dvb) { ++ mutex_lock(&dvb->lock); ++ if (dvb->feeding++ == 0) { ++ /* Start transport */ ++ ret = saa7164_dvb_start_port(port); ++ } ++ mutex_unlock(&dvb->lock); ++ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", ++ __func__, port->nr, dvb->feeding); ++ } + + return ret; + } +@@ -264,14 +327,16 @@ + + dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr); + +- mutex_lock(&dvb->lock); +- if (--dvb->feeding == 0) { +- /* Stop transport */ +- ret = saa7164_dvb_stop_streaming(port); +- } +- mutex_unlock(&dvb->lock); +- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", +- __func__, port->nr, dvb->feeding); ++ if (dvb) { ++ mutex_lock(&dvb->lock); ++ if (--dvb->feeding == 0) { ++ /* Stop transport */ ++ ret = saa7164_dvb_stop_streaming(port); ++ } ++ mutex_unlock(&dvb->lock); ++ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", ++ __func__, port->nr, dvb->feeding); ++ } + + return ret; + } +@@ -425,6 +490,7 @@ + struct saa7164_dev *dev = port->dev; + struct saa7164_buffer *b; + struct list_head *c, *n; ++ struct i2c_client *client; + + dprintk(DBGLVL_DVB, "%s()\n", __func__); + +@@ -443,6 +509,20 @@ + if (dvb->frontend == NULL) + return 0; + ++ /* remove I2C client for tuner */ ++ client = port->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* remove I2C client for demodulator */ ++ client = port->i2c_client_demod; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +@@ -462,6 +542,12 @@ + struct saa7164_dev *dev = port->dev; + struct saa7164_dvb *dvb = &port->dvb; + struct saa7164_i2c *i2c_bus = NULL; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ struct i2c_adapter *adapter; ++ struct i2c_board_info info; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; + int ret; + + dprintk(DBGLVL_DVB, "%s()\n", __func__); +@@ -528,6 +614,124 @@ + } + + break; ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ i2c_bus = &dev->i2c_bus[2]; ++ ++ if (port->nr == 0) { ++ port->dvb.frontend = dvb_attach(lgdt3306a_attach, ++ &hauppauge_hvr2255a_config, &i2c_bus->i2c_adap); ++ } else { ++ port->dvb.frontend = dvb_attach(lgdt3306a_attach, ++ &hauppauge_hvr2255b_config, &i2c_bus->i2c_adap); ++ } ++ ++ if (port->dvb.frontend != NULL) { ++ ++ if (port->nr == 0) { ++ si2157_attach(port, &dev->i2c_bus[0].i2c_adap, ++ port->dvb.frontend, 0xc0, ++ &hauppauge_hvr2255_tuner_config); ++ } else { ++ si2157_attach(port, &dev->i2c_bus[1].i2c_adap, ++ port->dvb.frontend, 0xc0, ++ &hauppauge_hvr2255_tuner_config); ++ } ++ } ++ break; ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: ++ ++ if (port->nr == 0) { ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &port->dvb.frontend; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0xc8 >> 1; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap, ++ &info); ++ if (!client_demod || !client_demod->dev.driver) ++ goto frontend_detach; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = port->dvb.frontend; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0xc0 >> 1; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(&dev->i2c_bus[0].i2c_adap, ++ &info); ++ if (!client_tuner || !client_tuner->dev.driver) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_tuner = client_tuner; ++ } else { ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &port->dvb.frontend; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0xcc >> 1; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap, ++ &info); ++ if (!client_demod || !client_demod->dev.driver) ++ goto frontend_detach; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = port->dvb.frontend; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0xc0 >> 1; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, ++ &info); ++ if (!client_tuner || !client_tuner->dev.driver) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_tuner = client_tuner; ++ } ++ ++ break; + default: + printk(KERN_ERR "%s: The frontend isn't supported\n", + dev->name); +@@ -548,5 +752,9 @@ + } + + return 0; ++ ++frontend_detach: ++ printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__); ++ return -1; + } + +diff -urN a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c +--- a/drivers/media/pci/saa7164/saa7164-encoder.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-encoder.c 2015-06-24 18:41:23.254376349 +0300 +@@ -721,13 +721,14 @@ + sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + +- cap->capabilities = ++ cap->device_caps = + V4L2_CAP_VIDEO_CAPTURE | +- V4L2_CAP_READWRITE | +- 0; ++ V4L2_CAP_READWRITE | ++ V4L2_CAP_TUNER; + +- cap->capabilities |= V4L2_CAP_TUNER; +- cap->version = 0; ++ cap->capabilities = cap->device_caps | ++ V4L2_CAP_VBI_CAPTURE | ++ V4L2_CAP_DEVICE_CAPS; + + return 0; + } +diff -urN a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h +--- a/drivers/media/pci/saa7164/saa7164.h 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164.h 2015-06-24 18:41:57.246377117 +0300 +@@ -83,6 +83,9 @@ + #define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8 + #define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9 + #define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2255proto 11 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2255 12 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2205 13 + + #define SAA7164_MAX_UNITS 8 + #define SAA7164_TS_NUMBER_OF_LINES 312 +@@ -371,6 +374,8 @@ + + /* --- DVB Transport Specific --- */ + struct saa7164_dvb dvb; ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; + + /* --- Encoder/V4L related attributes --- */ + /* Encoder */ +@@ -459,6 +464,7 @@ + /* Interrupt status and ack registers */ + u32 int_status; + u32 int_ack; ++ bool msi; + + struct cmd cmds[SAA_CMD_MAX_MSG_UNITS]; + struct mutex lock; +diff -urN a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c +--- a/drivers/media/pci/saa7164/saa7164-vbi.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-vbi.c 2015-06-24 18:42:05.582377305 +0300 +@@ -660,13 +660,14 @@ + sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + +- cap->capabilities = ++ cap->device_caps = + V4L2_CAP_VBI_CAPTURE | +- V4L2_CAP_READWRITE | +- 0; ++ V4L2_CAP_READWRITE | ++ V4L2_CAP_TUNER; + +- cap->capabilities |= V4L2_CAP_TUNER; +- cap->version = 0; ++ cap->capabilities = cap->device_caps | ++ V4L2_CAP_VIDEO_CAPTURE | ++ V4L2_CAP_DEVICE_CAPS; + + return 0; + }