V4L/DVB (7043): New card supported(partially): Pinnacle 800i
authorSteven Toth <stoth@hauppauge.com>
Sat, 5 Jan 2008 19:53:01 +0000 (16:53 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 25 Jan 2008 21:05:06 +0000 (19:05 -0200)
From Zhang: This patch continues the support for the Pinnacle HD 800i.

Patch committed as-is, cleanups to follow ... Steve

Signed-off-by: Chaogui Zhang <czhang1974@gmail.com>
Signed-off-by: Steven Toth <stoth@hauppauge.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Documentation/video4linux/CARDLIST.cx88
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88.h

index 82ac825..bc5593b 100644 (file)
@@ -56,3 +56,4 @@
  55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  [c180:c980]
  56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
  57 -> ADS Tech Instant Video PCI                          [1421:0390]
+ 58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
index d484e5c..3ba3157 100644 (file)
@@ -1375,6 +1375,32 @@ static const struct cx88_board cx88_boards[] = {
                        .gpio0  = 0x07fa,
                }},
        },
+       [CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
+               .name           = "Pinnacle PCTV HD 800i",
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ef,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ef,
+                       .audioroute = 1,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
 };
 
 /* ------------------------------------------------------------------ */
@@ -1684,6 +1710,10 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x1421,
                .subdevice = 0x0390,
                .card      = CX88_BOARD_ADSTECH_PTV_390,
+       },{
+               .subvendor = 0x11bd,
+               .subdevice = 0x0051,
+               .card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
        },
 };
 
@@ -1851,6 +1881,39 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
 }
 
 /* ----------------------------------------------------------------------- */
+/* 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)    */
+
+int cx88_tuner_callback(void *i2c_algo, int command, int arg)
+{
+       struct i2c_algo_bit_data *algo = i2c_algo;
+       struct cx88_core *core = algo->data;
+
+       switch(core->boardnr) {
+       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+               if(command == 0) { /* This is the reset command from xc5000 */
+                       /* Reset XC5000 tuner via GPIO pin #2 */
+                       cx_set(MO_GP0_IO, 0x00000400);
+                       cx_clear(MO_GP0_IO, 0x00000004);
+                       mdelay(200);
+                       cx_set(MO_GP0_IO, 0x00000004);
+                       printk(KERN_ERR "xc5000: in reset for xc5000\n");
+                       mdelay(200);
+                       return 0;
+               }
+               else {
+                       printk(KERN_ERR
+                               "xc5000: unknown tuner callback command.\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+       return 0; /* Should never be here */
+}
+EXPORT_SYMBOL(cx88_tuner_callback);
+
+/* ----------------------------------------------------------------------- */
 
 static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
 {
index fce19ca..0246f97 100644 (file)
@@ -40,6 +40,8 @@
 #include "cx22702.h"
 #include "or51132.h"
 #include "lgdt330x.h"
+#include "s5h1409.h"
+#include "xc5000.h"
 #include "nxt200x.h"
 #include "cx24123.h"
 #include "isl6421.h"
@@ -371,6 +373,22 @@ static struct cx24123_config kworld_dvbs_100_config = {
        .lnb_polarity  = 1,
 };
 
+static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+};
+
+static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
+       .i2c_address    = 0x64,
+       .if_khz         = 5380,
+       /* cannot set .video_dev here, do it right before attach */
+       .tuner_callback = cx88_tuner_callback,
+};
+
 static int dvb_register(struct cx8802_dev *dev)
 {
        /* init struct videobuf_dvb */
@@ -625,6 +643,24 @@ static int dvb_register(struct cx8802_dev *dev)
                        dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
                }
                break;
+       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+               /* Parallel mpeg data port and punctured clock mode */
+               dev->ts_gen_cntrl = 0x04;
+
+               dev->dvb.frontend = dvb_attach(s5h1409_attach,
+                                              &pinnacle_pctv_hd_800i_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       /* tuner_config.video_dev must point to
+                        * i2c_adap.algo_data
+                        */
+                       pinnacle_pctv_hd_800i_tuner_config.video_dev =
+                                               dev->core->i2c_adap.algo_data;
+                       dvb_attach(xc5000_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap,
+                                  &pinnacle_pctv_hd_800i_tuner_config);
+               }
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
index 937497c..566b26a 100644 (file)
@@ -109,20 +109,20 @@ static int attach_inform(struct i2c_client *client)
 
        if (core->board.radio_type != UNSET) {
                if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
-                       tun_setup.mode_mask = T_RADIO;
-                       tun_setup.type = core->board.radio_type;
-                       tun_setup.addr = core->board.radio_addr;
-
+                       tun_setup.mode_mask      = T_RADIO;
+                       tun_setup.type           = core->board.radio_type;
+                       tun_setup.addr           = core->board.radio_addr;
+                       tun_setup.tuner_callback = cx88_tuner_callback;
                        client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
                }
        }
        if (core->board.tuner_type != UNSET) {
                if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
 
-                       tun_setup.mode_mask = T_ANALOG_TV;
-                       tun_setup.type = core->board.tuner_type;
-                       tun_setup.addr = core->board.tuner_addr;
-
+                       tun_setup.mode_mask      = T_ANALOG_TV;
+                       tun_setup.type           = core->board.tuner_type;
+                       tun_setup.addr           = core->board.tuner_addr;
+                       tun_setup.tuner_callback = cx88_tuner_callback;
                        client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
                }
        }
@@ -182,6 +182,7 @@ static char *i2c_devs[128] = {
        [ 0xa0 >> 1 ] = "eeprom",
        [ 0xc0 >> 1 ] = "tuner (analog)",
        [ 0xc2 >> 1 ] = "tuner (analog/dvb)",
+       [ 0xc8 >> 1 ] = "xc5000",
 };
 
 static void do_i2c_scan(char *name, struct i2c_client *c)
index 339a88a..a21b503 100644 (file)
@@ -102,7 +102,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
                udelay(100);
                cx_write(MO_PINMUX_IO, 0x00);
-               cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
+               cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
                switch (core->boardnr) {
                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
@@ -117,6 +117,11 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                        break;
                case CX88_BOARD_HAUPPAUGE_HVR1300:
                        break;
+               case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+                       /* Enable MPEG parallel port */
+                       cx_write(MO_PINMUX_IO, 0x80);
+                       udelay(100);
+                       break;
                default:
                        cx_write(TS_SOP_STAT, 0x00);
                        break;
index 0cd2946..4e823f2 100644 (file)
@@ -210,6 +210,7 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_TE_DTV_250_OEM_SWANN    55
 #define CX88_BOARD_HAUPPAUGE_HVR1300       56
 #define CX88_BOARD_ADSTECH_PTV_390         57
+#define CX88_BOARD_PINNACLE_PCTV_HD_800i   58
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -589,6 +590,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core,
 /* ----------------------------------------------------------- */
 /* cx88-cards.c                                                */
 
+extern int cx88_tuner_callback(void *dev, int command, int arg);
 extern int cx88_get_resources(const struct cx88_core *core,
                              struct pci_dev *pci);
 extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);