From 11a2a949d05e9d2d9823f0c45fa476743d9e462b Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Mon, 4 Apr 2016 12:12:52 -0300 Subject: [PATCH] [media] em28xx: add support for Hauppauge WinTV-dualHD DVB tuner Hauppauge WinTV-dualHD is a USB 2.0 dual DVB-T/T2/C tuner with following components: USB bridge: Empia EM28274 (chip id is the same as EM28174) Demodulator: 2x Silicon Labs Si2168-B40 Tuner: 2x Silicon Labs Si2157-A30 This patch adds support only for the first tuner. The demodulator needs firmware, available for example here: http://palosaari.fi/linux/v4l-dvb/firmware/Si2168/Si2168-B40/4.0.11/ The demodulators sit on the same I2C bus and their addresses are 0x64 and 0x67. The tuners are behind the demodulators and their addresses are 0x60 and 0x63. Signed-off-by: Olli Salonen Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/usb/em28xx/em28xx-cards.c | 58 ++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 64 +++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-reg.h | 13 +++++ drivers/media/usb/em28xx/em28xx.h | 2 + 5 files changed, 138 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 82eb4e4b6f69..6784220c6a16 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -97,3 +97,4 @@ 96 -> Terratec Cinergy T2 Stick HD (em28178) [eb1a:8179] 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] 98 -> PLEX PX-BCUD (em28178) [3275:0085] + 99 -> Hauppauge WinTV-dualHD DVB (em28174) [2040:0265] diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 57c3b905bf0a..e397f544f108 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -506,6 +506,30 @@ static struct em28xx_reg_seq plex_px_bcud[] = { {-1, -1, -1, -1}, }; +/* + * 2040:0265 Hauppauge WinTV-dualHD DVB + * reg 0x80/0x84: + * GPIO_0: Yellow LED tuner 1, 0=on, 1=off + * GPIO_1: Green LED tuner 1, 0=on, 1=off + * GPIO_2: Yellow LED tuner 2, 0=on, 1=off + * GPIO_3: Green LED tuner 2, 0=on, 1=off + * GPIO_5: Reset #2, 0=active + * GPIO_6: Reset #1, 0=active + */ +static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = { + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0}, + {0x0d, 0xff, 0xff, 200}, + {0x50, 0x04, 0xff, 300}, + {EM2874_R80_GPIO_P0_CTRL, 0xbf, 0xff, 100}, /* demod 1 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xdf, 0xff, 100}, /* demod 2 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, + {EM2874_R5F_TS_ENABLE, 0x44, 0xff, 50}, + {EM2874_R5D_TS1_PKT_SIZE, 0x05, 0xff, 50}, + {EM2874_R5E_TS2_PKT_SIZE, 0x05, 0xff, 50}, + {-1, -1, -1, -1}, +}; + /* * Button definitions */ @@ -585,6 +609,22 @@ static struct em28xx_led terratec_grabby_leds[] = { {-1, 0, 0, 0}, }; +static struct em28xx_led hauppauge_dualhd_leds[] = { + { + .role = EM28XX_LED_DIGITAL_CAPTURING, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = EM_GPIO_1, + .inverted = 1, + }, + { + .role = EM28XX_LED_DIGITAL_CAPTURING_TS2, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = EM_GPIO_3, + .inverted = 1, + }, + {-1, 0, 0, 0}, +}; + /* * Board definitions */ @@ -2334,6 +2374,21 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = plex_px_bcud, .has_dvb = 1, }, + /* + * 2040:0265 Hauppauge WinTV-dualHD (DVB version). + * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 + */ + [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = { + .name = "Hauppauge WinTV-dualHD DVB", + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + .tuner_type = TUNER_ABSENT, + .tuner_gpio = hauppauge_dualhd_dvb, + .has_dvb = 1, + .ir_codes = RC_MAP_HAUPPAUGE, + .leds = hauppauge_dualhd_leds, + }, }; EXPORT_SYMBOL_GPL(em28xx_boards); @@ -2457,6 +2512,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x2040, 0x651f), .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, + { USB_DEVICE(0x2040, 0x0265), + .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB }, { USB_DEVICE(0x0438, 0xb002), .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, { USB_DEVICE(0x2001, 0xf112), @@ -2891,6 +2948,7 @@ static void em28xx_card_setup(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: { struct tveeprom tv; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index fbc4e4b3268e..1a5c01202f73 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1883,6 +1883,70 @@ static int em28xx_dvb_init(struct em28xx *dev) px_bcud_init(dev); } break; + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: + { + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + + /* attach demod */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &dvb->fe[0]; + si2168_config.ts_mode = SI2168_TS_SERIAL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module(info.type); + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + + } + break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 13cbb7f3ea10..afe7a66d7dc8 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -193,6 +193,19 @@ /* em2874 registers */ #define EM2874_R50_IR_CONFIG 0x50 #define EM2874_R51_IR 0x51 +#define EM2874_R5D_TS1_PKT_SIZE 0x5d +#define EM2874_R5E_TS2_PKT_SIZE 0x5e + /* + * For both TS1 and TS2, In isochronous mode: + * 0x01 188 bytes + * 0x02 376 bytes + * 0x03 564 bytes + * 0x04 752 bytes + * 0x05 940 bytes + * In bulk mode: + * 0x01..0xff total packet count in 188-byte + */ + #define EM2874_R5F_TS_ENABLE 0x5f /* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 9ad1240d5e22..d148463b22c1 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -146,6 +146,7 @@ #define EM28178_BOARD_TERRATEC_T2_STICK_HD 96 #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97 #define EM28178_BOARD_PLEX_PX_BCUD 98 +#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -407,6 +408,7 @@ enum em28xx_adecoder { enum em28xx_led_role { EM28XX_LED_ANALOG_CAPTURING = 0, EM28XX_LED_DIGITAL_CAPTURING, + EM28XX_LED_DIGITAL_CAPTURING_TS2, EM28XX_LED_ILLUMINATION, EM28XX_NUM_LED_ROLES, /* must be the last */ }; -- 2.39.5