V4L/DVB (10759): cx18: Convert GPIO connected functions to act as v4l2_subdevices
authorAndy Walls <awalls@radix.net>
Sat, 21 Feb 2009 21:42:49 +0000 (18:42 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:01 +0000 (12:43 -0300)
Convert GPIO line functions, such a audio routing and device resets, to
v4l2_subdevices.  This essentially completes the conversion of cx18 to the
v4l2_device/v4l2_subdevice framework.  No regression testing has taken place as
of yet.  Also an ivtv legacy bug with GPIO mux routing and going to/from radio
mode was commented, but not fixed.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
12 files changed:
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-controls.c
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
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-vbi.c
drivers/media/video/cx18/cx18-video.c

index 6644534..9bc2218 100644 (file)
@@ -56,7 +56,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
        .hw_audio_ctrl = CX18_HW_418_AV,
        .hw_muxer = CX18_HW_CS5345,
        .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_CS5345 | CX18_HW_DVB,
+                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
                { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
@@ -102,7 +102,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
        .hw_audio_ctrl = CX18_HW_418_AV,
        .hw_muxer = CX18_HW_CS5345,
        .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_CS5345 | CX18_HW_DVB,
+                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
                { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
@@ -155,7 +155,7 @@ static const struct cx18_card cx18_card_h900 = {
        .comment = "Analog TV capture supported\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
@@ -202,7 +202,7 @@ static const struct cx18_card cx18_card_mpc718 = {
        .comment = "Analog video capture works; some audio line in may not.\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
@@ -252,8 +252,8 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = {
        .comment = "Analog TV capture supported\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_AUDIO_MUX,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
@@ -307,7 +307,7 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
                  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE6 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
@@ -351,8 +351,9 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = {
                  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_AUDIO_MUX,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+                 CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
index bd7f955..3c552b6 100644 (file)
@@ -27,7 +27,8 @@
 #define CX18_HW_CS5345         (1 << 2)
 #define CX18_HW_DVB            (1 << 3)
 #define CX18_HW_418_AV         (1 << 4)
-#define CX18_HW_GPIO_AUDIO_MUX (1 << 5)
+#define CX18_HW_GPIO_MUX       (1 << 5)
+#define CX18_HW_GPIO_RESET_CTRL        (1 << 6)
 
 /* video inputs */
 #define        CX18_CARD_INPUT_VID_TUNER       1
index e5604c2..925e01f 100644 (file)
  */
 
 #include "cx18-driver.h"
-#include "cx18-av-core.h"
 #include "cx18-cards.h"
 #include "cx18-ioctl.h"
 #include "cx18-audio.h"
-#include "cx18-i2c.h"
 #include "cx18-mailbox.h"
 #include "cx18-controls.h"
 
index edbb83c..79b3bf5 100644 (file)
@@ -684,7 +684,6 @@ static void cx18_init_subdevs(struct cx18 *cx)
                        continue;
 
                switch (device) {
-               case CX18_HW_GPIO_AUDIO_MUX:
                case CX18_HW_DVB:
                case CX18_HW_TVEEPROM:
                        /* These subordinate devices do not use probing */
@@ -695,6 +694,16 @@ static void cx18_init_subdevs(struct cx18 *cx)
                        /* Just note that the card uses it (i.e. has analog) */
                        cx->hw_flags |= device;
                        break;
+               case CX18_HW_GPIO_RESET_CTRL:
+                       /*
+                        * The Reset Controller gets probed and added to
+                        * hw_flags earlier for i2c adapter/bus initialization
+                        */
+                       break;
+               case CX18_HW_GPIO_MUX:
+                       if (cx18_gpio_register(cx, device) == 0)
+                               cx->hw_flags |= device;
+                       break;
                default:
                        if (cx18_i2c_register(cx, i) == 0)
                                cx->hw_flags |= device;
@@ -793,7 +802,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
        cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
        cx18_init_scb(cx);
 
-       /* Initialize GPIO early so I2C device resets can be performed */
        cx18_gpio_init(cx);
 
        /* Initialize integrated A/V decoder early to set PLLs, just in case */
@@ -802,9 +810,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
                CX18_ERR("Could not register A/V decoder subdevice\n");
                goto free_map;
        }
-       /* Initialize the A/V decoder PLLs to sane defaults */
        cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS);
 
+       /* Initialize GPIO Reset Controller to do chip resets during i2c init */
+       if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
+               if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0)
+                       CX18_WARN("Could not register GPIO reset controller"
+                                 "subdevice; proceeding anyway.\n");
+               else
+                       cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL;
+       }
+
        /* active i2c  */
        CX18_DEBUG_INFO("activating i2c...\n");
        retval = init_cx18_i2c(cx);
index b81106d..9ee6080 100644 (file)
@@ -449,7 +449,7 @@ struct cx18 {
        struct pci_dev *pci_dev;
        struct v4l2_device v4l2_dev;
        struct v4l2_subdev *sd_av;     /* A/V decoder/digitizer sub-device */
-       struct v4l2_subdev *sd_extmux; /* External audio multiplexer sub-dev */
+       struct v4l2_subdev *sd_extmux; /* External multiplexer sub-dev */
 
        const struct cx18_card *card;   /* card information */
        const char *card_name;  /* full name of the card */
@@ -534,6 +534,8 @@ struct cx18 {
        u32 gpio_dir;
        u32 gpio_val;
        struct mutex gpio_lock;
+       struct v4l2_subdev sd_gpiomux;
+       struct v4l2_subdev sd_resetctrl;
 
        /* v4l2 and User settings */
 
index 1a99329..dcc19b1 100644 (file)
@@ -46,6 +46,9 @@
  * gpio13: cs5345 reset pin
 */
 
+/*
+ * File scope utility functions
+ */
 static void gpio_write(struct cx18 *cx)
 {
        u32 dir_lo = cx->gpio_dir & 0xffff;
@@ -63,73 +66,201 @@ static void gpio_write(struct cx18 *cx)
                                        CX18_REG_GPIO_OUT2, val_hi, dir_hi);
 }
 
-void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
+static void gpio_update(struct cx18 *cx, u32 mask, u32 data)
 {
-       const struct cx18_gpio_i2c_slave_reset *p;
+       if (mask == 0)
+               return;
 
-       p = &cx->card->gpio_i2c_slave_reset;
+       mutex_lock(&cx->gpio_lock);
+       cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
+       gpio_write(cx);
+       mutex_unlock(&cx->gpio_lock);
+}
+
+static void gpio_reset_seq(struct cx18 *cx, u32 active_lo, u32 active_hi,
+                          unsigned int assert_msecs,
+                          unsigned int recovery_msecs)
+{
+       u32 mask;
 
-       if ((p->active_lo_mask | p->active_hi_mask) == 0)
+       mask = active_lo | active_hi;
+       if (mask == 0)
                return;
 
-       /* Assuming that the masks are a subset of the bits in gpio_dir */
+       /*
+        * Assuming that active_hi and active_lo are a subsets of the bits in
+        * gpio_dir.  Also assumes that active_lo and active_hi don't overlap
+        * in any bit position
+        */
 
        /* Assert */
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_val =
-               (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
-       gpio_write(cx);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
+       gpio_update(cx, mask, ~active_lo);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs));
 
        /* Deassert */
-       cx->gpio_val =
-               (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
-       gpio_write(cx);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+       gpio_update(cx, mask, ~active_hi);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs));
+}
+
+/*
+ * GPIO Multiplexer - logical device
+ */
+static int gpiomux_log_status(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       mutex_lock(&cx->gpio_lock);
+       CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
+               cx->gpio_dir, cx->gpio_val);
        mutex_unlock(&cx->gpio_lock);
+       return 0;
 }
 
-void cx18_reset_ir_gpio(void *data)
+static int gpiomux_s_radio(struct v4l2_subdev *sd)
 {
-       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
-       const struct cx18_gpio_i2c_slave_reset *p;
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
 
-       p = &cx->card->gpio_i2c_slave_reset;
+       /*
+        * FIXME - work out the cx->active/audio_input mess - this is
+        * intended to handle the switch to radio mode and set the
+        * audio routing, but we need to update the state in cx
+        */
+       gpio_update(cx, cx->card->gpio_audio_input.mask,
+                       cx->card->gpio_audio_input.radio);
+       return 0;
+}
 
-       if (p->ir_reset_mask == 0)
-               return;
+static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u32 data;
 
-       CX18_DEBUG_INFO("Resetting IR microcontroller\n");
+       switch (cx->card->audio_inputs[cx->audio_input].muxer_input) {
+       case 1:
+               data = cx->card->gpio_audio_input.linein;
+               break;
+       case 0:
+               data = cx->card->gpio_audio_input.tuner;
+               break;
+       default:
+               /*
+                * FIXME - work out the cx->active/audio_input mess - this is
+                * intended to handle the switch from radio mode and set the
+                * audio routing, but we need to update the state in cx
+                */
+               data = cx->card->gpio_audio_input.tuner;
+               break;
+       }
+       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+       return 0;
+}
 
-       /*
-          Assert timing for the Z8F0811 on HVR-1600 boards:
-          1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
-          2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
-               (6,601,085 nanoseconds ~= 7 milliseconds)
-          3. DBG pin must be high before chip exits reset for normal operation.
-               DBG is open drain and hopefully pulled high since we don't
-               normally drive it (GPIO 1?) for the HVR-1600
-          4. Z8F0811 won't exit reset until RESET is deasserted
-       */
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
-       gpio_write(cx);
-       mutex_unlock(&cx->gpio_lock);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
+static int gpiomux_s_audio_routing(struct v4l2_subdev *sd,
+                                  const struct v4l2_routing *route)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u32 data;
+
+       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:
+               data = cx->card->gpio_audio_input.radio;
+               break;
+       default:
+               return -EINVAL;
+       }
+       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops gpiomux_core_ops = {
+       .log_status = gpiomux_log_status,
+};
+
+static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = {
+       .s_std = gpiomux_s_std,
+       .s_radio = gpiomux_s_radio,
+};
+
+static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = {
+       .s_routing = gpiomux_s_audio_routing,
+};
+
+static const struct v4l2_subdev_ops gpiomux_ops = {
+       .core = &gpiomux_core_ops,
+       .tuner = &gpiomux_tuner_ops,
+       .audio = &gpiomux_audio_ops,
+};
+
+/*
+ * GPIO Reset Controller - logical device
+ */
+static int resetctrl_log_status(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
 
-       /*
-          Zilog comes out of reset, loads reset vector address and executes
-          from there. Required recovery delay unknown.
-       */
        mutex_lock(&cx->gpio_lock);
-       cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
-       gpio_write(cx);
+       CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
+               cx->gpio_dir, cx->gpio_val);
        mutex_unlock(&cx->gpio_lock);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+       return 0;
 }
-EXPORT_SYMBOL(cx18_reset_ir_gpio);
-/* This symbol is exported for use by an infrared module for the IR-blaster */
 
+static int resetctrl_reset(struct v4l2_subdev *sd, u32 val)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       const struct cx18_gpio_i2c_slave_reset *p;
+
+       p = &cx->card->gpio_i2c_slave_reset;
+       switch (val) {
+       case CX18_GPIO_RESET_I2C:
+               gpio_reset_seq(cx, p->active_lo_mask, p->active_hi_mask,
+                              p->msecs_asserted, p->msecs_recovery);
+               break;
+       case CX18_GPIO_RESET_Z8F0811:
+               /*
+                * Assert timing for the Z8F0811 on HVR-1600 boards:
+                * 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to
+                *    initiate
+                * 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock
+                *    cycles (6,601,085 nanoseconds ~= 7 milliseconds)
+                * 3. DBG pin must be high before chip exits reset for normal
+                *    operation.  DBG is open drain and hopefully pulled high
+                *    since we don't normally drive it (GPIO 1?) for the
+                *    HVR-1600
+                * 4. Z8F0811 won't exit reset until RESET is deasserted
+                * 5. Zilog comes out of reset, loads reset vector address and
+                *    executes from there. Required recovery delay unknown.
+                */
+               gpio_reset_seq(cx, p->ir_reset_mask, 0,
+                              p->msecs_asserted, p->msecs_recovery);
+               break;
+       case CX18_GPIO_RESET_XC2028:
+               if (cx->card->tuners[0].tuner == TUNER_XC2028)
+                       gpio_reset_seq(cx, (1 << cx->card->xceive_pin), 0,
+                                      1, 1);
+               break;
+       }
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops resetctrl_core_ops = {
+       .log_status = resetctrl_log_status,
+       .reset = resetctrl_reset,
+};
+
+static const struct v4l2_subdev_ops resetctrl_ops = {
+       .core = &resetctrl_core_ops,
+};
+
+/*
+ * External entry points
+ */
 void cx18_gpio_init(struct cx18 *cx)
 {
        mutex_lock(&cx->gpio_lock);
@@ -156,6 +287,49 @@ void cx18_gpio_init(struct cx18 *cx)
        mutex_unlock(&cx->gpio_lock);
 }
 
+int cx18_gpio_register(struct cx18 *cx, u32 hw)
+{
+       struct v4l2_subdev *sd;
+       const struct v4l2_subdev_ops *ops;
+       char *str;
+
+       switch (hw) {
+       case CX18_HW_GPIO_MUX:
+               sd = &cx->sd_gpiomux;
+               ops = &gpiomux_ops;
+               str = "gpio mux";
+               break;
+       case CX18_HW_GPIO_RESET_CTRL:
+               sd = &cx->sd_resetctrl;
+               ops = &resetctrl_ops;
+               str = "gpio reset ctrl";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       v4l2_subdev_init(sd, ops);
+       v4l2_set_subdevdata(sd, cx);
+       snprintf(sd->name, sizeof(sd->name), "%s %s", cx->v4l2_dev.name, str);
+       sd->grp_id = hw;
+       return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+}
+
+void cx18_reset_ir_gpio(void *data)
+{
+       struct cx18 *cx = to_cx18((struct v4l2_device *)data);
+
+       if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
+               return;
+
+       CX18_DEBUG_INFO("Resetting IR microcontroller\n");
+
+       v4l2_subdev_call(&cx->sd_resetctrl,
+                        core, reset, CX18_GPIO_RESET_Z8F0811);
+}
+EXPORT_SYMBOL(cx18_reset_ir_gpio);
+/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */
+
 /* Xceive tuner reset function */
 int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
 {
@@ -163,56 +337,11 @@ int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
        struct cx18_i2c_algo_callback_data *cb_data = algo->data;
        struct cx18 *cx = cb_data->cx;
 
-       if (cmd != XC2028_TUNER_RESET)
+       if (cmd != XC2028_TUNER_RESET ||
+           cx->card->tuners[0].tuner != TUNER_XC2028)
                return 0;
-       CX18_DEBUG_INFO("Resetting tuner\n");
 
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_val &= ~(1 << cx->card->xceive_pin);
-       gpio_write(cx);
-       mutex_unlock(&cx->gpio_lock);
-       schedule_timeout_interruptible(msecs_to_jiffies(1));
-
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_val |= 1 << cx->card->xceive_pin;
-       gpio_write(cx);
-       mutex_unlock(&cx->gpio_lock);
-       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) {
-               mutex_lock(&cx->gpio_lock);
-               cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
-               gpio_write(cx);
-               mutex_unlock(&cx->gpio_lock);
-       }
-       return 0;
+       CX18_DEBUG_INFO("Resetting XCeive tuner\n");
+       return v4l2_subdev_call(&cx->sd_resetctrl,
+                               core, reset, CX18_GPIO_RESET_XC2028);
 }
index 39ffccc..f9a5ca3 100644 (file)
  */
 
 void cx18_gpio_init(struct cx18 *cx);
-void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
+int cx18_gpio_register(struct cx18 *cx, u32 hw);
+
+enum cx18_gpio_reset_type {
+       CX18_GPIO_RESET_I2C     = 0,
+       CX18_GPIO_RESET_Z8F0811 = 1,
+       CX18_GPIO_RESET_XC2028  = 2,
+};
+
 void cx18_reset_ir_gpio(void *data);
 int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
-int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
index 6357dc4..d092643 100644 (file)
@@ -26,7 +26,6 @@
 #include "cx18-io.h"
 #include "cx18-cards.h"
 #include "cx18-gpio.h"
-#include "cx18-av-core.h"
 #include "cx18-i2c.h"
 #include "cx18-irq.h"
 
@@ -49,7 +48,8 @@ static const u8 hw_addrs[] = {
        CX18_CS5345_I2C_ADDR,   /* CX18_HW_CS5345 */
        0,                      /* CX18_HW_DVB */
        0,                      /* CX18_HW_418_AV */
-       0,                      /* CX18_HW_GPIO_AUDIO_MUX */
+       0,                      /* CX18_HW_GPIO_MUX */
+       0,                      /* CX18_HW_GPIO_RESET_CTRL */
 };
 
 /* This array should match the CX18_HW_ defines */
@@ -60,7 +60,8 @@ static const u8 hw_bus[] = {
        0,      /* CX18_HW_CS5345 */
        0,      /* CX18_HW_DVB */
        0,      /* CX18_HW_418_AV */
-       0,      /* CX18_HW_GPIO_AUDIO_MUX */
+       0,      /* CX18_HW_GPIO_MUX */
+       0,      /* CX18_HW_GPIO_RESET_CTRL */
 };
 
 /* This array should match the CX18_HW_ defines */
@@ -70,7 +71,8 @@ static const char * const hw_modules[] = {
        "cs5345",       /* CX18_HW_CS5345 */
        NULL,           /* CX18_HW_DVB */
        NULL,           /* CX18_HW_418_AV */
-       NULL,           /* CX18_HW_GPIO_AUDIO_MUX */
+       NULL,           /* CX18_HW_GPIO_MUX */
+       NULL,           /* CX18_HW_GPIO_RESET_CTRL */
 };
 
 /* This array should match the CX18_HW_ defines */
@@ -80,7 +82,8 @@ static const char * const hw_devicenames[] = {
        "cs5345",
        "cx23418_DTV",
        "cx23418_AV",
-       "gpio_audio_mux",
+       "gpio_mux",
+       "gpio_reset_ctrl",
 };
 
 int cx18_i2c_register(struct cx18 *cx, unsigned idx)
@@ -262,7 +265,8 @@ int init_cx18_i2c(struct cx18 *cx)
        cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
        cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 
-       cx18_reset_i2c_slaves_gpio(cx);
+       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+                    core, reset, (u32) CX18_GPIO_RESET_I2C);
 
        return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
                i2c_bit_add_bus(&cx->i2c_adap[1]);
index 13ebd4a..e4c9e3d 100644 (file)
@@ -940,7 +940,8 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
                u32 val = *(u32 *)arg;
 
                if ((val == 0) || (val & 0x01))
-                       cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]);
+                       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
+                                    (u32) CX18_GPIO_RESET_Z8F0811);
                break;
        }
 
index 1d17884..ce65cc6 100644 (file)
@@ -32,7 +32,6 @@
 #include "cx18-streams.h"
 #include "cx18-cards.h"
 #include "cx18-scb.h"
-#include "cx18-av-core.h"
 #include "cx18-dvb.h"
 
 #define CX18_DSP0_INTERRUPT_MASK       0xd0004C
index 91c21dc..a81fe2e 100644 (file)
@@ -25,7 +25,6 @@
 #include "cx18-vbi.h"
 #include "cx18-ioctl.h"
 #include "cx18-queue.h"
-#include "cx18-av-core.h"
 
 /*
  * Raster Reference/Protection (RP) bytes, used in Start/End Active
index fabacb0..6fdaded 100644 (file)
@@ -21,7 +21,6 @@
 
 #include "cx18-driver.h"
 #include "cx18-video.h"
-#include "cx18-av-core.h"
 #include "cx18-cards.h"
 
 void cx18_video_set_io(struct cx18 *cx)