aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2006-02-25 01:50:47 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 17:49:59 -0500
commit2ffab02fea5880da284dc5511479b25a796a8dee (patch)
treeb94481244ae823598d06cd72472b9c76e9639bd1
parent7039f4224d4e40b06308d5c1a97427af1a142459 (diff)
[PATCH] USB: SN9C10x driver updates
SN9C10x driver updates. Changes: + new, - removed, * cleanup, @ bugfix @ Fix stream_interrupt() @ Fix vidioc_enum_input() and split vidioc_gs_input() @ Need usb_get|put_dev() when disconnecting, if the device is open * Use wait_event_interruptible_timeout() instead of wait_event_interruptible() when waiting for video frames * replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream) * Cleanups and updates in the documentation + Use per-device sensor structures + Add support for PAS202BCA image sensors + Add frame_timeout module parameter Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/usb/sn9c102.txt11
-rw-r--r--drivers/usb/media/Makefile5
-rw-r--r--drivers/usb/media/sn9c102.h23
-rw-r--r--drivers/usb/media/sn9c102_core.c170
-rw-r--r--drivers/usb/media/sn9c102_ov7630.c33
-rw-r--r--drivers/usb/media/sn9c102_pas202bca.c238
-rw-r--r--drivers/usb/media/sn9c102_pas202bcb.c2
-rw-r--r--drivers/usb/media/sn9c102_sensor.h15
-rw-r--r--drivers/usb/media/sn9c102_tas5110c1b.c14
-rw-r--r--drivers/usb/media/sn9c102_tas5130d1b.c12
10 files changed, 416 insertions, 107 deletions
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index c6b76414172c..b957beae5607 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -196,6 +196,14 @@ Description: Force the application to unmap previously mapped buffer memory
196 1 = force memory unmapping (save memory) 196 1 = force memory unmapping (save memory)
197Default: 0 197Default: 0
198------------------------------------------------------------------------------- 198-------------------------------------------------------------------------------
199Name: frame_timeout
200Type: uint array (min = 0, max = 64)
201Syntax: <n[,...]>
202Description: Timeout for a video frame in seconds. This parameter is
203 specific for each detected camera. This parameter can be
204 changed at runtime thanks to the /sys filesystem interface.
205Default: 2
206-------------------------------------------------------------------------------
199Name: debug 207Name: debug
200Type: ushort 208Type: ushort
201Syntax: <n> 209Syntax: <n>
@@ -321,6 +329,7 @@ Vendor ID Product ID
321--------- ---------- 329--------- ----------
3220x0c45 0x6001 3300x0c45 0x6001
3230x0c45 0x6005 3310x0c45 0x6005
3320x0c45 0x6007
3240x0c45 0x6009 3330x0c45 0x6009
3250x0c45 0x600d 3340x0c45 0x600d
3260x0c45 0x6024 3350x0c45 0x6024
@@ -370,6 +379,7 @@ HV7131D Hynix Semiconductor, Inc.
370MI-0343 Micron Technology, Inc. 379MI-0343 Micron Technology, Inc.
371OV7630 OmniVision Technologies, Inc. 380OV7630 OmniVision Technologies, Inc.
372PAS106B PixArt Imaging, Inc. 381PAS106B PixArt Imaging, Inc.
382PAS202BCA PixArt Imaging, Inc.
373PAS202BCB PixArt Imaging, Inc. 383PAS202BCB PixArt Imaging, Inc.
374TAS5110C1B Taiwan Advanced Sensor Corporation 384TAS5110C1B Taiwan Advanced Sensor Corporation
375TAS5130D1B Taiwan Advanced Sensor Corporation 385TAS5130D1B Taiwan Advanced Sensor Corporation
@@ -493,6 +503,7 @@ Many thanks to following persons for their contribute (listed in alphabetical
493order): 503order):
494 504
495- Luca Capello for the donation of a webcam; 505- Luca Capello for the donation of a webcam;
506- Philippe Coval for having helped testing the PAS202BCA image sensor;
496- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the 507- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
497 donation of a webcam; 508 donation of a webcam;
498- Jon Hollstrom for the donation of a webcam; 509- Jon Hollstrom for the donation of a webcam;
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 333bf09ca2d6..50e89a33b85e 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -2,7 +2,10 @@
2# Makefile for USB Media drivers 2# Makefile for USB Media drivers
3# 3#
4 4
5sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o 5sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
6 sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
7 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
8 sn9c102_tas5130d1b.o
6et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o 9et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
7zc0301-objs := zc0301_core.o zc0301_pas202bcb.o 10zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
8 11
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index 59e44be27cb4..1d70a62b9f23 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -34,7 +34,8 @@
34#include <linux/param.h> 34#include <linux/param.h>
35#include <linux/rwsem.h> 35#include <linux/rwsem.h>
36#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <asm/semaphore.h> 37#include <linux/string.h>
38#include <linux/stddef.h>
38 39
39#include "sn9c102_sensor.h" 40#include "sn9c102_sensor.h"
40 41
@@ -51,6 +52,7 @@
51#define SN9C102_ALTERNATE_SETTING 8 52#define SN9C102_ALTERNATE_SETTING 8
52#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) 53#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
53#define SN9C102_CTRL_TIMEOUT 300 54#define SN9C102_CTRL_TIMEOUT 300
55#define SN9C102_FRAME_TIMEOUT 2
54 56
55/*****************************************************************************/ 57/*****************************************************************************/
56 58
@@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr {
108 110
109struct sn9c102_module_param { 111struct sn9c102_module_param {
110 u8 force_munmap; 112 u8 force_munmap;
113 u16 frame_timeout;
111}; 114};
112 115
113static DEFINE_MUTEX(sn9c102_sysfs_lock); 116static DEFINE_MUTEX(sn9c102_sysfs_lock);
@@ -117,7 +120,7 @@ struct sn9c102_device {
117 struct video_device* v4ldev; 120 struct video_device* v4ldev;
118 121
119 enum sn9c102_bridge bridge; 122 enum sn9c102_bridge bridge;
120 struct sn9c102_sensor* sensor; 123 struct sn9c102_sensor sensor;
121 124
122 struct usb_device* usbdev; 125 struct usb_device* usbdev;
123 struct urb* urb[SN9C102_URBS]; 126 struct urb* urb[SN9C102_URBS];
@@ -149,12 +152,21 @@ struct sn9c102_device {
149 152
150/*****************************************************************************/ 153/*****************************************************************************/
151 154
155struct sn9c102_device*
156sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
157{
158 if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
159 return cam;
160
161 return NULL;
162}
163
164
152void 165void
153sn9c102_attach_sensor(struct sn9c102_device* cam, 166sn9c102_attach_sensor(struct sn9c102_device* cam,
154 struct sn9c102_sensor* sensor) 167 struct sn9c102_sensor* sensor)
155{ 168{
156 cam->sensor = sensor; 169 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
157 cam->sensor->usbdev = cam->usbdev;
158} 170}
159 171
160/*****************************************************************************/ 172/*****************************************************************************/
@@ -197,7 +209,8 @@ do { \
197 209
198#undef PDBG 210#undef PDBG
199#define PDBG(fmt, args...) \ 211#define PDBG(fmt, args...) \
200dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) 212dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
213 __FUNCTION__, __LINE__ , ## args)
201 214
202#undef PDBGG 215#undef PDBGG
203#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ 216#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 30119080871b..4c6cc6395723 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -25,11 +25,9 @@
25#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
26#include <linux/errno.h> 26#include <linux/errno.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/string.h>
29#include <linux/device.h> 28#include <linux/device.h>
30#include <linux/fs.h> 29#include <linux/fs.h>
31#include <linux/delay.h> 30#include <linux/delay.h>
32#include <linux/stddef.h>
33#include <linux/compiler.h> 31#include <linux/compiler.h>
34#include <linux/ioctl.h> 32#include <linux/ioctl.h>
35#include <linux/poll.h> 33#include <linux/poll.h>
@@ -49,8 +47,8 @@
49#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" 47#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
50#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
51#define SN9C102_MODULE_LICENSE "GPL" 49#define SN9C102_MODULE_LICENSE "GPL"
52#define SN9C102_MODULE_VERSION "1:1.26" 50#define SN9C102_MODULE_VERSION "1:1.27"
53#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26) 51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27)
54 52
55/*****************************************************************************/ 53/*****************************************************************************/
56 54
@@ -89,6 +87,15 @@ MODULE_PARM_DESC(force_munmap,
89 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." 87 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
90 "\n"); 88 "\n");
91 89
90static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
91 SN9C102_FRAME_TIMEOUT};
92module_param_array(frame_timeout, uint, NULL, 0644);
93MODULE_PARM_DESC(frame_timeout,
94 "\n<n[,...]> Timeout for a video frame in seconds."
95 "\nThis parameter is specific for each detected camera."
96 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
97 "\n");
98
92#ifdef SN9C102_DEBUG 99#ifdef SN9C102_DEBUG
93static unsigned short debug = SN9C102_DEBUG_LEVEL; 100static unsigned short debug = SN9C102_DEBUG_LEVEL;
94module_param(debug, ushort, 0644); 101module_param(debug, ushort, 0644);
@@ -128,8 +135,8 @@ static u32
128sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, 135sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
129 enum sn9c102_io_method io) 136 enum sn9c102_io_method io)
130{ 137{
131 struct v4l2_pix_format* p = &(cam->sensor->pix_format); 138 struct v4l2_pix_format* p = &(cam->sensor.pix_format);
132 struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); 139 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
133 const size_t imagesize = cam->module_param.force_munmap || 140 const size_t imagesize = cam->module_param.force_munmap ||
134 io == IO_READ ? 141 io == IO_READ ?
135 (p->width * p->height * p->priv) / 8 : 142 (p->width * p->height * p->priv) / 8 :
@@ -449,19 +456,13 @@ sn9c102_i2c_try_write(struct sn9c102_device* cam,
449 456
450int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) 457int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
451{ 458{
452 if (!cam->sensor) 459 return sn9c102_i2c_try_read(cam, &cam->sensor, address);
453 return -1;
454
455 return sn9c102_i2c_try_read(cam, cam->sensor, address);
456} 460}
457 461
458 462
459int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) 463int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
460{ 464{
461 if (!cam->sensor) 465 return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
462 return -1;
463
464 return sn9c102_i2c_try_write(cam, cam->sensor, address, value);
465} 466}
466 467
467/*****************************************************************************/ 468/*****************************************************************************/
@@ -505,7 +506,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
505 size_t eoflen = sizeof(sn9c102_eof_header_t), i; 506 size_t eoflen = sizeof(sn9c102_eof_header_t), i;
506 unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; 507 unsigned j, n = sizeof(sn9c102_eof_header) / eoflen;
507 508
508 if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) 509 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
509 return NULL; /* EOF header does not exist in compressed data */ 510 return NULL; /* EOF header does not exist in compressed data */
510 511
511 for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) 512 for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++)
@@ -535,7 +536,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
535 if ((*f)) 536 if ((*f))
536 (*f)->state = F_QUEUED; 537 (*f)->state = F_QUEUED;
537 DBG(3, "Stream interrupted"); 538 DBG(3, "Stream interrupted");
538 wake_up_interruptible(&cam->wait_stream); 539 wake_up(&cam->wait_stream);
539 } 540 }
540 541
541 if (cam->state & DEV_DISCONNECTED) 542 if (cam->state & DEV_DISCONNECTED)
@@ -553,9 +554,9 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
553 (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, 554 (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
554 frame); 555 frame);
555 556
556 imagesize = (cam->sensor->pix_format.width * 557 imagesize = (cam->sensor.pix_format.width *
557 cam->sensor->pix_format.height * 558 cam->sensor.pix_format.height *
558 cam->sensor->pix_format.priv) / 8; 559 cam->sensor.pix_format.priv) / 8;
559 560
560 soflen = (cam->bridge) == BRIDGE_SN9C103 ? 561 soflen = (cam->bridge) == BRIDGE_SN9C103 ?
561 sizeof(sn9c103_sof_header_t) : 562 sizeof(sn9c103_sof_header_t) :
@@ -579,7 +580,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
579 580
580redo: 581redo:
581 sof = sn9c102_find_sof_header(cam, pos, len); 582 sof = sn9c102_find_sof_header(cam, pos, len);
582 if (!sof) { 583 if (likely(!sof)) {
583 eof = sn9c102_find_eof_header(cam, pos, len); 584 eof = sn9c102_find_eof_header(cam, pos, len);
584 if ((*f)->state == F_GRABBING) { 585 if ((*f)->state == F_GRABBING) {
585end_of_frame: 586end_of_frame:
@@ -589,8 +590,9 @@ end_of_frame:
589 img = (eof > pos) ? eof - pos - 1 : 0; 590 img = (eof > pos) ? eof - pos - 1 : 0;
590 591
591 if ((*f)->buf.bytesused+img > imagesize) { 592 if ((*f)->buf.bytesused+img > imagesize) {
592 u32 b = (*f)->buf.bytesused + img - 593 u32 b;
593 imagesize; 594 b = (*f)->buf.bytesused + img -
595 imagesize;
594 img = imagesize - (*f)->buf.bytesused; 596 img = imagesize - (*f)->buf.bytesused;
595 DBG(3, "Expected EOF not found: " 597 DBG(3, "Expected EOF not found: "
596 "video frame cut"); 598 "video frame cut");
@@ -608,9 +610,10 @@ end_of_frame:
608 (*f)->buf.bytesused += img; 610 (*f)->buf.bytesused += img;
609 611
610 if ((*f)->buf.bytesused == imagesize || 612 if ((*f)->buf.bytesused == imagesize ||
611 (cam->sensor->pix_format.pixelformat == 613 (cam->sensor.pix_format.pixelformat ==
612 V4L2_PIX_FMT_SN9C10X && eof)) { 614 V4L2_PIX_FMT_SN9C10X && eof)) {
613 u32 b = (*f)->buf.bytesused; 615 u32 b;
616 b = (*f)->buf.bytesused;
614 (*f)->state = F_DONE; 617 (*f)->state = F_DONE;
615 (*f)->buf.sequence= ++cam->frame_count; 618 (*f)->buf.sequence= ++cam->frame_count;
616 spin_lock(&cam->queue_lock); 619 spin_lock(&cam->queue_lock);
@@ -667,7 +670,7 @@ start_of_frame:
667 if (eof && eof < sof) 670 if (eof && eof < sof)
668 goto end_of_frame; /* (1) */ 671 goto end_of_frame; /* (1) */
669 else { 672 else {
670 if (cam->sensor->pix_format.pixelformat == 673 if (cam->sensor.pix_format.pixelformat ==
671 V4L2_PIX_FMT_SN9C10X) { 674 V4L2_PIX_FMT_SN9C10X) {
672 eof = sof - soflen; 675 eof = sof - soflen;
673 goto end_of_frame; 676 goto end_of_frame;
@@ -808,20 +811,21 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam)
808 811
809static int sn9c102_stream_interrupt(struct sn9c102_device* cam) 812static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
810{ 813{
811 int err = 0; 814 long timeout;
812 815
813 cam->stream = STREAM_INTERRUPT; 816 cam->stream = STREAM_INTERRUPT;
814 err = wait_event_timeout(cam->wait_stream, 817 timeout = wait_event_timeout(cam->wait_stream,
815 (cam->stream == STREAM_OFF) || 818 (cam->stream == STREAM_OFF) ||
816 (cam->state & DEV_DISCONNECTED), 819 (cam->state & DEV_DISCONNECTED),
817 SN9C102_URB_TIMEOUT); 820 SN9C102_URB_TIMEOUT);
818 if (cam->state & DEV_DISCONNECTED) 821 if (cam->state & DEV_DISCONNECTED)
819 return -ENODEV; 822 return -ENODEV;
820 else if (err) { 823 else if (cam->stream != STREAM_OFF) {
821 cam->state |= DEV_MISCONFIGURED; 824 cam->state |= DEV_MISCONFIGURED;
822 DBG(1, "The camera is misconfigured. To use it, close and " 825 DBG(1, "URB timeout reached. The camera is misconfigured. "
823 "open /dev/video%d again.", cam->v4ldev->minor); 826 "To use it, close and open /dev/video%d again.",
824 return err; 827 cam->v4ldev->minor);
828 return -EIO;
825 } 829 }
826 830
827 return 0; 831 return 0;
@@ -1057,7 +1061,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
1057 return -ENODEV; 1061 return -ENODEV;
1058 } 1062 }
1059 1063
1060 if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { 1064 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
1061 mutex_unlock(&sn9c102_sysfs_lock); 1065 mutex_unlock(&sn9c102_sysfs_lock);
1062 return -ENOSYS; 1066 return -ENOSYS;
1063 } 1067 }
@@ -1094,7 +1098,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
1094 return -ENODEV; 1098 return -ENODEV;
1095 } 1099 }
1096 1100
1097 if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { 1101 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
1098 mutex_unlock(&sn9c102_sysfs_lock); 1102 mutex_unlock(&sn9c102_sysfs_lock);
1099 return -ENOSYS; 1103 return -ENOSYS;
1100 } 1104 }
@@ -1249,7 +1253,7 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
1249 video_device_create_file(v4ldev, &class_device_attr_blue); 1253 video_device_create_file(v4ldev, &class_device_attr_blue);
1250 video_device_create_file(v4ldev, &class_device_attr_red); 1254 video_device_create_file(v4ldev, &class_device_attr_red);
1251 } 1255 }
1252 if (cam->sensor && cam->sensor->sysfs_ops) { 1256 if (cam->sensor.sysfs_ops) {
1253 video_device_create_file(v4ldev, &class_device_attr_i2c_reg); 1257 video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
1254 video_device_create_file(v4ldev, &class_device_attr_i2c_val); 1258 video_device_create_file(v4ldev, &class_device_attr_i2c_val);
1255 } 1259 }
@@ -1312,7 +1316,7 @@ static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
1312 1316
1313static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) 1317static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
1314{ 1318{
1315 struct sn9c102_sensor* s = cam->sensor; 1319 struct sn9c102_sensor* s = &cam->sensor;
1316 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), 1320 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
1317 v_start = (u8)(rect->top - s->cropcap.bounds.top), 1321 v_start = (u8)(rect->top - s->cropcap.bounds.top),
1318 h_size = (u8)(rect->width / 16), 1322 h_size = (u8)(rect->width / 16),
@@ -1335,7 +1339,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
1335 1339
1336static int sn9c102_init(struct sn9c102_device* cam) 1340static int sn9c102_init(struct sn9c102_device* cam)
1337{ 1341{
1338 struct sn9c102_sensor* s = cam->sensor; 1342 struct sn9c102_sensor* s = &cam->sensor;
1339 struct v4l2_control ctrl; 1343 struct v4l2_control ctrl;
1340 struct v4l2_queryctrl *qctrl; 1344 struct v4l2_queryctrl *qctrl;
1341 struct v4l2_rect* rect; 1345 struct v4l2_rect* rect;
@@ -1428,6 +1432,8 @@ static void sn9c102_release_resources(struct sn9c102_device* cam)
1428 video_set_drvdata(cam->v4ldev, NULL); 1432 video_set_drvdata(cam->v4ldev, NULL);
1429 video_unregister_device(cam->v4ldev); 1433 video_unregister_device(cam->v4ldev);
1430 1434
1435 usb_put_dev(cam->usbdev);
1436
1431 mutex_unlock(&sn9c102_sysfs_lock); 1437 mutex_unlock(&sn9c102_sysfs_lock);
1432 1438
1433 kfree(cam->control_buffer); 1439 kfree(cam->control_buffer);
@@ -1541,6 +1547,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1541 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); 1547 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
1542 struct sn9c102_frame_t* f, * i; 1548 struct sn9c102_frame_t* f, * i;
1543 unsigned long lock_flags; 1549 unsigned long lock_flags;
1550 long timeout;
1544 int err = 0; 1551 int err = 0;
1545 1552
1546 if (mutex_lock_interruptible(&cam->fileop_mutex)) 1553 if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -1592,20 +1599,22 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1592 mutex_unlock(&cam->fileop_mutex); 1599 mutex_unlock(&cam->fileop_mutex);
1593 return -EAGAIN; 1600 return -EAGAIN;
1594 } 1601 }
1595 err = wait_event_interruptible 1602 timeout = wait_event_interruptible_timeout
1596 ( cam->wait_frame, 1603 ( cam->wait_frame,
1597 (!list_empty(&cam->outqueue)) || 1604 (!list_empty(&cam->outqueue)) ||
1598 (cam->state & DEV_DISCONNECTED) || 1605 (cam->state & DEV_DISCONNECTED) ||
1599 (cam->state & DEV_MISCONFIGURED) ); 1606 (cam->state & DEV_MISCONFIGURED),
1600 if (err) { 1607 cam->module_param.frame_timeout *
1608 1000 * msecs_to_jiffies(1) );
1609 if (timeout < 0) {
1601 mutex_unlock(&cam->fileop_mutex); 1610 mutex_unlock(&cam->fileop_mutex);
1602 return err; 1611 return timeout;
1603 } 1612 }
1604 if (cam->state & DEV_DISCONNECTED) { 1613 if (cam->state & DEV_DISCONNECTED) {
1605 mutex_unlock(&cam->fileop_mutex); 1614 mutex_unlock(&cam->fileop_mutex);
1606 return -ENODEV; 1615 return -ENODEV;
1607 } 1616 }
1608 if (cam->state & DEV_MISCONFIGURED) { 1617 if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
1609 mutex_unlock(&cam->fileop_mutex); 1618 mutex_unlock(&cam->fileop_mutex);
1610 return -EIO; 1619 return -EIO;
1611 } 1620 }
@@ -1816,6 +1825,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
1816 1825
1817 memset(&i, 0, sizeof(i)); 1826 memset(&i, 0, sizeof(i));
1818 strcpy(i.name, "Camera"); 1827 strcpy(i.name, "Camera");
1828 i.type = V4L2_INPUT_TYPE_CAMERA;
1819 1829
1820 if (copy_to_user(arg, &i, sizeof(i))) 1830 if (copy_to_user(arg, &i, sizeof(i)))
1821 return -EFAULT; 1831 return -EFAULT;
@@ -1825,7 +1835,19 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
1825 1835
1826 1836
1827static int 1837static int
1828sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) 1838sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
1839{
1840 int index = 0;
1841
1842 if (copy_to_user(arg, &index, sizeof(index)))
1843 return -EFAULT;
1844
1845 return 0;
1846}
1847
1848
1849static int
1850sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
1829{ 1851{
1830 int index; 1852 int index;
1831 1853
@@ -1842,7 +1864,7 @@ sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg)
1842static int 1864static int
1843sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) 1865sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
1844{ 1866{
1845 struct sn9c102_sensor* s = cam->sensor; 1867 struct sn9c102_sensor* s = &cam->sensor;
1846 struct v4l2_queryctrl qc; 1868 struct v4l2_queryctrl qc;
1847 u8 i; 1869 u8 i;
1848 1870
@@ -1864,7 +1886,7 @@ sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
1864static int 1886static int
1865sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) 1887sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
1866{ 1888{
1867 struct sn9c102_sensor* s = cam->sensor; 1889 struct sn9c102_sensor* s = &cam->sensor;
1868 struct v4l2_control ctrl; 1890 struct v4l2_control ctrl;
1869 int err = 0; 1891 int err = 0;
1870 u8 i; 1892 u8 i;
@@ -1896,7 +1918,7 @@ exit:
1896static int 1918static int
1897sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) 1919sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
1898{ 1920{
1899 struct sn9c102_sensor* s = cam->sensor; 1921 struct sn9c102_sensor* s = &cam->sensor;
1900 struct v4l2_control ctrl; 1922 struct v4l2_control ctrl;
1901 u8 i; 1923 u8 i;
1902 int err = 0; 1924 int err = 0;
@@ -1909,6 +1931,8 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
1909 1931
1910 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) 1932 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1911 if (ctrl.id == s->qctrl[i].id) { 1933 if (ctrl.id == s->qctrl[i].id) {
1934 if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
1935 return -EINVAL;
1912 if (ctrl.value < s->qctrl[i].minimum || 1936 if (ctrl.value < s->qctrl[i].minimum ||
1913 ctrl.value > s->qctrl[i].maximum) 1937 ctrl.value > s->qctrl[i].maximum)
1914 return -ERANGE; 1938 return -ERANGE;
@@ -1931,7 +1955,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
1931static int 1955static int
1932sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) 1956sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
1933{ 1957{
1934 struct v4l2_cropcap* cc = &(cam->sensor->cropcap); 1958 struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
1935 1959
1936 cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1960 cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1937 cc->pixelaspect.numerator = 1; 1961 cc->pixelaspect.numerator = 1;
@@ -1947,7 +1971,7 @@ sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
1947static int 1971static int
1948sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) 1972sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
1949{ 1973{
1950 struct sn9c102_sensor* s = cam->sensor; 1974 struct sn9c102_sensor* s = &cam->sensor;
1951 struct v4l2_crop crop = { 1975 struct v4l2_crop crop = {
1952 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 1976 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1953 }; 1977 };
@@ -1964,7 +1988,7 @@ sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
1964static int 1988static int
1965sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) 1989sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
1966{ 1990{
1967 struct sn9c102_sensor* s = cam->sensor; 1991 struct sn9c102_sensor* s = &cam->sensor;
1968 struct v4l2_crop crop; 1992 struct v4l2_crop crop;
1969 struct v4l2_rect* rect; 1993 struct v4l2_rect* rect;
1970 struct v4l2_rect* bounds = &(s->cropcap.bounds); 1994 struct v4l2_rect* bounds = &(s->cropcap.bounds);
@@ -2105,7 +2129,7 @@ static int
2105sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) 2129sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2106{ 2130{
2107 struct v4l2_format format; 2131 struct v4l2_format format;
2108 struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); 2132 struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
2109 2133
2110 if (copy_from_user(&format, arg, sizeof(format))) 2134 if (copy_from_user(&format, arg, sizeof(format)))
2111 return -EFAULT; 2135 return -EFAULT;
@@ -2130,7 +2154,7 @@ static int
2130sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, 2154sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2131 void __user * arg) 2155 void __user * arg)
2132{ 2156{
2133 struct sn9c102_sensor* s = cam->sensor; 2157 struct sn9c102_sensor* s = &cam->sensor;
2134 struct v4l2_format format; 2158 struct v4l2_format format;
2135 struct v4l2_pix_format* pix; 2159 struct v4l2_pix_format* pix;
2136 struct v4l2_pix_format* pfmt = &(s->pix_format); 2160 struct v4l2_pix_format* pfmt = &(s->pix_format);
@@ -2417,7 +2441,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2417 struct v4l2_buffer b; 2441 struct v4l2_buffer b;
2418 struct sn9c102_frame_t *f; 2442 struct sn9c102_frame_t *f;
2419 unsigned long lock_flags; 2443 unsigned long lock_flags;
2420 int err = 0; 2444 long timeout;
2421 2445
2422 if (copy_from_user(&b, arg, sizeof(b))) 2446 if (copy_from_user(&b, arg, sizeof(b)))
2423 return -EFAULT; 2447 return -EFAULT;
@@ -2430,16 +2454,18 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2430 return -EINVAL; 2454 return -EINVAL;
2431 if (filp->f_flags & O_NONBLOCK) 2455 if (filp->f_flags & O_NONBLOCK)
2432 return -EAGAIN; 2456 return -EAGAIN;
2433 err = wait_event_interruptible 2457 timeout = wait_event_interruptible_timeout
2434 ( cam->wait_frame, 2458 ( cam->wait_frame,
2435 (!list_empty(&cam->outqueue)) || 2459 (!list_empty(&cam->outqueue)) ||
2436 (cam->state & DEV_DISCONNECTED) || 2460 (cam->state & DEV_DISCONNECTED) ||
2437 (cam->state & DEV_MISCONFIGURED) ); 2461 (cam->state & DEV_MISCONFIGURED),
2438 if (err) 2462 cam->module_param.frame_timeout *
2439 return err; 2463 1000 * msecs_to_jiffies(1) );
2464 if (timeout < 0)
2465 return timeout;
2440 if (cam->state & DEV_DISCONNECTED) 2466 if (cam->state & DEV_DISCONNECTED)
2441 return -ENODEV; 2467 return -ENODEV;
2442 if (cam->state & DEV_MISCONFIGURED) 2468 if (!timeout || (cam->state & DEV_MISCONFIGURED))
2443 return -EIO; 2469 return -EIO;
2444 } 2470 }
2445 2471
@@ -2571,8 +2597,10 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
2571 return sn9c102_vidioc_enuminput(cam, arg); 2597 return sn9c102_vidioc_enuminput(cam, arg);
2572 2598
2573 case VIDIOC_G_INPUT: 2599 case VIDIOC_G_INPUT:
2600 return sn9c102_vidioc_g_input(cam, arg);
2601
2574 case VIDIOC_S_INPUT: 2602 case VIDIOC_S_INPUT:
2575 return sn9c102_vidioc_gs_input(cam, arg); 2603 return sn9c102_vidioc_s_input(cam, arg);
2576 2604
2577 case VIDIOC_QUERYCTRL: 2605 case VIDIOC_QUERYCTRL:
2578 return sn9c102_vidioc_query_ctrl(cam, arg); 2606 return sn9c102_vidioc_query_ctrl(cam, arg);
@@ -2752,10 +2780,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2752 break; 2780 break;
2753 } 2781 }
2754 2782
2755 if (!err && cam->sensor) { 2783 if (!err) {
2756 DBG(2, "%s image sensor detected", cam->sensor->name); 2784 DBG(2, "%s image sensor detected", cam->sensor.name);
2757 DBG(3, "Support for %s maintained by %s", 2785 DBG(3, "Support for %s maintained by %s",
2758 cam->sensor->name, cam->sensor->maintainer); 2786 cam->sensor.name, cam->sensor.maintainer);
2759 } else { 2787 } else {
2760 DBG(1, "No supported image sensor detected"); 2788 DBG(1, "No supported image sensor detected");
2761 err = -ENODEV; 2789 err = -ENODEV;
@@ -2793,6 +2821,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2793 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); 2821 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
2794 2822
2795 cam->module_param.force_munmap = force_munmap[dev_nr]; 2823 cam->module_param.force_munmap = force_munmap[dev_nr];
2824 cam->module_param.frame_timeout = frame_timeout[dev_nr];
2796 2825
2797 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; 2826 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
2798 2827
@@ -2841,7 +2870,8 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
2841 sn9c102_stop_transfer(cam); 2870 sn9c102_stop_transfer(cam);
2842 cam->state |= DEV_DISCONNECTED; 2871 cam->state |= DEV_DISCONNECTED;
2843 wake_up_interruptible(&cam->wait_frame); 2872 wake_up_interruptible(&cam->wait_frame);
2844 wake_up_interruptible(&cam->wait_stream); 2873 wake_up(&cam->wait_stream);
2874 usb_get_dev(cam->usbdev);
2845 } else { 2875 } else {
2846 cam->state |= DEV_DISCONNECTED; 2876 cam->state |= DEV_DISCONNECTED;
2847 sn9c102_release_resources(cam); 2877 sn9c102_release_resources(cam);
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c
index 4a36519b5af4..42852b7cb042 100644
--- a/drivers/usb/media/sn9c102_ov7630.c
+++ b/drivers/usb/media/sn9c102_ov7630.c
@@ -34,8 +34,8 @@ static int ov7630_init(struct sn9c102_device* cam)
34 err += sn9c102_write_reg(cam, 0x0f, 0x18); 34 err += sn9c102_write_reg(cam, 0x0f, 0x18);
35 err += sn9c102_write_reg(cam, 0x50, 0x19); 35 err += sn9c102_write_reg(cam, 0x50, 0x19);
36 36
37 err += sn9c102_i2c_write(cam, 0x12, 0x8d); 37 err += sn9c102_i2c_write(cam, 0x12, 0x80);
38 err += sn9c102_i2c_write(cam, 0x11, 0x00); 38 err += sn9c102_i2c_write(cam, 0x11, 0x01);
39 err += sn9c102_i2c_write(cam, 0x15, 0x34); 39 err += sn9c102_i2c_write(cam, 0x15, 0x34);
40 err += sn9c102_i2c_write(cam, 0x16, 0x03); 40 err += sn9c102_i2c_write(cam, 0x16, 0x03);
41 err += sn9c102_i2c_write(cam, 0x17, 0x1c); 41 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
@@ -43,12 +43,14 @@ static int ov7630_init(struct sn9c102_device* cam)
43 err += sn9c102_i2c_write(cam, 0x19, 0x06); 43 err += sn9c102_i2c_write(cam, 0x19, 0x06);
44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6); 44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
45 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 45 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
46 err += sn9c102_i2c_write(cam, 0x20, 0x44); 46 err += sn9c102_i2c_write(cam, 0x20, 0xf6);
47 err += sn9c102_i2c_write(cam, 0x23, 0xee); 47 err += sn9c102_i2c_write(cam, 0x23, 0xee);
48 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 48 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
49 err += sn9c102_i2c_write(cam, 0x27, 0x9a); 49 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
50 err += sn9c102_i2c_write(cam, 0x28, 0x20); 50 err += sn9c102_i2c_write(cam, 0x28, 0xa0);
51 err += sn9c102_i2c_write(cam, 0x29, 0x30); 51 err += sn9c102_i2c_write(cam, 0x29, 0x30);
52 err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
53 err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
52 err += sn9c102_i2c_write(cam, 0x2f, 0x3d); 54 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
53 err += sn9c102_i2c_write(cam, 0x30, 0x24); 55 err += sn9c102_i2c_write(cam, 0x30, 0x24);
54 err += sn9c102_i2c_write(cam, 0x32, 0x86); 56 err += sn9c102_i2c_write(cam, 0x32, 0x86);
@@ -80,7 +82,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
80 err += sn9c102_i2c_write(cam, 0x02, ctrl->value); 82 err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
81 break; 83 break;
82 case V4L2_CID_BLUE_BALANCE: 84 case V4L2_CID_BLUE_BALANCE:
83 err += sn9c102_i2c_write(cam, 0x03, ctrl->value); 85 err += sn9c102_i2c_write(cam, 0x01, ctrl->value);
84 break; 86 break;
85 case V4L2_CID_GAIN: 87 case V4L2_CID_GAIN:
86 err += sn9c102_i2c_write(cam, 0x00, ctrl->value); 88 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
@@ -108,7 +110,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
108 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); 110 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
109 break; 111 break;
110 case V4L2_CID_AUTO_WHITE_BALANCE: 112 case V4L2_CID_AUTO_WHITE_BALANCE:
111 err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09); 113 err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
112 break; 114 break;
113 case V4L2_CID_AUTOGAIN: 115 case V4L2_CID_AUTOGAIN:
114 err += sn9c102_i2c_write(cam, 0x13, ctrl->value); 116 err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
@@ -371,26 +373,29 @@ static struct sn9c102_sensor ov7630 = {
371 373
372int sn9c102_probe_ov7630(struct sn9c102_device* cam) 374int sn9c102_probe_ov7630(struct sn9c102_device* cam)
373{ 375{
376 const struct usb_device_id ov7630_id_table[] = {
377 { USB_DEVICE(0x0c45, 0x602c), },
378 { USB_DEVICE(0x0c45, 0x602d), },
379 { USB_DEVICE(0x0c45, 0x608f), },
380 { USB_DEVICE(0x0c45, 0x60b0), },
381 { }
382 };
374 int err = 0; 383 int err = 0;
375 384
376 sn9c102_attach_sensor(cam, &ov7630); 385 if (!sn9c102_match_id(cam, ov7630_id_table))
377
378 if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c &&
379 le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d &&
380 le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
381 le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0)
382 return -ENODEV; 386 return -ENODEV;
383 387
384 err += sn9c102_write_reg(cam, 0x01, 0x01); 388 err += sn9c102_write_reg(cam, 0x01, 0x01);
385 err += sn9c102_write_reg(cam, 0x00, 0x01); 389 err += sn9c102_write_reg(cam, 0x00, 0x01);
386 err += sn9c102_write_reg(cam, 0x28, 0x17); 390 err += sn9c102_write_reg(cam, 0x28, 0x17);
387
388 if (err) 391 if (err)
389 return -EIO; 392 return -EIO;
390 393
391 err += sn9c102_i2c_write(cam, 0x0b, 0); 394 err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0);
392 if (err) 395 if (err)
393 return -ENODEV; 396 return -ENODEV;
394 397
398 sn9c102_attach_sensor(cam, &ov7630);
399
395 return 0; 400 return 0;
396} 401}
diff --git a/drivers/usb/media/sn9c102_pas202bca.c b/drivers/usb/media/sn9c102_pas202bca.c
new file mode 100644
index 000000000000..3453237055bb
--- /dev/null
+++ b/drivers/usb/media/sn9c102_pas202bca.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include <linux/delay.h>
23#include "sn9c102_sensor.h"
24
25
26static struct sn9c102_sensor pas202bca;
27
28
29static int pas202bca_init(struct sn9c102_device* cam)
30{
31 int err = 0;
32
33 err += sn9c102_write_reg(cam, 0x00, 0x10);
34 err += sn9c102_write_reg(cam, 0x00, 0x11);
35 err += sn9c102_write_reg(cam, 0x00, 0x14);
36 err += sn9c102_write_reg(cam, 0x20, 0x17);
37 err += sn9c102_write_reg(cam, 0x30, 0x19);
38 err += sn9c102_write_reg(cam, 0x09, 0x18);
39
40 err += sn9c102_i2c_write(cam, 0x02, 0x14);
41 err += sn9c102_i2c_write(cam, 0x03, 0x40);
42 err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
43 err += sn9c102_i2c_write(cam, 0x0e, 0x01);
44 err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
45 err += sn9c102_i2c_write(cam, 0x10, 0x08);
46 err += sn9c102_i2c_write(cam, 0x13, 0x63);
47 err += sn9c102_i2c_write(cam, 0x15, 0x70);
48 err += sn9c102_i2c_write(cam, 0x11, 0x01);
49
50 msleep(400);
51
52 return err;
53}
54
55
56static int pas202bca_set_pix_format(struct sn9c102_device* cam,
57 const struct v4l2_pix_format* pix)
58{
59 int err = 0;
60
61 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
62 err += sn9c102_write_reg(cam, 0x24, 0x17);
63 else
64 err += sn9c102_write_reg(cam, 0x20, 0x17);
65
66 return err;
67}
68
69
70static int pas202bca_set_ctrl(struct sn9c102_device* cam,
71 const struct v4l2_control* ctrl)
72{
73 int err = 0;
74
75 switch (ctrl->id) {
76 case V4L2_CID_EXPOSURE:
77 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
78 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
79 break;
80 case V4L2_CID_RED_BALANCE:
81 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
82 break;
83 case V4L2_CID_BLUE_BALANCE:
84 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
85 break;
86 case V4L2_CID_GAIN:
87 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
88 break;
89 case SN9C102_V4L2_CID_GREEN_BALANCE:
90 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
91 break;
92 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
93 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
94 break;
95 default:
96 return -EINVAL;
97 }
98 err += sn9c102_i2c_write(cam, 0x11, 0x01);
99
100 return err ? -EIO : 0;
101}
102
103
104static int pas202bca_set_crop(struct sn9c102_device* cam,
105 const struct v4l2_rect* rect)
106{
107 struct sn9c102_sensor* s = &pas202bca;
108 int err = 0;
109 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3,
110 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
111
112 err += sn9c102_write_reg(cam, h_start, 0x12);
113 err += sn9c102_write_reg(cam, v_start, 0x13);
114
115 return err;
116}
117
118
119static struct sn9c102_sensor pas202bca = {
120 .name = "PAS202BCA",
121 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
122 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
123 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
124 .interface = SN9C102_I2C_2WIRES,
125 .i2c_slave_id = 0x40,
126 .init = &pas202bca_init,
127 .qctrl = {
128 {
129 .id = V4L2_CID_EXPOSURE,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "exposure",
132 .minimum = 0x01e5,
133 .maximum = 0x3fff,
134 .step = 0x0001,
135 .default_value = 0x01e5,
136 .flags = 0,
137 },
138 {
139 .id = V4L2_CID_GAIN,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "global gain",
142 .minimum = 0x00,
143 .maximum = 0x1f,
144 .step = 0x01,
145 .default_value = 0x0c,
146 .flags = 0,
147 },
148 {
149 .id = V4L2_CID_RED_BALANCE,
150 .type = V4L2_CTRL_TYPE_INTEGER,
151 .name = "red balance",
152 .minimum = 0x00,
153 .maximum = 0x0f,
154 .step = 0x01,
155 .default_value = 0x01,
156 .flags = 0,
157 },
158 {
159 .id = V4L2_CID_BLUE_BALANCE,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "blue balance",
162 .minimum = 0x00,
163 .maximum = 0x0f,
164 .step = 0x01,
165 .default_value = 0x05,
166 .flags = 0,
167 },
168 {
169 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "green balance",
172 .minimum = 0x00,
173 .maximum = 0x0f,
174 .step = 0x01,
175 .default_value = 0x00,
176 .flags = 0,
177 },
178 {
179 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "DAC magnitude",
182 .minimum = 0x00,
183 .maximum = 0xff,
184 .step = 0x01,
185 .default_value = 0x04,
186 .flags = 0,
187 },
188 },
189 .set_ctrl = &pas202bca_set_ctrl,
190 .cropcap = {
191 .bounds = {
192 .left = 0,
193 .top = 0,
194 .width = 640,
195 .height = 480,
196 },
197 .defrect = {
198 .left = 0,
199 .top = 0,
200 .width = 640,
201 .height = 480,
202 },
203 },
204 .set_crop = &pas202bca_set_crop,
205 .pix_format = {
206 .width = 640,
207 .height = 480,
208 .pixelformat = V4L2_PIX_FMT_SBGGR8,
209 .priv = 8,
210 },
211 .set_pix_format = &pas202bca_set_pix_format
212};
213
214
215int sn9c102_probe_pas202bca(struct sn9c102_device* cam)
216{
217 const struct usb_device_id pas202bca_id_table[] = {
218 { USB_DEVICE(0x0c45, 0x60af), },
219 { }
220 };
221 int err = 0;
222
223 if (!sn9c102_match_id(cam,pas202bca_id_table))
224 return -ENODEV;
225
226 err += sn9c102_write_reg(cam, 0x01, 0x01);
227 err += sn9c102_write_reg(cam, 0x40, 0x01);
228 err += sn9c102_write_reg(cam, 0x28, 0x17);
229 if (err)
230 return -EIO;
231
232 if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */
233 return -ENODEV;
234
235 sn9c102_attach_sensor(cam, &pas202bca);
236
237 return 0;
238}
diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c
index 5ca54c7daaf2..d068616ab337 100644
--- a/drivers/usb/media/sn9c102_pas202bcb.c
+++ b/drivers/usb/media/sn9c102_pas202bcb.c
@@ -263,7 +263,7 @@ static struct sn9c102_sensor pas202bcb = {
263 263
264 264
265int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) 265int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
266{ 266{
267 int r0 = 0, r1 = 0, err = 0; 267 int r0 = 0, r1 = 0, err = 0;
268 unsigned int pid = 0; 268 unsigned int pid = 0;
269 269
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index 7d953b24f2f2..2afd9e9d09bb 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -66,6 +66,7 @@ extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
67extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 67extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
68extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 68extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
69extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
69extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); 70extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
70extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); 71extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
71extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); 72extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
@@ -81,12 +82,17 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \
81 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ 82 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
82 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ 83 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \
83 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ 84 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \
85 &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \
84 &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ 86 &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \
85 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ 87 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
86 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ 88 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
87 NULL, \ 89 NULL, \
88}; 90};
89 91
92/* Device identification */
93extern struct sn9c102_device*
94sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
95
90/* Attach a probed sensor to the camera. */ 96/* Attach a probed sensor to the camera. */
91extern void 97extern void
92sn9c102_attach_sensor(struct sn9c102_device* cam, 98sn9c102_attach_sensor(struct sn9c102_device* cam,
@@ -108,6 +114,7 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
108static const struct usb_device_id sn9c102_id_table[] = { \ 114static const struct usb_device_id sn9c102_id_table[] = { \
109 { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ 115 { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \
110 { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ 116 { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \
117 { USB_DEVICE(0x0c45, 0x6007), }, \
111 { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ 118 { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \
112 { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ 119 { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \
113 { USB_DEVICE(0x0c45, 0x6024), }, \ 120 { USB_DEVICE(0x0c45, 0x6024), }, \
@@ -126,7 +133,7 @@ static const struct usb_device_id sn9c102_id_table[] = { \
126 { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ 133 { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \
127 { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ 134 { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \
128 { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ 135 { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \
129 { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \ 136 { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \
130 { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ 137 { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \
131 { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ 138 { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \
132 { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ 139 { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \
@@ -359,12 +366,6 @@ struct sn9c102_sensor {
359 error code without rolling back. 366 error code without rolling back.
360 */ 367 */
361 368
362 const struct usb_device* usbdev;
363 /*
364 Points to the usb_device struct after the sensor is attached.
365 Do not touch unless you know what you are doing.
366 */
367
368 /* 369 /*
369 Do NOT write to the data below, it's READ ONLY. It is used by the 370 Do NOT write to the data below, it's READ ONLY. It is used by the
370 core module to store successfully updated values of the above 371 core module to store successfully updated values of the above
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 32ddf236cafe..2e08c552f40a 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -142,14 +142,18 @@ static struct sn9c102_sensor tas5110c1b = {
142 142
143int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) 143int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
144{ 144{
145 /* This sensor has no identifiers, so let's attach it anyway */ 145 const struct usb_device_id tas5110c1b_id_table[] = {
146 sn9c102_attach_sensor(cam, &tas5110c1b); 146 { USB_DEVICE(0x0c45, 0x6001), },
147 { USB_DEVICE(0x0c45, 0x6005), },
148 { USB_DEVICE(0x0c45, 0x60ab), },
149 { }
150 };
147 151
148 /* Sensor detection is based on USB pid/vid */ 152 /* Sensor detection is based on USB pid/vid */
149 if (le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6001 && 153 if (!sn9c102_match_id(cam, tas5110c1b_id_table))
150 le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6005 &&
151 le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x60ab)
152 return -ENODEV; 154 return -ENODEV;
153 155
156 sn9c102_attach_sensor(cam, &tas5110c1b);
157
154 return 0; 158 return 0;
155} 159}
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index a0728f0ae00c..c7b339740bbf 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -153,13 +153,17 @@ static struct sn9c102_sensor tas5130d1b = {
153 153
154int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) 154int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
155{ 155{
156 /* This sensor has no identifiers, so let's attach it anyway */ 156 const struct usb_device_id tas5130d1b_id_table[] = {
157 sn9c102_attach_sensor(cam, &tas5130d1b); 157 { USB_DEVICE(0x0c45, 0x6025), },
158 { USB_DEVICE(0x0c45, 0x60aa), },
159 { }
160 };
158 161
159 /* Sensor detection is based on USB pid/vid */ 162 /* Sensor detection is based on USB pid/vid */
160 if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6025 && 163 if (!sn9c102_match_id(cam, tas5130d1b_id_table))
161 le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x60aa)
162 return -ENODEV; 164 return -ENODEV;
163 165
166 sn9c102_attach_sensor(cam, &tas5130d1b);
167
164 return 0; 168 return 0;
165} 169}