From 4cbca185e9adf3d48205b60bf196ebb9882af043 Mon Sep 17 00:00:00 2001 From: Marco Schluessler Date: Sun, 21 Jan 2007 19:43:38 -0300 Subject: V4L/DVB (5113): Adds video output routing Nexus CA needs to use a different routing on saa7115 module. Signed-off-by: Marco Schluessler Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c2374ed7ba9..389e518bc3e 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -71,6 +71,7 @@ I2C_CLIENT_INSMOD; struct saa711x_state { v4l2_std_id std; int input; + int output; int enable; int radio; int bright; @@ -1301,7 +1302,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar struct v4l2_routing *route = arg; route->input = state->input; - route->output = 0; + route->output = state->output; break; } @@ -1309,7 +1310,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "decoder set input %d\n", route->input); + v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); /* saa7113 does not have these inputs */ if (state->ident == V4L2_IDENT_SAA7113 && (route->input == SAA7115_COMPOSITE4 || @@ -1318,10 +1319,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar } if (route->input > SAA7115_SVIDEO3) return -EINVAL; - if (state->input == route->input) + if (route->output > SAA7115_IPORT_ON) + return -EINVAL; + if (state->input == route->input && state->output == route->output) break; - v4l_dbg(1, debug, client, "now setting %s input\n", - (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite"); + v4l_dbg(1, debug, client, "now setting %s input %s output\n", + (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); state->input = route->input; /* select mode */ @@ -1333,6 +1336,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar saa711x_write(client, R_09_LUMA_CNTL, (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); + + state->output = route->output; + if (state->ident == V4L2_IDENT_SAA7114 || + state->ident == V4L2_IDENT_SAA7115) { + saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, + (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | + (state->output & 0x01)); + } break; } @@ -1492,6 +1503,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) return -ENOMEM; } state->input = -1; + state->output = SAA7115_IPORT_ON; state->enable = 1; state->radio = 0; state->bright = 128; @@ -1550,7 +1562,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) static int saa711x_probe(struct i2c_adapter *adapter) { - if (adapter->class & I2C_CLASS_TV_ANALOG) + if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL) return i2c_probe(adapter, &addr_data, &saa711x_attach); return 0; } -- cgit v1.2.3-70-g09d2 From 52ebc763d8e0c9f2ab48af89a75e90e2318bac86 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 23 Jan 2007 22:38:13 -0300 Subject: V4L/DVB (5146): Make VIDIOC_INT_[SG]_REGISTER ioctls no longer internal only The direct register access ioctls were defined as kernel internal only, but they are very useful for debugging hardware from userspace and are used as such. Officially export them. VIDIOC_INT_[SG]_REGISTER is renamed to VIDIOC_DBG_[SG]_REGISTER Definition of ioctl and struct v4l2_register is moved from v4l2-common.h to videodev2.h. Types used in struct v4l2_register are changed to the userspace exportable versions (u32 -> __u32, etc). Use of VIDIOC_DBG_S_REGISTER requires CAP_SYS_ADMIN permission, so move the check into the video_ioctl2() dispatcher so it doesn't need to be duplicated in each driver's call-back function. CAP_SYS_ADMIN check is added to pvrusb2 (which doesn't use video_ioctl2). Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 4 ++-- drivers/media/video/cx88/cx88-video.c | 2 -- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +++--- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 14 +++++++++----- drivers/media/video/saa7115.c | 4 ++-- drivers/media/video/saa7127.c | 4 ++-- drivers/media/video/tvp5150.c | 4 ++-- drivers/media/video/upd64031a.c | 4 ++-- drivers/media/video/upd64083.c | 4 ++-- drivers/media/video/usbvision/usbvision-video.c | 12 ++++++------ drivers/media/video/v4l2-common.c | 11 ++++++----- drivers/media/video/videodev.c | 8 +++++--- include/linux/videodev2.h | 14 ++++++++++++++ include/media/v4l2-common.h | 11 +---------- include/media/v4l2-dev.h | 3 --- 16 files changed, 57 insertions(+), 50 deletions(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 7bb7589a07c..6515b2a7841 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -628,7 +628,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, #ifdef CONFIG_VIDEO_ADV_DEBUG /* ioctls to allow direct access to the * cx25840 registers for testing */ - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -638,7 +638,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ee8cbd33cfc..f6736eb786b 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1405,8 +1405,6 @@ static int vidioc_s_register (struct file *file, void *fh, if (reg->i2c_id != 0) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx_write(reg->reg&0xffffff, reg->val); return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 5e166ed19fc..2a350755bd3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3277,7 +3277,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 chip_id,unsigned long reg_id, + u32 chip_id, u32 reg_id, int setFl,u32 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -3295,8 +3295,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, cp = list_entry(item,struct pvr2_i2c_client,list); if (cp->client->driver->id != chip_id) continue; stat = pvr2_i2c_client_cmd( - cp,(setFl ? VIDIOC_INT_S_REGISTER : - VIDIOC_INT_G_REGISTER),&req); + cp,(setFl ? VIDIOC_DBG_S_REGISTER : + VIDIOC_DBG_G_REGISTER),&req); if (!setFl) *val_ptr = req.val; okFl = !0; break; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index dc7a3ba8dd1..e6df8e4a7fe 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -222,7 +222,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 chip_id,unsigned long reg_id, + u32 chip_id,u32 reg_id, int setFl,u32 *val_ptr); /* The following entry points are all lower level things you normally don't diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 49f5d3c3614..cde5f5f3e8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -738,16 +738,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, break; } #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: + if (!capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + break; + } /* fall through */ + case VIDIOC_DBG_G_REGISTER: { u32 val; struct v4l2_register *req = (struct v4l2_register *)arg; - if (cmd == VIDIOC_INT_S_REGISTER) val = req->val; + if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( hdw,req->i2c_id,req->reg, - cmd == VIDIOC_INT_S_REGISTER,&val); - if (cmd == VIDIOC_INT_G_REGISTER) req->val = val; + cmd == VIDIOC_DBG_S_REGISTER,&val); + if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; } #endif diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 389e518bc3e..bb6aa135002 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1417,7 +1417,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar } #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -1427,7 +1427,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index ad401bdefea..304375ade4a 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -614,7 +614,7 @@ static int saa7127_command(struct i2c_client *client, break; #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -624,7 +624,7 @@ static int saa7127_command(struct i2c_client *client, break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index bc0a4fc27b2..65d4389690a 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -950,7 +950,7 @@ static int tvp5150_command(struct i2c_client *c, } #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -960,7 +960,7 @@ static int tvp5150_command(struct i2c_client *c, break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index fc52201d607..0eee82ba52b 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -162,7 +162,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * break; #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -172,7 +172,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; u8 addr = reg->reg & 0xff; diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index c3a7ffe5c26..3f0eec0cdb4 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -139,7 +139,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a break; #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; @@ -149,7 +149,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; u8 addr = reg->reg & 0xff; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 82c39767ba3..b6fabeeb8ab 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -519,7 +519,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_VIDEO_ADV_DEBUG /* ioctls to allow direct acces to the NT100x registers */ - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *reg = arg; int errCode; @@ -529,17 +529,17 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, /* NT100x has a 8-bit register space */ errCode = usbvision_read_reg(usbvision, reg->reg&0xff); if (errCode < 0) { - err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); + err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", __FUNCTION__, errCode); } else { reg->val=(unsigned char)errCode; - PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", + PDEBUG(DBG_IOCTL, "VIDIOC_DBG_G_REGISTER reg=0x%02X, value=0x%02X", (unsigned int)reg->reg, reg->val); errCode = 0; // No error } return errCode; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; int errCode; @@ -550,10 +550,10 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, return -EPERM; errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { - err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); + err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode); } else { - PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", + PDEBUG(DBG_IOCTL, "VIDIOC_DBG_S_REGISTER reg=0x%02X, value=0x%02X", (unsigned int)reg->reg, reg->val); errCode = 0; } diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index dab87512b9b..d20d4ca5d8a 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -400,9 +400,10 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", + [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", - [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER", - [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER", [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", @@ -753,11 +754,11 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) p->id,p->index,p->name); break; } - case VIDIOC_INT_G_REGISTER: - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *p=arg; - printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s, + printk ("%s: i2c_id=%d, reg=%d, val=%d\n", s, p->i2c_id,p->reg,p->val); break; diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 4b5d5f771e4..764a53b70db 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1454,17 +1454,19 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, break; } #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_INT_G_REGISTER: + case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *p=arg; if (vfd->vidioc_g_register) ret=vfd->vidioc_g_register(file, fh, p); break; } - case VIDIOC_INT_S_REGISTER: + case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *p=arg; - if (vfd->vidioc_s_register) + if (!capable(CAP_SYS_ADMIN)) + ret=-EPERM; + else if (vfd->vidioc_s_register) ret=vfd->vidioc_s_register(file, fh, p); break; } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 112b28c1f63..fe6ccdfa9d4 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1270,6 +1270,17 @@ struct v4l2_streamparm } parm; }; +/* + * A D V A N C E D D E B U G G I N G + */ + +/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ +struct v4l2_register { + __u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */ + __u32 reg; + __u32 val; +}; + /* * 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 * @@ -1339,6 +1350,9 @@ struct v4l2_streamparm #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum) #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum) #endif +/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ +#define VIDIOC_DBG_S_REGISTER _IOW ('d', 100, struct v4l2_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('d', 101, struct v4l2_register) #ifdef __OLD_VIDIOC_ /* for compatibility, will go away some day */ diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 91b19921f95..959e6f6a4ef 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -99,13 +99,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* Internal ioctls */ -/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */ -struct v4l2_register { - u32 i2c_id; /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */ - unsigned long reg; - u32 val; -}; - /* VIDIOC_INT_DECODE_VBI_LINE */ struct v4l2_decode_vbi_line { u32 is_second_field; /* Set to 0 for the first (odd) field, @@ -175,9 +168,7 @@ enum v4l2_chip_ident { Replacement of TUNER_SET_STANDBY. */ #define VIDIOC_INT_S_STANDBY _IOW('d', 94, u32) -/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ -#define VIDIOC_INT_S_REGISTER _IOW ('d', 100, struct v4l2_register) -#define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register) +/* 100, 101 used by VIDIOC_DBG_[SG]_REGISTER */ /* Generic reset command. The argument selects which subsystems to reset. Passing 0 will always reset the whole chip. */ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 46eb71f5653..aeec56992ef 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -77,9 +77,6 @@ int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); -/* Forward definition of v4l2-common.h defined structure */ -struct v4l2_register; - /* * Newer version of video_device, handled by videodev2.c * This version moves redundant code from video device code to -- cgit v1.2.3-70-g09d2 From 62d50addf0774115adaa9e01e09099c3d7daa13d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 30 Jan 2007 23:25:41 -0300 Subject: V4L/DVB (5163): Add checks for CAP_SYS_ADMIN to VIDIOC_DBG_G_REGISTER Before, root privileges were only needed to set hardware registers, not to read them. On some hardware, reading from the wrong place at the wrong time can hang the machine. So, to be consistent, root privileges are required to read registers on all hardware. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 14 +++------ drivers/media/video/saa7115.c | 14 +++------ drivers/media/video/saa7127.c | 14 +++------ drivers/media/video/tvp5150.c | 14 +++------ drivers/media/video/upd64031a.c | 16 +++------- drivers/media/video/upd64083.c | 16 +++------- drivers/media/video/usbvision/usbvision-video.c | 40 +++++++++---------------- drivers/media/video/videodev.c | 4 ++- 8 files changed, 41 insertions(+), 91 deletions(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 6515b2a7841..92357772329 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -629,15 +629,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, /* ioctls to allow direct access to the * cx25840 registers for testing */ case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_CX25840) - return -EINVAL; - reg->val = cx25840_read(client, reg->reg & 0x0fff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -646,7 +637,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = cx25840_read(client, reg->reg & 0x0fff); + else + cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index bb6aa135002..71777216b60 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1418,15 +1418,6 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_SAA711X) - return -EINVAL; - reg->val = saa711x_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -1435,7 +1426,10 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = saa711x_read(client, reg->reg & 0xff); + else + saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 304375ade4a..bd9c4f3ad02 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -615,15 +615,6 @@ static int saa7127_command(struct i2c_client *client, #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_SAA7127) - return -EINVAL; - reg->val = saa7127_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -632,7 +623,10 @@ static int saa7127_command(struct i2c_client *client, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = saa7127_read(client, reg->reg & 0xff); + else + saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 65d4389690a..886b5df7c9d 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -951,15 +951,6 @@ static int tvp5150_command(struct i2c_client *c, #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_TVP5150) - return -EINVAL; - reg->val = tvp5150_read(c, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -968,7 +959,10 @@ static int tvp5150_command(struct i2c_client *c, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = tvp5150_read(c, reg->reg & 0xff); + else + tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 0eee82ba52b..b3b5fd536dc 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -163,26 +163,18 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) - return -EINVAL; - reg->val = upd64031a_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; - u8 addr = reg->reg & 0xff; - u8 val = reg->val & 0xff; if (reg->i2c_id != I2C_DRIVERID_UPD64031A) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - upd64031a_write(client, addr, val); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = upd64031a_read(client, reg->reg & 0xff); + else + upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 3f0eec0cdb4..8852903e7a9 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -140,26 +140,18 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_UPD64083) - return -EINVAL; - reg->val = upd64083_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; - u8 addr = reg->reg & 0xff; - u8 val = reg->val & 0xff; if (reg->i2c_id != I2C_DRIVERID_UPD64083) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - upd64083_write(client, addr, val); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = upd64083_read(client, reg->reg & 0xff); + else + upd64083_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b6fabeeb8ab..6a61ebcdf13 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -520,25 +520,6 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_VIDEO_ADV_DEBUG /* ioctls to allow direct acces to the NT100x registers */ case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (reg->i2c_id != 0) - return -EINVAL; - /* NT100x has a 8-bit register space */ - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - if (errCode < 0) { - err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - reg->val=(unsigned char)errCode; - PDEBUG(DBG_IOCTL, "VIDIOC_DBG_G_REGISTER reg=0x%02X, value=0x%02X", - (unsigned int)reg->reg, reg->val); - errCode = 0; // No error - } - return errCode; - } case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -548,15 +529,22 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + /* NT100x has a 8-bit register space */ + if (cmd == VIDIOC_DBG_G_REGISTER) + errCode = usbvision_read_reg(usbvision, reg->reg&0xff); + else + errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { - err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - PDEBUG(DBG_IOCTL, "VIDIOC_DBG_S_REGISTER reg=0x%02X, value=0x%02X", - (unsigned int)reg->reg, reg->val); - errCode = 0; + err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__, + cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode); + return errCode; } + if (cmd == VIDIOC_DBG_S_REGISTER) + reg->val = (u8)errCode; + + PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", + cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', + (unsigned int)reg->reg, reg->val); return 0; } #endif diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 764a53b70db..dc9b1ef678a 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1457,7 +1457,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *p=arg; - if (vfd->vidioc_g_register) + if (!capable(CAP_SYS_ADMIN)) + ret=-EPERM; + else if (vfd->vidioc_g_register) ret=vfd->vidioc_g_register(file, fh, p); break; } -- cgit v1.2.3-70-g09d2 From faeb4ab38f6fec62d50a023e1778d13e73a0b088 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 3 Feb 2007 06:35:07 -0300 Subject: V4L/DVB (5183): Fix CC handling in VIDIOC_INT_G_VBI_DATA When capturing a 60 Hz input the internal field ID is inverted. The VIDIOC_INT_G_VBI_DATA didn't take that into account and so returned XDS instead of CC and vice versa. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 71777216b60..c4f066d6668 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1388,6 +1388,9 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_sliced_vbi_data *data = arg; + /* Note: the internal field ID is inverted for NTSC, + so data->field 0 maps to the saa7115 even field, + whereas for PAL it maps to the saa7115 odd field. */ switch (data->id) { case V4L2_SLICED_WSS_625: if (saa711x_read(client, 0x6b) & 0xc0) @@ -1398,17 +1401,17 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar case V4L2_SLICED_CAPTION_525: if (data->field == 0) { /* CC */ - if (saa711x_read(client, 0x66) & 0xc0) + if (saa711x_read(client, 0x66) & 0x30) return -EIO; - data->data[0] = saa711x_read(client, 0x67); - data->data[1] = saa711x_read(client, 0x68); + data->data[0] = saa711x_read(client, 0x69); + data->data[1] = saa711x_read(client, 0x6a); return 0; } /* XDS */ - if (saa711x_read(client, 0x66) & 0x30) + if (saa711x_read(client, 0x66) & 0xc0) return -EIO; - data->data[0] = saa711x_read(client, 0x69); - data->data[1] = saa711x_read(client, 0x6a); + data->data[0] = saa711x_read(client, 0x67); + data->data[1] = saa711x_read(client, 0x68); return 0; default: return -EINVAL; -- cgit v1.2.3-70-g09d2 From f3d092b84a855c44914fea0648695bef7d751266 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 23 Feb 2007 20:55:14 -0300 Subject: V4L/DVB (5304): Improve chip matching in v4l2_register The chip matching in struct v4l2_register for VIDIOC_DBG_G/S_REGISTER was rather primitive. It could not be extended to other busses besides i2c and it lacked a way to. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 2 +- drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 +++++---- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 7 +++--- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 ++-- drivers/media/video/saa7115.c | 2 +- drivers/media/video/saa7127.c | 2 +- drivers/media/video/tvp5150.c | 2 +- drivers/media/video/upd64031a.c | 2 +- drivers/media/video/upd64083.c | 2 +- drivers/media/video/usbvision/usbvision-video.c | 4 ++-- drivers/media/video/v4l2-common.c | 30 +++++++++++++++++++++++++ include/linux/videodev2.h | 11 +++++++-- include/media/v4l2-common.h | 8 +++++++ 14 files changed, 70 insertions(+), 21 deletions(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 3ff5fc00c09..774d2536555 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -633,7 +633,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_CX25840) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a97be1bdc31..bdfe2af7012 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1389,7 +1389,7 @@ static int vidioc_g_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* cx2388x has a 24-bit register space */ reg->val = cx_read(reg->reg&0xffffff); @@ -1401,7 +1401,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx_write(reg->reg&0xffffff, reg->val); return 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a1ca0f5007e..1cd4bb3ae26 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3256,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 chip_id, u64 reg_id, - int setFl,u32 *val_ptr) + u32 match_type, u32 match_chip, u64 reg_id, + int setFl,u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct list_head *item; @@ -3268,13 +3268,16 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.i2c_id = chip_id; + req.match_type = match_type; + req.match_chip = match_chip; req.reg = reg_id; if (setFl) req.val = *val_ptr; mutex_lock(&hdw->i2c_list_lock); do { list_for_each(item,&hdw->i2c_clients) { cp = list_entry(item,struct pvr2_i2c_client,list); - if (cp->client->driver->id != chip_id) continue; + if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) { + continue; + } stat = pvr2_i2c_client_cmd( cp,(setFl ? VIDIOC_DBG_S_REGISTER : VIDIOC_DBG_G_REGISTER),&req); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 566a8ef7e12..0c9cca43ff8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -217,13 +217,14 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); /* Direct read/write access to chip's registers: - chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) + match_type - how to interpret match_chip (e.g. driver ID, i2c address) + match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) reg_id - register number to access setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 chip_id,u64 reg_id, - int setFl,u32 *val_ptr); + u32 match_type, u32 match_chip,u64 reg_id, + int setFl,u64 *val_ptr); /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4fe4136204c..5313d342666 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -740,11 +740,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: { - u32 val; + u64 val; struct v4l2_register *req = (struct v4l2_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( - hdw,req->i2c_id,req->reg, + hdw,req->match_type,req->match_chip,req->reg, cmd == VIDIOC_DBG_S_REGISTER,&val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c4f066d6668..7735b675892 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1425,7 +1425,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA711X) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bd9c4f3ad02..654863db159 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -619,7 +619,7 @@ static int saa7127_command(struct i2c_client *client, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA7127) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 886b5df7c9d..d5ec05f56ad 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -955,7 +955,7 @@ static int tvp5150_command(struct i2c_client *c, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_TVP5150) + if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index b3b5fd536dc..28d1133a3b7 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -167,7 +167,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 8852903e7a9..fe38224150d 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -144,7 +144,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64083) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index ae5f42562c0..6fc14557d62 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -521,7 +521,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_register *reg = arg; int errCode; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -540,7 +540,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, reg->val); + (unsigned int)reg->reg, (unsigned int)reg->val); return 0; } #endif diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index ddfd80c5618..3506cb66711 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -947,6 +948,32 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) return **ctrl_classes; } +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_ALWAYS: + return 1; + case V4L2_CHIP_MATCH_I2C_DRIVER: + return (c != NULL && c->driver != NULL && c->driver->id == match_chip); + case V4L2_CHIP_MATCH_I2C_ADDR: + return (c != NULL && c->addr == match_chip); + default: + return 0; + } +} + +int v4l2_chip_match_host(u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_ALWAYS: + return 1; + case V4L2_CHIP_MATCH_HOST: + return match_chip == 0; + default: + return 0; + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_norm_to_name); @@ -970,6 +997,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); EXPORT_SYMBOL(v4l2_ctrl_query_fill); EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); +EXPORT_SYMBOL(v4l2_chip_match_i2c_client); +EXPORT_SYMBOL(v4l2_chip_match_host); + /* * Local variables: * c-basic-offset: 8 diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65a165f918c..e3ab047f90e 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1306,10 +1306,17 @@ struct v4l2_streamparm */ /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_ALWAYS 0 /* Match always (match_chip is not used) */ +#define V4L2_CHIP_MATCH_HOST 1 /* Match against chip ID on host (0 for the host) */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 2 /* Match against I2C driver ID */ +#define V4L2_CHIP_MATCH_I2C_ADDR 3 /* Match against I2C 7-bit address */ + struct v4l2_register { + __u32 match_type; /* Match type */ + __u32 match_chip; /* Match this chip, meaning determined by match_type */ __u64 reg; - __u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */ - __u32 val; + __u64 val; }; /* diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 244e440edb5..6eaeec98ed8 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -94,6 +94,14 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ +/* Register/chip ident helper function */ + +struct i2c_client; /* forward reference */ +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id); +int v4l2_chip_match_host(u32 id_type, u32 chip_id); + +/* ------------------------------------------------------------------------- */ + /* Internal ioctls */ /* VIDIOC_INT_DECODE_VBI_LINE */ -- cgit v1.2.3-70-g09d2 From a9aaec4e83e687d23b78b38e331bbd6a10b96380 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 13 Mar 2007 13:41:49 -0300 Subject: V4L/DVB (5408): Fix SECAM handling on saa7115 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 7735b675892..4d5bbd859de 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -961,7 +961,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) reg |= 0x10; } else if (std == V4L2_STD_NTSC_M_JP) { reg |= 0x40; - } else if (std == V4L2_STD_SECAM) { + } else if (std & V4L2_STD_SECAM) { reg |= 0x50; } saa711x_write(client, R_0E_CHROMA_CNTL_1, reg); -- cgit v1.2.3-70-g09d2 From 3434eb7e14d9587ee56f3462bcfa5726b62dadb9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 27 Apr 2007 12:31:08 -0300 Subject: 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 8 +++- drivers/media/video/cx25840/cx25840-core.c | 9 +++-- drivers/media/video/cx25840/cx25840-core.h | 3 +- drivers/media/video/ov7670.c | 6 +-- drivers/media/video/saa7115.c | 9 ++--- drivers/media/video/saa7127.c | 8 ++-- drivers/media/video/v4l2-common.c | 21 +++++++++- drivers/media/video/videodev.c | 10 +++++ include/linux/videodev2.h | 10 +++++ include/media/v4l2-chip-ident.h | 62 ++++++++++++++++++++++++++++++ include/media/v4l2-common.h | 39 +------------------ include/media/v4l2-dev.h | 2 + 12 files changed, 130 insertions(+), 57 deletions(-) create mode 100644 include/media/v4l2-chip-ident.h (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 710c11a6829..4d4db7b2b61 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 774d2536555..1757a588970 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #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); diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 28049064dd7..f4b56d2fd6b 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -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; }; diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 5ed0adc4ca2..5234762c542 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -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); diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 4d5bbd859de..26c9b64c748 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 50dbb76d4a7..9f986930490 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -54,6 +54,7 @@ #include #include #include +#include #include 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; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 4a3635cd6f9..49f1df74aa2 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -60,6 +60,7 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include +#include #ifdef CONFIG_KMOD #include @@ -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); /* diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5c9f2116d7b..fdfef0b5331 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -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) { diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a08ef2c1630..a25c2afa67e 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -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 */ + __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 index 00000000000..f6686ce133d --- /dev/null +++ b/include/media/v4l2-chip-ident.h @@ -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 + + 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 diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index abb9ce9b21b..181a40c46a5 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -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. diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2693f3ae6ff..d62847f846c 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -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 */ -- cgit v1.2.3-70-g09d2 From 1e5e9aab31d3f73977d2b14189a0bb08b582cbb9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 10 Mar 2007 20:11:23 -0300 Subject: V4L/DVB (5414): Add missing kfree in early exit of saa7115. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video/saa7115.c') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 26c9b64c748..2d18f006982 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1486,6 +1486,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) if (memcmp(name, "1f711", 5)) { v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", address << 1, name); + kfree(client); return 0; } -- cgit v1.2.3-70-g09d2