diff options
author | Olli Salonen <olli.salonen@iki.fi> | 2017-11-23 03:24:46 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-12-13 08:16:53 -0500 |
commit | c4d84547d5ae4fafe2dde649deaf10047ef34d00 (patch) | |
tree | f00556e84ac3222760ef05d76cde4c437adb8979 /drivers/media/usb | |
parent | 148abd3b5b146021a637d36ac5c0ee91cd4ad520 (diff) |
media: dib0700: add support for Xbox One Digital TV Tuner
Xbox One Digital TV Tuner is a low-cost USB 2.0 multistandard TV tuner. It supports DVB-T, DVB-T2 and DVB-C broadcast standards.
USB bridge: DibCom 0700C
Demodulator: Panasonic MN88472
Tuner: TDA18250BHN
The demodulator requires firmware. Download one from here:
http://palosaari.fi/linux/v4l-dvb/firmware/MN88472/02/latest/
Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r-- | drivers/media/usb/dvb-usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_core.c | 26 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_devices.c | 109 |
4 files changed, 137 insertions, 2 deletions
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig index 959fa09dfd92..2651ae277347 100644 --- a/drivers/media/usb/dvb-usb/Kconfig +++ b/drivers/media/usb/dvb-usb/Kconfig @@ -86,6 +86,7 @@ config DVB_USB_DIB0700 select DVB_USB_DIB3000MC if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MN88472 if MEDIA_SUBDRV_AUTOSELECT select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT select DVB_TUNER_DIB0090 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT @@ -94,6 +95,7 @@ config DVB_USB_DIB0700 select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18250 if MEDIA_SUBDRV_AUTOSELECT help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB diff --git a/drivers/media/usb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h index f89ab3b5a6c4..3a9d4c288cc2 100644 --- a/drivers/media/usb/dvb-usb/dib0700.h +++ b/drivers/media/usb/dvb-usb/dib0700.h @@ -51,6 +51,8 @@ struct dib0700_state { int (*read_status)(struct dvb_frontend *, enum fe_status *); int (*sleep)(struct dvb_frontend* fe); u8 buf[255]; + struct i2c_client *i2c_client_demod; + struct i2c_client *i2c_client_tuner; }; extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 1ee7ec558293..94bd176104c1 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -911,10 +911,34 @@ static int dib0700_probe(struct usb_interface *intf, return -ENODEV; } +static void dib0700_disconnect(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + struct dib0700_state *st = d->priv; + struct i2c_client *client; + + /* remove I2C client for tuner */ + client = st->i2c_client_tuner; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + /* remove I2C client for demodulator */ + client = st->i2c_client_demod; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + dvb_usb_device_exit(intf); +} + + static struct usb_driver dib0700_driver = { .name = "dvb_usb_dib0700", .probe = dib0700_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = dib0700_disconnect, .id_table = dib0700_usb_id_table, }; diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 366b05529915..470836a274dd 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -23,6 +23,9 @@ #include "dib0090.h" #include "lgdt3305.h" #include "mxl5007t.h" +#include "mn88472.h" +#include "tda18250.h" + static int force_lna_activation; module_param(force_lna_activation, int, 0644); @@ -3725,6 +3728,90 @@ static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap) &hcw_mxl5007t_config) == NULL ? -ENODEV : 0; } +static int xbox_one_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_state *st = adap->dev->priv; + struct i2c_client *client_demod, *client_tuner; + struct dvb_usb_device *d = adap->dev; + struct mn88472_config mn88472_config = { }; + struct tda18250_config tda18250_config; + struct i2c_board_info info; + + st->fw_use_new_i2c_api = 1; + st->disable_streaming_master_mode = 1; + + /* fe power enable */ + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(30); + + /* demod reset */ + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + + /* attach demod */ + mn88472_config.fe = &adap->fe_adap[0].fe; + mn88472_config.i2c_wr_max = 22; + mn88472_config.xtal = 20500000; + mn88472_config.ts_mode = PARALLEL_TS_MODE; + mn88472_config.ts_clock = FIXED_TS_CLOCK; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "mn88472", I2C_NAME_SIZE); + info.addr = 0x18; + info.platform_data = &mn88472_config; + request_module(info.type); + client_demod = i2c_new_device(&d->i2c_adap, &info); + if (client_demod == NULL || client_demod->dev.driver == NULL) + goto fail_demod_device; + if (!try_module_get(client_demod->dev.driver->owner)) + goto fail_demod_module; + + st->i2c_client_demod = client_demod; + + adap->fe_adap[0].fe = mn88472_config.get_dvb_frontend(client_demod); + + /* attach tuner */ + memset(&tda18250_config, 0, sizeof(tda18250_config)); + tda18250_config.if_dvbt_6 = 3950; + tda18250_config.if_dvbt_7 = 4450; + tda18250_config.if_dvbt_8 = 4950; + tda18250_config.if_dvbc_6 = 4950; + tda18250_config.if_dvbc_8 = 4950; + tda18250_config.if_atsc = 4079; + tda18250_config.loopthrough = true; + tda18250_config.xtal_freq = TDA18250_XTAL_FREQ_27MHZ; + tda18250_config.fe = adap->fe_adap[0].fe; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "tda18250", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &tda18250_config; + + request_module(info.type); + client_tuner = i2c_new_device(&adap->dev->i2c_adap, &info); + if (client_tuner == NULL || client_tuner->dev.driver == NULL) + goto fail_tuner_device; + if (!try_module_get(client_tuner->dev.driver->owner)) + goto fail_tuner_module; + + st->i2c_client_tuner = client_tuner; + return 0; + +fail_tuner_module: + i2c_unregister_device(client_tuner); +fail_tuner_device: + module_put(client_demod->dev.driver->owner); +fail_demod_module: + i2c_unregister_device(client_demod); +fail_demod_device: + return -ENODEV; +} + /* DVB-USB and USB stuff follows */ struct usb_device_id dib0700_usb_id_table[] = { @@ -3816,7 +3903,8 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096PVR) }, - { USB_DEVICE(USB_VID_HAMA, USB_PID_HAMA_DVBT_HYBRID) }, +/* 85 */{ USB_DEVICE(USB_VID_HAMA, USB_PID_HAMA_DVBT_HYBRID) }, + { USB_DEVICE(USB_VID_MICROSOFT, USB_PID_XBOX_ONE_TUNER) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -5040,6 +5128,25 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_PROTO_BIT_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + DIB0700_NUM_FRONTENDS(1), + .fe = {{ + .frontend_attach = xbox_one_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x82), + } }, + }, + }, + .num_device_descs = 1, + .devices = { + { "Microsoft Xbox One Digital TV Tuner", + { &dib0700_usb_id_table[86], NULL }, + { NULL }, + }, + }, }, }; |