V4L/DVB (8089): cx18: add support for Conexant Raptor PAL/SECAM card
authorSri Deevi <Srinivasa.Deevi@conexant.com>
Sat, 21 Jun 2008 14:06:44 +0000 (11:06 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 20 Jul 2008 10:11:13 +0000 (07:11 -0300)
Patch provided courtesy of Conexant http://www.conexant.com.

Signed-off-by: Srinivasa Deevi <srinivasa.deevi@conexant.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-gpio.c
drivers/media/video/cx18/cx18-gpio.h
drivers/media/video/cx18/cx18-i2c.c

index c26e0ef5b07583927c5d5ddd80fee3c304557741..90857bedccae89c80cfaefe7bdbd9daaa74a17db 100644 (file)
@@ -27,6 +27,8 @@
 #include "cx18-i2c.h"
 #include <media/cs5345.h>
 
+#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM)
+
 /********************** card configuration *******************************/
 
 /* usual i2c tuner addresses to probe */
@@ -232,11 +234,64 @@ static const struct cx18_card cx18_card_mpc718 = {
        .i2c = &cx18_i2c_std,
 };
 
+/* ------------------------------------------------------------------------- */
+
+/* Conexant Raptor PAL/SECAM: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_CONEXANT, 0x0009 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_cnxt_raptor_pal = {
+       .type = CX18_CARD_CNXT_RAPTOR_PAL,
+       .name = "Conexant Raptor PAL/SECAM",
+       .comment = "VBI is not yet supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_muxer = CX18_HW_GPIO,
+       .hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+               { CX18_CARD_INPUT_SVIDEO2,    2,
+                       CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 1 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL, 0 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL, 0 },
+       },
+       .tuners = {
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+       },
+       .ddr = {
+               /* MT 46V16M16 memory */
+               .chip_config = 0x50306,
+               .refresh = 0x753,
+               .timing1 = 0x33220953,
+               .timing2 = 0x09,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .gpio_init.initial_value = 0x02,
+       .gpio_init.direction = 0x02,
+       .gpio_audio_input  = { .mask = 0x02, .tuner  = 0x02, .linein = 0x00 },
+       .pci_list = cx18_pci_cnxt_raptor_pal,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
 static const struct cx18_card *cx18_card_list[] = {
        &cx18_card_hvr1600_esmt,
        &cx18_card_hvr1600_samsung,
        &cx18_card_h900,
        &cx18_card_mpc718,
+       &cx18_card_cnxt_raptor_pal,
 };
 
 const struct cx18_card *cx18_get_card(u16 index)
index dc2dd945d4c3be4aefd2b324a6d4f368b8825c8c..b5f894c0afa907e1dbe0362bd4f333093b260238 100644 (file)
@@ -85,6 +85,13 @@ struct cx18_gpio_i2c_slave_reset {
        int msecs_recovery; /* time after deassert for chips to be ready */
 };
 
+struct ivtv_gpio_audio_input {         /* select tuner/line in input */
+       u32 mask;               /* leave to 0 if not supported */
+       u32 tuner;
+       u32 linein;
+       u32 radio;
+};
+
 struct cx18_card_tuner {
        v4l2_std_id std;        /* standard for which the tuner is suitable */
        int         tuner;      /* tuner ID (from tuner.h) */
@@ -123,6 +130,7 @@ struct cx18_card {
        u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
        struct cx18_gpio_init            gpio_init;
        struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
+       struct ivtv_gpio_audio_input    gpio_audio_input;
 
        struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
        struct cx18_card_tuner_i2c *i2c;
index e9c7e07b9fed07a7ce7f219f5fecebd901f9af79..71bb04ab91d798a5a108e585ab74cd0427654b35 100644 (file)
@@ -120,6 +120,7 @@ MODULE_PARM_DESC(cardtype,
                 "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
                 "\t\t\t 3 = Compro VideoMate H900\n"
                 "\t\t\t 4 = Yuan MPC718\n"
+                "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
                 "\t\t\t 0 = Autodetect (default)\n"
                 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -435,7 +436,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
                (cx->params.video_temporal_filter_mode << 1) |
                (cx->params.video_median_filter_type << 2);
        cx->params.port = CX2341X_PORT_MEMORY;
-       cx->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
+       cx->params.capabilities = 0;
        init_waitqueue_head(&cx->cap_w);
        init_waitqueue_head(&cx->mb_apu_waitq);
        init_waitqueue_head(&cx->mb_cpu_waitq);
index de14ab59a206b6c84e88f07e53b0124a5b5a7281..b421e0268b00eb3df33a2b7f45736cf725a366d7 100644 (file)
@@ -75,7 +75,8 @@
 #define CX18_CARD_HVR_1600_SAMSUNG    1        /* Hauppauge HVR 1600 (Samsung memory) */
 #define CX18_CARD_COMPRO_H900        2 /* Compro VideoMate H900 */
 #define CX18_CARD_YUAN_MPC718        3 /* Yuan MPC718 */
-#define CX18_CARD_LAST                       3
+#define CX18_CARD_CNXT_RAPTOR_PAL     4        /* Conexant Raptor PAL */
+#define CX18_CARD_LAST                       4
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
 #define CX18_ENC_STREAM_TYPE_TS   1
@@ -94,6 +95,7 @@
 #define CX18_PCI_ID_HAUPPAUGE          0x0070
 #define CX18_PCI_ID_COMPRO             0x185b
 #define CX18_PCI_ID_YUAN               0x12ab
+#define CX18_PCI_ID_CONEXANT           0x14f1
 
 /* ======================================================================== */
 /* ========================== START USER SETTABLE DMA VARIABLES =========== */
index b302833f6f9dd8d8250f4e716ed5fa9084d515d6..089bad6d85a0f347f390c67a9947f782c72041a4 100644 (file)
@@ -122,3 +122,37 @@ int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
        schedule_timeout_interruptible(msecs_to_jiffies(1));
        return 0;
 }
+
+int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg)
+{
+       struct v4l2_routing *route = arg;
+       u32 mask, data;
+
+       switch (command) {
+       case VIDIOC_INT_S_AUDIO_ROUTING:
+               if (route->input > 2)
+                       return -EINVAL;
+               mask = cx->card->gpio_audio_input.mask;
+               switch (route->input) {
+               case 0:
+                       data = cx->card->gpio_audio_input.tuner;
+                       break;
+               case 1:
+                       data = cx->card->gpio_audio_input.linein;
+                       break;
+               case 2:
+               default:
+                       data = cx->card->gpio_audio_input.radio;
+                       break;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       if (mask) {
+               cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
+               gpio_write(cx);
+       }
+       return 0;
+}
index 525c328f748a3d0f677863bdc4fdde9ae4bdc0fb..7447fed357676acb2fd8a5c5121825311554b8b4 100644 (file)
@@ -23,3 +23,4 @@
 void cx18_gpio_init(struct cx18 *cx);
 void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
 int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
+int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
index 680bc4e35b79a3c67d38e072af2471fb30e35e2d..bca905901d61f99f02c33e5eb0eadaee60f47563 100644 (file)
@@ -311,8 +311,12 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
 {
        int addr;
 
-       if (hw == CX18_HW_GPIO || hw == 0)
+       if (hw == 0)
                return 0;
+
+       if (hw == CX18_HW_GPIO)
+               return cx18_gpio(cx, cmd, arg);
+
        if (hw == CX18_HW_CX23418)
                return cx18_av_cmd(cx, cmd, arg);
 
@@ -350,6 +354,8 @@ void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
        cx18_av_cmd(cx, cmd, arg);
        i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
        i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
+       if (cx->hw_flags & CX18_HW_GPIO)
+               cx18_gpio(cx, cmd, arg);
 }
 
 /* init + register i2c algo-bit adapter */
@@ -358,6 +364,18 @@ int init_cx18_i2c(struct cx18 *cx)
        int i;
        CX18_DEBUG_I2C("i2c init\n");
 
+       /* Sanity checks for the I2C hardware arrays. They must be the
+        * same size and GPIO/CX23418 must be the last entries.
+        */
+       if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) ||
+           ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
+           CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) ||
+           CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) ||
+           hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) {
+               CX18_ERR("Mismatched I2C hardware arrays\n");
+               return -ENODEV;
+       }
+
        for (i = 0; i < 2; i++) {
                memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
                        sizeof(struct i2c_adapter));