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 710c11a682964b88f525a0517b9f3a2032f5ad70..4d4db7b2b611fd9941b3e324fd4279f1d8b4abd6 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 774d2536555b8d6dbe7001c1c6f8b7b6928e4020..1757a588970fc242717128f707765029a9862eac 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 28049064dd7d4d7cb02fc1314de47bf3d48d66ec..f4b56d2fd6b6cee76c936c1ed645f9e1c628d8da 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 5ed0adc4ca26ba3eafa62175c143eda9591a580e..5234762c5427da469c607a3350fa5091d20ccff3 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 4d5bbd859de1d6e13cf8f3226291594f0594afa9..26c9b64c748c0bc9b0278ea4dd3cd3f5a9d47bbb 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 50dbb76d4a7f380eab51d2794ebb0dd7421829de..9f986930490f7022326cd3c4a1b844b13a3e573d 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 4a3635cd6f9ee3a500d060ddf818000488223ba4..49f1df74aa21d9f008717d598be1ae8a87a9c7bc 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 5c9f2116d7bf52bbff5db53182a18da50257736f..fdfef0b53315d0426e048def4454336d444056a2 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 a08ef2c16300327a71359d84397732ee092e5404..a25c2afa67e100cb2c5f9736c186ea7ae262a95c 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 abb9ce9b21b8ce9699cb7ae01f6c2304dca0c967..181a40c46a52d866f5c1d3cb83cdbfeeea0387c1 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 2693f3ae6ffb5f303910f7d1339f9f5998ee5d35..d62847f846c2f7640526a8332c03d573e21576c6 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 */