summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2007-02-24 00:55:14 +0100
committerHans Verkuil <hverkuil@xs4all.nl>2007-02-24 00:55:14 +0100
commit547bf60a782e5d6397e4ed6c001bd1ae0633d8f0 (patch)
treed5723ea3f30bbf1d07cd8a3725ec886b43b6e3e2 /linux/drivers/media
parent834c26ef6c6e90c342478b0ce181bd0c91af4062 (diff)
downloadmediapointer-dvb-s2-547bf60a782e5d6397e4ed6c001bd1ae0633d8f0.tar.gz
mediapointer-dvb-s2-547bf60a782e5d6397e4ed6c001bd1ae0633d8f0.tar.bz2
Improve chip matching in v4l2_register for VIDIOC_DBG_G/S_REGISTER
From: Hans Verkuil <hverkuil@xs4all.nl> The chip matching in struct v4l2_register was rather primitive. It could not be extended to other busses besides i2c and it lacked a way to differentiate between two i2c chips driven by the same driver on one board (e.g. a PVR500 with two tuner chips, one for analog TV and one for radio). It has now been improved making it much more powerful. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> CC: Mike Isely <isely@isely.net> CC: Trent Piepho <xyzzy@speakeasy.org>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/video/cx25840/cx25840-core.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c11
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h7
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c4
-rw-r--r--linux/drivers/media/video/saa7115.c2
-rw-r--r--linux/drivers/media/video/saa7127.c2
-rw-r--r--linux/drivers/media/video/tvp5150.c2
-rw-r--r--linux/drivers/media/video/upd64031a.c2
-rw-r--r--linux/drivers/media/video/upd64083.c2
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-video.c4
-rw-r--r--linux/drivers/media/video/v4l2-common.c35
12 files changed, 56 insertions, 21 deletions
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c
index 75dbba700..5fafe6b23 100644
--- a/linux/drivers/media/video/cx25840/cx25840-core.c
+++ b/linux/drivers/media/video/cx25840/cx25840-core.c
@@ -644,7 +644,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/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index 2af3f3d2c..2e6259ceb 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1670,7 +1670,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);
@@ -1682,7 +1682,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/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 1f7586078..c5b238694 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -3369,8 +3369,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;
@@ -3381,13 +3381,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/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index aa45114ba..319dab523 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -226,13 +226,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/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 992269abd..9f2f11754 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -741,11 +741,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/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c
index d868920de..8e92c91ed 100644
--- a/linux/drivers/media/video/saa7115.c
+++ b/linux/drivers/media/video/saa7115.c
@@ -1436,7 +1436,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/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c
index 89a889591..455c6f74a 100644
--- a/linux/drivers/media/video/saa7127.c
+++ b/linux/drivers/media/video/saa7127.c
@@ -631,7 +631,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/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c
index 46b97d9b1..1e7c25ba0 100644
--- a/linux/drivers/media/video/tvp5150.c
+++ b/linux/drivers/media/video/tvp5150.c
@@ -1051,7 +1051,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/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c
index f73cb2c81..3a7db9f7a 100644
--- a/linux/drivers/media/video/upd64031a.c
+++ b/linux/drivers/media/video/upd64031a.c
@@ -175,7 +175,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/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c
index 1fdde6e06..317baed46 100644
--- a/linux/drivers/media/video/upd64083.c
+++ b/linux/drivers/media/video/upd64083.c
@@ -152,7 +152,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/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c
index a1e6b2594..89aedd783 100644
--- a/linux/drivers/media/video/usbvision/usbvision-video.c
+++ b/linux/drivers/media/video/usbvision/usbvision-video.c
@@ -561,7 +561,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;
@@ -580,7 +580,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/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index 61cf41995..9d0df66e9 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -51,6 +51,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -806,8 +807,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case VIDIOC_DBG_S_REGISTER:
{
struct v4l2_register *p=arg;
- printk ("%s: i2c_id=%d, reg=%llu, val=%u\n", s,
- p->i2c_id,(unsigned long long)p->reg,p->val);
+ printk ("%s: match_type=%d, match_chip=%d, reg=%llu, val=%llu\n", s,
+ p->match_type, p->match_chip,
+ (unsigned long long)p->reg, (unsigned long long)p->val);
break;
}
@@ -1590,6 +1592,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);
@@ -1613,6 +1641,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