V4L/DVB (13085): cx23885: Fix support for v4l2-dbg access to CX2388[578] and CX23417...
authorAndy Walls <awalls@radix.net>
Sun, 27 Sep 2009 01:50:44 +0000 (22:50 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:40:16 +0000 (18:40 -0200)
This changes corrects the ioctl() operations for both the CX2388[578] analog
video and MPEG video device nodes to properly and consistently support
VIDIOC_G_CHIP_IDENT, VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER ioctl()s.

This caused some ioctl() support routines to be broken out into a separate
source file.

Now v4l2-dbg can be used to manipulate CX2388[578] and CX23417 registers
including the CX2388[57] functions handled by the cx25840 module.

This was done in anticipation of developing a new v4l2_subdev for the
integrated IR controller of the CX23888.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx23885/Makefile
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-ioctl.c [new file with mode: 0644]
drivers/media/video/cx23885/cx23885-ioctl.h [new file with mode: 0644]
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h

index ab8ea35..93a954c 100644 (file)
@@ -1,5 +1,6 @@
 cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
                    cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
+                   cx23885-ioctl.o \
                    netup-init.o cimax2.o netup-eeprom.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
index 6c3b51c..0eed852 100644 (file)
@@ -37,6 +37,7 @@
 #include <media/cx2341x.h>
 
 #include "cx23885.h"
+#include "cx23885-ioctl.h"
 
 #define CX23885_FIRM_IMAGE_SIZE 376836
 #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -318,7 +319,7 @@ static int mc417_wait_ready(struct cx23885_dev *dev)
        }
 }
 
-static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
+int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
 {
        u32 regval;
 
@@ -382,7 +383,7 @@ static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
        return mc417_wait_ready(dev);
 }
 
-static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
+int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
 {
        int retval;
        u32 regval;
@@ -1724,6 +1725,11 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_log_status       = vidioc_log_status,
        .vidioc_querymenu        = vidioc_querymenu,
        .vidioc_queryctrl        = vidioc_queryctrl,
+       .vidioc_g_chip_ident     = cx23885_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register       = cx23885_g_register,
+       .vidioc_s_register       = cx23885_s_register,
+#endif
 };
 
 static struct video_device cx23885_mpeg_template = {
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
new file mode 100644 (file)
index 0000000..3a497b6
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx23885.h"
+#include <media/v4l2-chip-ident.h>
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+                        struct v4l2_dbg_chip_ident *chip)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+       int err = 0;
+       u8 rev;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               switch (chip->match.addr) {
+               case 0:
+                       rev = cx_read(RDR_CFG2) & 0xff;
+                       switch (dev->pci->device) {
+                       case 0x8852:
+                               /* rev 0x04 could be '885 or '888. Pick '888. */
+                               if (rev == 0x04)
+                                       chip->ident = V4L2_IDENT_CX23888;
+                               else
+                                       chip->ident = V4L2_IDENT_CX23885;
+                               break;
+                       case 0x8880:
+                               if (rev == 0x0e || rev == 0x0f)
+                                       chip->ident = V4L2_IDENT_CX23887;
+                               else
+                                       chip->ident = V4L2_IDENT_CX23888;
+                               break;
+                       default:
+                               chip->ident = V4L2_IDENT_UNKNOWN;
+                               break;
+                       }
+                       chip->revision = (dev->pci->device << 16) | (rev << 8) |
+                                        (dev->hwrevision & 0xff);
+                       break;
+               case 1:
+                       if (dev->v4l_device != NULL) {
+                               chip->ident = V4L2_IDENT_CX23417;
+                               chip->revision = 0;
+                       }
+                       break;
+               default:
+                       err = -EINVAL; /* per V4L2 spec */
+                       break;
+               }
+               break;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
+               call_all(dev, core, g_chip_ident, chip);
+               break;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /*
+                * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
+                * to look if a chip is at the address with no driver.  That's a
+                * dangerous thing to do with EEPROMs anyway.
+                */
+               call_all(dev, core, g_chip_ident, chip);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       return err;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx23885_g_host_register(struct cx23885_dev *dev,
+                                  struct v4l2_dbg_register *reg)
+{
+       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+               return -EINVAL;
+
+       reg->size = 4;
+       reg->val = cx_read(reg->reg);
+       return 0;
+}
+
+static int cx23417_g_register(struct cx23885_dev *dev,
+                             struct v4l2_dbg_register *reg)
+{
+       u32 value;
+
+       if (dev->v4l_device == NULL)
+               return -EINVAL;
+
+       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+               return -EINVAL;
+
+       if (mc417_register_read(dev, (u16) reg->reg, &value))
+               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+       reg->size = 4;
+       reg->val = value;
+       return 0;
+}
+
+int cx23885_g_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+               switch (reg->match.addr) {
+               case 0:
+                       return cx23885_g_host_register(dev, reg);
+               case 1:
+                       return cx23417_g_register(dev, reg);
+               default:
+                       break;
+               }
+       }
+
+       /* FIXME - any error returns should not be ignored */
+       call_all(dev, core, g_register, reg);
+       return 0;
+}
+
+static int cx23885_s_host_register(struct cx23885_dev *dev,
+                                  struct v4l2_dbg_register *reg)
+{
+       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+               return -EINVAL;
+
+       reg->size = 4;
+       cx_write(reg->reg, reg->val);
+       return 0;
+}
+
+static int cx23417_s_register(struct cx23885_dev *dev,
+                             struct v4l2_dbg_register *reg)
+{
+       if (dev->v4l_device == NULL)
+               return -EINVAL;
+
+       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+               return -EINVAL;
+
+       if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
+               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+       reg->size = 4;
+       return 0;
+}
+
+int cx23885_s_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+               switch (reg->match.addr) {
+               case 0:
+                       return cx23885_s_host_register(dev, reg);
+               case 1:
+                       return cx23417_s_register(dev, reg);
+               default:
+                       break;
+               }
+       }
+
+       /* FIXME - any error returns should not be ignored */
+       call_all(dev, core, s_register, reg);
+       return 0;
+}
+#endif
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h
new file mode 100644 (file)
index 0000000..80b0f49
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _CX23885_IOCTL_H_
+#define _CX23885_IOCTL_H_
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+                        struct v4l2_dbg_chip_ident *chip);
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx23885_g_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg);
+
+
+int cx23885_s_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg);
+
+#endif
+#endif
index 654cc25..3f1d07e 100644 (file)
@@ -35,6 +35,7 @@
 #include "cx23885.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include "cx23885-ioctl.h"
 
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -1312,34 +1313,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                cx23885_set_freq(dev, f);
 }
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       call_all(dev, core, g_register, reg);
-
-       return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       call_all(dev, core, s_register, reg);
-
-       return 0;
-}
-#endif
-
 /* ----------------------------------------------------------- */
 
 static void cx23885_vid_timeout(unsigned long data)
@@ -1449,9 +1422,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_g_frequency   = vidioc_g_frequency,
        .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_g_chip_ident  = cx23885_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
+       .vidioc_g_register    = cx23885_g_register,
+       .vidioc_s_register    = cx23885_s_register,
 #endif
 };
 
index cc7a165..f4c4108 100644 (file)
@@ -515,6 +515,10 @@ extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
 extern void cx23885_mc417_init(struct cx23885_dev *dev);
 extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
 extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
+extern int mc417_register_read(struct cx23885_dev *dev,
+                               u16 address, u32 *value);
+extern int mc417_register_write(struct cx23885_dev *dev,
+                               u16 address, u32 value);
 extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
 extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
 extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);