Browse Source

[PATCH] USB: ZC0301 driver updates

ZC0301 driver updates.

Changes: + new, - removed, * cleanup, @ bugfix

@ Need usb_get|put_dev() when disconnecting, if the device is open
* Cleanups and updates in the documentation
+ Use per-device sensor structures
+ Add frame_timeout module parameter

Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Luca Risolia 19 years ago
parent
commit
a847423905

+ 19 - 10
Documentation/usb/zc0301.txt

@@ -68,11 +68,6 @@ Some of the features of the driver are:
   data transfers;
   data transfers;
 - automatic detection of image sensor;
 - automatic detection of image sensor;
 - video format is standard JPEG;
 - video format is standard JPEG;
-- full support for the capabilities of every possible image sensors that can
-  be connected to the ZC0301 bridges, including, for istance, red, green,
-  blue and global gain adjustments and exposure control (see "Supported
-  devices" paragraph for details);
-- use of default color settings for sunlight conditions;
 - dynamic driver control thanks to various module parameters (see "Module
 - dynamic driver control thanks to various module parameters (see "Module
   parameters" paragraph);
   parameters" paragraph);
 - up to 64 cameras can be handled at the same time; they can be connected and
 - up to 64 cameras can be handled at the same time; they can be connected and
@@ -171,6 +166,14 @@ Description:    Force the application to unmap previously mapped buffer memory
                 1 = force memory unmapping (save memory)
                 1 = force memory unmapping (save memory)
 Default:        0
 Default:        0
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
+Name:           frame_timeout
+Type:           uint array (min = 0, max = 64)
+Syntax:         <n[,...]>
+Description:    Timeout for a video frame in seconds. This parameter is
+                specific for each detected camera. This parameter can be
+                changed at runtime thanks to the /sys filesystem interface.
+Default:        2
+-------------------------------------------------------------------------------
 Name:           debug
 Name:           debug
 Type:           ushort
 Type:           ushort
 Syntax:         <n>
 Syntax:         <n>
@@ -198,17 +201,23 @@ devices mounting the ZC0301 Image Processor and Control Chips:
 
 
 Vendor ID  Product ID
 Vendor ID  Product ID
 ---------  ----------
 ---------  ----------
+0x10fd     0x8050
+0x041e     0x0417
+0x041e     0x041e
+0x041e     0x081c
+0x041e     0x0834
+0x041e     0x0835
 0x046d     0x08ae
 0x046d     0x08ae
+0x0ac8     0x0301
 
 
-The following image sensors are supported:
+The list above does not imply that all those devices work with this driver: up
+until now only the ones that mount the following image sensors are supported;
+kernel messages will always tell you whether this is the case:
 
 
 Model       Manufacturer
 Model       Manufacturer
 -----       ------------
 -----       ------------
 PAS202BCB   PixArt Imaging, Inc.
 PAS202BCB   PixArt Imaging, Inc.
 
 
-All the available control settings of each image sensor are supported through
-the V4L2 interface.
-
 
 
 9. Notes for V4L2 application developers
 9. Notes for V4L2 application developers
 ========================================
 ========================================
@@ -240,6 +249,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
 - Informations about the chip internals needed to enable the I2C protocol have
 - Informations about the chip internals needed to enable the I2C protocol have
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   by Andrew Birkett <andy@nobugs.org>;
   by Andrew Birkett <andy@nobugs.org>;
-- Initialization values of the ZC0301 controller connected to the PAS202BCB
+- The initialization values of the ZC0301 controller connected to the PAS202BCB
   image sensor have been taken from the SPCA5XX driver maintained by
   image sensor have been taken from the SPCA5XX driver maintained by
   Michel Xhaard <mxhaard@magic.fr>.
   Michel Xhaard <mxhaard@magic.fr>.

+ 15 - 5
drivers/usb/media/zc0301.h

@@ -34,7 +34,8 @@
 #include <linux/param.h>
 #include <linux/param.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/rwsem.h>
 #include <linux/rwsem.h>
-#include <asm/semaphore.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
 
 
 #include "zc0301_sensor.h"
 #include "zc0301_sensor.h"
 
 
@@ -51,7 +52,7 @@
 #define ZC0301_ALTERNATE_SETTING   7
 #define ZC0301_ALTERNATE_SETTING   7
 #define ZC0301_URB_TIMEOUT         msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
 #define ZC0301_URB_TIMEOUT         msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
 #define ZC0301_CTRL_TIMEOUT        100
 #define ZC0301_CTRL_TIMEOUT        100
-#define ZC0301_FRAME_TIMEOUT       2 * 1000 * msecs_to_jiffies(1)
+#define ZC0301_FRAME_TIMEOUT       2
 
 
 /*****************************************************************************/
 /*****************************************************************************/
 
 
@@ -94,6 +95,7 @@ enum zc0301_stream_state {
 
 
 struct zc0301_module_param {
 struct zc0301_module_param {
 	u8 force_munmap;
 	u8 force_munmap;
+	u16 frame_timeout;
 };
 };
 
 
 static DECLARE_RWSEM(zc0301_disconnect);
 static DECLARE_RWSEM(zc0301_disconnect);
@@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect);
 struct zc0301_device {
 struct zc0301_device {
 	struct video_device* v4ldev;
 	struct video_device* v4ldev;
 
 
-	struct zc0301_sensor* sensor;
+	struct zc0301_sensor sensor;
 
 
 	struct usb_device* usbdev;
 	struct usb_device* usbdev;
 	struct urb* urb[ZC0301_URBS];
 	struct urb* urb[ZC0301_URBS];
@@ -129,11 +131,19 @@ struct zc0301_device {
 
 
 /*****************************************************************************/
 /*****************************************************************************/
 
 
+struct zc0301_device*
+zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id)
+{
+	if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
+		return cam;
+
+	return NULL;
+}
+
 void
 void
 zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
 zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
 {
 {
-	cam->sensor = sensor;
-	cam->sensor->usbdev = cam->usbdev;
+	memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor));
 }
 }
 
 
 /*****************************************************************************/
 /*****************************************************************************/

+ 36 - 22
drivers/usb/media/zc0301_core.c

@@ -29,11 +29,9 @@
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
-#include <linux/stddef.h>
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
 #include <linux/poll.h>
@@ -54,8 +52,8 @@
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.01"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 1)
+#define ZC0301_MODULE_VERSION "1:1.02"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 2)
 
 
 /*****************************************************************************/
 /*****************************************************************************/
 
 
@@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap,
                  "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
                  "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
                  "\n");
                  "\n");
 
 
+static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
+                                       ZC0301_FRAME_TIMEOUT};
+module_param_array(frame_timeout, uint, NULL, 0644);
+MODULE_PARM_DESC(frame_timeout,
+                 "\n<n[,...]> Timeout for a video frame in seconds."
+                 "\nThis parameter is specific for each detected camera."
+                 "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
+                 "\n");
+
 #ifdef ZC0301_DEBUG
 #ifdef ZC0301_DEBUG
 static unsigned short debug = ZC0301_DEBUG_LEVEL;
 static unsigned short debug = ZC0301_DEBUG_LEVEL;
 module_param(debug, ushort, 0644);
 module_param(debug, ushort, 0644);
@@ -115,8 +122,8 @@ static u32
 zc0301_request_buffers(struct zc0301_device* cam, u32 count,
 zc0301_request_buffers(struct zc0301_device* cam, u32 count,
                        enum zc0301_io_method io)
                        enum zc0301_io_method io)
 {
 {
-	struct v4l2_pix_format* p = &(cam->sensor->pix_format);
-	struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
+	struct v4l2_pix_format* p = &(cam->sensor.pix_format);
+	struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
 	const size_t imagesize = cam->module_param.force_munmap ||
 	const size_t imagesize = cam->module_param.force_munmap ||
 	                         io == IO_READ ?
 	                         io == IO_READ ?
 	                         (p->width * p->height * p->priv) / 8 :
 	                         (p->width * p->height * p->priv) / 8 :
@@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
 		(*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
 		(*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
 		                  frame);
 		                  frame);
 
 
-	imagesize = (cam->sensor->pix_format.width *
-	             cam->sensor->pix_format.height *
-	             cam->sensor->pix_format.priv) / 8;
+	imagesize = (cam->sensor.pix_format.width *
+	             cam->sensor.pix_format.height *
+	             cam->sensor.pix_format.priv) / 8;
 
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 	for (i = 0; i < urb->number_of_packets; i++) {
 		unsigned int len, status;
 		unsigned int len, status;
@@ -555,7 +562,7 @@ zc0301_set_compression(struct zc0301_device* cam,
 
 
 static int zc0301_init(struct zc0301_device* cam)
 static int zc0301_init(struct zc0301_device* cam)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_control ctrl;
 	struct v4l2_control ctrl;
 	struct v4l2_queryctrl *qctrl;
 	struct v4l2_queryctrl *qctrl;
 	struct v4l2_rect* rect;
 	struct v4l2_rect* rect;
@@ -630,6 +637,7 @@ static void zc0301_release_resources(struct zc0301_device* cam)
 	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
 	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_unregister_device(cam->v4ldev);
 	video_unregister_device(cam->v4ldev);
+	usb_put_dev(cam->usbdev);
 	kfree(cam->control_buffer);
 	kfree(cam->control_buffer);
 }
 }
 
 
@@ -798,7 +806,8 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
 		            (!list_empty(&cam->outqueue)) ||
 		            (!list_empty(&cam->outqueue)) ||
 		            (cam->state & DEV_DISCONNECTED) ||
 		            (cam->state & DEV_DISCONNECTED) ||
 		            (cam->state & DEV_MISCONFIGURED),
 		            (cam->state & DEV_MISCONFIGURED),
-		            ZC0301_FRAME_TIMEOUT );
+		            cam->module_param.frame_timeout *
+		            1000 * msecs_to_jiffies(1) );
 		if (timeout < 0) {
 		if (timeout < 0) {
 			mutex_unlock(&cam->fileop_mutex);
 			mutex_unlock(&cam->fileop_mutex);
 			return timeout;
 			return timeout;
@@ -1056,7 +1065,7 @@ zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg)
 static int
 static int
 zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_queryctrl qc;
 	struct v4l2_queryctrl qc;
 	u8 i;
 	u8 i;
 
 
@@ -1078,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
 static int
 static int
 zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_control ctrl;
 	struct v4l2_control ctrl;
 	int err = 0;
 	int err = 0;
 	u8 i;
 	u8 i;
@@ -1110,7 +1119,7 @@ exit:
 static int
 static int
 zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_control ctrl;
 	struct v4l2_control ctrl;
 	u8 i;
 	u8 i;
 	int err = 0;
 	int err = 0;
@@ -1123,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 
 
 	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 		if (ctrl.id == s->qctrl[i].id) {
 		if (ctrl.id == s->qctrl[i].id) {
+			if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
+				return -EINVAL;
 			if (ctrl.value < s->qctrl[i].minimum ||
 			if (ctrl.value < s->qctrl[i].minimum ||
 			    ctrl.value > s->qctrl[i].maximum)
 			    ctrl.value > s->qctrl[i].maximum)
 				return -ERANGE;
 				return -ERANGE;
@@ -1142,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 static int
 static int
 zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+	struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
 
 
 	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	cc->pixelaspect.numerator = 1;
 	cc->pixelaspect.numerator = 1;
@@ -1158,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
 static int
 static int
 zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_crop crop = {
 	struct v4l2_crop crop = {
 		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
 		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
 	};
 	};
@@ -1175,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
 static int
 static int
 zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_crop crop;
 	struct v4l2_crop crop;
 	struct v4l2_rect* rect;
 	struct v4l2_rect* rect;
 	struct v4l2_rect* bounds = &(s->cropcap.bounds);
 	struct v4l2_rect* bounds = &(s->cropcap.bounds);
@@ -1304,7 +1315,7 @@ static int
 zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
 zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
 {
 {
 	struct v4l2_format format;
 	struct v4l2_format format;
-	struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+	struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
 
 
 	if (copy_from_user(&format, arg, sizeof(format)))
 	if (copy_from_user(&format, arg, sizeof(format)))
 		return -EFAULT;
 		return -EFAULT;
@@ -1328,7 +1339,7 @@ static int
 zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
 zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
                         void __user * arg)
                         void __user * arg)
 {
 {
-	struct zc0301_sensor* s = cam->sensor;
+	struct zc0301_sensor* s = &cam->sensor;
 	struct v4l2_format format;
 	struct v4l2_format format;
 	struct v4l2_pix_format* pix;
 	struct v4l2_pix_format* pix;
 	struct v4l2_pix_format* pfmt = &(s->pix_format);
 	struct v4l2_pix_format* pfmt = &(s->pix_format);
@@ -1612,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp,
 		            (!list_empty(&cam->outqueue)) ||
 		            (!list_empty(&cam->outqueue)) ||
 		            (cam->state & DEV_DISCONNECTED) ||
 		            (cam->state & DEV_DISCONNECTED) ||
 		            (cam->state & DEV_MISCONFIGURED),
 		            (cam->state & DEV_MISCONFIGURED),
-		            ZC0301_FRAME_TIMEOUT );
+		            cam->module_param.frame_timeout *
+		            1000 * msecs_to_jiffies(1) );
 		if (timeout < 0)
 		if (timeout < 0)
 			return timeout;
 			return timeout;
 		if (cam->state & DEV_DISCONNECTED)
 		if (cam->state & DEV_DISCONNECTED)
@@ -1911,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 			break;
 			break;
 	}
 	}
 
 
-	if (!err && cam->sensor)
-		DBG(2, "%s image sensor detected", cam->sensor->name);
+	if (!err)
+		DBG(2, "%s image sensor detected", cam->sensor.name);
 	else {
 	else {
 		DBG(1, "No supported image sensor detected");
 		DBG(1, "No supported image sensor detected");
 		err = -ENODEV;
 		err = -ENODEV;
@@ -1950,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
 	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
 
 
 	cam->module_param.force_munmap = force_munmap[dev_nr];
 	cam->module_param.force_munmap = force_munmap[dev_nr];
+	cam->module_param.frame_timeout = frame_timeout[dev_nr];
 
 
 	dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
 	dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
 
@@ -1994,6 +2007,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf)
 		cam->state |= DEV_DISCONNECTED;
 		cam->state |= DEV_DISCONNECTED;
 		wake_up_interruptible(&cam->wait_frame);
 		wake_up_interruptible(&cam->wait_frame);
 		wake_up(&cam->wait_stream);
 		wake_up(&cam->wait_stream);
+		usb_get_dev(cam->usbdev);
 	} else {
 	} else {
 		cam->state |= DEV_DISCONNECTED;
 		cam->state |= DEV_DISCONNECTED;
 		zc0301_release_resources(cam);
 		zc0301_release_resources(cam);

+ 23 - 15
drivers/usb/media/zc0301_pas202bcb.c

@@ -22,6 +22,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
  ***************************************************************************/
 
 
+/*
+   NOTE: Sensor controls are disabled for now, becouse changing them while
+         streaming sometimes results in out-of-sync video frames. We'll use
+         the default initialization, until we know how to stop and start video
+         in the chip. However, the image quality still looks good under various
+         light conditions.
+*/
+
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include "zc0301_sensor.h"
 #include "zc0301_sensor.h"
 
 
@@ -245,7 +253,7 @@ static struct zc0301_sensor pas202bcb = {
 			.maximum = 0x3fff,
 			.maximum = 0x3fff,
 			.step = 0x0001,
 			.step = 0x0001,
 			.default_value = 0x01e5,
 			.default_value = 0x01e5,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
 		},
 		},
 		{
 		{
 			.id = V4L2_CID_GAIN,
 			.id = V4L2_CID_GAIN,
@@ -255,7 +263,17 @@ static struct zc0301_sensor pas202bcb = {
 			.maximum = 0x1f,
 			.maximum = 0x1f,
 			.step = 0x01,
 			.step = 0x01,
 			.default_value = 0x0c,
 			.default_value = 0x0c,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
+		},
+		{
+			.id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "DAC magnitude",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
 		},
 		},
 		{
 		{
 			.id = V4L2_CID_RED_BALANCE,
 			.id = V4L2_CID_RED_BALANCE,
@@ -265,7 +283,7 @@ static struct zc0301_sensor pas202bcb = {
 			.maximum = 0x0f,
 			.maximum = 0x0f,
 			.step = 0x01,
 			.step = 0x01,
 			.default_value = 0x01,
 			.default_value = 0x01,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
 		},
 		},
 		{
 		{
 			.id = V4L2_CID_BLUE_BALANCE,
 			.id = V4L2_CID_BLUE_BALANCE,
@@ -275,7 +293,7 @@ static struct zc0301_sensor pas202bcb = {
 			.maximum = 0x0f,
 			.maximum = 0x0f,
 			.step = 0x01,
 			.step = 0x01,
 			.default_value = 0x05,
 			.default_value = 0x05,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
 		},
 		},
 		{
 		{
 			.id = ZC0301_V4L2_CID_GREEN_BALANCE,
 			.id = ZC0301_V4L2_CID_GREEN_BALANCE,
@@ -285,17 +303,7 @@ static struct zc0301_sensor pas202bcb = {
 			.maximum = 0x0f,
 			.maximum = 0x0f,
 			.step = 0x01,
 			.step = 0x01,
 			.default_value = 0x00,
 			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "DAC magnitude",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x04,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_DISABLED,
 		},
 		},
 	},
 	},
 	.get_ctrl = &pas202bcb_get_ctrl,
 	.get_ctrl = &pas202bcb_get_ctrl,

+ 15 - 10
drivers/usb/media/zc0301_sensor.h

@@ -43,9 +43,11 @@ static int (*zc0301_sensor_table[])(struct zc0301_device*) = {                \
 	NULL,                                                                 \
 	NULL,                                                                 \
 };
 };
 
 
+extern struct zc0301_device*
+zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id);
+
 extern void
 extern void
-zc0301_attach_sensor(struct zc0301_device* cam,
-                       struct zc0301_sensor* sensor);
+zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
 
 
 #define ZC0301_USB_DEVICE(vend, prod, intclass)                               \
 #define ZC0301_USB_DEVICE(vend, prod, intclass)                               \
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
@@ -56,7 +58,14 @@ zc0301_attach_sensor(struct zc0301_device* cam,
 
 
 #define ZC0301_ID_TABLE                                                       \
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
+	{ ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */          \
+	{ ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), },                         \
+	{ ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */           \
+	{ ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */            \
+	{ ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */            \
+	{ ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */            \
 	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */         \
 	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */         \
+	{ ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), },                         \
 	{ }                                                                   \
 	{ }                                                                   \
 };
 };
 
 
@@ -80,15 +89,11 @@ struct zc0301_sensor {
 	struct v4l2_cropcap cropcap;
 	struct v4l2_cropcap cropcap;
 	struct v4l2_pix_format pix_format;
 	struct v4l2_pix_format pix_format;
 
 
-	int (*init)(struct zc0301_device* cam);
-	int (*get_ctrl)(struct zc0301_device* cam,
-	                struct v4l2_control* ctrl);
-	int (*set_ctrl)(struct zc0301_device* cam,
+	int (*init)(struct zc0301_device*);
+	int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl);
+	int (*set_ctrl)(struct zc0301_device*,
 	                const struct v4l2_control* ctrl);
 	                const struct v4l2_control* ctrl);
-	int (*set_crop)(struct zc0301_device* cam,
-	                const struct v4l2_rect* rect);
-
-	const struct usb_device* usbdev;
+	int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect);
 
 
 	/* Private */
 	/* Private */
 	struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS];
 	struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS];