#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>
        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 */
  */
 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);
        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);
 
 #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"
                        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;
 {
        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
        state->audmode = V4L2_TUNER_MODE_LANG1;
        state->vbi_line_offset = 8;
        state->id = id;
+       state->rev = device_id;
 
        i2c_attach_client(client);
 
 
        u32 audclk_freq;
        int audmode;
        int vbi_line_offset;
-       enum v4l2_chip_ident id;
+       u32 id;
+       u32 rev;
        int is_cx25836;
 };
 
 
 #include <linux/delay.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 #include <linux/i2c.h>
 
 
                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);
 
 #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>
 
        int sat;
        int width;
        int height;
-       enum v4l2_chip_ident ident;
+       u32 ident;
        u32 audclk_freq;
        u32 crystal_freq;
        u8 ucgc;
 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) {
        }
 #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;
 
 #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;
 
 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;
                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;
 
 #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>
 
        [_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)
        [_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",
        }
 }
 
+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) {
 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);
 
 /*
 
                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) {
 
        __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
  *
 /* 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_
 
--- /dev/null
+/*
+    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
 
 
 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);
 
 /* ------------------------------------------------------------------------- */
        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 */
    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.
 
        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 */