V4L/DVB (5306): Add support for VIDIOC_G_CHIP_IDENT
authorHans Verkuil <hverkuil@xs4all.nl>
Fri, 27 Apr 2007 15:31:08 +0000 (12:31 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 27 Apr 2007 18:43:27 +0000 (15:43 -0300)
VIDIOC_G_CHIP_IDENT improves debugging of card problems: it can be
used to detect which chips are on the board and based on that information
selected register dumps can be made, making it easy to debug complicated
media chips containing tens or hundreds of registers.
This ioctl replaces the internal VIDIOC_INT_G_CHIP_IDENT ioctl.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
12 files changed:
drivers/media/video/cafe_ccic.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/ov7670.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
include/linux/videodev2.h
include/media/v4l2-chip-ident.h [new file with mode: 0644]
include/media/v4l2-common.h
include/media/v4l2-dev.h

index 710c11a..4d4db7b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/list.h>
@@ -164,7 +165,7 @@ struct cafe_camera
        struct tasklet_struct s_tasklet;
 
        /* Current operating parameters */
-       enum v4l2_chip_ident sensor_type;               /* Currently ov7670 only */
+       u32 sensor_type;                /* Currently ov7670 only */
        struct v4l2_pix_format pix_format;
 
        /* Locks */
@@ -818,6 +819,7 @@ static int __cafe_cam_reset(struct cafe_camera *cam)
  */
 static int cafe_cam_init(struct cafe_camera *cam)
 {
+       struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 };
        int ret;
 
        mutex_lock(&cam->s_mutex);
@@ -827,9 +829,11 @@ static int cafe_cam_init(struct cafe_camera *cam)
        ret = __cafe_cam_reset(cam);
        if (ret)
                goto out;
-       ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type);
+       chip.match_chip = cam->sensor->addr;
+       ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip);
        if (ret)
                goto out;
+       cam->sensor_type = chip.ident;
 //     if (cam->sensor->addr != OV7xx0_SID) {
        if (cam->sensor_type != V4L2_IDENT_OV7670) {
                cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);
index 774d253..1757a58 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/cx25840.h>
 
 #include "cx25840-core.h"
@@ -827,9 +828,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                        cx25840_initialize(client, 0);
                break;
 
-       case VIDIOC_INT_G_CHIP_IDENT:
-               *(enum v4l2_chip_ident *)arg = state->id;
-               break;
+       case VIDIOC_G_CHIP_IDENT:
+               return v4l2_chip_ident_i2c_client(client, arg, state->id, state->rev);
 
        default:
                return -EINVAL;
@@ -847,7 +847,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
 {
        struct i2c_client *client;
        struct cx25840_state *state;
-       enum v4l2_chip_ident id;
+       u32 id;
        u16 device_id;
 
        /* Check if the adapter supports the needed features
@@ -902,6 +902,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        state->audmode = V4L2_TUNER_MODE_LANG1;
        state->vbi_line_offset = 8;
        state->id = id;
+       state->rev = device_id;
 
        i2c_attach_client(client);
 
index 2804906..f4b56d2 100644 (file)
@@ -43,7 +43,8 @@ struct cx25840_state {
        u32 audclk_freq;
        int audmode;
        int vbi_line_offset;
-       enum v4l2_chip_ident id;
+       u32 id;
+       u32 rev;
        int is_cx25836;
 };
 
index 5ed0adc..5234762 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <linux/i2c.h>
 
 
@@ -1270,9 +1271,8 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
                void *arg)
 {
        switch (cmd) {
-       case VIDIOC_INT_G_CHIP_IDENT:
-               * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670;
-               return 0;
+       case VIDIOC_G_CHIP_IDENT:
+               return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0);
 
        case VIDIOC_INT_RESET:
                ov7670_reset(client);
index 4d5bbd8..26c9b64 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/saa7115.h>
 #include <asm/div64.h>
 
@@ -80,7 +81,7 @@ struct saa711x_state {
        int sat;
        int width;
        int height;
-       enum v4l2_chip_ident ident;
+       u32 ident;
        u32 audclk_freq;
        u32 crystal_freq;
        u8 ucgc;
@@ -1232,7 +1233,6 @@ static void saa711x_decode_vbi_line(struct i2c_client *client,
 static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
        struct saa711x_state *state = i2c_get_clientdata(client);
-       int *iarg = arg;
 
        /* ioctls to allow direct access to the saa7115 registers for testing */
        switch (cmd) {
@@ -1437,9 +1437,8 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 #endif
 
-       case VIDIOC_INT_G_CHIP_IDENT:
-               *iarg = state->ident;
-               break;
+       case VIDIOC_G_CHIP_IDENT:
+               return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0);
 
        default:
                return -EINVAL;
index 50dbb76..9f98693 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/saa7127.h>
 
 static int debug = 0;
@@ -234,7 +235,7 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = {
 
 struct saa7127_state {
        v4l2_std_id std;
-       enum v4l2_chip_ident ident;
+       u32 ident;
        enum saa7127_input_type input_type;
        enum saa7127_output_type output_type;
        int video_enable;
@@ -650,9 +651,8 @@ static int saa7127_command(struct i2c_client *client,
                break;
        }
 
-       case VIDIOC_INT_G_CHIP_IDENT:
-               *(enum v4l2_chip_ident *)arg = state->ident;
-               break;
+       case VIDIOC_G_CHIP_IDENT:
+               return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0);
 
        default:
                return -EINVAL;
index 4a3635c..49f1df7 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/video_decoder.h>
 #define __OLD_VIDIOC_ /* To allow fixing old calls*/
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
@@ -383,6 +384,8 @@ static const char *v4l2_ioctls[] = {
 
        [_IOC_NR(VIDIOC_DBG_S_REGISTER)]   = "VIDIOC_DBG_S_REGISTER",
        [_IOC_NR(VIDIOC_DBG_G_REGISTER)]   = "VIDIOC_DBG_G_REGISTER",
+
+       [_IOC_NR(VIDIOC_G_CHIP_IDENT)]     = "VIDIOC_G_CHIP_IDENT",
 #endif
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -413,7 +416,6 @@ static const char *v4l2_int_ioctls[] = {
        [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
        [_IOC_NR(VIDIOC_INT_S_VBI_DATA)]       = "VIDIOC_INT_S_VBI_DATA",
        [_IOC_NR(VIDIOC_INT_G_VBI_DATA)]       = "VIDIOC_INT_G_VBI_DATA",
-       [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)]     = "VIDIOC_INT_G_CHIP_IDENT",
        [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)]   = "VIDIOC_INT_I2S_CLOCK_FREQ",
        [_IOC_NR(VIDIOC_INT_S_STANDBY)]        = "VIDIOC_INT_S_STANDBY",
        [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
@@ -981,6 +983,22 @@ int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_c
        }
 }
 
+int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
+               u32 ident, u32 revision)
+{
+       if (!v4l2_chip_match_i2c_client(c, chip->match_type, chip->match_chip))
+               return 0;
+       if (chip->ident == V4L2_IDENT_NONE) {
+               chip->ident = ident;
+               chip->revision = revision;
+       }
+       else {
+               chip->ident = V4L2_IDENT_AMBIGUOUS;
+               chip->revision = 0;
+       }
+       return 0;
+}
+
 int v4l2_chip_match_host(u32 match_type, u32 match_chip)
 {
        switch (match_type) {
@@ -1015,6 +1033,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill);
 EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
 
 EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
+EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
 EXPORT_SYMBOL(v4l2_chip_match_host);
 
 /*
index 5c9f211..fdfef0b 100644 (file)
@@ -1532,6 +1532,16 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                break;
        }
 #endif
+       case VIDIOC_G_CHIP_IDENT:
+       {
+               struct v4l2_chip_ident *p=arg;
+               if (!vfd->vidioc_g_chip_ident)
+                       break;
+               ret=vfd->vidioc_g_chip_ident(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
+               break;
+       }
        } /* switch */
 
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
index a08ef2c..a25c2af 100644 (file)
@@ -1398,6 +1398,14 @@ struct v4l2_register {
        __u64 val;
 };
 
+/* VIDIOC_G_CHIP_IDENT */
+struct v4l2_chip_ident {
+       __u32 match_type;  /* Match type */
+       __u32 match_chip;  /* Match this chip, meaning determined by match_type */
+       __u32 ident;       /* chip identifier as specified in <media/v4l2-chip-ident.h> */
+       __u32 revision;    /* chip revision, chip specific */
+};
+
 /*
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -1471,6 +1479,8 @@ struct v4l2_register {
 /* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
 #define        VIDIOC_DBG_S_REGISTER   _IOW  ('V', 79, struct v4l2_register)
 #define        VIDIOC_DBG_G_REGISTER   _IOWR ('V', 80, struct v4l2_register)
+
+#define VIDIOC_G_CHIP_IDENT     _IOWR ('V', 81, struct v4l2_chip_ident)
 #endif
 
 #ifdef __OLD_VIDIOC_
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
new file mode 100644 (file)
index 0000000..f6686ce
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+    v4l2 chip identifiers header
+
+    This header provides a list of chip identifiers that can be returned
+    through the VIDIOC_G_CHIP_IDENT ioctl.
+
+    Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+
+    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef V4L2_CHIP_IDENT_H_
+#define V4L2_CHIP_IDENT_H_
+
+/* VIDIOC_G_CHIP_IDENT: identifies the actual chip installed on the board */
+enum {
+       /* general idents: reserved range 0-49 */
+       V4L2_IDENT_NONE      = 0,       /* No chip matched */
+       V4L2_IDENT_AMBIGUOUS = 1,       /* Match too general, multiple chips matched */
+       V4L2_IDENT_UNKNOWN   = 2,       /* Chip found, but cannot identify */
+
+       /* module saa7110: just ident= 100 */
+       V4L2_IDENT_SAA7110 = 100,
+
+       /* module saa7111: just ident= 101 */
+       V4L2_IDENT_SAA7111 = 101,
+
+       /* module saa7115: reserved range 102-149 */
+       V4L2_IDENT_SAA7113 = 103,
+       V4L2_IDENT_SAA7114 = 104,
+       V4L2_IDENT_SAA7115 = 105,
+       V4L2_IDENT_SAA7118 = 108,
+
+       /* module saa7127: reserved range 150-199 */
+       V4L2_IDENT_SAA7127 = 157,
+       V4L2_IDENT_SAA7129 = 159,
+
+       /* module cx25840: reserved range 200-249 */
+       V4L2_IDENT_CX25836 = 236,
+       V4L2_IDENT_CX25837 = 237,
+       V4L2_IDENT_CX25840 = 240,
+       V4L2_IDENT_CX25841 = 241,
+       V4L2_IDENT_CX25842 = 242,
+       V4L2_IDENT_CX25843 = 243,
+
+       /* OmniVision sensors - range 250-299 */
+       V4L2_IDENT_OV7670 = 250,
+};
+
+#endif
index abb9ce9..181a40c 100644 (file)
@@ -98,6 +98,8 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 struct i2c_client; /* forward reference */
 int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id);
+int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
+               u32 ident, u32 revision);
 int v4l2_chip_match_host(u32 id_type, u32 chip_id);
 
 /* ------------------------------------------------------------------------- */
@@ -114,39 +116,6 @@ struct v4l2_decode_vbi_line {
        u32 type;               /* VBI service type (V4L2_SLICED_*). 0 if no service found */
 };
 
-/* VIDIOC_INT_G_CHIP_IDENT: identifies the actual chip installed on the board */
-enum v4l2_chip_ident {
-       /* general idents: reserved range 0-49 */
-       V4L2_IDENT_UNKNOWN = 0,
-
-       /* module saa7110: just ident= 100 */
-       V4L2_IDENT_SAA7110 = 100,
-
-       /* module saa7111: just ident= 101 */
-       V4L2_IDENT_SAA7111 = 101,
-
-       /* module saa7115: reserved range 102-149 */
-       V4L2_IDENT_SAA7113 = 103,
-       V4L2_IDENT_SAA7114 = 104,
-       V4L2_IDENT_SAA7115 = 105,
-       V4L2_IDENT_SAA7118 = 108,
-
-       /* module saa7127: reserved range 150-199 */
-       V4L2_IDENT_SAA7127 = 157,
-       V4L2_IDENT_SAA7129 = 159,
-
-       /* module cx25840: reserved range 200-249 */
-       V4L2_IDENT_CX25836 = 236,
-       V4L2_IDENT_CX25837 = 237,
-       V4L2_IDENT_CX25840 = 240,
-       V4L2_IDENT_CX25841 = 241,
-       V4L2_IDENT_CX25842 = 242,
-       V4L2_IDENT_CX25843 = 243,
-
-       /* OmniVision sensors - range 250-299 */
-       V4L2_IDENT_OV7670 = 250,
-};
-
 /* audio ioctls */
 
 /* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */
@@ -208,10 +177,6 @@ enum v4l2_chip_ident {
    whether CC data from the first or second field should be obtained). */
 #define VIDIOC_INT_G_VBI_DATA          _IOWR('d', 106, struct v4l2_sliced_vbi_data)
 
-/* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can
-   be made. */
-#define VIDIOC_INT_G_CHIP_IDENT                _IOR ('d', 107, enum v4l2_chip_ident)
-
 /* Sets I2S speed in bps. This is used to provide a standard way to select I2S
    clock used by driving digital audio streams at some board designs.
    Usual values for the frequency are 1024000 and 2048000.
index 2693f3a..d62847f 100644 (file)
@@ -317,6 +317,8 @@ struct video_device
        int (*vidioc_s_register)       (struct file *file, void *fh,
                                        struct v4l2_register *reg);
 #endif
+       int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
+                                       struct v4l2_chip_ident *chip);
 
 
 #ifdef OBSOLETE_OWNER /* to be removed soon */