diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-cards.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-cards.c --- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-cards.c 2010-02-12 02:11:30.000000000 +0100 +++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-cards.c 2010-02-17 17:18:17.000000000 +0100 @@ -27,8 +27,9 @@ #include "compat.h" #include "cx88.h" #include "tea5767.h" +#include "xc4000.h" static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; @@ -2119,8 +2120,60 @@ .vmux = 0, } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_WINFAST_DTV2000H_PLUS] = { + .name = "WinFast DTV2000 H PLUS", + .tuner_type = TUNER_XC4000, + .radio_type = TUNER_XC4000, + .tuner_addr = 0x61, + .radio_addr = 0x61, + /* + * GPIO + * 2: 1: mute audio + * 12: 0: reset XC4000 + * 13: 1: audio input is line in (0: tuner) + * 14: 0: FM radio + * 16: 0: RF input is cable + */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0403, + .gpio1 = 0xF0D7, + .gpio2 = 0x0101, + .gpio3 = 0x0000, + }, { + .type = CX88_VMUX_CABLE, + .vmux = 0, + .gpio0 = 0x0403, + .gpio1 = 0xF0D7, + .gpio2 = 0x0100, + .gpio3 = 0x0000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0403, /* was 0x0407 */ + .gpio1 = 0xF0F7, + .gpio2 = 0x0101, + .gpio3 = 0x0000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0403, /* was 0x0407 */ + .gpio1 = 0xF0F7, + .gpio2 = 0x0101, + .gpio3 = 0x0000, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x0403, + .gpio1 = 0xF097, + .gpio2 = 0x0100, + .gpio3 = 0x0000, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ /* PCI subsystem IDs */ @@ -2545,8 +2598,12 @@ .subvendor = 0x107d, .subdevice = 0x6654, .card = CX88_BOARD_WINFAST_DTV1800H, }, { + .subvendor = 0x107d, + .subdevice = 0x6f42, + .card = CX88_BOARD_WINFAST_DTV2000H_PLUS, + }, { /* PVR2000 PAL Model [107d:6630] */ .subvendor = 0x107d, .subdevice = 0x6630, .card = CX88_BOARD_LEADTEK_PVR2000, @@ -2803,8 +2860,25 @@ } return -EINVAL; } +static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core, + int command, int arg) +{ + switch (command) { + case XC4000_TUNER_RESET: + /* GPIO 12 (xc4000 tuner reset) */ + cx_set(MO_GP1_IO, 0x1010); + mdelay(50); + cx_clear(MO_GP1_IO, 0x10); + mdelay(50); + cx_set(MO_GP1_IO, 0x10); + mdelay(50); + return 0; + } + return -EINVAL; +} + /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ static int cx88_pv_8000gt_callback(struct cx88_core *core, int command, int arg) @@ -2905,8 +2979,20 @@ } return -EINVAL; } +static int cx88_xc4000_tuner_callback(struct cx88_core *core, + int command, int arg) +{ + /* Board-specific callbacks */ + switch (core->boardnr) { + case CX88_BOARD_WINFAST_DTV2000H_PLUS: + return cx88_xc4000_winfast2000h_plus_callback(core, + command, arg); + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* Tuner callback function. Currently only needed for the Pinnacle * * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both * * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */ @@ -2979,8 +3065,11 @@ switch (core->board.tuner_type) { case TUNER_XC2028: info_printk(core, "Calling XC2028/3028 callback\n"); return cx88_xc2028_tuner_callback(core, command, arg); + case TUNER_XC4000: + info_printk(core, "Calling XC4000 callback\n"); + return cx88_xc4000_tuner_callback(core, command, arg); case TUNER_XC5000: info_printk(core, "Calling XC5000 callback\n"); return cx88_xc5000_tuner_callback(core, command, arg); } @@ -3066,9 +3155,10 @@ break; case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: - /* GPIO 12 (xc3028 tuner reset) */ + case CX88_BOARD_WINFAST_DTV2000H_PLUS: + /* GPIO 12 (xc3028/xc4000 tuner reset) */ cx_set(MO_GP1_IO, 0x1010); mdelay(50); cx_clear(MO_GP1_IO, 0x10); mdelay(50); diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-dvb.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-dvb.c --- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-dvb.c 2010-02-12 02:11:30.000000000 +0100 +++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-dvb.c 2010-02-17 17:18:17.000000000 +0100 @@ -41,8 +41,9 @@ #include "cx22702.h" #include "or51132.h" #include "lgdt330x.h" #include "s5h1409.h" +#include "xc4000.h" #include "xc5000.h" #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" @@ -573,8 +574,47 @@ return 0; } +static int attach_xc4000(struct cx8802_dev *dev, u8 card_type) +{ + struct dvb_frontend *fe; + struct videobuf_dvb_frontend *fe0 = NULL; + struct xc4000_config cfg = { + .card_type = card_type, + .i2c_address = 0x61, /* these will be set by xc4000.c */ + .if_khz = 5400 + }; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + + if (!fe0->dvb.frontend) { + printk(KERN_ERR "%s/2: dvb frontend not attached. " + "Can't attach xc4000\n", + dev->core->name); + return -EINVAL; + } + + fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap, + &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc4000 attach failed\n", + dev->core->name); + dvb_frontend_detach(fe0->dvb.frontend); + dvb_unregister_frontend(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; + return -EINVAL; + } + + printk(KERN_INFO "%s/2: xc4000 attached\n", + dev->core->name); + + return 0; +} + static int cx24116_set_ts_param(struct dvb_frontend *fe, int is_punctured) { struct cx8802_dev *dev = fe->dvb->priv; @@ -1049,9 +1089,9 @@ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } break; - case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_PINNACLE_HYBRID_PCTV: case CX88_BOARD_WINFAST_DTV1800H: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); @@ -1060,18 +1100,28 @@ if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } break; - case CX88_BOARD_GENIATECH_X8000_MT: + case CX88_BOARD_WINFAST_DTV2000H_PLUS: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_pinnacle_hybrid_pctv, + &core->i2c_adap); + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc4000(dev, XC4000_CARD_DTV2000H_PLUS) < 0) + goto frontend_detach; + } + break; + case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; - case CX88_BOARD_KWORLD_ATSC_120: + case CX88_BOARD_KWORLD_ATSC_120: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88.h v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88.h --- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88.h 2010-02-12 02:11:30.000000000 +0100 +++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88.h 2010-02-17 17:18:17.000000000 +0100 @@ -239,8 +239,9 @@ #define CX88_BOARD_HAUPPAUGE_IRONLY 80 #define CX88_BOARD_WINFAST_DTV1800H 81 #define CX88_BOARD_WINFAST_DTV2000H_J 82 #define CX88_BOARD_PROF_7301 83 +#define CX88_BOARD_WINFAST_DTV2000H_PLUS 84 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, CX88_VMUX_COMPOSITE2, diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-input.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-input.c --- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-input.c 2010-02-12 02:11:30.000000000 +0100 +++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-input.c 2010-02-17 17:18:17.000000000 +0100 @@ -92,8 +92,9 @@ gpio=(gpio & 0x7fd) + (auxgpio & 0xef); break; case CX88_BOARD_WINFAST_DTV1000: case CX88_BOARD_WINFAST_DTV1800H: + case CX88_BOARD_WINFAST_DTV2000H_PLUS: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); auxgpio = gpio; break; @@ -236,8 +237,9 @@ break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: + case CX88_BOARD_WINFAST_DTV2000H_PLUS: ir_codes = &ir_codes_winfast_table; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100;