[PATCH] dvb: add support for kworld 340u to em28xx-dvb This adds support for the KWorld PlusTV 340U (ATSC), an eMPIA em2870-based usb tv tuner stick. The device has an LG Electronics LGDT3304 ATSC/QAM demodulator and an NXP TDA18271HD/C1 tuner, and has been tested succesfully with both VSB_8 and QAM_256 signals. Its using lgdt3304 support added to the lgdt3305 driver by a prior patch, rather than the current lgdt3304 driver, as its severely lacking in functionality by comparison (see said patch for details). Signed-off-by: Jarod Wilson --- em28xx-cards.c | 26 ++++++++++++++++++++++++++ em28xx-dvb.c | 32 ++++++++++++++++++++++++++++++++ em28xx.h | 1 + 3 files changed, 59 insertions(+) diff -r b362d09e34d4 linux/drivers/media/video/em28xx/em28xx-cards.c --- a/linux/drivers/media/video/em28xx/em28xx-cards.c Tue Jun 23 03:27:42 2009 -0300 +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c Tue Jun 23 15:11:56 2009 -0400 @@ -170,6 +170,23 @@ { -1, -1, -1, -1}, }; +/* + * KWorld PlusTV 340U (ATSC) GPIOs map: + * EM_GPIO_0 - currently unknown + * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on) + * EM_GPIO_2 - currently unknown + * EM_GPIO_3 - currently unknown + * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset) + * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset) + * EM_GPIO_6 - currently unknown + * EM_GPIO_7 - currently unknown + */ +static struct em28xx_reg_seq kworld_340u_digital[] = { + /* only diff from default gpio is to keep 1 clear to turn on LED */ + {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -1559,6 +1576,13 @@ .gpio = evga_indtube_analog, } }, }, + [EM2870_BOARD_KWORLD_PLUSTV_340U] = { + .name = "KWorld PlusTV 340U (ATSC)", + .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD/C1 */ + .has_dvb = 1, + .dvb_gpio = kworld_340u_digital, + .tuner_gpio = default_tuner_gpio, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1672,6 +1696,8 @@ .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, { USB_DEVICE(0x04bb, 0x0515), .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, + { USB_DEVICE(0x1b80, 0xa340), + .driver_info = EM2870_BOARD_KWORLD_PLUSTV_340U }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); diff -r b362d09e34d4 linux/drivers/media/video/em28xx/em28xx-dvb.c --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c Tue Jun 23 03:27:42 2009 -0300 +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c Tue Jun 23 15:11:56 2009 -0400 @@ -30,8 +30,10 @@ #include "tuner-simple.h" #include "lgdt330x.h" +#include "lgdt3305.h" #include "zl10353.h" #include "s5h1409.h" +#include "tda18271.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); @@ -228,6 +230,17 @@ .demod_chip = LGDT3303, }; +static struct lgdt3305_config em2870_lgdt3304_dev = { + .i2c_addr = 0x0e, + .demod_chip = LGDT3304, + .spectral_inversion = 1, + .mpeg_mode = LGDT3305_MPEG_PARALLEL, + .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .vsb_if_khz = 3250, + .qam_if_khz = 4000, +}; + static struct zl10353_config em28xx_zl10353_with_xc3028 = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -244,6 +257,17 @@ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +static struct tda18271_std_map kworld_340u_std_map = { + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, + .if_lvl = 1, .rfagc_top = 0x37, }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, + .if_lvl = 1, .rfagc_top = 0x37, }, +}; + +static struct tda18271_config kworld_340u_config = { + .std_map = &kworld_340u_std_map, +}; + #ifdef EM28XX_DRX397XD_SUPPORT /* [TODO] djh - not sure yet what the device config needs to contain */ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { @@ -480,6 +504,14 @@ } break; #endif + case EM2870_BOARD_KWORLD_PLUSTV_340U: + dvb->frontend = dvb_attach(lgdt3305_attach, + &em2870_lgdt3304_dev, + &dev->i2c_adap); + if (dvb->frontend != NULL) + dvb_attach(tda18271_attach, dvb->frontend, 0x60, + &dev->i2c_adap, &kworld_340u_config); + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" " isn't supported yet\n", diff -r b362d09e34d4 linux/drivers/media/video/em28xx/em28xx.h --- a/linux/drivers/media/video/em28xx/em28xx.h Tue Jun 23 03:27:42 2009 -0300 +++ b/linux/drivers/media/video/em28xx/em28xx.h Tue Jun 23 15:11:56 2009 -0400 @@ -108,6 +108,7 @@ #define EM2860_BOARD_TERRATEC_AV350 68 #define EM2882_BOARD_KWORLD_ATSC_315U 69 #define EM2882_BOARD_EVGA_INDTUBE 70 +#define EM2870_BOARD_KWORLD_PLUSTV_340U 71 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4