Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (5306): Add support for VIDIOC_G_CHIP_IDENT

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>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
3434eb7e ced80c67

+130 -57
+6 -2
drivers/media/video/cafe_ccic.c
··· 22 22 #include <linux/spinlock.h> 23 23 #include <linux/videodev2.h> 24 24 #include <media/v4l2-common.h> 25 + #include <media/v4l2-chip-ident.h> 25 26 #include <linux/device.h> 26 27 #include <linux/wait.h> 27 28 #include <linux/list.h> ··· 165 164 struct tasklet_struct s_tasklet; 166 165 167 166 /* Current operating parameters */ 168 - enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */ 167 + u32 sensor_type; /* Currently ov7670 only */ 169 168 struct v4l2_pix_format pix_format; 170 169 171 170 /* Locks */ ··· 819 818 */ 820 819 static int cafe_cam_init(struct cafe_camera *cam) 821 820 { 821 + struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 }; 822 822 int ret; 823 823 824 824 mutex_lock(&cam->s_mutex); ··· 829 827 ret = __cafe_cam_reset(cam); 830 828 if (ret) 831 829 goto out; 832 - ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type); 830 + chip.match_chip = cam->sensor->addr; 831 + ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip); 833 832 if (ret) 834 833 goto out; 834 + cam->sensor_type = chip.ident; 835 835 // if (cam->sensor->addr != OV7xx0_SID) { 836 836 if (cam->sensor_type != V4L2_IDENT_OV7670) { 837 837 cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);
+5 -4
drivers/media/video/cx25840/cx25840-core.c
··· 35 35 #include <linux/videodev2.h> 36 36 #include <linux/i2c.h> 37 37 #include <media/v4l2-common.h> 38 + #include <media/v4l2-chip-ident.h> 38 39 #include <media/cx25840.h> 39 40 40 41 #include "cx25840-core.h" ··· 828 827 cx25840_initialize(client, 0); 829 828 break; 830 829 831 - case VIDIOC_INT_G_CHIP_IDENT: 832 - *(enum v4l2_chip_ident *)arg = state->id; 833 - break; 830 + case VIDIOC_G_CHIP_IDENT: 831 + return v4l2_chip_ident_i2c_client(client, arg, state->id, state->rev); 834 832 835 833 default: 836 834 return -EINVAL; ··· 847 847 { 848 848 struct i2c_client *client; 849 849 struct cx25840_state *state; 850 - enum v4l2_chip_ident id; 850 + u32 id; 851 851 u16 device_id; 852 852 853 853 /* Check if the adapter supports the needed features ··· 902 902 state->audmode = V4L2_TUNER_MODE_LANG1; 903 903 state->vbi_line_offset = 8; 904 904 state->id = id; 905 + state->rev = device_id; 905 906 906 907 i2c_attach_client(client); 907 908
+2 -1
drivers/media/video/cx25840/cx25840-core.h
··· 43 43 u32 audclk_freq; 44 44 int audmode; 45 45 int vbi_line_offset; 46 - enum v4l2_chip_ident id; 46 + u32 id; 47 + u32 rev; 47 48 int is_cx25836; 48 49 }; 49 50
+3 -3
drivers/media/video/ov7670.c
··· 15 15 #include <linux/delay.h> 16 16 #include <linux/videodev.h> 17 17 #include <media/v4l2-common.h> 18 + #include <media/v4l2-chip-ident.h> 18 19 #include <linux/i2c.h> 19 20 20 21 ··· 1271 1270 void *arg) 1272 1271 { 1273 1272 switch (cmd) { 1274 - case VIDIOC_INT_G_CHIP_IDENT: 1275 - * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670; 1276 - return 0; 1273 + case VIDIOC_G_CHIP_IDENT: 1274 + return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0); 1277 1275 1278 1276 case VIDIOC_INT_RESET: 1279 1277 ov7670_reset(client);
+4 -5
drivers/media/video/saa7115.c
··· 45 45 #include <linux/i2c.h> 46 46 #include <linux/videodev2.h> 47 47 #include <media/v4l2-common.h> 48 + #include <media/v4l2-chip-ident.h> 48 49 #include <media/saa7115.h> 49 50 #include <asm/div64.h> 50 51 ··· 81 80 int sat; 82 81 int width; 83 82 int height; 84 - enum v4l2_chip_ident ident; 83 + u32 ident; 85 84 u32 audclk_freq; 86 85 u32 crystal_freq; 87 86 u8 ucgc; ··· 1233 1232 static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *arg) 1234 1233 { 1235 1234 struct saa711x_state *state = i2c_get_clientdata(client); 1236 - int *iarg = arg; 1237 1235 1238 1236 /* ioctls to allow direct access to the saa7115 registers for testing */ 1239 1237 switch (cmd) { ··· 1437 1437 } 1438 1438 #endif 1439 1439 1440 - case VIDIOC_INT_G_CHIP_IDENT: 1441 - *iarg = state->ident; 1442 - break; 1440 + case VIDIOC_G_CHIP_IDENT: 1441 + return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); 1443 1442 1444 1443 default: 1445 1444 return -EINVAL;
+4 -4
drivers/media/video/saa7127.c
··· 54 54 #include <linux/i2c.h> 55 55 #include <linux/videodev2.h> 56 56 #include <media/v4l2-common.h> 57 + #include <media/v4l2-chip-ident.h> 57 58 #include <media/saa7127.h> 58 59 59 60 static int debug = 0; ··· 235 234 236 235 struct saa7127_state { 237 236 v4l2_std_id std; 238 - enum v4l2_chip_ident ident; 237 + u32 ident; 239 238 enum saa7127_input_type input_type; 240 239 enum saa7127_output_type output_type; 241 240 int video_enable; ··· 651 650 break; 652 651 } 653 652 654 - case VIDIOC_INT_G_CHIP_IDENT: 655 - *(enum v4l2_chip_ident *)arg = state->ident; 656 - break; 653 + case VIDIOC_G_CHIP_IDENT: 654 + return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); 657 655 658 656 default: 659 657 return -EINVAL;
+20 -1
drivers/media/video/v4l2-common.c
··· 60 60 #include <linux/video_decoder.h> 61 61 #define __OLD_VIDIOC_ /* To allow fixing old calls*/ 62 62 #include <media/v4l2-common.h> 63 + #include <media/v4l2-chip-ident.h> 63 64 64 65 #ifdef CONFIG_KMOD 65 66 #include <linux/kmod.h> ··· 384 383 385 384 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", 386 385 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", 386 + 387 + [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT", 387 388 #endif 388 389 }; 389 390 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) ··· 416 413 [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", 417 414 [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA", 418 415 [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA", 419 - [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT", 420 416 [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ", 421 417 [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY", 422 418 [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", ··· 983 981 } 984 982 } 985 983 984 + int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, 985 + u32 ident, u32 revision) 986 + { 987 + if (!v4l2_chip_match_i2c_client(c, chip->match_type, chip->match_chip)) 988 + return 0; 989 + if (chip->ident == V4L2_IDENT_NONE) { 990 + chip->ident = ident; 991 + chip->revision = revision; 992 + } 993 + else { 994 + chip->ident = V4L2_IDENT_AMBIGUOUS; 995 + chip->revision = 0; 996 + } 997 + return 0; 998 + } 999 + 986 1000 int v4l2_chip_match_host(u32 match_type, u32 match_chip) 987 1001 { 988 1002 switch (match_type) { ··· 1033 1015 EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); 1034 1016 1035 1017 EXPORT_SYMBOL(v4l2_chip_match_i2c_client); 1018 + EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); 1036 1019 EXPORT_SYMBOL(v4l2_chip_match_host); 1037 1020 1038 1021 /*
+10
drivers/media/video/videodev.c
··· 1532 1532 break; 1533 1533 } 1534 1534 #endif 1535 + case VIDIOC_G_CHIP_IDENT: 1536 + { 1537 + struct v4l2_chip_ident *p=arg; 1538 + if (!vfd->vidioc_g_chip_ident) 1539 + break; 1540 + ret=vfd->vidioc_g_chip_ident(file, fh, p); 1541 + if (!ret) 1542 + dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); 1543 + break; 1544 + } 1535 1545 } /* switch */ 1536 1546 1537 1547 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+10
include/linux/videodev2.h
··· 1398 1398 __u64 val; 1399 1399 }; 1400 1400 1401 + /* VIDIOC_G_CHIP_IDENT */ 1402 + struct v4l2_chip_ident { 1403 + __u32 match_type; /* Match type */ 1404 + __u32 match_chip; /* Match this chip, meaning determined by match_type */ 1405 + __u32 ident; /* chip identifier as specified in <media/v4l2-chip-ident.h> */ 1406 + __u32 revision; /* chip revision, chip specific */ 1407 + }; 1408 + 1401 1409 /* 1402 1410 * 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 1403 1411 * ··· 1479 1471 /* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ 1480 1472 #define VIDIOC_DBG_S_REGISTER _IOW ('V', 79, struct v4l2_register) 1481 1473 #define VIDIOC_DBG_G_REGISTER _IOWR ('V', 80, struct v4l2_register) 1474 + 1475 + #define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident) 1482 1476 #endif 1483 1477 1484 1478 #ifdef __OLD_VIDIOC_
+62
include/media/v4l2-chip-ident.h
··· 1 + /* 2 + v4l2 chip identifiers header 3 + 4 + This header provides a list of chip identifiers that can be returned 5 + through the VIDIOC_G_CHIP_IDENT ioctl. 6 + 7 + Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 8 + 9 + This program is free software; you can redistribute it and/or modify 10 + it under the terms of the GNU General Public License as published by 11 + the Free Software Foundation; either version 2 of the License, or 12 + (at your option) any later version. 13 + 14 + This program is distributed in the hope that it will be useful, 15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + GNU General Public License for more details. 18 + 19 + You should have received a copy of the GNU General Public License 20 + along with this program; if not, write to the Free Software 21 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 + */ 23 + 24 + #ifndef V4L2_CHIP_IDENT_H_ 25 + #define V4L2_CHIP_IDENT_H_ 26 + 27 + /* VIDIOC_G_CHIP_IDENT: identifies the actual chip installed on the board */ 28 + enum { 29 + /* general idents: reserved range 0-49 */ 30 + V4L2_IDENT_NONE = 0, /* No chip matched */ 31 + V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */ 32 + V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */ 33 + 34 + /* module saa7110: just ident= 100 */ 35 + V4L2_IDENT_SAA7110 = 100, 36 + 37 + /* module saa7111: just ident= 101 */ 38 + V4L2_IDENT_SAA7111 = 101, 39 + 40 + /* module saa7115: reserved range 102-149 */ 41 + V4L2_IDENT_SAA7113 = 103, 42 + V4L2_IDENT_SAA7114 = 104, 43 + V4L2_IDENT_SAA7115 = 105, 44 + V4L2_IDENT_SAA7118 = 108, 45 + 46 + /* module saa7127: reserved range 150-199 */ 47 + V4L2_IDENT_SAA7127 = 157, 48 + V4L2_IDENT_SAA7129 = 159, 49 + 50 + /* module cx25840: reserved range 200-249 */ 51 + V4L2_IDENT_CX25836 = 236, 52 + V4L2_IDENT_CX25837 = 237, 53 + V4L2_IDENT_CX25840 = 240, 54 + V4L2_IDENT_CX25841 = 241, 55 + V4L2_IDENT_CX25842 = 242, 56 + V4L2_IDENT_CX25843 = 243, 57 + 58 + /* OmniVision sensors - range 250-299 */ 59 + V4L2_IDENT_OV7670 = 250, 60 + }; 61 + 62 + #endif
+2 -37
include/media/v4l2-common.h
··· 98 98 99 99 struct i2c_client; /* forward reference */ 100 100 int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id); 101 + int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, 102 + u32 ident, u32 revision); 101 103 int v4l2_chip_match_host(u32 id_type, u32 chip_id); 102 104 103 105 /* ------------------------------------------------------------------------- */ ··· 114 112 On exit points to the start of the payload. */ 115 113 u32 line; /* Line number of the sliced VBI data (1-23) */ 116 114 u32 type; /* VBI service type (V4L2_SLICED_*). 0 if no service found */ 117 - }; 118 - 119 - /* VIDIOC_INT_G_CHIP_IDENT: identifies the actual chip installed on the board */ 120 - enum v4l2_chip_ident { 121 - /* general idents: reserved range 0-49 */ 122 - V4L2_IDENT_UNKNOWN = 0, 123 - 124 - /* module saa7110: just ident= 100 */ 125 - V4L2_IDENT_SAA7110 = 100, 126 - 127 - /* module saa7111: just ident= 101 */ 128 - V4L2_IDENT_SAA7111 = 101, 129 - 130 - /* module saa7115: reserved range 102-149 */ 131 - V4L2_IDENT_SAA7113 = 103, 132 - V4L2_IDENT_SAA7114 = 104, 133 - V4L2_IDENT_SAA7115 = 105, 134 - V4L2_IDENT_SAA7118 = 108, 135 - 136 - /* module saa7127: reserved range 150-199 */ 137 - V4L2_IDENT_SAA7127 = 157, 138 - V4L2_IDENT_SAA7129 = 159, 139 - 140 - /* module cx25840: reserved range 200-249 */ 141 - V4L2_IDENT_CX25836 = 236, 142 - V4L2_IDENT_CX25837 = 237, 143 - V4L2_IDENT_CX25840 = 240, 144 - V4L2_IDENT_CX25841 = 241, 145 - V4L2_IDENT_CX25842 = 242, 146 - V4L2_IDENT_CX25843 = 243, 147 - 148 - /* OmniVision sensors - range 250-299 */ 149 - V4L2_IDENT_OV7670 = 250, 150 115 }; 151 116 152 117 /* audio ioctls */ ··· 176 207 you must fill in the 'id' member and the 'field' member (to determine 177 208 whether CC data from the first or second field should be obtained). */ 178 209 #define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data) 179 - 180 - /* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can 181 - be made. */ 182 - #define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident) 183 210 184 211 /* Sets I2S speed in bps. This is used to provide a standard way to select I2S 185 212 clock used by driving digital audio streams at some board designs.
+2
include/media/v4l2-dev.h
··· 317 317 int (*vidioc_s_register) (struct file *file, void *fh, 318 318 struct v4l2_register *reg); 319 319 #endif 320 + int (*vidioc_g_chip_ident) (struct file *file, void *fh, 321 + struct v4l2_chip_ident *chip); 320 322 321 323 322 324 #ifdef OBSOLETE_OWNER /* to be removed soon */