From 1dc1829e27ce5205f46a65e63d9bc7f2bf3dc1a9 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 20 Feb 2007 19:32:08 +0100 Subject: added support for deferred module requesting to cx88 From: Markus Rechberger added support for deferred module requesting to cx88 Signed-off-by: Markus Rechberger --- linux/drivers/media/video/cx88/cx88-mpeg.c | 44 ++++++++++++++++++++++++++++++ linux/drivers/media/video/cx88/cx88.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index f90a9e7fd..c7b5a2081 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -56,6 +56,47 @@ MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); #define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) +#if defined(CONFIG_MODULES) && defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void request_module_async(void *ptr){ + struct cx8802_dev *dev=(struct cx8802_dev*)ptr; +#else +static void request_module_async(struct work_struct *work){ + struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); +#endif + switch (cx88_boards[dev->core->board].mpeg) { + case CX88_MPEG_BLACKBIRD: + request_module("cx88-blackbird"); + break; + case CX88_MPEG_DVB: + request_module("cx88-dvb"); + break; + case CX88_BOARD_NONE: + /* reaching this one isn't possible */ + break; + default: + printk("cx88-mpeg.c: WARNING extension [%d] is not supposed to be supported\n",cx88_boards[dev->core->board].mpeg); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define request_modules(dev) +#else +static void request_modules(struct cx8802_dev *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&dev->request_module_wk, request_module_async, (void*)dev); +#else + INIT_WORK(&dev->request_module_wk, request_module_async); +#endif + schedule_work(&dev->request_module_wk); +} +#endif +#else +#define request_modules(dev) +#endif /* CONFIG_MODULES */ + + static LIST_HEAD(cx8802_devlist); /* ------------------------------------------------------------------ */ @@ -823,6 +864,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, /* Maintain a reference so cx88-video can query the 8802 device. */ core->dvbdev = dev; + + /* now autoload cx88-dvb or cx88-blackbird */ + request_modules(dev); return 0; fail_free: diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 8a8b58f99..4719046e1 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -514,6 +514,8 @@ struct cx8802_dev { /* List of attached drivers */ struct cx8802_driver drvlist; + struct work_struct request_module_wk; + }; /* ----------------------------------------------------------- */ -- cgit v1.2.3 From ddbfb0b75082cb12cbd091238eac94a3c8145135 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 20 Feb 2007 19:51:54 +0100 Subject: added support for loading cx88-dvb and cx88-blackbird From: Markus Rechberger added support for loading cx88-dvb and cx88-blackbird Signed-off-by: Markus Rechberger --- linux/drivers/media/video/cx88/cx88-mpeg.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index c7b5a2081..39a556c63 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -64,19 +64,11 @@ static void request_module_async(void *ptr){ static void request_module_async(struct work_struct *work){ struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); #endif - switch (cx88_boards[dev->core->board].mpeg) { - case CX88_MPEG_BLACKBIRD: - request_module("cx88-blackbird"); - break; - case CX88_MPEG_DVB: + + if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB) request_module("cx88-dvb"); - break; - case CX88_BOARD_NONE: - /* reaching this one isn't possible */ - break; - default: - printk("cx88-mpeg.c: WARNING extension [%d] is not supposed to be supported\n",cx88_boards[dev->core->board].mpeg); - } + if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD) + request_module("cx88-blackbird"); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -- cgit v1.2.3 From b64c80be829fbeb8b936ca6d61a59013d8ad2bba Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Wed, 21 Feb 2007 19:56:50 +0100 Subject: coding style changes From: Markus Rechberger coding style changes Signed-off-by: Markus Rechberger --- linux/drivers/media/video/cx88/cx88-mpeg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 39a556c63..cb642ca03 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -58,10 +58,12 @@ MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); #if defined(CONFIG_MODULES) && defined(MODULE) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void request_module_async(void *ptr){ +static void request_module_async(void *ptr) +{ struct cx8802_dev *dev=(struct cx8802_dev*)ptr; #else -static void request_module_async(struct work_struct *work){ +static void request_module_async(struct work_struct *work) +{ struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); #endif -- cgit v1.2.3 From f253110d360e84ef2572d6cde588352b40072db9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 23 Feb 2007 22:29:23 +0100 Subject: Mark V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY as experimental From: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/include/linux/videodev2.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 769b37bd3..69577c73d 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -145,7 +145,10 @@ enum v4l2_buf_type { V4L2_BUF_TYPE_VBI_OUTPUT = 5, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, +#if 1 /*KEEP*/ + /* Experimental */ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, +#endif V4L2_BUF_TYPE_PRIVATE = 0x80, }; -- cgit v1.2.3 From 834c26ef6c6e90c342478b0ce181bd0c91af4062 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 23 Feb 2007 22:29:51 +0100 Subject: Rename 'x, y' to 'left, top' to be consistent with struct v4l2_rect. From: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/include/linux/videodev2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 69577c73d..588c7694d 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -267,8 +267,8 @@ struct v4l2_pix_format __u32 sizeimage; enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ - __u32 x; /* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */ - __u32 y; /* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */ + __u32 left; /* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */ + __u32 top; /* only valid if V4L2_CAP_VIDEO_OUTPUT_POS is set */ }; /* Pixel format FOURCC depth Description */ -- cgit v1.2.3 From 547bf60a782e5d6397e4ed6c001bd1ae0633d8f0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 24 Feb 2007 00:55:14 +0100 Subject: Improve chip matching in v4l2_register for VIDIOC_DBG_G/S_REGISTER From: Hans Verkuil 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 CC: Mike Isely CC: Trent Piepho --- linux/drivers/media/video/cx25840/cx25840-core.c | 2 +- linux/drivers/media/video/cx88/cx88-video.c | 4 +-- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 ++++--- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 7 +++-- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 +-- linux/drivers/media/video/saa7115.c | 2 +- linux/drivers/media/video/saa7127.c | 2 +- linux/drivers/media/video/tvp5150.c | 2 +- linux/drivers/media/video/upd64031a.c | 2 +- linux/drivers/media/video/upd64083.c | 2 +- .../media/video/usbvision/usbvision-video.c | 4 +-- linux/drivers/media/video/v4l2-common.c | 35 ++++++++++++++++++++-- linux/include/linux/videodev2.h | 11 +++++-- linux/include/media/v4l2-common.h | 8 +++++ 14 files changed, 73 insertions(+), 23 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 #include #include +#include #include #include #include @@ -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 diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 588c7694d..6a4123620 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1384,10 +1384,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/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index 08a002966..e5a73cc08 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -100,6 +100,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 From f3e6f8836e980f471dbd3e9746a40199cd121f72 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 24 Feb 2007 01:16:01 +0100 Subject: Mark VIDIOC_DBG_S/G_REGISTER as experimental, but no longer internal From: Hans Verkuil Move VIDIOC_DBG_S/G_REGISTER from the internal ioctl list to the public ioctls, but mark it as experimental for now. Signed-off-by: Hans Verkuil CC: Trent Piepho --- linux/drivers/media/video/v4l2-common.c | 8 ++++---- linux/include/linux/videodev2.h | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 9d0df66e9..6df4d7ea1 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -406,7 +406,10 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", - [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD" + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", #endif }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -431,9 +434,6 @@ 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_RESET)] = "VIDIOC_INT_RESET", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 6a4123620..4977ae997 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1381,6 +1381,8 @@ struct v4l2_streamparm /* * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API */ /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ @@ -1466,10 +1468,11 @@ struct v4l2_register { #define VIDIOC_G_ENC_INDEX _IOR ('V', 76, struct v4l2_enc_idx) #define VIDIOC_ENCODER_CMD _IOWR ('V', 77, struct v4l2_encoder_cmd) #define VIDIOC_TRY_ENCODER_CMD _IOWR ('V', 78, struct v4l2_encoder_cmd) + +/* 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) #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 */ -- cgit v1.2.3 From 2be3674b75c83865e9a131c6c54aaee005df47ed Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 24 Feb 2007 01:27:26 +0100 Subject: Add support for VIDIOC_G_CHIP_IDENT From: Hans Verkuil 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 CC: Jonathan Corbet --- linux/drivers/media/video/cafe_ccic.c | 7 ++- linux/drivers/media/video/cx25840/cx25840-core.c | 15 ++++-- linux/drivers/media/video/cx25840/cx25840-core.h | 3 +- linux/drivers/media/video/ov7670.c | 12 ++++- linux/drivers/media/video/saa7115.c | 15 ++++-- linux/drivers/media/video/saa7127.c | 14 ++++-- linux/drivers/media/video/v4l2-common.c | 3 +- linux/drivers/media/video/videodev.c | 10 ++++ linux/include/linux/videodev2.h | 10 ++++ linux/include/media/v4l2-chip-ident.h | 60 ++++++++++++++++++++++++ linux/include/media/v4l2-common.h | 37 --------------- linux/include/media/v4l2-dev.h | 2 + 12 files changed, 135 insertions(+), 53 deletions(-) create mode 100644 linux/include/media/v4l2-chip-ident.h diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index a21d1b5b7..5f35836ad 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -23,6 +23,7 @@ #include #include "compat.h" #include +#include #include #include #include @@ -165,7 +166,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 */ @@ -825,6 +826,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_ALWAYS }; int ret; mutex_lock(&cam->s_mutex); @@ -834,9 +836,10 @@ 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); + 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/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 5fafe6b23..d5a0789bc 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "compat.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -838,9 +839,16 @@ 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; + case VIDIOC_G_CHIP_IDENT: + { + struct v4l2_chip_ident *chip = arg; + + if (!v4l2_chip_match_i2c_client(client, chip->match_type, chip->match_chip)) + return -EINVAL; + chip->ident = state->id; + chip->revision = state->rev; break; + } default: return -EINVAL; @@ -861,7 +869,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 @@ -923,6 +931,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/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index 2bfedc95d..bcb624124 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -44,7 +44,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/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index 1fee42eaa..d68f36851 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -16,6 +16,7 @@ #include #include "compat.h" #include +#include #include @@ -1314,9 +1315,16 @@ 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; + case VIDIOC_G_CHIP_IDENT: + { + struct v4l2_chip_ident *chip = arg; + + if (!v4l2_chip_match_i2c_client(client, chip->match_type, chip->match_chip)) + return -EINVAL; + chip->ident = V4L2_IDENT_OV7670; + chip->revision = 0; return 0; + } case VIDIOC_INT_RESET: ov7670_reset(client); diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 8e92c91ed..8b4abb3a1 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" @@ -91,7 +92,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; @@ -1243,7 +1244,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) { @@ -1448,9 +1448,16 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar } #endif - case VIDIOC_INT_G_CHIP_IDENT: - *iarg = state->ident; + case VIDIOC_G_CHIP_IDENT: + { + struct v4l2_chip_ident *chip = arg; + + if (!v4l2_chip_match_i2c_client(client, chip->match_type, chip->match_chip)) + return -EINVAL; + chip->ident = state->ident; + chip->revision = 0; break; + } default: return -EINVAL; diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 455c6f74a..28306f15d 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" @@ -246,7 +247,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; @@ -662,9 +663,16 @@ static int saa7127_command(struct i2c_client *client, break; } - case VIDIOC_INT_G_CHIP_IDENT: - *(enum v4l2_chip_ident *)arg = state->ident; + case VIDIOC_G_CHIP_IDENT: + { + struct v4l2_chip_ident *chip = arg; + + if (!v4l2_chip_match_i2c_client(client, chip->match_type, chip->match_chip)) + return -EINVAL; + chip->ident = state->ident; + chip->revision = 0; break; + } default: return -EINVAL; diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 6df4d7ea1..b2d57d888 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -410,6 +410,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) @@ -440,7 +442,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", diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c index b1cd0bb72..acb3c4fbf 100644 --- a/linux/drivers/media/video/videodev.c +++ b/linux/drivers/media/video/videodev.c @@ -1555,6 +1555,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/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 4977ae997..8a5aabb84 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1399,6 +1399,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 * @@ -1472,6 +1480,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/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h new file mode 100644 index 000000000..67a34d528 --- /dev/null +++ b/linux/include/media/v4l2-chip-ident.h @@ -0,0 +1,60 @@ +/* + 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_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, +}; + +#endif diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index e5a73cc08..cc2ab055a 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -120,39 +120,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 */ @@ -214,10 +181,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/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index f3c230f3c..c24d96af7 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -329,6 +329,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); #if 0 /* old, obsolete interface */ int (*open)(struct video_device *, int mode); -- cgit v1.2.3