diff options
author | Steven Toth <stoth@kernellabs.com> | 2015-07-18 17:56:56 -0400 |
---|---|---|
committer | Steven Toth <stoth@kernellabs.com> | 2015-07-18 17:56:56 -0400 |
commit | 91bd0a5bbbc3759bb3fd6516d8c322b030620b46 (patch) | |
tree | 2e84f8a6902cb303c7bfce9ea4b321398dab28a0 | |
parent | e271a9ef2c77dde2d4deb11a9cee5eade720b2f9 (diff) |
[media] cx23885: Add support for three new Hauppauge cards.hvr-1275
HVR1275 - ATSC model
HVR1275 - DVB-T/T2 model
HVR1275 - Combo model (ATSC and DVB-T), two demodulators, single tuner
sharing a single transport bus.
Tested with a combo card, in all three modes.
ATSC and DVB-T2 models should work, although no hardware was available
for testing.
Signed-off-by: Steven Toth <stoth@kernellabs.com>
-rw-r--r-- | drivers/media/pci/cx23885/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-cards.c | 48 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-dvb.c | 150 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885.h | 3 |
4 files changed, 202 insertions, 0 deletions
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index 2e1b88ccdbf2..3e6398ff1b8e 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig @@ -15,6 +15,7 @@ config VIDEO_CX23885 select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index f384f295676e..5b4cfe45510e 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -715,6 +715,19 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC] = { + .name = "Hauppauge HVR1275-ATSC", + .portc = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT] = { + .name = "Hauppauge HVR1275-DVBT/2", + .portc = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO] = { + .name = "Hauppauge HVR1275-ATSC/DVBT/T2", + .num_fds_portc = 2, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -1002,6 +1015,18 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0xf038, .card = CX23885_BOARD_HAUPPAUGE_HVR5525, + }, { + .subvendor = 0x0070, + .subdevice = 0x2a18, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC, + }, { + .subvendor = 0x0070, + .subdevice = 0x2a28, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT, + }, { + .subvendor = 0x0070, + .subdevice = 0x2a38, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1176,6 +1201,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) Dual channel ATSC and Basic analog */ case 150329: /* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */ + case 161100: + /* HVR1275 (PCIe, Retail, half height) + * ATSC/QAM LG3306, DVB-T/T2/C SI2168 and basic analog, IR Recv */ break; default: printk(KERN_WARNING "%s: warning: " @@ -1671,6 +1699,17 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_set(dev, GPIO_8 | GPIO_9); msleep(100); break; + case CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC: + case CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT: + case CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO: + /* + * GPIO-00 IR_WIDE + * GPIO-07 PROG# (EEProm W/P) + * GPIO-19 IR_NARROW + * GPIO-20 IR Blast + * Demodulator resets on RESET_OUT_N + */ + break; } } @@ -1716,6 +1755,9 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: case CX23885_BOARD_HAUPPAUGE_HVR1210: + case CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC: + case CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT: + case CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO: /* FIXME: Implement me */ break; case CX23885_BOARD_HAUPPAUGE_HVR1270: @@ -1914,6 +1956,9 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_STARBURST: case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE: case CX23885_BOARD_HAUPPAUGE_HVR5525: + case CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC: + case CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT: + case CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -2071,6 +2116,9 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: + case CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC: + case CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT: + case CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 6e8c24cdb2cd..96b920589da8 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -74,6 +74,7 @@ #include "sp2.h" #include "m88ds3103.h" #include "m88rs6000t.h" +#include "lgdt3306a.h" static unsigned int debug; @@ -572,6 +573,53 @@ static struct stb6100_config prof_8000_stb6100_config = { .refclock = 27000000, }; +static struct lgdt3306a_config hauppauge_hvr1275_atsc_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 si2157_config hauppauge_hvr1275_atsc_tuner_config = { + .inversion = 1, + .if_port = 1, +}; + +static int si2157_attach(struct cx23885_tsport *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 p8000_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { @@ -2264,6 +2312,108 @@ static int dvb_register(struct cx23885_tsport *port) break; } break; + case CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(lgdt3306a_attach, + &hauppauge_hvr1275_atsc_config, &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + si2157_attach(port, &dev->i2c_bus[1].i2c_adap, + fe0->dvb.frontend, 0xc0, + &hauppauge_hvr1275_atsc_tuner_config); + } + break; + case CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT: + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &fe0->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 = 0x64; + info.platform_data = &si2168_config; + request_module("%s", info.type); + client_demod = i2c_new_device(&dev->i2c_bus[0].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 = fe0->dvb.frontend; + si2157_config.if_port = 1; + 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("%s", 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); + port->i2c_client_demod = NULL; + 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); + port->i2c_client_demod = NULL; + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; + break; + case CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO: + + /* Single TS bus (bridge/adapter), multiple frontends */ + mfe_shared = 1; /* MFE - Multi-frontend support required */ + port->frontends.gate = 0; /* not clear for me yet */ + + /* frontend0 - Bring up ATSC first */ + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(lgdt3306a_attach, + &hauppauge_hvr1275_atsc_config, &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + si2157_attach(port, &dev->i2c_bus[1].i2c_adap, + fe0->dvb.frontend, 0xc0, + &hauppauge_hvr1275_atsc_tuner_config); + cx23885_set_frontend_hook(port, fe0->dvb.frontend); + } + + /* frontend1 - Now we need the DVB-T/T2 support */ + fe1 = vb2_dvb_get_frontend(&port->frontends, 2); + if (fe1 == NULL) + goto frontend_detach; + + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &fe1->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 = 0x64; + info.platform_data = &si2168_config; + request_module("%s", info.type); + client_demod = i2c_new_device(&dev->i2c_bus[0].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; + fe1->dvb.frontend->id = 1; + + /* Attach the second demod to the first and only tuner */ + memcpy(&fe1->dvb.frontend->ops.tuner_ops, &fe0->dvb.frontend->ops.tuner_ops, + sizeof(struct dvb_tuner_ops)); + fe1->dvb.frontend->tuner_priv = fe0->dvb.frontend->tuner_priv; + + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 027ead438194..86d6f43cf3fc 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -101,6 +101,9 @@ #define CX23885_BOARD_DVBSKY_T982 51 #define CX23885_BOARD_HAUPPAUGE_HVR5525 52 #define CX23885_BOARD_HAUPPAUGE_STARBURST 53 +#define CX23885_BOARD_HAUPPAUGE_HVR1275_ATSC 54 +#define CX23885_BOARD_HAUPPAUGE_HVR1275_DVBT 55 +#define CX23885_BOARD_HAUPPAUGE_HVR1275_COMBO 56 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 |