diff options
author | Luca Risolia <luca.risolia@studio.unibo.it> | 2006-02-25 01:50:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-20 17:49:59 -0500 |
commit | 2ffab02fea5880da284dc5511479b25a796a8dee (patch) | |
tree | b94481244ae823598d06cd72472b9c76e9639bd1 /drivers | |
parent | 7039f4224d4e40b06308d5c1a97427af1a142459 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/media/Makefile | 5 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102.h | 23 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_core.c | 170 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_ov7630.c | 33 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_pas202bca.c | 238 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_pas202bcb.c | 2 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_sensor.h | 15 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_tas5110c1b.c | 14 | ||||
-rw-r--r-- | drivers/usb/media/sn9c102_tas5130d1b.c | 12 |
9 files changed, 405 insertions, 107 deletions
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 | ||
5 | sn9c102-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 | 5 | sn9c102-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 | ||
6 | et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o | 9 | et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o |
7 | zc0301-objs := zc0301_core.o zc0301_pas202bcb.o | 10 | zc0301-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 | ||
109 | struct sn9c102_module_param { | 111 | struct sn9c102_module_param { |
110 | u8 force_munmap; | 112 | u8 force_munmap; |
113 | u16 frame_timeout; | ||
111 | }; | 114 | }; |
112 | 115 | ||
113 | static DEFINE_MUTEX(sn9c102_sysfs_lock); | 116 | static 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 | ||
155 | struct sn9c102_device* | ||
156 | sn9c102_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 | |||
152 | void | 165 | void |
153 | sn9c102_attach_sensor(struct sn9c102_device* cam, | 166 | sn9c102_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...) \ |
200 | dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) | 212 | dev_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 | ||
90 | static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = | ||
91 | SN9C102_FRAME_TIMEOUT}; | ||
92 | module_param_array(frame_timeout, uint, NULL, 0644); | ||
93 | MODULE_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 |
93 | static unsigned short debug = SN9C102_DEBUG_LEVEL; | 100 | static unsigned short debug = SN9C102_DEBUG_LEVEL; |
94 | module_param(debug, ushort, 0644); | 101 | module_param(debug, ushort, 0644); |
@@ -128,8 +135,8 @@ static u32 | |||
128 | sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, | 135 | sn9c102_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 | ||
450 | int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) | 457 | int 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 | ||
459 | int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) | 463 | int 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 | ||
580 | redo: | 581 | redo: |
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) { |
585 | end_of_frame: | 586 | end_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 | ||
809 | static int sn9c102_stream_interrupt(struct sn9c102_device* cam) | 812 | static 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 | ||
1313 | static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) | 1317 | static 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 | ||
1336 | static int sn9c102_init(struct sn9c102_device* cam) | 1340 | static 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 | ||
1827 | static int | 1837 | static int |
1828 | sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) | 1838 | sn9c102_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 | |||
1849 | static int | ||
1850 | sn9c102_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) | |||
1842 | static int | 1864 | static int |
1843 | sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) | 1865 | sn9c102_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) | |||
1864 | static int | 1886 | static int |
1865 | sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) | 1887 | sn9c102_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: | |||
1896 | static int | 1918 | static int |
1897 | sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) | 1919 | sn9c102_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) | |||
1931 | static int | 1955 | static int |
1932 | sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) | 1956 | sn9c102_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) | |||
1947 | static int | 1971 | static int |
1948 | sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) | 1972 | sn9c102_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) | |||
1964 | static int | 1988 | static int |
1965 | sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) | 1989 | sn9c102_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 | |||
2105 | sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) | 2129 | sn9c102_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 | |||
2130 | sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, | 2154 | sn9c102_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 | ||
372 | int sn9c102_probe_ov7630(struct sn9c102_device* cam) | 374 | int 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 | |||
26 | static struct sn9c102_sensor pas202bca; | ||
27 | |||
28 | |||
29 | static 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 | |||
56 | static 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 | |||
70 | static 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 | |||
104 | static 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 | |||
119 | static 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 | |||
215 | int 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 | ||
265 | int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) | 265 | int 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); | |||
66 | extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); | 66 | extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); |
67 | extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); | 67 | extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); |
68 | extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); | 68 | extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); |
69 | extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); | ||
69 | extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); | 70 | extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); |
70 | extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); | 71 | extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); |
71 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); | 72 | extern 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 */ | ||
93 | extern struct sn9c102_device* | ||
94 | sn9c102_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. */ |
91 | extern void | 97 | extern void |
92 | sn9c102_attach_sensor(struct sn9c102_device* cam, | 98 | sn9c102_attach_sensor(struct sn9c102_device* cam, |
@@ -108,6 +114,7 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, | |||
108 | static const struct usb_device_id sn9c102_id_table[] = { \ | 114 | static 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 | ||
143 | int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) | 143 | int 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 | ||
154 | int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) | 154 | int 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 | } |