aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2007-01-08 08:43:56 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-02-21 10:34:19 -0500
commitf327ebbd004fb2f08291ca4c6637f5f27319683c (patch)
tree9f8ea1a6ae5554a7137e9c8e1c92adda8d06eab4 /drivers/media
parent19790db00bb7ff4d6621b82933afb3423586644e (diff)
V4L/DVB (5062): SN9C102 driver updates
- Add support for SN9C105 and SN9C120 - Add some more USB device identifiers - Add support for OV7660 - Implement audio ioctl's and VIDIOC_ENUM_FRAMESIZES - Add preliminary support for 0x0c45/0x6007 - Documentation updates - Generic improvements Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/sn9c102/Kconfig4
-rw-r--r--drivers/media/video/sn9c102/Makefile2
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h57
-rw-r--r--drivers/media/video/sn9c102/sn9c102_config.h86
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c719
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h142
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c7
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c7
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c336
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c592
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c7
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bca.c238
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c97
-rw-r--r--drivers/media/video/sn9c102/sn9c102_sensor.h168
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c8
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c8
16 files changed, 1742 insertions, 736 deletions
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
index cf552e6b8ecf..1a7ccb666ab0 100644
--- a/drivers/media/video/sn9c102/Kconfig
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -1,9 +1,9 @@
1config USB_SN9C102 1config USB_SN9C102
2 tristate "USB SN9C10x PC Camera Controller support" 2 tristate "USB SN9C1xx PC Camera Controller support"
3 depends on USB && VIDEO_V4L1 3 depends on USB && VIDEO_V4L1
4 ---help--- 4 ---help---
5 Say Y here if you want support for cameras based on SONiX SN9C101, 5 Say Y here if you want support for cameras based on SONiX SN9C101,
6 SN9C102 or SN9C103 PC Camera Controllers. 6 SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
7 7
8 See <file:Documentation/video4linux/sn9c102.txt> for more info. 8 See <file:Documentation/video4linux/sn9c102.txt> for more info.
9 9
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
index 536ad3098da4..30e3dfe537fe 100644
--- a/drivers/media/video/sn9c102/Makefile
+++ b/drivers/media/video/sn9c102/Makefile
@@ -1,5 +1,5 @@
1sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ 1sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
2 sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ 2 sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
3 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ 3 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
4 sn9c102_tas5130d1b.o 4 sn9c102_tas5130d1b.o
5 5
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 2c6ff396dafc..5428f34e7c5b 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -1,5 +1,5 @@
1/*************************************************************************** 1/***************************************************************************
2 * V4L2 driver for SN9C10x PC Camera Controllers * 2 * V4L2 driver for SN9C1xx PC Camera Controllers *
3 * * 3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * * 5 * *
@@ -37,33 +37,10 @@
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/stddef.h> 38#include <linux/stddef.h>
39 39
40#include "sn9c102_config.h"
40#include "sn9c102_sensor.h" 41#include "sn9c102_sensor.h"
42#include "sn9c102_devtable.h"
41 43
42/*****************************************************************************/
43
44#define SN9C102_DEBUG
45#define SN9C102_DEBUG_LEVEL 2
46#define SN9C102_MAX_DEVICES 64
47#define SN9C102_PRESERVE_IMGSCALE 0
48#define SN9C102_FORCE_MUNMAP 0
49#define SN9C102_MAX_FRAMES 32
50#define SN9C102_URBS 2
51#define SN9C102_ISO_PACKETS 7
52#define SN9C102_ALTERNATE_SETTING 8
53#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
54#define SN9C102_CTRL_TIMEOUT 300
55#define SN9C102_FRAME_TIMEOUT 2
56
57/*****************************************************************************/
58
59enum sn9c102_bridge {
60 BRIDGE_SN9C101 = 0x01,
61 BRIDGE_SN9C102 = 0x02,
62 BRIDGE_SN9C103 = 0x04,
63};
64
65SN9C102_ID_TABLE
66SN9C102_SENSOR_TABLE
67 44
68enum sn9c102_frame_state { 45enum sn9c102_frame_state {
69 F_UNUSED, 46 F_UNUSED,
@@ -99,13 +76,11 @@ enum sn9c102_stream_state {
99 STREAM_ON, 76 STREAM_ON,
100}; 77};
101 78
102typedef char sn9c103_sof_header_t[18]; 79typedef char sn9c102_sof_header_t[62];
103typedef char sn9c102_sof_header_t[12];
104typedef char sn9c102_eof_header_t[4];
105 80
106struct sn9c102_sysfs_attr { 81struct sn9c102_sysfs_attr {
107 u8 reg, i2c_reg; 82 u8 reg, i2c_reg;
108 sn9c103_sof_header_t frame_header; 83 sn9c102_sof_header_t frame_header;
109}; 84};
110 85
111struct sn9c102_module_param { 86struct sn9c102_module_param {
@@ -137,8 +112,8 @@ struct sn9c102_device {
137 struct v4l2_jpegcompression compression; 112 struct v4l2_jpegcompression compression;
138 113
139 struct sn9c102_sysfs_attr sysfs; 114 struct sn9c102_sysfs_attr sysfs;
140 sn9c103_sof_header_t sof_header; 115 sn9c102_sof_header_t sof_header;
141 u16 reg[63]; 116 u16 reg[384];
142 117
143 struct sn9c102_module_param module_param; 118 struct sn9c102_module_param module_param;
144 119
@@ -155,10 +130,7 @@ struct sn9c102_device {
155struct sn9c102_device* 130struct sn9c102_device*
156sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) 131sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
157{ 132{
158 if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) 133 return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
159 return cam;
160
161 return NULL;
162} 134}
163 135
164 136
@@ -169,6 +141,19 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
169 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); 141 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
170} 142}
171 143
144
145enum sn9c102_bridge
146sn9c102_get_bridge(struct sn9c102_device* cam)
147{
148 return cam->bridge;
149}
150
151
152struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam)
153{
154 return &cam->sensor;
155}
156
172/*****************************************************************************/ 157/*****************************************************************************/
173 158
174#undef DBG 159#undef DBG
diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h
new file mode 100644
index 000000000000..0f4e0378b071
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_config.h
@@ -0,0 +1,86 @@
1/***************************************************************************
2 * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_CONFIG_H_
22#define _SN9C102_CONFIG_H_
23
24#include <linux/types.h>
25#include <linux/jiffies.h>
26
27#define SN9C102_DEBUG
28#define SN9C102_DEBUG_LEVEL 2
29#define SN9C102_MAX_DEVICES 64
30#define SN9C102_PRESERVE_IMGSCALE 0
31#define SN9C102_FORCE_MUNMAP 0
32#define SN9C102_MAX_FRAMES 32
33#define SN9C102_URBS 2
34#define SN9C102_ISO_PACKETS 7
35#define SN9C102_ALTERNATE_SETTING 8
36#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
37#define SN9C102_CTRL_TIMEOUT 300
38#define SN9C102_FRAME_TIMEOUT 0
39
40/*****************************************************************************/
41
42static const u8 SN9C102_Y_QTABLE0[64] = {
43 8, 5, 5, 8, 12, 20, 25, 30,
44 6, 6, 7, 9, 13, 29, 30, 27,
45 7, 6, 8, 12, 20, 28, 34, 28,
46 7, 8, 11, 14, 25, 43, 40, 31,
47 9, 11, 18, 28, 34, 54, 51, 38,
48 12, 17, 27, 32, 40, 52, 56, 46,
49 24, 32, 39, 43, 51, 60, 60, 50,
50 36, 46, 47, 49, 56, 50, 51, 49
51};
52
53static const u8 SN9C102_UV_QTABLE0[64] = {
54 8, 9, 12, 23, 49, 49, 49, 49,
55 9, 10, 13, 33, 49, 49, 49, 49,
56 12, 13, 28, 49, 49, 49, 49, 49,
57 23, 33, 49, 49, 49, 49, 49, 49,
58 49, 49, 49, 49, 49, 49, 49, 49,
59 49, 49, 49, 49, 49, 49, 49, 49,
60 49, 49, 49, 49, 49, 49, 49, 49,
61 49, 49, 49, 49, 49, 49, 49, 49
62};
63
64static const u8 SN9C102_Y_QTABLE1[64] = {
65 16, 11, 10, 16, 24, 40, 51, 61,
66 12, 12, 14, 19, 26, 58, 60, 55,
67 14, 13, 16, 24, 40, 57, 69, 56,
68 14, 17, 22, 29, 51, 87, 80, 62,
69 18, 22, 37, 56, 68, 109, 103, 77,
70 24, 35, 55, 64, 81, 104, 113, 92,
71 49, 64, 78, 87, 103, 121, 120, 101,
72 72, 92, 95, 98, 112, 100, 103, 99
73};
74
75static const u8 SN9C102_UV_QTABLE1[64] = {
76 17, 18, 24, 47, 99, 99, 99, 99,
77 18, 21, 26, 66, 99, 99, 99, 99,
78 24, 26, 56, 99, 99, 99, 99, 99,
79 47, 66, 99, 99, 99, 99, 99, 99,
80 99, 99, 99, 99, 99, 99, 99, 99,
81 99, 99, 99, 99, 99, 99, 99, 99,
82 99, 99, 99, 99, 99, 99, 99, 99,
83 99, 99, 99, 99, 99, 99, 99, 99
84};
85
86#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 04d4c8f28b89..d0e2b40a7725 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1,7 +1,7 @@
1/*************************************************************************** 1/***************************************************************************
2 * V4L2 driver for SN9C10x PC Camera Controllers * 2 * V4L2 driver for SN9C1xx PC Camera Controllers *
3 * * 3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 4 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * * 5 * *
6 * This program is free software; you can redistribute it and/or modify * 6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by * 7 * it under the terms of the GNU General Public License as published by *
@@ -43,12 +43,12 @@
43 43
44/*****************************************************************************/ 44/*****************************************************************************/
45 45
46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" 46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
47#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" 47#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
49#define SN9C102_MODULE_LICENSE "GPL" 49#define SN9C102_MODULE_LICENSE "GPL"
50#define SN9C102_MODULE_VERSION "1:1.27" 50#define SN9C102_MODULE_VERSION "1:1.34"
51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) 51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34)
52 52
53/*****************************************************************************/ 53/*****************************************************************************/
54 54
@@ -91,7 +91,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
91 SN9C102_FRAME_TIMEOUT}; 91 SN9C102_FRAME_TIMEOUT};
92module_param_array(frame_timeout, uint, NULL, 0644); 92module_param_array(frame_timeout, uint, NULL, 0644);
93MODULE_PARM_DESC(frame_timeout, 93MODULE_PARM_DESC(frame_timeout,
94 "\n<n[,...]> Timeout for a video frame in seconds." 94 "\n<0|n[,...]> Timeout for a video frame in seconds before"
95 "\nreturning an I/O error; 0 for infinity."
95 "\nThis parameter is specific for each detected camera." 96 "\nThis parameter is specific for each detected camera."
96 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." 97 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
97 "\n"); 98 "\n");
@@ -113,32 +114,13 @@ MODULE_PARM_DESC(debug,
113 114
114/*****************************************************************************/ 115/*****************************************************************************/
115 116
116static sn9c102_sof_header_t sn9c102_sof_header[] = {
117 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00},
118 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
119};
120
121static sn9c103_sof_header_t sn9c103_sof_header[] = {
122 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
123};
124
125static sn9c102_eof_header_t sn9c102_eof_header[] = {
126 {0x00, 0x00, 0x00, 0x00},
127 {0x40, 0x00, 0x00, 0x00},
128 {0x80, 0x00, 0x00, 0x00},
129 {0xc0, 0x00, 0x00, 0x00},
130};
131
132/*****************************************************************************/
133
134static u32 117static u32
135sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, 118sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
136 enum sn9c102_io_method io) 119 enum sn9c102_io_method io)
137{ 120{
138 struct v4l2_pix_format* p = &(cam->sensor.pix_format); 121 struct v4l2_pix_format* p = &(cam->sensor.pix_format);
139 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); 122 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
140 const size_t imagesize = cam->module_param.force_munmap || 123 size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
141 io == IO_READ ?
142 (p->width * p->height * p->priv) / 8 : 124 (p->width * p->height * p->priv) / 8 :
143 (r->width * r->height * p->priv) / 8; 125 (r->width * r->height * p->priv) / 8;
144 void* buff = NULL; 126 void* buff = NULL;
@@ -147,9 +129,13 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
147 if (count > SN9C102_MAX_FRAMES) 129 if (count > SN9C102_MAX_FRAMES)
148 count = SN9C102_MAX_FRAMES; 130 count = SN9C102_MAX_FRAMES;
149 131
132 if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
133 imagesize += 589 + 2; /* length of JPEG header + EOI marker */
134
150 cam->nbuffers = count; 135 cam->nbuffers = count;
151 while (cam->nbuffers > 0) { 136 while (cam->nbuffers > 0) {
152 if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) 137 if ((buff = vmalloc_32_user(cam->nbuffers *
138 PAGE_ALIGN(imagesize))))
153 break; 139 break;
154 cam->nbuffers--; 140 cam->nbuffers--;
155 } 141 }
@@ -322,9 +308,21 @@ static int
322sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, 308sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
323 struct sn9c102_sensor* sensor) 309 struct sn9c102_sensor* sensor)
324{ 310{
325 int r; 311 int r , err = 0;
312
326 r = sn9c102_read_reg(cam, 0x08); 313 r = sn9c102_read_reg(cam, 0x08);
327 return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0; 314 if (r < 0)
315 err += r;
316
317 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
318 if (!(r & 0x08))
319 err += -1;
320 } else {
321 if (r & 0x08)
322 err += -1;
323 }
324
325 return err ? -EIO : 0;
328} 326}
329 327
330 328
@@ -415,7 +413,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
415 data[4] = data3; 413 data[4] = data3;
416 data[5] = data4; 414 data[5] = data4;
417 data[6] = data5; 415 data[6] = data5;
418 data[7] = 0x14; 416 data[7] = 0x17;
419 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 417 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
420 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); 418 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
421 if (res < 0) 419 if (res < 0)
@@ -467,31 +465,35 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
467 465
468/*****************************************************************************/ 466/*****************************************************************************/
469 467
470static void* 468static size_t sn9c102_sof_length(struct sn9c102_device* cam)
471sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
472{ 469{
473 size_t soflen = 0, i;
474 u8 j, n = 0;
475
476 switch (cam->bridge) { 470 switch (cam->bridge) {
477 case BRIDGE_SN9C101: 471 case BRIDGE_SN9C101:
478 case BRIDGE_SN9C102: 472 case BRIDGE_SN9C102:
479 soflen = sizeof(sn9c102_sof_header_t); 473 return 12;
480 n = sizeof(sn9c102_sof_header) / soflen;
481 break;
482 case BRIDGE_SN9C103: 474 case BRIDGE_SN9C103:
483 soflen = sizeof(sn9c103_sof_header_t); 475 return 18;
484 n = sizeof(sn9c103_sof_header) / soflen; 476 case BRIDGE_SN9C105:
477 case BRIDGE_SN9C120:
478 return 62;
485 } 479 }
486 480
481 return 0;
482}
483
484
485static void*
486sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
487{
488 char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
489 size_t soflen = 0, i;
490
491 soflen = sn9c102_sof_length(cam);
492
487 for (i = 0; (len >= soflen) && (i <= len - soflen); i++) 493 for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
488 for (j = 0; j < n; j++) 494 if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
489 /* The invariable part of the header is 6 bytes long */ 495 memcpy(cam->sof_header, mem + i,
490 if ((cam->bridge != BRIDGE_SN9C103 && 496 sizeof(sn9c102_sof_header_t));
491 !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
492 (cam->bridge == BRIDGE_SN9C103 &&
493 !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
494 memcpy(cam->sof_header, mem + i, soflen);
495 /* Skip the header */ 497 /* Skip the header */
496 return mem + i + soflen; 498 return mem + i + soflen;
497 } 499 }
@@ -503,21 +505,123 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
503static void* 505static void*
504sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) 506sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
505{ 507{
506 size_t eoflen = sizeof(sn9c102_eof_header_t), i; 508 char eof_header[4][4] = {
507 unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; 509 {0x00, 0x00, 0x00, 0x00},
510 {0x40, 0x00, 0x00, 0x00},
511 {0x80, 0x00, 0x00, 0x00},
512 {0xc0, 0x00, 0x00, 0x00},
513 };
514 size_t i, j;
508 515
509 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) 516 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
517 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
510 return NULL; /* EOF header does not exist in compressed data */ 518 return NULL; /* EOF header does not exist in compressed data */
511 519
512 for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) 520 for (i = 0; (len >= 4) && (i <= len - 4); i++)
513 for (j = 0; j < n; j++) 521 for (j = 0; j < ARRAY_SIZE(eof_header); j++)
514 if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) 522 if (!memcmp(mem + i, eof_header[j], 4))
515 return mem + i; 523 return mem + i;
516 524
517 return NULL; 525 return NULL;
518} 526}
519 527
520 528
529static void
530sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
531{
532 static u8 jpeg_header[589] = {
533 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
534 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
535 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
536 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
537 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
538 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
539 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
540 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
541 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
542 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
543 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
544 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
545 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
546 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
547 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
549 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
550 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
551 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
552 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
553 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
554 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
555 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
556 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
557 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
558 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
559 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
560 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
561 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
562 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
563 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
564 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
565 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
566 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
567 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
568 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
569 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
570 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
571 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
572 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
573 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
574 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
575 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
576 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
577 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
578 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
579 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
580 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
581 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
582 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
583 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
584 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
585 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
586 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
587 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
588 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
589 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
590 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
591 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
592 };
593 u8 *pos = f->bufmem;
594
595 memcpy(pos, jpeg_header, sizeof(jpeg_header));
596 *(pos + 6) = 0x00;
597 *(pos + 7 + 64) = 0x01;
598 if (cam->compression.quality == 0) {
599 memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
600 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
601 } else if (cam->compression.quality == 1) {
602 memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
603 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
604 }
605 *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
606 *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
607 *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
608 *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
609 *(pos + 567) = 0x21;
610
611 f->buf.bytesused += sizeof(jpeg_header);
612}
613
614
615static void
616sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
617{
618 static const u8 eoi_marker[2] = {0xff, 0xd9};
619
620 memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
621 f->buf.bytesused += sizeof(eoi_marker);
622}
623
624
521static void sn9c102_urb_complete(struct urb *urb) 625static void sn9c102_urb_complete(struct urb *urb)
522{ 626{
523 struct sn9c102_device* cam = urb->context; 627 struct sn9c102_device* cam = urb->context;
@@ -535,7 +639,7 @@ static void sn9c102_urb_complete(struct urb *urb)
535 cam->stream = STREAM_OFF; 639 cam->stream = STREAM_OFF;
536 if ((*f)) 640 if ((*f))
537 (*f)->state = F_QUEUED; 641 (*f)->state = F_QUEUED;
538 DBG(3, "Stream interrupted"); 642 DBG(3, "Stream interrupted by application");
539 wake_up(&cam->wait_stream); 643 wake_up(&cam->wait_stream);
540 } 644 }
541 645
@@ -557,10 +661,9 @@ static void sn9c102_urb_complete(struct urb *urb)
557 imagesize = (cam->sensor.pix_format.width * 661 imagesize = (cam->sensor.pix_format.width *
558 cam->sensor.pix_format.height * 662 cam->sensor.pix_format.height *
559 cam->sensor.pix_format.priv) / 8; 663 cam->sensor.pix_format.priv) / 8;
560 664 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
561 soflen = (cam->bridge) == BRIDGE_SN9C103 ? 665 imagesize += 589; /* length of jpeg header */
562 sizeof(sn9c103_sof_header_t) : 666 soflen = sn9c102_sof_length(cam);
563 sizeof(sn9c102_sof_header_t);
564 667
565 for (i = 0; i < urb->number_of_packets; i++) { 668 for (i = 0; i < urb->number_of_packets; i++) {
566 unsigned int img, len, status; 669 unsigned int img, len, status;
@@ -610,12 +713,21 @@ end_of_frame:
610 (*f)->buf.bytesused += img; 713 (*f)->buf.bytesused += img;
611 714
612 if ((*f)->buf.bytesused == imagesize || 715 if ((*f)->buf.bytesused == imagesize ||
613 (cam->sensor.pix_format.pixelformat == 716 ((cam->sensor.pix_format.pixelformat ==
614 V4L2_PIX_FMT_SN9C10X && eof)) { 717 V4L2_PIX_FMT_SN9C10X ||
718 cam->sensor.pix_format.pixelformat ==
719 V4L2_PIX_FMT_JPEG) && eof)) {
615 u32 b; 720 u32 b;
721
722 if (cam->sensor.pix_format.pixelformat
723 == V4L2_PIX_FMT_JPEG)
724 sn9c102_write_eoimarker(cam,
725 (*f));
726
616 b = (*f)->buf.bytesused; 727 b = (*f)->buf.bytesused;
617 (*f)->state = F_DONE; 728 (*f)->state = F_DONE;
618 (*f)->buf.sequence= ++cam->frame_count; 729 (*f)->buf.sequence= ++cam->frame_count;
730
619 spin_lock(&cam->queue_lock); 731 spin_lock(&cam->queue_lock);
620 list_move_tail(&(*f)->frame, 732 list_move_tail(&(*f)->frame,
621 &cam->outqueue); 733 &cam->outqueue);
@@ -627,8 +739,10 @@ end_of_frame:
627 else 739 else
628 (*f) = NULL; 740 (*f) = NULL;
629 spin_unlock(&cam->queue_lock); 741 spin_unlock(&cam->queue_lock);
742
630 memcpy(cam->sysfs.frame_header, 743 memcpy(cam->sysfs.frame_header,
631 cam->sof_header, soflen); 744 cam->sof_header, soflen);
745
632 DBG(3, "Video frame captured: %lu " 746 DBG(3, "Video frame captured: %lu "
633 "bytes", (unsigned long)(b)); 747 "bytes", (unsigned long)(b));
634 748
@@ -661,6 +775,9 @@ start_of_frame:
661 (*f)->buf.bytesused = 0; 775 (*f)->buf.bytesused = 0;
662 len -= (sof - pos); 776 len -= (sof - pos);
663 pos = sof; 777 pos = sof;
778 if (cam->sensor.pix_format.pixelformat ==
779 V4L2_PIX_FMT_JPEG)
780 sn9c102_write_jpegheader(cam, (*f));
664 DBG(3, "SOF detected: new video frame"); 781 DBG(3, "SOF detected: new video frame");
665 if (len) 782 if (len)
666 goto redo; 783 goto redo;
@@ -671,7 +788,9 @@ start_of_frame:
671 goto end_of_frame; /* (1) */ 788 goto end_of_frame; /* (1) */
672 else { 789 else {
673 if (cam->sensor.pix_format.pixelformat == 790 if (cam->sensor.pix_format.pixelformat ==
674 V4L2_PIX_FMT_SN9C10X) { 791 V4L2_PIX_FMT_SN9C10X ||
792 cam->sensor.pix_format.pixelformat ==
793 V4L2_PIX_FMT_JPEG) {
675 eof = sof - soflen; 794 eof = sof - soflen;
676 goto end_of_frame; 795 goto end_of_frame;
677 } else { 796 } else {
@@ -701,13 +820,11 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
701{ 820{
702 struct usb_device *udev = cam->usbdev; 821 struct usb_device *udev = cam->usbdev;
703 struct urb* urb; 822 struct urb* urb;
704 const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, 823 struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
705 680, 800, 900, 1023}; 824 usb_ifnum_to_if(udev, 0),
706 const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, 825 SN9C102_ALTERNATE_SETTING);
707 680, 800, 900, 1003}; 826 const unsigned int psz = le16_to_cpu(altsetting->
708 const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? 827 endpoint[0].desc.wMaxPacketSize);
709 sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
710 sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
711 s8 i, j; 828 s8 i, j;
712 int err = 0; 829 int err = 0;
713 830
@@ -775,7 +892,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
775 return 0; 892 return 0;
776 893
777free_urbs: 894free_urbs:
778 for (i = 0; i < SN9C102_URBS; i++) 895 for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
779 usb_free_urb(cam->urb[i]); 896 usb_free_urb(cam->urb[i]);
780 897
781free_buffers: 898free_buffers:
@@ -834,29 +951,29 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
834/*****************************************************************************/ 951/*****************************************************************************/
835 952
836#ifdef CONFIG_VIDEO_ADV_DEBUG 953#ifdef CONFIG_VIDEO_ADV_DEBUG
837static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) 954static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
838{ 955{
839 char str[5]; 956 char str[7];
840 char* endp; 957 char* endp;
841 unsigned long val; 958 unsigned long val;
842 959
843 if (len < 4) { 960 if (len < 6) {
844 strncpy(str, buff, len); 961 strncpy(str, buff, len);
845 str[len+1] = '\0'; 962 str[len+1] = '\0';
846 } else { 963 } else {
847 strncpy(str, buff, 4); 964 strncpy(str, buff, 4);
848 str[4] = '\0'; 965 str[6] = '\0';
849 } 966 }
850 967
851 val = simple_strtoul(str, &endp, 0); 968 val = simple_strtoul(str, &endp, 0);
852 969
853 *count = 0; 970 *count = 0;
854 if (val <= 0xff) 971 if (val <= 0xffff)
855 *count = (ssize_t)(endp - str); 972 *count = (ssize_t)(endp - str);
856 if ((*count) && (len == *count+1) && (buff[*count] == '\n')) 973 if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
857 *count += 1; 974 *count += 1;
858 975
859 return (u8)val; 976 return (u16)val;
860} 977}
861 978
862/* 979/*
@@ -873,7 +990,8 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
873 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 990 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
874 return -ERESTARTSYS; 991 return -ERESTARTSYS;
875 992
876 cam = video_get_drvdata(to_video_device(cd)); 993 cam = video_get_drvdata(container_of(cd, struct video_device,
994 class_dev));
877 if (!cam) { 995 if (!cam) {
878 mutex_unlock(&sn9c102_sysfs_lock); 996 mutex_unlock(&sn9c102_sysfs_lock);
879 return -ENODEV; 997 return -ENODEV;
@@ -891,27 +1009,28 @@ static ssize_t
891sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) 1009sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
892{ 1010{
893 struct sn9c102_device* cam; 1011 struct sn9c102_device* cam;
894 u8 index; 1012 u16 index;
895 ssize_t count; 1013 ssize_t count;
896 1014
897 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1015 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
898 return -ERESTARTSYS; 1016 return -ERESTARTSYS;
899 1017
900 cam = video_get_drvdata(to_video_device(cd)); 1018 cam = video_get_drvdata(container_of(cd, struct video_device,
1019 class_dev));
901 if (!cam) { 1020 if (!cam) {
902 mutex_unlock(&sn9c102_sysfs_lock); 1021 mutex_unlock(&sn9c102_sysfs_lock);
903 return -ENODEV; 1022 return -ENODEV;
904 } 1023 }
905 1024
906 index = sn9c102_strtou8(buf, len, &count); 1025 index = sn9c102_strtou16(buf, len, &count);
907 if (index > 0x1f || !count) { 1026 if (index >= ARRAY_SIZE(cam->reg) || !count) {
908 mutex_unlock(&sn9c102_sysfs_lock); 1027 mutex_unlock(&sn9c102_sysfs_lock);
909 return -EINVAL; 1028 return -EINVAL;
910 } 1029 }
911 1030
912 cam->sysfs.reg = index; 1031 cam->sysfs.reg = index;
913 1032
914 DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); 1033 DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
915 DBG(3, "Written bytes: %zd", count); 1034 DBG(3, "Written bytes: %zd", count);
916 1035
917 mutex_unlock(&sn9c102_sysfs_lock); 1036 mutex_unlock(&sn9c102_sysfs_lock);
@@ -929,7 +1048,8 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
929 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1048 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
930 return -ERESTARTSYS; 1049 return -ERESTARTSYS;
931 1050
932 cam = video_get_drvdata(to_video_device(cd)); 1051 cam = video_get_drvdata(container_of(cd, struct video_device,
1052 class_dev));
933 if (!cam) { 1053 if (!cam) {
934 mutex_unlock(&sn9c102_sysfs_lock); 1054 mutex_unlock(&sn9c102_sysfs_lock);
935 return -ENODEV; 1055 return -ENODEV;
@@ -954,20 +1074,21 @@ static ssize_t
954sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) 1074sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
955{ 1075{
956 struct sn9c102_device* cam; 1076 struct sn9c102_device* cam;
957 u8 value; 1077 u16 value;
958 ssize_t count; 1078 ssize_t count;
959 int err; 1079 int err;
960 1080
961 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1081 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
962 return -ERESTARTSYS; 1082 return -ERESTARTSYS;
963 1083
964 cam = video_get_drvdata(to_video_device(cd)); 1084 cam = video_get_drvdata(container_of(cd, struct video_device,
1085 class_dev));
965 if (!cam) { 1086 if (!cam) {
966 mutex_unlock(&sn9c102_sysfs_lock); 1087 mutex_unlock(&sn9c102_sysfs_lock);
967 return -ENODEV; 1088 return -ENODEV;
968 } 1089 }
969 1090
970 value = sn9c102_strtou8(buf, len, &count); 1091 value = sn9c102_strtou16(buf, len, &count);
971 if (!count) { 1092 if (!count) {
972 mutex_unlock(&sn9c102_sysfs_lock); 1093 mutex_unlock(&sn9c102_sysfs_lock);
973 return -EINVAL; 1094 return -EINVAL;
@@ -979,7 +1100,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
979 return -EIO; 1100 return -EIO;
980 } 1101 }
981 1102
982 DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", 1103 DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
983 cam->sysfs.reg, value); 1104 cam->sysfs.reg, value);
984 DBG(3, "Written bytes: %zd", count); 1105 DBG(3, "Written bytes: %zd", count);
985 1106
@@ -997,7 +1118,8 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
997 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1118 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
998 return -ERESTARTSYS; 1119 return -ERESTARTSYS;
999 1120
1000 cam = video_get_drvdata(to_video_device(cd)); 1121 cam = video_get_drvdata(container_of(cd, struct video_device,
1122 class_dev));
1001 if (!cam) { 1123 if (!cam) {
1002 mutex_unlock(&sn9c102_sysfs_lock); 1124 mutex_unlock(&sn9c102_sysfs_lock);
1003 return -ENODEV; 1125 return -ENODEV;
@@ -1017,19 +1139,20 @@ static ssize_t
1017sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) 1139sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
1018{ 1140{
1019 struct sn9c102_device* cam; 1141 struct sn9c102_device* cam;
1020 u8 index; 1142 u16 index;
1021 ssize_t count; 1143 ssize_t count;
1022 1144
1023 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1145 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1024 return -ERESTARTSYS; 1146 return -ERESTARTSYS;
1025 1147
1026 cam = video_get_drvdata(to_video_device(cd)); 1148 cam = video_get_drvdata(container_of(cd, struct video_device,
1149 class_dev));
1027 if (!cam) { 1150 if (!cam) {
1028 mutex_unlock(&sn9c102_sysfs_lock); 1151 mutex_unlock(&sn9c102_sysfs_lock);
1029 return -ENODEV; 1152 return -ENODEV;
1030 } 1153 }
1031 1154
1032 index = sn9c102_strtou8(buf, len, &count); 1155 index = sn9c102_strtou16(buf, len, &count);
1033 if (!count) { 1156 if (!count) {
1034 mutex_unlock(&sn9c102_sysfs_lock); 1157 mutex_unlock(&sn9c102_sysfs_lock);
1035 return -EINVAL; 1158 return -EINVAL;
@@ -1055,7 +1178,8 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
1055 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1178 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1056 return -ERESTARTSYS; 1179 return -ERESTARTSYS;
1057 1180
1058 cam = video_get_drvdata(to_video_device(cd)); 1181 cam = video_get_drvdata(container_of(cd, struct video_device,
1182 class_dev));
1059 if (!cam) { 1183 if (!cam) {
1060 mutex_unlock(&sn9c102_sysfs_lock); 1184 mutex_unlock(&sn9c102_sysfs_lock);
1061 return -ENODEV; 1185 return -ENODEV;
@@ -1085,14 +1209,15 @@ static ssize_t
1085sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) 1209sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
1086{ 1210{
1087 struct sn9c102_device* cam; 1211 struct sn9c102_device* cam;
1088 u8 value; 1212 u16 value;
1089 ssize_t count; 1213 ssize_t count;
1090 int err; 1214 int err;
1091 1215
1092 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1216 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1093 return -ERESTARTSYS; 1217 return -ERESTARTSYS;
1094 1218
1095 cam = video_get_drvdata(to_video_device(cd)); 1219 cam = video_get_drvdata(container_of(cd, struct video_device,
1220 class_dev));
1096 if (!cam) { 1221 if (!cam) {
1097 mutex_unlock(&sn9c102_sysfs_lock); 1222 mutex_unlock(&sn9c102_sysfs_lock);
1098 return -ENODEV; 1223 return -ENODEV;
@@ -1103,7 +1228,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
1103 return -ENOSYS; 1228 return -ENOSYS;
1104 } 1229 }
1105 1230
1106 value = sn9c102_strtou8(buf, len, &count); 1231 value = sn9c102_strtou16(buf, len, &count);
1107 if (!count) { 1232 if (!count) {
1108 mutex_unlock(&sn9c102_sysfs_lock); 1233 mutex_unlock(&sn9c102_sysfs_lock);
1109 return -EINVAL; 1234 return -EINVAL;
@@ -1131,13 +1256,14 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
1131 struct sn9c102_device* cam; 1256 struct sn9c102_device* cam;
1132 enum sn9c102_bridge bridge; 1257 enum sn9c102_bridge bridge;
1133 ssize_t res = 0; 1258 ssize_t res = 0;
1134 u8 value; 1259 u16 value;
1135 ssize_t count; 1260 ssize_t count;
1136 1261
1137 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1262 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1138 return -ERESTARTSYS; 1263 return -ERESTARTSYS;
1139 1264
1140 cam = video_get_drvdata(to_video_device(cd)); 1265 cam = video_get_drvdata(container_of(cd, struct video_device,
1266 class_dev));
1141 if (!cam) { 1267 if (!cam) {
1142 mutex_unlock(&sn9c102_sysfs_lock); 1268 mutex_unlock(&sn9c102_sysfs_lock);
1143 return -ENODEV; 1269 return -ENODEV;
@@ -1147,7 +1273,7 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
1147 1273
1148 mutex_unlock(&sn9c102_sysfs_lock); 1274 mutex_unlock(&sn9c102_sysfs_lock);
1149 1275
1150 value = sn9c102_strtou8(buf, len, &count); 1276 value = sn9c102_strtou16(buf, len, &count);
1151 if (!count) 1277 if (!count)
1152 return -EINVAL; 1278 return -EINVAL;
1153 1279
@@ -1160,9 +1286,11 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
1160 res = sn9c102_store_val(cd, buf, len); 1286 res = sn9c102_store_val(cd, buf, len);
1161 break; 1287 break;
1162 case BRIDGE_SN9C103: 1288 case BRIDGE_SN9C103:
1289 case BRIDGE_SN9C105:
1290 case BRIDGE_SN9C120:
1163 if (value > 0x7f) 1291 if (value > 0x7f)
1164 return -EINVAL; 1292 return -EINVAL;
1165 if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) 1293 if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0)
1166 res = sn9c102_store_val(cd, buf, len); 1294 res = sn9c102_store_val(cd, buf, len);
1167 break; 1295 break;
1168 } 1296 }
@@ -1175,10 +1303,10 @@ static ssize_t
1175sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) 1303sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
1176{ 1304{
1177 ssize_t res = 0; 1305 ssize_t res = 0;
1178 u8 value; 1306 u16 value;
1179 ssize_t count; 1307 ssize_t count;
1180 1308
1181 value = sn9c102_strtou8(buf, len, &count); 1309 value = sn9c102_strtou16(buf, len, &count);
1182 if (!count || value > 0x7f) 1310 if (!count || value > 0x7f)
1183 return -EINVAL; 1311 return -EINVAL;
1184 1312
@@ -1193,10 +1321,10 @@ static ssize_t
1193sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) 1321sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
1194{ 1322{
1195 ssize_t res = 0; 1323 ssize_t res = 0;
1196 u8 value; 1324 u16 value;
1197 ssize_t count; 1325 ssize_t count;
1198 1326
1199 value = sn9c102_strtou8(buf, len, &count); 1327 value = sn9c102_strtou16(buf, len, &count);
1200 if (!count || value > 0x7f) 1328 if (!count || value > 0x7f)
1201 return -EINVAL; 1329 return -EINVAL;
1202 1330
@@ -1212,7 +1340,8 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
1212 struct sn9c102_device* cam; 1340 struct sn9c102_device* cam;
1213 ssize_t count; 1341 ssize_t count;
1214 1342
1215 cam = video_get_drvdata(to_video_device(cd)); 1343 cam = video_get_drvdata(container_of(cd, struct video_device,
1344 class_dev));
1216 if (!cam) 1345 if (!cam)
1217 return -ENODEV; 1346 return -ENODEV;
1218 1347
@@ -1243,30 +1372,36 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
1243static int sn9c102_create_sysfs(struct sn9c102_device* cam) 1372static int sn9c102_create_sysfs(struct sn9c102_device* cam)
1244{ 1373{
1245 struct video_device *v4ldev = cam->v4ldev; 1374 struct video_device *v4ldev = cam->v4ldev;
1246 int rc; 1375 int err = 0;
1247 1376
1248 rc = video_device_create_file(v4ldev, &class_device_attr_reg); 1377 if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
1249 if (rc) goto err; 1378 goto err_out;
1250 rc = video_device_create_file(v4ldev, &class_device_attr_val); 1379 if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
1251 if (rc) goto err_reg; 1380 goto err_reg;
1252 rc = video_device_create_file(v4ldev, &class_device_attr_frame_header); 1381 if ((err = video_device_create_file(v4ldev,
1253 if (rc) goto err_val; 1382 &class_device_attr_frame_header)))
1383 goto err_val;
1254 1384
1255 if (cam->sensor.sysfs_ops) { 1385 if (cam->sensor.sysfs_ops) {
1256 rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); 1386 if ((err = video_device_create_file(v4ldev,
1257 if (rc) goto err_frhead; 1387 &class_device_attr_i2c_reg)))
1258 rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); 1388 goto err_frame_header;
1259 if (rc) goto err_i2c_reg; 1389 if ((err = video_device_create_file(v4ldev,
1390 &class_device_attr_i2c_val)))
1391 goto err_i2c_reg;
1260 } 1392 }
1261 1393
1262 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { 1394 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
1263 rc = video_device_create_file(v4ldev, &class_device_attr_green); 1395 if ((err = video_device_create_file(v4ldev,
1264 if (rc) goto err_i2c_val; 1396 &class_device_attr_green)))
1265 } else if (cam->bridge == BRIDGE_SN9C103) { 1397 goto err_i2c_val;
1266 rc = video_device_create_file(v4ldev, &class_device_attr_blue); 1398 } else {
1267 if (rc) goto err_i2c_val; 1399 if ((err = video_device_create_file(v4ldev,
1268 rc = video_device_create_file(v4ldev, &class_device_attr_red); 1400 &class_device_attr_blue)))
1269 if (rc) goto err_blue; 1401 goto err_i2c_val;
1402 if ((err = video_device_create_file(v4ldev,
1403 &class_device_attr_red)))
1404 goto err_blue;
1270 } 1405 }
1271 1406
1272 return 0; 1407 return 0;
@@ -1279,14 +1414,14 @@ err_i2c_val:
1279err_i2c_reg: 1414err_i2c_reg:
1280 if (cam->sensor.sysfs_ops) 1415 if (cam->sensor.sysfs_ops)
1281 video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); 1416 video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
1282err_frhead: 1417err_frame_header:
1283 video_device_remove_file(v4ldev, &class_device_attr_frame_header); 1418 video_device_remove_file(v4ldev, &class_device_attr_frame_header);
1284err_val: 1419err_val:
1285 video_device_remove_file(v4ldev, &class_device_attr_val); 1420 video_device_remove_file(v4ldev, &class_device_attr_val);
1286err_reg: 1421err_reg:
1287 video_device_remove_file(v4ldev, &class_device_attr_reg); 1422 video_device_remove_file(v4ldev, &class_device_attr_reg);
1288err: 1423err_out:
1289 return rc; 1424 return err;
1290} 1425}
1291#endif /* CONFIG_VIDEO_ADV_DEBUG */ 1426#endif /* CONFIG_VIDEO_ADV_DEBUG */
1292 1427
@@ -1297,10 +1432,36 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
1297{ 1432{
1298 int err = 0; 1433 int err = 0;
1299 1434
1300 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 1435 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
1301 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); 1436 pix->pixelformat == V4L2_PIX_FMT_JPEG) {
1302 else 1437 switch (cam->bridge) {
1303 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); 1438 case BRIDGE_SN9C101:
1439 case BRIDGE_SN9C102:
1440 case BRIDGE_SN9C103:
1441 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1442 0x18);
1443 break;
1444 case BRIDGE_SN9C105:
1445 case BRIDGE_SN9C120:
1446 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1447 0x18);
1448 break;
1449 }
1450 } else {
1451 switch (cam->bridge) {
1452 case BRIDGE_SN9C101:
1453 case BRIDGE_SN9C102:
1454 case BRIDGE_SN9C103:
1455 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1456 0x18);
1457 break;
1458 case BRIDGE_SN9C105:
1459 case BRIDGE_SN9C120:
1460 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1461 0x18);
1462 break;
1463 }
1464 }
1304 1465
1305 return err ? -EIO : 0; 1466 return err ? -EIO : 0;
1306} 1467}
@@ -1310,12 +1471,46 @@ static int
1310sn9c102_set_compression(struct sn9c102_device* cam, 1471sn9c102_set_compression(struct sn9c102_device* cam,
1311 struct v4l2_jpegcompression* compression) 1472 struct v4l2_jpegcompression* compression)
1312{ 1473{
1313 int err = 0; 1474 int i, err = 0;
1314 1475
1476 switch (cam->bridge) {
1477 case BRIDGE_SN9C101:
1478 case BRIDGE_SN9C102:
1479 case BRIDGE_SN9C103:
1315 if (compression->quality == 0) 1480 if (compression->quality == 0)
1316 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); 1481 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
1482 0x17);
1317 else if (compression->quality == 1) 1483 else if (compression->quality == 1)
1318 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); 1484 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
1485 0x17);
1486 break;
1487 case BRIDGE_SN9C105:
1488 case BRIDGE_SN9C120:
1489 if (compression->quality == 0) {
1490 for (i = 0; i <= 63; i++) {
1491 err += sn9c102_write_reg(cam,
1492 SN9C102_Y_QTABLE0[i],
1493 0x100 + i);
1494 err += sn9c102_write_reg(cam,
1495 SN9C102_UV_QTABLE0[i],
1496 0x140 + i);
1497 }
1498 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
1499 0x18);
1500 } else if (compression->quality == 1) {
1501 for (i = 0; i <= 63; i++) {
1502 err += sn9c102_write_reg(cam,
1503 SN9C102_Y_QTABLE1[i],
1504 0x100 + i);
1505 err += sn9c102_write_reg(cam,
1506 SN9C102_UV_QTABLE1[i],
1507 0x140 + i);
1508 }
1509 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
1510 0x18);
1511 }
1512 break;
1513 }
1319 1514
1320 return err ? -EIO : 0; 1515 return err ? -EIO : 0;
1321} 1516}
@@ -1399,7 +1594,16 @@ static int sn9c102_init(struct sn9c102_device* cam)
1399 } 1594 }
1400 1595
1401 if (!(cam->state & DEV_INITIALIZED)) 1596 if (!(cam->state & DEV_INITIALIZED))
1402 cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; 1597 if (cam->bridge == BRIDGE_SN9C101 ||
1598 cam->bridge == BRIDGE_SN9C102 ||
1599 cam->bridge == BRIDGE_SN9C103) {
1600 cam->compression.quality = cam->reg[0x17] & 0x01 ?
1601 0 : 1;
1602 } else {
1603 cam->compression.quality = cam->reg[0x18] & 0x40 ?
1604 0 : 1;
1605 err += sn9c102_set_compression(cam, &cam->compression);
1606 }
1403 else 1607 else
1404 err += sn9c102_set_compression(cam, &cam->compression); 1608 err += sn9c102_set_compression(cam, &cam->compression);
1405 err += sn9c102_set_pix_format(cam, &s->pix_format); 1609 err += sn9c102_set_pix_format(cam, &s->pix_format);
@@ -1408,7 +1612,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
1408 if (err) 1612 if (err)
1409 return err; 1613 return err;
1410 1614
1411 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) 1615 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
1616 s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1412 DBG(3, "Compressed video format is active, quality %d", 1617 DBG(3, "Compressed video format is active, quality %d",
1413 cam->compression.quality); 1618 cam->compression.quality);
1414 else 1619 else
@@ -1490,6 +1695,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
1490 1695
1491 if (cam->users) { 1696 if (cam->users) {
1492 DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); 1697 DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
1698 DBG(3, "Simultaneous opens are not supported");
1493 if ((filp->f_flags & O_NONBLOCK) || 1699 if ((filp->f_flags & O_NONBLOCK) ||
1494 (filp->f_flags & O_NDELAY)) { 1700 (filp->f_flags & O_NDELAY)) {
1495 err = -EWOULDBLOCK; 1701 err = -EWOULDBLOCK;
@@ -1628,6 +1834,17 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1628 mutex_unlock(&cam->fileop_mutex); 1834 mutex_unlock(&cam->fileop_mutex);
1629 return -EAGAIN; 1835 return -EAGAIN;
1630 } 1836 }
1837 if (!cam->module_param.frame_timeout) {
1838 err = wait_event_interruptible
1839 ( cam->wait_frame,
1840 (!list_empty(&cam->outqueue)) ||
1841 (cam->state & DEV_DISCONNECTED) ||
1842 (cam->state & DEV_MISCONFIGURED) );
1843 if (err) {
1844 mutex_unlock(&cam->fileop_mutex);
1845 return err;
1846 }
1847 } else {
1631 timeout = wait_event_interruptible_timeout 1848 timeout = wait_event_interruptible_timeout
1632 ( cam->wait_frame, 1849 ( cam->wait_frame,
1633 (!list_empty(&cam->outqueue)) || 1850 (!list_empty(&cam->outqueue)) ||
@@ -1638,12 +1855,18 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1638 if (timeout < 0) { 1855 if (timeout < 0) {
1639 mutex_unlock(&cam->fileop_mutex); 1856 mutex_unlock(&cam->fileop_mutex);
1640 return timeout; 1857 return timeout;
1858 } else if (timeout == 0 &&
1859 !(cam->state & DEV_DISCONNECTED)) {
1860 DBG(1, "Video frame timeout elapsed");
1861 mutex_unlock(&cam->fileop_mutex);
1862 return -EIO;
1863 }
1641 } 1864 }
1642 if (cam->state & DEV_DISCONNECTED) { 1865 if (cam->state & DEV_DISCONNECTED) {
1643 mutex_unlock(&cam->fileop_mutex); 1866 mutex_unlock(&cam->fileop_mutex);
1644 return -ENODEV; 1867 return -ENODEV;
1645 } 1868 }
1646 if (!timeout || (cam->state & DEV_MISCONFIGURED)) { 1869 if (cam->state & DEV_MISCONFIGURED) {
1647 mutex_unlock(&cam->fileop_mutex); 1870 mutex_unlock(&cam->fileop_mutex);
1648 return -EIO; 1871 return -EIO;
1649 } 1872 }
@@ -1940,6 +2163,9 @@ exit:
1940 if (copy_to_user(arg, &ctrl, sizeof(ctrl))) 2163 if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
1941 return -EFAULT; 2164 return -EFAULT;
1942 2165
2166 PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
2167 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
2168
1943 return err; 2169 return err;
1944} 2170}
1945 2171
@@ -2127,6 +2353,45 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
2127 2353
2128 2354
2129static int 2355static int
2356sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
2357{
2358 struct v4l2_frmsizeenum frmsize;
2359
2360 if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
2361 return -EFAULT;
2362
2363 if (frmsize.index != 0)
2364 return -EINVAL;
2365
2366 switch (cam->bridge) {
2367 case BRIDGE_SN9C101:
2368 case BRIDGE_SN9C102:
2369 case BRIDGE_SN9C103:
2370 if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
2371 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2372 return -EINVAL;
2373 case BRIDGE_SN9C105:
2374 case BRIDGE_SN9C120:
2375 if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
2376 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2377 return -EINVAL;
2378 }
2379
2380 frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
2381 frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
2382 frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
2383 frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
2384 frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
2385 memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
2386
2387 if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
2388 return -EFAULT;
2389
2390 return 0;
2391}
2392
2393
2394static int
2130sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) 2395sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2131{ 2396{
2132 struct v4l2_fmtdesc fmtd; 2397 struct v4l2_fmtdesc fmtd;
@@ -2134,12 +2399,26 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2134 if (copy_from_user(&fmtd, arg, sizeof(fmtd))) 2399 if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
2135 return -EFAULT; 2400 return -EFAULT;
2136 2401
2402 if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2403 return -EINVAL;
2404
2137 if (fmtd.index == 0) { 2405 if (fmtd.index == 0) {
2138 strcpy(fmtd.description, "bayer rgb"); 2406 strcpy(fmtd.description, "bayer rgb");
2139 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; 2407 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
2140 } else if (fmtd.index == 1) { 2408 } else if (fmtd.index == 1) {
2409 switch (cam->bridge) {
2410 case BRIDGE_SN9C101:
2411 case BRIDGE_SN9C102:
2412 case BRIDGE_SN9C103:
2141 strcpy(fmtd.description, "compressed"); 2413 strcpy(fmtd.description, "compressed");
2142 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; 2414 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
2415 break;
2416 case BRIDGE_SN9C105:
2417 case BRIDGE_SN9C120:
2418 strcpy(fmtd.description, "JPEG");
2419 fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
2420 break;
2421 }
2143 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; 2422 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
2144 } else 2423 } else
2145 return -EINVAL; 2424 return -EINVAL;
@@ -2166,7 +2445,8 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2166 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2445 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2167 return -EINVAL; 2446 return -EINVAL;
2168 2447
2169 pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) 2448 pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X ||
2449 pfmt->pixelformat==V4L2_PIX_FMT_JPEG)
2170 ? 0 : (pfmt->width * pfmt->priv) / 8; 2450 ? 0 : (pfmt->width * pfmt->priv) / 8;
2171 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); 2451 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2172 pfmt->field = V4L2_FIELD_NONE; 2452 pfmt->field = V4L2_FIELD_NONE;
@@ -2237,12 +2517,25 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2237 pix->width = rect.width / scale; 2517 pix->width = rect.width / scale;
2238 pix->height = rect.height / scale; 2518 pix->height = rect.height / scale;
2239 2519
2520 switch (cam->bridge) {
2521 case BRIDGE_SN9C101:
2522 case BRIDGE_SN9C102:
2523 case BRIDGE_SN9C103:
2240 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && 2524 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2241 pix->pixelformat != V4L2_PIX_FMT_SBGGR8) 2525 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2242 pix->pixelformat = pfmt->pixelformat; 2526 pix->pixelformat = pfmt->pixelformat;
2527 break;
2528 case BRIDGE_SN9C105:
2529 case BRIDGE_SN9C120:
2530 if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
2531 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2532 pix->pixelformat = pfmt->pixelformat;
2533 break;
2534 }
2243 pix->priv = pfmt->priv; /* bpp */ 2535 pix->priv = pfmt->priv; /* bpp */
2244 pix->colorspace = pfmt->colorspace; 2536 pix->colorspace = pfmt->colorspace;
2245 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 2537 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2538 pix->pixelformat == V4L2_PIX_FMT_JPEG)
2246 ? 0 : (pix->width * pix->priv) / 8; 2539 ? 0 : (pix->width * pix->priv) / 8;
2247 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); 2540 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
2248 pix->field = V4L2_FIELD_NONE; 2541 pix->field = V4L2_FIELD_NONE;
@@ -2315,8 +2608,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2315static int 2608static int
2316sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) 2609sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
2317{ 2610{
2318 if (copy_to_user(arg, &cam->compression, 2611 if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
2319 sizeof(cam->compression)))
2320 return -EFAULT; 2612 return -EFAULT;
2321 2613
2322 return 0; 2614 return 0;
@@ -2471,6 +2763,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2471 struct sn9c102_frame_t *f; 2763 struct sn9c102_frame_t *f;
2472 unsigned long lock_flags; 2764 unsigned long lock_flags;
2473 long timeout; 2765 long timeout;
2766 int err = 0;
2474 2767
2475 if (copy_from_user(&b, arg, sizeof(b))) 2768 if (copy_from_user(&b, arg, sizeof(b)))
2476 return -EFAULT; 2769 return -EFAULT;
@@ -2483,6 +2776,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2483 return -EINVAL; 2776 return -EINVAL;
2484 if (filp->f_flags & O_NONBLOCK) 2777 if (filp->f_flags & O_NONBLOCK)
2485 return -EAGAIN; 2778 return -EAGAIN;
2779 if (!cam->module_param.frame_timeout) {
2780 err = wait_event_interruptible
2781 ( cam->wait_frame,
2782 (!list_empty(&cam->outqueue)) ||
2783 (cam->state & DEV_DISCONNECTED) ||
2784 (cam->state & DEV_MISCONFIGURED) );
2785 if (err)
2786 return err;
2787 } else {
2486 timeout = wait_event_interruptible_timeout 2788 timeout = wait_event_interruptible_timeout
2487 ( cam->wait_frame, 2789 ( cam->wait_frame,
2488 (!list_empty(&cam->outqueue)) || 2790 (!list_empty(&cam->outqueue)) ||
@@ -2492,9 +2794,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2492 1000 * msecs_to_jiffies(1) ); 2794 1000 * msecs_to_jiffies(1) );
2493 if (timeout < 0) 2795 if (timeout < 0)
2494 return timeout; 2796 return timeout;
2797 else if (timeout == 0 &&
2798 !(cam->state & DEV_DISCONNECTED)) {
2799 DBG(1, "Video frame timeout elapsed");
2800 return -EIO;
2801 }
2802 }
2495 if (cam->state & DEV_DISCONNECTED) 2803 if (cam->state & DEV_DISCONNECTED)
2496 return -ENODEV; 2804 return -ENODEV;
2497 if (!timeout || (cam->state & DEV_MISCONFIGURED)) 2805 if (cam->state & DEV_MISCONFIGURED)
2498 return -EIO; 2806 return -EIO;
2499 } 2807 }
2500 2808
@@ -2612,6 +2920,70 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
2612} 2920}
2613 2921
2614 2922
2923static int
2924sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
2925{
2926 struct v4l2_audio audio;
2927
2928 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
2929 return -EINVAL;
2930
2931 if (copy_from_user(&audio, arg, sizeof(audio)))
2932 return -EFAULT;
2933
2934 if (audio.index != 0)
2935 return -EINVAL;
2936
2937 strcpy(audio.name, "Microphone");
2938 audio.capability = 0;
2939 audio.mode = 0;
2940
2941 if (copy_to_user(arg, &audio, sizeof(audio)))
2942 return -EFAULT;
2943
2944 return 0;
2945}
2946
2947
2948static int
2949sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
2950{
2951 struct v4l2_audio audio;
2952
2953 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
2954 return -EINVAL;
2955
2956 if (copy_from_user(&audio, arg, sizeof(audio)))
2957 return -EFAULT;
2958
2959 memset(&audio, 0, sizeof(audio));
2960 strcpy(audio.name, "Microphone");
2961
2962 if (copy_to_user(arg, &audio, sizeof(audio)))
2963 return -EFAULT;
2964
2965 return 0;
2966}
2967
2968
2969static int
2970sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
2971{
2972 struct v4l2_audio audio;
2973
2974 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
2975 return -EINVAL;
2976
2977 if (copy_from_user(&audio, arg, sizeof(audio)))
2978 return -EFAULT;
2979
2980 if (audio.index != 0)
2981 return -EINVAL;
2982
2983 return 0;
2984}
2985
2986
2615static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, 2987static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
2616 unsigned int cmd, void __user * arg) 2988 unsigned int cmd, void __user * arg)
2617{ 2989{
@@ -2649,6 +3021,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
2649 case VIDIOC_S_CROP: 3021 case VIDIOC_S_CROP:
2650 return sn9c102_vidioc_s_crop(cam, arg); 3022 return sn9c102_vidioc_s_crop(cam, arg);
2651 3023
3024 case VIDIOC_ENUM_FRAMESIZES:
3025 return sn9c102_vidioc_enum_framesizes(cam, arg);
3026
2652 case VIDIOC_ENUM_FMT: 3027 case VIDIOC_ENUM_FMT:
2653 return sn9c102_vidioc_enum_fmt(cam, arg); 3028 return sn9c102_vidioc_enum_fmt(cam, arg);
2654 3029
@@ -2689,11 +3064,21 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
2689 case VIDIOC_S_PARM: 3064 case VIDIOC_S_PARM:
2690 return sn9c102_vidioc_s_parm(cam, arg); 3065 return sn9c102_vidioc_s_parm(cam, arg);
2691 3066
3067 case VIDIOC_ENUMAUDIO:
3068 return sn9c102_vidioc_enumaudio(cam, arg);
3069
3070 case VIDIOC_G_AUDIO:
3071 return sn9c102_vidioc_g_audio(cam, arg);
3072
3073 case VIDIOC_S_AUDIO:
3074 return sn9c102_vidioc_s_audio(cam, arg);
3075
2692 case VIDIOC_G_STD: 3076 case VIDIOC_G_STD:
2693 case VIDIOC_S_STD: 3077 case VIDIOC_S_STD:
2694 case VIDIOC_QUERYSTD: 3078 case VIDIOC_QUERYSTD:
2695 case VIDIOC_ENUMSTD: 3079 case VIDIOC_ENUMSTD:
2696 case VIDIOC_QUERYMENU: 3080 case VIDIOC_QUERYMENU:
3081 case VIDIOC_ENUM_FRAMEINTERVALS:
2697 return -EINVAL; 3082 return -EINVAL;
2698 3083
2699 default: 3084 default:
@@ -2741,6 +3126,7 @@ static const struct file_operations sn9c102_fops = {
2741 .open = sn9c102_open, 3126 .open = sn9c102_open,
2742 .release = sn9c102_release, 3127 .release = sn9c102_release,
2743 .ioctl = sn9c102_ioctl, 3128 .ioctl = sn9c102_ioctl,
3129 .compat_ioctl = v4l_compat_ioctl32,
2744 .read = sn9c102_read, 3130 .read = sn9c102_read,
2745 .poll = sn9c102_poll, 3131 .poll = sn9c102_poll,
2746 .mmap = sn9c102_mmap, 3132 .mmap = sn9c102_mmap,
@@ -2765,7 +3151,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2765 cam->usbdev = udev; 3151 cam->usbdev = udev;
2766 3152
2767 if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { 3153 if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
2768 DBG(1, "kmalloc() failed"); 3154 DBG(1, "kzalloc() failed");
2769 err = -ENOMEM; 3155 err = -ENOMEM;
2770 goto fail; 3156 goto fail;
2771 } 3157 }
@@ -2779,24 +3165,31 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2779 mutex_init(&cam->dev_mutex); 3165 mutex_init(&cam->dev_mutex);
2780 3166
2781 r = sn9c102_read_reg(cam, 0x00); 3167 r = sn9c102_read_reg(cam, 0x00);
2782 if (r < 0 || r != 0x10) { 3168 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
2783 DBG(1, "Sorry, this is not a SN9C10x based camera " 3169 DBG(1, "Sorry, this is not a SN9C1xx based camera "
2784 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 3170 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
2785 err = -ENODEV; 3171 err = -ENODEV;
2786 goto fail; 3172 goto fail;
2787 } 3173 }
2788 3174
2789 cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? 3175 cam->bridge = id->driver_info;
2790 BRIDGE_SN9C103 : BRIDGE_SN9C102;
2791 switch (cam->bridge) { 3176 switch (cam->bridge) {
2792 case BRIDGE_SN9C101: 3177 case BRIDGE_SN9C101:
2793 case BRIDGE_SN9C102: 3178 case BRIDGE_SN9C102:
2794 DBG(2, "SN9C10[12] PC Camera Controller detected " 3179 DBG(2, "SN9C10[12] PC Camera Controller detected "
2795 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 3180 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
2796 break; 3181 break;
2797 case BRIDGE_SN9C103: 3182 case BRIDGE_SN9C103:
2798 DBG(2, "SN9C103 PC Camera Controller detected " 3183 DBG(2, "SN9C103 PC Camera Controller detected "
2799 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 3184 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3185 break;
3186 case BRIDGE_SN9C105:
3187 DBG(2, "SN9C105 PC Camera Controller detected "
3188 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3189 break;
3190 case BRIDGE_SN9C120:
3191 DBG(2, "SN9C120 PC Camera Controller detected "
3192 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
2800 break; 3193 break;
2801 } 3194 }
2802 3195
@@ -2816,12 +3209,18 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2816 goto fail; 3209 goto fail;
2817 } 3210 }
2818 3211
3212 if (!(cam->bridge & cam->sensor.supported_bridge)) {
3213 DBG(1, "Bridge not supported");
3214 err = -ENODEV;
3215 goto fail;
3216 }
3217
2819 if (sn9c102_init(cam)) { 3218 if (sn9c102_init(cam)) {
2820 DBG(1, "Initialization failed. I will retry on open()."); 3219 DBG(1, "Initialization failed. I will retry on open().");
2821 cam->state |= DEV_MISCONFIGURED; 3220 cam->state |= DEV_MISCONFIGURED;
2822 } 3221 }
2823 3222
2824 strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); 3223 strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
2825 cam->v4ldev->owner = THIS_MODULE; 3224 cam->v4ldev->owner = THIS_MODULE;
2826 cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; 3225 cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
2827 cam->v4ldev->hardware = 0; 3226 cam->v4ldev->hardware = 0;
@@ -2838,7 +3237,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2838 DBG(1, "V4L2 device registration failed"); 3237 DBG(1, "V4L2 device registration failed");
2839 if (err == -ENFILE && video_nr[dev_nr] == -1) 3238 if (err == -ENFILE && video_nr[dev_nr] == -1)
2840 DBG(1, "Free /dev/videoX node not found"); 3239 DBG(1, "Free /dev/videoX node not found");
2841 goto fail2; 3240 video_nr[dev_nr] = -1;
3241 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
3242 mutex_unlock(&cam->dev_mutex);
3243 goto fail;
2842 } 3244 }
2843 3245
2844 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); 3246 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
@@ -2850,9 +3252,14 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2850 3252
2851#ifdef CONFIG_VIDEO_ADV_DEBUG 3253#ifdef CONFIG_VIDEO_ADV_DEBUG
2852 err = sn9c102_create_sysfs(cam); 3254 err = sn9c102_create_sysfs(cam);
2853 if (err) 3255 if (!err)
2854 goto fail3; 3256 DBG(2, "Optional device control through 'sysfs' "
2855 DBG(2, "Optional device control through 'sysfs' interface ready"); 3257 "interface ready");
3258 else
3259 DBG(2, "Failed to create optional 'sysfs' interface for "
3260 "device controlling. Error #%d", err);
3261#else
3262 DBG(2, "Optional device control through 'sysfs' interface disabled");
2856#endif 3263#endif
2857 3264
2858 usb_set_intfdata(intf, cam); 3265 usb_set_intfdata(intf, cam);
@@ -2861,14 +3268,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2861 3268
2862 return 0; 3269 return 0;
2863 3270
2864#ifdef CONFIG_VIDEO_ADV_DEBUG
2865fail3:
2866 video_unregister_device(cam->v4ldev);
2867#endif
2868fail2:
2869 video_nr[dev_nr] = -1;
2870 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
2871 mutex_unlock(&cam->dev_mutex);
2872fail: 3271fail:
2873 if (cam) { 3272 if (cam) {
2874 kfree(cam->control_buffer); 3273 kfree(cam->control_buffer);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
new file mode 100644
index 000000000000..3a682eca6c65
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -0,0 +1,142 @@
1/***************************************************************************
2 * Table of device identifiers of the SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_DEVTABLE_H_
22#define _SN9C102_DEVTABLE_H_
23
24#include <linux/usb.h>
25
26struct sn9c102_device;
27
28/*
29 Each SN9C1xx camera has proper PID/VID identifiers.
30 SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
31 handle the video class interface.
32*/
33#define SN9C102_USB_DEVICE(vend, prod, bridge) \
34 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
35 USB_DEVICE_ID_MATCH_INT_CLASS, \
36 .idVendor = (vend), \
37 .idProduct = (prod), \
38 .bInterfaceClass = 0xff, \
39 .driver_info = (bridge)
40
41static const struct usb_device_id sn9c102_id_table[] = {
42 /* SN9C101 and SN9C102 */
43 { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
44 { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
45 { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
46 { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
47 { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), },
48 { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
49 { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
50 { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
51 { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
52 { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
53 { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
54 { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
55 { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
56 { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
57 { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
58 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
59 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
60 { SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), },
61 /* SN9C103 */
62 { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
63 { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
64 { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), },
65 { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
66 { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
67 { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
68 { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
69 { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), },
70 { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
71 { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
72 { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
73 { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
74 { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), },
75 { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), },
76 { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), },
77 { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
78 { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
79 { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
80 { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
81 { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
82 { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
83 { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
84 { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), },
85 { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), },
86 { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
87 { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
88 /* SN9C105 */
89 { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
90 { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
91 { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
92 { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
93 { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
94 { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
95 { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
96 { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
97 { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
98 { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
99 { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
100 /* SN9C120 */
101 { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
102 { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
103 { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
104 { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
105 { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
106 { }
107};
108
109/*
110 Probing functions: on success, you must attach the sensor to the camera
111 by calling sn9c102_attach_sensor().
112 To enable the I2C communication, you might need to perform a really basic
113 initialization of the SN9C1XX chip.
114 Functions must return 0 on success, the appropriate error otherwise.
115*/
116extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
117extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
118extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
119extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
120extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
121extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
122extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
123extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
124
125/*
126 Add the above entries to this table. Be sure to add the entry in the right
127 place, since, on failure, the next probing routine is called according to
128 the order of the list below, from top to bottom.
129*/
130static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
131 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
132 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
133 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
134 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
135 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
136 &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
137 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
138 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
139 NULL,
140};
141
142#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index c4117bf64b69..7ae368f60d89 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -124,7 +124,7 @@ static int hv7131d_set_ctrl(struct sn9c102_device* cam,
124static int hv7131d_set_crop(struct sn9c102_device* cam, 124static int hv7131d_set_crop(struct sn9c102_device* cam,
125 const struct v4l2_rect* rect) 125 const struct v4l2_rect* rect)
126{ 126{
127 struct sn9c102_sensor* s = &hv7131d; 127 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
128 int err = 0; 128 int err = 0;
129 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, 129 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
130 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; 130 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -153,6 +153,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
153static struct sn9c102_sensor hv7131d = { 153static struct sn9c102_sensor hv7131d = {
154 .name = "HV7131D", 154 .name = "HV7131D",
155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
156 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
156 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 157 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
157 .frequency = SN9C102_I2C_100KHZ, 158 .frequency = SN9C102_I2C_100KHZ,
158 .interface = SN9C102_I2C_2WIRES, 159 .interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index 4169ea4a2e20..a33d1bc10f90 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -201,7 +201,7 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
201static int mi0343_set_crop(struct sn9c102_device* cam, 201static int mi0343_set_crop(struct sn9c102_device* cam,
202 const struct v4l2_rect* rect) 202 const struct v4l2_rect* rect)
203{ 203{
204 struct sn9c102_sensor* s = &mi0343; 204 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
205 int err = 0; 205 int err = 0;
206 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, 206 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
207 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; 207 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -237,6 +237,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
237static struct sn9c102_sensor mi0343 = { 237static struct sn9c102_sensor mi0343 = {
238 .name = "MI-0343", 238 .name = "MI-0343",
239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
240 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
240 .frequency = SN9C102_I2C_100KHZ, 241 .frequency = SN9C102_I2C_100KHZ,
241 .interface = SN9C102_I2C_2WIRES, 242 .interface = SN9C102_I2C_2WIRES,
242 .i2c_slave_id = 0x5d, 243 .i2c_slave_id = 0x5d,
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 3da042021787..7df09ff38e63 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -29,13 +29,17 @@ static int ov7630_init(struct sn9c102_device* cam)
29{ 29{
30 int err = 0; 30 int err = 0;
31 31
32 switch (sn9c102_get_bridge(cam)) {
33 case BRIDGE_SN9C101:
34 case BRIDGE_SN9C102:
32 err += sn9c102_write_reg(cam, 0x00, 0x14); 35 err += sn9c102_write_reg(cam, 0x00, 0x14);
33 err += sn9c102_write_reg(cam, 0x60, 0x17); 36 err += sn9c102_write_reg(cam, 0x60, 0x17);
34 err += sn9c102_write_reg(cam, 0x0f, 0x18); 37 err += sn9c102_write_reg(cam, 0x0f, 0x18);
35 err += sn9c102_write_reg(cam, 0x50, 0x19); 38 err += sn9c102_write_reg(cam, 0x50, 0x19);
36 39
37 err += sn9c102_i2c_write(cam, 0x12, 0x80); 40 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
38 err += sn9c102_i2c_write(cam, 0x11, 0x01); 41 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
42 err += sn9c102_i2c_write(cam, 0x11, 0x00);
39 err += sn9c102_i2c_write(cam, 0x15, 0x34); 43 err += sn9c102_i2c_write(cam, 0x15, 0x34);
40 err += sn9c102_i2c_write(cam, 0x16, 0x03); 44 err += sn9c102_i2c_write(cam, 0x16, 0x03);
41 err += sn9c102_i2c_write(cam, 0x17, 0x1c); 45 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
@@ -43,14 +47,72 @@ static int ov7630_init(struct sn9c102_device* cam)
43 err += sn9c102_i2c_write(cam, 0x19, 0x06); 47 err += sn9c102_i2c_write(cam, 0x19, 0x06);
44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6); 48 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
45 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 49 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
46 err += sn9c102_i2c_write(cam, 0x20, 0xf6); 50 err += sn9c102_i2c_write(cam, 0x20, 0x44);
51 err += sn9c102_i2c_write(cam, 0x23, 0xee);
52 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
53 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
54 err += sn9c102_i2c_write(cam, 0x28, 0x20);
55 err += sn9c102_i2c_write(cam, 0x29, 0x30);
56 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
57 err += sn9c102_i2c_write(cam, 0x30, 0x24);
58 err += sn9c102_i2c_write(cam, 0x32, 0x86);
59 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
60 err += sn9c102_i2c_write(cam, 0x61, 0x42);
61 err += sn9c102_i2c_write(cam, 0x65, 0x00);
62 err += sn9c102_i2c_write(cam, 0x69, 0x38);
63 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
64 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
65 err += sn9c102_i2c_write(cam, 0x71, 0x00);
66 err += sn9c102_i2c_write(cam, 0x74, 0x21);
67 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
68 break;
69 case BRIDGE_SN9C103:
70 err += sn9c102_write_reg(cam, 0x00, 0x02);
71 err += sn9c102_write_reg(cam, 0x00, 0x03);
72 err += sn9c102_write_reg(cam, 0x1a, 0x04);
73 err += sn9c102_write_reg(cam, 0x20, 0x05);
74 err += sn9c102_write_reg(cam, 0x20, 0x06);
75 err += sn9c102_write_reg(cam, 0x20, 0x07);
76 err += sn9c102_write_reg(cam, 0x03, 0x10);
77 err += sn9c102_write_reg(cam, 0x0a, 0x14);
78 err += sn9c102_write_reg(cam, 0x60, 0x17);
79 err += sn9c102_write_reg(cam, 0x0f, 0x18);
80 err += sn9c102_write_reg(cam, 0x50, 0x19);
81 err += sn9c102_write_reg(cam, 0x1d, 0x1a);
82 err += sn9c102_write_reg(cam, 0x10, 0x1b);
83 err += sn9c102_write_reg(cam, 0x02, 0x1c);
84 err += sn9c102_write_reg(cam, 0x03, 0x1d);
85 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
86 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
87 err += sn9c102_write_reg(cam, 0x00, 0x20);
88 err += sn9c102_write_reg(cam, 0x10, 0x21);
89 err += sn9c102_write_reg(cam, 0x20, 0x22);
90 err += sn9c102_write_reg(cam, 0x30, 0x23);
91 err += sn9c102_write_reg(cam, 0x40, 0x24);
92 err += sn9c102_write_reg(cam, 0x50, 0x25);
93 err += sn9c102_write_reg(cam, 0x60, 0x26);
94 err += sn9c102_write_reg(cam, 0x70, 0x27);
95 err += sn9c102_write_reg(cam, 0x80, 0x28);
96 err += sn9c102_write_reg(cam, 0x90, 0x29);
97 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
98 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
99 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
100 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
101 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
102 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
103 err += sn9c102_write_reg(cam, 0xff, 0x30);
104
105 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
106 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
107 err += sn9c102_i2c_write(cam, 0x15, 0x34);
108 err += sn9c102_i2c_write(cam, 0x11, 0x01);
109 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
110 err += sn9c102_i2c_write(cam, 0x20, 0x44);
47 err += sn9c102_i2c_write(cam, 0x23, 0xee); 111 err += sn9c102_i2c_write(cam, 0x23, 0xee);
48 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 112 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
49 err += sn9c102_i2c_write(cam, 0x27, 0x9a); 113 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
50 err += sn9c102_i2c_write(cam, 0x28, 0xa0); 114 err += sn9c102_i2c_write(cam, 0x28, 0x20);
51 err += sn9c102_i2c_write(cam, 0x29, 0x30); 115 err += sn9c102_i2c_write(cam, 0x29, 0x30);
52 err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
53 err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
54 err += sn9c102_i2c_write(cam, 0x2f, 0x3d); 116 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
55 err += sn9c102_i2c_write(cam, 0x30, 0x24); 117 err += sn9c102_i2c_write(cam, 0x30, 0x24);
56 err += sn9c102_i2c_write(cam, 0x32, 0x86); 118 err += sn9c102_i2c_write(cam, 0x32, 0x86);
@@ -63,45 +125,97 @@ static int ov7630_init(struct sn9c102_device* cam)
63 err += sn9c102_i2c_write(cam, 0x71, 0x00); 125 err += sn9c102_i2c_write(cam, 0x71, 0x00);
64 err += sn9c102_i2c_write(cam, 0x74, 0x21); 126 err += sn9c102_i2c_write(cam, 0x74, 0x21);
65 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 127 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
128 break;
129 default:
130 break;
131 }
66 132
67 return err; 133 return err;
68} 134}
69 135
70 136
71static int ov7630_set_ctrl(struct sn9c102_device* cam, 137static int ov7630_get_ctrl(struct sn9c102_device* cam,
72 const struct v4l2_control* ctrl) 138 struct v4l2_control* ctrl)
73{ 139{
74 int err = 0; 140 int err = 0;
75 141
76 switch (ctrl->id) { 142 switch (ctrl->id) {
77 case V4L2_CID_EXPOSURE: 143 case V4L2_CID_EXPOSURE:
78 err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2); 144 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
79 err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03); 145 return -EIO;
80 break; 146 break;
81 case V4L2_CID_RED_BALANCE: 147 case V4L2_CID_RED_BALANCE:
82 err += sn9c102_i2c_write(cam, 0x02, ctrl->value); 148 ctrl->value = sn9c102_pread_reg(cam, 0x07);
83 break; 149 break;
84 case V4L2_CID_BLUE_BALANCE: 150 case V4L2_CID_BLUE_BALANCE:
85 err += sn9c102_i2c_write(cam, 0x01, ctrl->value); 151 ctrl->value = sn9c102_pread_reg(cam, 0x06);
152 break;
153 case SN9C102_V4L2_CID_GREEN_BALANCE:
154 ctrl->value = sn9c102_pread_reg(cam, 0x05);
86 break; 155 break;
87 case V4L2_CID_GAIN: 156 case V4L2_CID_GAIN:
88 err += sn9c102_i2c_write(cam, 0x00, ctrl->value); 157 if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
158 return -EIO;
159 ctrl->value &= 0x3f;
160 break;
161 case V4L2_CID_DO_WHITE_BALANCE:
162 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
163 return -EIO;
164 ctrl->value &= 0x3f;
165 break;
166 case V4L2_CID_WHITENESS:
167 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
168 return -EIO;
169 ctrl->value &= 0x3f;
170 break;
171 case V4L2_CID_AUTOGAIN:
172 if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
173 return -EIO;
174 ctrl->value &= 0x01;
175 break;
176 case V4L2_CID_VFLIP:
177 if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
178 return -EIO;
179 ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
180 break;
181 case SN9C102_V4L2_CID_GAMMA:
182 if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
183 return -EIO;
184 ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
185 break;
186 case SN9C102_V4L2_CID_BAND_FILTER:
187 if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
188 return -EIO;
189 ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
190 break;
191 default:
192 return -EINVAL;
193 }
194
195 return err ? -EIO : 0;
196}
197
198
199static int ov7630_set_ctrl(struct sn9c102_device* cam,
200 const struct v4l2_control* ctrl)
201{
202 int err = 0;
203
204 switch (ctrl->id) {
205 case V4L2_CID_EXPOSURE:
206 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
89 break; 207 break;
90 case V4L2_CID_CONTRAST: 208 case V4L2_CID_RED_BALANCE:
91 err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, 209 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
92 (ctrl->value-1) | 0x20)
93 : sn9c102_i2c_write(cam, 0x05, 0x00);
94 break; 210 break;
95 case V4L2_CID_BRIGHTNESS: 211 case V4L2_CID_BLUE_BALANCE:
96 err += sn9c102_i2c_write(cam, 0x06, ctrl->value); 212 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
97 break; 213 break;
98 case V4L2_CID_SATURATION: 214 case SN9C102_V4L2_CID_GREEN_BALANCE:
99 err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4); 215 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
100 break; 216 break;
101 case V4L2_CID_HUE: 217 case V4L2_CID_GAIN:
102 err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, 218 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
103 (ctrl->value-1) | 0x20)
104 : sn9c102_i2c_write(cam, 0x04, 0x00);
105 break; 219 break;
106 case V4L2_CID_DO_WHITE_BALANCE: 220 case V4L2_CID_DO_WHITE_BALANCE:
107 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); 221 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
@@ -109,23 +223,15 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
109 case V4L2_CID_WHITENESS: 223 case V4L2_CID_WHITENESS:
110 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); 224 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
111 break; 225 break;
112 case V4L2_CID_AUTO_WHITE_BALANCE:
113 err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
114 break;
115 case V4L2_CID_AUTOGAIN: 226 case V4L2_CID_AUTOGAIN:
116 err += sn9c102_i2c_write(cam, 0x13, ctrl->value); 227 err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
228 (ctrl->value << 1));
117 break; 229 break;
118 case V4L2_CID_VFLIP: 230 case V4L2_CID_VFLIP:
119 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); 231 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
120 break; 232 break;
121 case V4L2_CID_BLACK_LEVEL:
122 err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
123 break;
124 case SN9C102_V4L2_CID_BRIGHT_LEVEL:
125 err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
126 break;
127 case SN9C102_V4L2_CID_GAMMA: 233 case SN9C102_V4L2_CID_GAMMA:
128 err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80); 234 err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
129 break; 235 break;
130 case SN9C102_V4L2_CID_BAND_FILTER: 236 case SN9C102_V4L2_CID_BAND_FILTER:
131 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); 237 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
@@ -141,10 +247,12 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
141static int ov7630_set_crop(struct sn9c102_device* cam, 247static int ov7630_set_crop(struct sn9c102_device* cam,
142 const struct v4l2_rect* rect) 248 const struct v4l2_rect* rect)
143{ 249{
144 struct sn9c102_sensor* s = &ov7630; 250 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
145 int err = 0; 251 int err = 0;
146 u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; 252 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
253 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
147 254
255 err += sn9c102_write_reg(cam, h_start, 0x12);
148 err += sn9c102_write_reg(cam, v_start, 0x13); 256 err += sn9c102_write_reg(cam, v_start, 0x13);
149 257
150 return err; 258 return err;
@@ -168,7 +276,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
168static struct sn9c102_sensor ov7630 = { 276static struct sn9c102_sensor ov7630 = {
169 .name = "OV7630", 277 .name = "OV7630",
170 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 278 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
171 .sysfs_ops = SN9C102_I2C_WRITE, 279 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
280 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
172 .frequency = SN9C102_I2C_100KHZ, 281 .frequency = SN9C102_I2C_100KHZ,
173 .interface = SN9C102_I2C_2WIRES, 282 .interface = SN9C102_I2C_2WIRES,
174 .i2c_slave_id = 0x21, 283 .i2c_slave_id = 0x21,
@@ -185,73 +294,23 @@ static struct sn9c102_sensor ov7630 = {
185 .flags = 0, 294 .flags = 0,
186 }, 295 },
187 { 296 {
188 .id = V4L2_CID_HUE,
189 .type = V4L2_CTRL_TYPE_INTEGER,
190 .name = "hue",
191 .minimum = 0x00,
192 .maximum = 0x1f+1,
193 .step = 0x01,
194 .default_value = 0x00,
195 .flags = 0,
196 },
197 {
198 .id = V4L2_CID_SATURATION,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "saturation",
201 .minimum = 0x00,
202 .maximum = 0x0f,
203 .step = 0x01,
204 .default_value = 0x08,
205 .flags = 0,
206 },
207 {
208 .id = V4L2_CID_CONTRAST,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "contrast",
211 .minimum = 0x00,
212 .maximum = 0x1f+1,
213 .step = 0x01,
214 .default_value = 0x00,
215 .flags = 0,
216 },
217 {
218 .id = V4L2_CID_EXPOSURE, 297 .id = V4L2_CID_EXPOSURE,
219 .type = V4L2_CTRL_TYPE_INTEGER, 298 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "exposure", 299 .name = "exposure",
221 .minimum = 0x000,
222 .maximum = 0x3ff,
223 .step = 0x001,
224 .default_value = 0x83<<2,
225 .flags = 0,
226 },
227 {
228 .id = V4L2_CID_RED_BALANCE,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "red balance",
231 .minimum = 0x00,
232 .maximum = 0xff,
233 .step = 0x01,
234 .default_value = 0x3a,
235 .flags = 0,
236 },
237 {
238 .id = V4L2_CID_BLUE_BALANCE,
239 .type = V4L2_CTRL_TYPE_INTEGER,
240 .name = "blue balance",
241 .minimum = 0x00, 300 .minimum = 0x00,
242 .maximum = 0xff, 301 .maximum = 0xff,
243 .step = 0x01, 302 .step = 0x01,
244 .default_value = 0x77, 303 .default_value = 0x60,
245 .flags = 0, 304 .flags = 0,
246 }, 305 },
247 { 306 {
248 .id = V4L2_CID_BRIGHTNESS, 307 .id = V4L2_CID_WHITENESS,
249 .type = V4L2_CTRL_TYPE_INTEGER, 308 .type = V4L2_CTRL_TYPE_INTEGER,
250 .name = "brightness", 309 .name = "white balance background: red",
251 .minimum = 0x00, 310 .minimum = 0x00,
252 .maximum = 0xff, 311 .maximum = 0x3f,
253 .step = 0x01, 312 .step = 0x01,
254 .default_value = 0xa0, 313 .default_value = 0x20,
255 .flags = 0, 314 .flags = 0,
256 }, 315 },
257 { 316 {
@@ -265,31 +324,31 @@ static struct sn9c102_sensor ov7630 = {
265 .flags = 0, 324 .flags = 0,
266 }, 325 },
267 { 326 {
268 .id = V4L2_CID_WHITENESS, 327 .id = V4L2_CID_RED_BALANCE,
269 .type = V4L2_CTRL_TYPE_INTEGER, 328 .type = V4L2_CTRL_TYPE_INTEGER,
270 .name = "white balance background: red", 329 .name = "red balance",
271 .minimum = 0x00, 330 .minimum = 0x00,
272 .maximum = 0x3f, 331 .maximum = 0x7f,
273 .step = 0x01, 332 .step = 0x01,
274 .default_value = 0x20, 333 .default_value = 0x20,
275 .flags = 0, 334 .flags = 0,
276 }, 335 },
277 { 336 {
278 .id = V4L2_CID_AUTO_WHITE_BALANCE, 337 .id = V4L2_CID_BLUE_BALANCE,
279 .type = V4L2_CTRL_TYPE_BOOLEAN, 338 .type = V4L2_CTRL_TYPE_INTEGER,
280 .name = "auto white balance", 339 .name = "blue balance",
281 .minimum = 0x00, 340 .minimum = 0x00,
282 .maximum = 0x01, 341 .maximum = 0x7f,
283 .step = 0x01, 342 .step = 0x01,
284 .default_value = 0x01, 343 .default_value = 0x20,
285 .flags = 0, 344 .flags = 0,
286 }, 345 },
287 { 346 {
288 .id = V4L2_CID_AUTOGAIN, 347 .id = V4L2_CID_AUTOGAIN,
289 .type = V4L2_CTRL_TYPE_INTEGER, 348 .type = V4L2_CTRL_TYPE_BOOLEAN,
290 .name = "gain & exposure mode", 349 .name = "auto adjust",
291 .minimum = 0x00, 350 .minimum = 0x00,
292 .maximum = 0x03, 351 .maximum = 0x01,
293 .step = 0x01, 352 .step = 0x01,
294 .default_value = 0x00, 353 .default_value = 0x00,
295 .flags = 0, 354 .flags = 0,
@@ -305,23 +364,13 @@ static struct sn9c102_sensor ov7630 = {
305 .flags = 0, 364 .flags = 0,
306 }, 365 },
307 { 366 {
308 .id = V4L2_CID_BLACK_LEVEL, 367 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
309 .type = V4L2_CTRL_TYPE_INTEGER, 368 .type = V4L2_CTRL_TYPE_INTEGER,
310 .name = "black pixel ratio", 369 .name = "green balance",
311 .minimum = 0x01, 370 .minimum = 0x00,
312 .maximum = 0x9a, 371 .maximum = 0x7f,
313 .step = 0x01,
314 .default_value = 0x8a,
315 .flags = 0,
316 },
317 {
318 .id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
319 .type = V4L2_CTRL_TYPE_INTEGER,
320 .name = "bright pixel ratio",
321 .minimum = 0x01,
322 .maximum = 0x9a,
323 .step = 0x01, 372 .step = 0x01,
324 .default_value = 0x10, 373 .default_value = 0x20,
325 .flags = 0, 374 .flags = 0,
326 }, 375 },
327 { 376 {
@@ -345,6 +394,7 @@ static struct sn9c102_sensor ov7630 = {
345 .flags = 0, 394 .flags = 0,
346 }, 395 },
347 }, 396 },
397 .get_ctrl = &ov7630_get_ctrl,
348 .set_ctrl = &ov7630_set_ctrl, 398 .set_ctrl = &ov7630_set_ctrl,
349 .cropcap = { 399 .cropcap = {
350 .bounds = { 400 .bounds = {
@@ -364,7 +414,7 @@ static struct sn9c102_sensor ov7630 = {
364 .pix_format = { 414 .pix_format = {
365 .width = 640, 415 .width = 640,
366 .height = 480, 416 .height = 480,
367 .pixelformat = V4L2_PIX_FMT_SBGGR8, 417 .pixelformat = V4L2_PIX_FMT_SN9C10X,
368 .priv = 8, 418 .priv = 8,
369 }, 419 },
370 .set_pix_format = &ov7630_set_pix_format 420 .set_pix_format = &ov7630_set_pix_format
@@ -373,28 +423,36 @@ static struct sn9c102_sensor ov7630 = {
373 423
374int sn9c102_probe_ov7630(struct sn9c102_device* cam) 424int sn9c102_probe_ov7630(struct sn9c102_device* cam)
375{ 425{
376 const struct usb_device_id ov7630_id_table[] = { 426 int pid, ver, err = 0;
377 { USB_DEVICE(0x0c45, 0x602c), },
378 { USB_DEVICE(0x0c45, 0x602d), },
379 { USB_DEVICE(0x0c45, 0x608f), },
380 { USB_DEVICE(0x0c45, 0x60b0), },
381 { }
382 };
383 int err = 0;
384
385 if (!sn9c102_match_id(cam, ov7630_id_table))
386 return -ENODEV;
387 427
428 switch (sn9c102_get_bridge(cam)) {
429 case BRIDGE_SN9C101:
430 case BRIDGE_SN9C102:
388 err += sn9c102_write_reg(cam, 0x01, 0x01); 431 err += sn9c102_write_reg(cam, 0x01, 0x01);
389 err += sn9c102_write_reg(cam, 0x00, 0x01); 432 err += sn9c102_write_reg(cam, 0x00, 0x01);
390 err += sn9c102_write_reg(cam, 0x28, 0x17); 433 err += sn9c102_write_reg(cam, 0x28, 0x17);
391 if (err) 434 break;
392 return -EIO; 435 case BRIDGE_SN9C103: /* do _not_ change anything! */
436 err += sn9c102_write_reg(cam, 0x09, 0x01);
437 err += sn9c102_write_reg(cam, 0x42, 0x01);
438 err += sn9c102_write_reg(cam, 0x28, 0x17);
439 err += sn9c102_write_reg(cam, 0x44, 0x02);
440 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
441 if (err || pid < 0) { /* try a different initialization */
442 err = sn9c102_write_reg(cam, 0x01, 0x01);
443 err += sn9c102_write_reg(cam, 0x00, 0x01);
444 }
445 break;
446 default:
447 break;
448 }
393 449
394 err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); 450 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
395 if (err) 451 ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
452 if (err || pid < 0 || ver < 0)
453 return -EIO;
454 if (pid != 0x76 || ver != 0x31)
396 return -ENODEV; 455 return -ENODEV;
397
398 sn9c102_attach_sensor(cam, &ov7630); 456 sn9c102_attach_sensor(cam, &ov7630);
399 457
400 return 0; 458 return 0;
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
new file mode 100644
index 000000000000..d670c24d4435
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -0,0 +1,592 @@
1/***************************************************************************
2 * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2007 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 "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor ov7660;
26
27
28static int ov7660_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x40, 0x02);
33 err += sn9c102_write_reg(cam, 0x00, 0x03);
34 err += sn9c102_write_reg(cam, 0x1a, 0x04);
35 err += sn9c102_write_reg(cam, 0x03, 0x10);
36 err += sn9c102_write_reg(cam, 0x08, 0x14);
37 err += sn9c102_write_reg(cam, 0x20, 0x17);
38 err += sn9c102_write_reg(cam, 0x8b, 0x18);
39 err += sn9c102_write_reg(cam, 0x00, 0x19);
40 err += sn9c102_write_reg(cam, 0x1d, 0x1a);
41 err += sn9c102_write_reg(cam, 0x10, 0x1b);
42 err += sn9c102_write_reg(cam, 0x02, 0x1c);
43 err += sn9c102_write_reg(cam, 0x03, 0x1d);
44 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
45 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
46 err += sn9c102_write_reg(cam, 0x00, 0x20);
47 err += sn9c102_write_reg(cam, 0x29, 0x21);
48 err += sn9c102_write_reg(cam, 0x40, 0x22);
49 err += sn9c102_write_reg(cam, 0x54, 0x23);
50 err += sn9c102_write_reg(cam, 0x66, 0x24);
51 err += sn9c102_write_reg(cam, 0x76, 0x25);
52 err += sn9c102_write_reg(cam, 0x85, 0x26);
53 err += sn9c102_write_reg(cam, 0x94, 0x27);
54 err += sn9c102_write_reg(cam, 0xa1, 0x28);
55 err += sn9c102_write_reg(cam, 0xae, 0x29);
56 err += sn9c102_write_reg(cam, 0xbb, 0x2a);
57 err += sn9c102_write_reg(cam, 0xc7, 0x2b);
58 err += sn9c102_write_reg(cam, 0xd3, 0x2c);
59 err += sn9c102_write_reg(cam, 0xde, 0x2d);
60 err += sn9c102_write_reg(cam, 0xea, 0x2e);
61 err += sn9c102_write_reg(cam, 0xf4, 0x2f);
62 err += sn9c102_write_reg(cam, 0xff, 0x30);
63 err += sn9c102_write_reg(cam, 0x00, 0x3F);
64 err += sn9c102_write_reg(cam, 0xC7, 0x40);
65 err += sn9c102_write_reg(cam, 0x01, 0x41);
66 err += sn9c102_write_reg(cam, 0x44, 0x42);
67 err += sn9c102_write_reg(cam, 0x00, 0x43);
68 err += sn9c102_write_reg(cam, 0x44, 0x44);
69 err += sn9c102_write_reg(cam, 0x00, 0x45);
70 err += sn9c102_write_reg(cam, 0x44, 0x46);
71 err += sn9c102_write_reg(cam, 0x00, 0x47);
72 err += sn9c102_write_reg(cam, 0xC7, 0x48);
73 err += sn9c102_write_reg(cam, 0x01, 0x49);
74 err += sn9c102_write_reg(cam, 0xC7, 0x4A);
75 err += sn9c102_write_reg(cam, 0x01, 0x4B);
76 err += sn9c102_write_reg(cam, 0xC7, 0x4C);
77 err += sn9c102_write_reg(cam, 0x01, 0x4D);
78 err += sn9c102_write_reg(cam, 0x44, 0x4E);
79 err += sn9c102_write_reg(cam, 0x00, 0x4F);
80 err += sn9c102_write_reg(cam, 0x44, 0x50);
81 err += sn9c102_write_reg(cam, 0x00, 0x51);
82 err += sn9c102_write_reg(cam, 0x44, 0x52);
83 err += sn9c102_write_reg(cam, 0x00, 0x53);
84 err += sn9c102_write_reg(cam, 0xC7, 0x54);
85 err += sn9c102_write_reg(cam, 0x01, 0x55);
86 err += sn9c102_write_reg(cam, 0xC7, 0x56);
87 err += sn9c102_write_reg(cam, 0x01, 0x57);
88 err += sn9c102_write_reg(cam, 0xC7, 0x58);
89 err += sn9c102_write_reg(cam, 0x01, 0x59);
90 err += sn9c102_write_reg(cam, 0x44, 0x5A);
91 err += sn9c102_write_reg(cam, 0x00, 0x5B);
92 err += sn9c102_write_reg(cam, 0x44, 0x5C);
93 err += sn9c102_write_reg(cam, 0x00, 0x5D);
94 err += sn9c102_write_reg(cam, 0x44, 0x5E);
95 err += sn9c102_write_reg(cam, 0x00, 0x5F);
96 err += sn9c102_write_reg(cam, 0xC7, 0x60);
97 err += sn9c102_write_reg(cam, 0x01, 0x61);
98 err += sn9c102_write_reg(cam, 0xC7, 0x62);
99 err += sn9c102_write_reg(cam, 0x01, 0x63);
100 err += sn9c102_write_reg(cam, 0xC7, 0x64);
101 err += sn9c102_write_reg(cam, 0x01, 0x65);
102 err += sn9c102_write_reg(cam, 0x44, 0x66);
103 err += sn9c102_write_reg(cam, 0x00, 0x67);
104 err += sn9c102_write_reg(cam, 0x44, 0x68);
105 err += sn9c102_write_reg(cam, 0x00, 0x69);
106 err += sn9c102_write_reg(cam, 0x44, 0x6A);
107 err += sn9c102_write_reg(cam, 0x00, 0x6B);
108 err += sn9c102_write_reg(cam, 0xC7, 0x6C);
109 err += sn9c102_write_reg(cam, 0x01, 0x6D);
110 err += sn9c102_write_reg(cam, 0xC7, 0x6E);
111 err += sn9c102_write_reg(cam, 0x01, 0x6F);
112 err += sn9c102_write_reg(cam, 0xC7, 0x70);
113 err += sn9c102_write_reg(cam, 0x01, 0x71);
114 err += sn9c102_write_reg(cam, 0x44, 0x72);
115 err += sn9c102_write_reg(cam, 0x00, 0x73);
116 err += sn9c102_write_reg(cam, 0x44, 0x74);
117 err += sn9c102_write_reg(cam, 0x00, 0x75);
118 err += sn9c102_write_reg(cam, 0x44, 0x76);
119 err += sn9c102_write_reg(cam, 0x00, 0x77);
120 err += sn9c102_write_reg(cam, 0xC7, 0x78);
121 err += sn9c102_write_reg(cam, 0x01, 0x79);
122 err += sn9c102_write_reg(cam, 0xC7, 0x7A);
123 err += sn9c102_write_reg(cam, 0x01, 0x7B);
124 err += sn9c102_write_reg(cam, 0xC7, 0x7C);
125 err += sn9c102_write_reg(cam, 0x01, 0x7D);
126 err += sn9c102_write_reg(cam, 0x44, 0x7E);
127 err += sn9c102_write_reg(cam, 0x00, 0x7F);
128 err += sn9c102_write_reg(cam, 0x14, 0x84);
129 err += sn9c102_write_reg(cam, 0x00, 0x85);
130 err += sn9c102_write_reg(cam, 0x27, 0x86);
131 err += sn9c102_write_reg(cam, 0x00, 0x87);
132 err += sn9c102_write_reg(cam, 0x07, 0x88);
133 err += sn9c102_write_reg(cam, 0x00, 0x89);
134 err += sn9c102_write_reg(cam, 0xEC, 0x8A);
135 err += sn9c102_write_reg(cam, 0x0f, 0x8B);
136 err += sn9c102_write_reg(cam, 0xD8, 0x8C);
137 err += sn9c102_write_reg(cam, 0x0f, 0x8D);
138 err += sn9c102_write_reg(cam, 0x3D, 0x8E);
139 err += sn9c102_write_reg(cam, 0x00, 0x8F);
140 err += sn9c102_write_reg(cam, 0x3D, 0x90);
141 err += sn9c102_write_reg(cam, 0x00, 0x91);
142 err += sn9c102_write_reg(cam, 0xCD, 0x92);
143 err += sn9c102_write_reg(cam, 0x0f, 0x93);
144 err += sn9c102_write_reg(cam, 0xf7, 0x94);
145 err += sn9c102_write_reg(cam, 0x0f, 0x95);
146 err += sn9c102_write_reg(cam, 0x0C, 0x96);
147 err += sn9c102_write_reg(cam, 0x00, 0x97);
148 err += sn9c102_write_reg(cam, 0x00, 0x98);
149 err += sn9c102_write_reg(cam, 0x66, 0x99);
150 err += sn9c102_write_reg(cam, 0x05, 0x9A);
151 err += sn9c102_write_reg(cam, 0x00, 0x9B);
152 err += sn9c102_write_reg(cam, 0x04, 0x9C);
153 err += sn9c102_write_reg(cam, 0x00, 0x9D);
154 err += sn9c102_write_reg(cam, 0x08, 0x9E);
155 err += sn9c102_write_reg(cam, 0x00, 0x9F);
156 err += sn9c102_write_reg(cam, 0x2D, 0xC0);
157 err += sn9c102_write_reg(cam, 0x2D, 0xC1);
158 err += sn9c102_write_reg(cam, 0x3A, 0xC2);
159 err += sn9c102_write_reg(cam, 0x05, 0xC3);
160 err += sn9c102_write_reg(cam, 0x04, 0xC4);
161 err += sn9c102_write_reg(cam, 0x3F, 0xC5);
162 err += sn9c102_write_reg(cam, 0x00, 0xC6);
163 err += sn9c102_write_reg(cam, 0x00, 0xC7);
164 err += sn9c102_write_reg(cam, 0x50, 0xC8);
165 err += sn9c102_write_reg(cam, 0x3C, 0xC9);
166 err += sn9c102_write_reg(cam, 0x28, 0xCA);
167 err += sn9c102_write_reg(cam, 0xD8, 0xCB);
168 err += sn9c102_write_reg(cam, 0x14, 0xCC);
169 err += sn9c102_write_reg(cam, 0xEC, 0xCD);
170 err += sn9c102_write_reg(cam, 0x32, 0xCE);
171 err += sn9c102_write_reg(cam, 0xDD, 0xCF);
172 err += sn9c102_write_reg(cam, 0x32, 0xD0);
173 err += sn9c102_write_reg(cam, 0xDD, 0xD1);
174 err += sn9c102_write_reg(cam, 0x6A, 0xD2);
175 err += sn9c102_write_reg(cam, 0x50, 0xD3);
176 err += sn9c102_write_reg(cam, 0x00, 0xD4);
177 err += sn9c102_write_reg(cam, 0x00, 0xD5);
178 err += sn9c102_write_reg(cam, 0x00, 0xD6);
179
180 err += sn9c102_i2c_write(cam, 0x12, 0x80);
181 err += sn9c102_i2c_write(cam, 0x11, 0x09);
182 err += sn9c102_i2c_write(cam, 0x00, 0x0A);
183 err += sn9c102_i2c_write(cam, 0x01, 0x78);
184 err += sn9c102_i2c_write(cam, 0x02, 0x90);
185 err += sn9c102_i2c_write(cam, 0x03, 0x00);
186 err += sn9c102_i2c_write(cam, 0x04, 0x00);
187 err += sn9c102_i2c_write(cam, 0x05, 0x08);
188 err += sn9c102_i2c_write(cam, 0x06, 0x0B);
189 err += sn9c102_i2c_write(cam, 0x07, 0x00);
190 err += sn9c102_i2c_write(cam, 0x08, 0x1C);
191 err += sn9c102_i2c_write(cam, 0x09, 0x01);
192 err += sn9c102_i2c_write(cam, 0x0A, 0x76);
193 err += sn9c102_i2c_write(cam, 0x0B, 0x60);
194 err += sn9c102_i2c_write(cam, 0x0C, 0x00);
195 err += sn9c102_i2c_write(cam, 0x0D, 0x08);
196 err += sn9c102_i2c_write(cam, 0x0E, 0x04);
197 err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
198 err += sn9c102_i2c_write(cam, 0x10, 0x20);
199 err += sn9c102_i2c_write(cam, 0x11, 0x03);
200 err += sn9c102_i2c_write(cam, 0x12, 0x05);
201 err += sn9c102_i2c_write(cam, 0x13, 0xF8);
202 err += sn9c102_i2c_write(cam, 0x14, 0x2C);
203 err += sn9c102_i2c_write(cam, 0x15, 0x00);
204 err += sn9c102_i2c_write(cam, 0x16, 0x02);
205 err += sn9c102_i2c_write(cam, 0x17, 0x10);
206 err += sn9c102_i2c_write(cam, 0x18, 0x60);
207 err += sn9c102_i2c_write(cam, 0x19, 0x02);
208 err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
209 err += sn9c102_i2c_write(cam, 0x1B, 0x02);
210 err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
211 err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
212 err += sn9c102_i2c_write(cam, 0x1E, 0x01);
213 err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
214 err += sn9c102_i2c_write(cam, 0x20, 0x05);
215 err += sn9c102_i2c_write(cam, 0x21, 0x05);
216 err += sn9c102_i2c_write(cam, 0x22, 0x05);
217 err += sn9c102_i2c_write(cam, 0x23, 0x05);
218 err += sn9c102_i2c_write(cam, 0x24, 0x68);
219 err += sn9c102_i2c_write(cam, 0x25, 0x58);
220 err += sn9c102_i2c_write(cam, 0x26, 0xD4);
221 err += sn9c102_i2c_write(cam, 0x27, 0x80);
222 err += sn9c102_i2c_write(cam, 0x28, 0x80);
223 err += sn9c102_i2c_write(cam, 0x29, 0x30);
224 err += sn9c102_i2c_write(cam, 0x2A, 0x00);
225 err += sn9c102_i2c_write(cam, 0x2B, 0x00);
226 err += sn9c102_i2c_write(cam, 0x2C, 0x80);
227 err += sn9c102_i2c_write(cam, 0x2D, 0x00);
228 err += sn9c102_i2c_write(cam, 0x2E, 0x00);
229 err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
230 err += sn9c102_i2c_write(cam, 0x30, 0x08);
231 err += sn9c102_i2c_write(cam, 0x31, 0x30);
232 err += sn9c102_i2c_write(cam, 0x32, 0xB4);
233 err += sn9c102_i2c_write(cam, 0x33, 0x00);
234 err += sn9c102_i2c_write(cam, 0x34, 0x07);
235 err += sn9c102_i2c_write(cam, 0x35, 0x84);
236 err += sn9c102_i2c_write(cam, 0x36, 0x00);
237 err += sn9c102_i2c_write(cam, 0x37, 0x0C);
238 err += sn9c102_i2c_write(cam, 0x38, 0x02);
239 err += sn9c102_i2c_write(cam, 0x39, 0x43);
240 err += sn9c102_i2c_write(cam, 0x3A, 0x00);
241 err += sn9c102_i2c_write(cam, 0x3B, 0x02);
242 err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
243 err += sn9c102_i2c_write(cam, 0x3D, 0x99);
244 err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
245 err += sn9c102_i2c_write(cam, 0x3F, 0x41);
246 err += sn9c102_i2c_write(cam, 0x40, 0xC1);
247 err += sn9c102_i2c_write(cam, 0x41, 0x22);
248 err += sn9c102_i2c_write(cam, 0x42, 0x08);
249 err += sn9c102_i2c_write(cam, 0x43, 0xF0);
250 err += sn9c102_i2c_write(cam, 0x44, 0x10);
251 err += sn9c102_i2c_write(cam, 0x45, 0x78);
252 err += sn9c102_i2c_write(cam, 0x46, 0xA8);
253 err += sn9c102_i2c_write(cam, 0x47, 0x60);
254 err += sn9c102_i2c_write(cam, 0x48, 0x80);
255 err += sn9c102_i2c_write(cam, 0x49, 0x00);
256 err += sn9c102_i2c_write(cam, 0x4A, 0x00);
257 err += sn9c102_i2c_write(cam, 0x4B, 0x00);
258 err += sn9c102_i2c_write(cam, 0x4C, 0x00);
259 err += sn9c102_i2c_write(cam, 0x4D, 0x00);
260 err += sn9c102_i2c_write(cam, 0x4E, 0x00);
261 err += sn9c102_i2c_write(cam, 0x4F, 0x46);
262 err += sn9c102_i2c_write(cam, 0x50, 0x36);
263 err += sn9c102_i2c_write(cam, 0x51, 0x0F);
264 err += sn9c102_i2c_write(cam, 0x52, 0x17);
265 err += sn9c102_i2c_write(cam, 0x53, 0x7F);
266 err += sn9c102_i2c_write(cam, 0x54, 0x96);
267 err += sn9c102_i2c_write(cam, 0x55, 0x40);
268 err += sn9c102_i2c_write(cam, 0x56, 0x40);
269 err += sn9c102_i2c_write(cam, 0x57, 0x40);
270 err += sn9c102_i2c_write(cam, 0x58, 0x0F);
271 err += sn9c102_i2c_write(cam, 0x59, 0xBA);
272 err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
273 err += sn9c102_i2c_write(cam, 0x5B, 0x22);
274 err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
275 err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
276 err += sn9c102_i2c_write(cam, 0x5E, 0x10);
277 err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
278 err += sn9c102_i2c_write(cam, 0x60, 0x05);
279 err += sn9c102_i2c_write(cam, 0x61, 0x60);
280 err += sn9c102_i2c_write(cam, 0x62, 0x00);
281 err += sn9c102_i2c_write(cam, 0x63, 0x00);
282 err += sn9c102_i2c_write(cam, 0x64, 0x50);
283 err += sn9c102_i2c_write(cam, 0x65, 0x30);
284 err += sn9c102_i2c_write(cam, 0x66, 0x00);
285 err += sn9c102_i2c_write(cam, 0x67, 0x80);
286 err += sn9c102_i2c_write(cam, 0x68, 0x7A);
287 err += sn9c102_i2c_write(cam, 0x69, 0x90);
288 err += sn9c102_i2c_write(cam, 0x6A, 0x80);
289 err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
290 err += sn9c102_i2c_write(cam, 0x6C, 0x30);
291 err += sn9c102_i2c_write(cam, 0x6D, 0x48);
292 err += sn9c102_i2c_write(cam, 0x6E, 0x80);
293 err += sn9c102_i2c_write(cam, 0x6F, 0x74);
294 err += sn9c102_i2c_write(cam, 0x70, 0x64);
295 err += sn9c102_i2c_write(cam, 0x71, 0x60);
296 err += sn9c102_i2c_write(cam, 0x72, 0x5C);
297 err += sn9c102_i2c_write(cam, 0x73, 0x58);
298 err += sn9c102_i2c_write(cam, 0x74, 0x54);
299 err += sn9c102_i2c_write(cam, 0x75, 0x4C);
300 err += sn9c102_i2c_write(cam, 0x76, 0x40);
301 err += sn9c102_i2c_write(cam, 0x77, 0x38);
302 err += sn9c102_i2c_write(cam, 0x78, 0x34);
303 err += sn9c102_i2c_write(cam, 0x79, 0x30);
304 err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
305 err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
306 err += sn9c102_i2c_write(cam, 0x7C, 0x03);
307 err += sn9c102_i2c_write(cam, 0x7D, 0x07);
308 err += sn9c102_i2c_write(cam, 0x7E, 0x17);
309 err += sn9c102_i2c_write(cam, 0x7F, 0x34);
310 err += sn9c102_i2c_write(cam, 0x80, 0x41);
311 err += sn9c102_i2c_write(cam, 0x81, 0x4D);
312 err += sn9c102_i2c_write(cam, 0x82, 0x58);
313 err += sn9c102_i2c_write(cam, 0x83, 0x63);
314 err += sn9c102_i2c_write(cam, 0x84, 0x6E);
315 err += sn9c102_i2c_write(cam, 0x85, 0x77);
316 err += sn9c102_i2c_write(cam, 0x86, 0x87);
317 err += sn9c102_i2c_write(cam, 0x87, 0x95);
318 err += sn9c102_i2c_write(cam, 0x88, 0xAF);
319 err += sn9c102_i2c_write(cam, 0x89, 0xC7);
320 err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
321 err += sn9c102_i2c_write(cam, 0x8B, 0x99);
322 err += sn9c102_i2c_write(cam, 0x8C, 0x99);
323 err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
324 err += sn9c102_i2c_write(cam, 0x8E, 0x20);
325 err += sn9c102_i2c_write(cam, 0x8F, 0x26);
326 err += sn9c102_i2c_write(cam, 0x90, 0x10);
327 err += sn9c102_i2c_write(cam, 0x91, 0x0C);
328 err += sn9c102_i2c_write(cam, 0x92, 0x25);
329 err += sn9c102_i2c_write(cam, 0x93, 0x00);
330 err += sn9c102_i2c_write(cam, 0x94, 0x50);
331 err += sn9c102_i2c_write(cam, 0x95, 0x50);
332 err += sn9c102_i2c_write(cam, 0x96, 0x00);
333 err += sn9c102_i2c_write(cam, 0x97, 0x01);
334 err += sn9c102_i2c_write(cam, 0x98, 0x10);
335 err += sn9c102_i2c_write(cam, 0x99, 0x40);
336 err += sn9c102_i2c_write(cam, 0x9A, 0x40);
337 err += sn9c102_i2c_write(cam, 0x9B, 0x20);
338 err += sn9c102_i2c_write(cam, 0x9C, 0x00);
339 err += sn9c102_i2c_write(cam, 0x9D, 0x99);
340 err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
341 err += sn9c102_i2c_write(cam, 0x9F, 0x00);
342 err += sn9c102_i2c_write(cam, 0xA0, 0x00);
343 err += sn9c102_i2c_write(cam, 0xA1, 0x00);
344
345 return err;
346}
347
348
349static int ov7660_get_ctrl(struct sn9c102_device* cam,
350 struct v4l2_control* ctrl)
351{
352 int err = 0;
353
354 switch (ctrl->id) {
355 case V4L2_CID_EXPOSURE:
356 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
357 return -EIO;
358 break;
359 case V4L2_CID_DO_WHITE_BALANCE:
360 ctrl->value = sn9c102_pread_reg(cam, 0x02);
361 ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
362 break;
363 case V4L2_CID_RED_BALANCE:
364 ctrl->value = sn9c102_pread_reg(cam, 0x05);
365 ctrl->value &= 0x7f;
366 break;
367 case V4L2_CID_BLUE_BALANCE:
368 ctrl->value = sn9c102_pread_reg(cam, 0x06);
369 ctrl->value &= 0x7f;
370 break;
371 case SN9C102_V4L2_CID_GREEN_BALANCE:
372 ctrl->value = sn9c102_pread_reg(cam, 0x07);
373 ctrl->value &= 0x7f;
374 break;
375 case V4L2_CID_GAIN:
376 if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
377 return -EIO;
378 ctrl->value &= 0x7f;
379 break;
380 case V4L2_CID_AUTOGAIN:
381 if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
382 return -EIO;
383 ctrl->value &= 0x01;
384 break;
385 default:
386 return -EINVAL;
387 }
388
389 return err ? -EIO : 0;
390}
391
392
393static int ov7660_set_ctrl(struct sn9c102_device* cam,
394 const struct v4l2_control* ctrl)
395{
396 int err = 0;
397
398 switch (ctrl->id) {
399 case V4L2_CID_EXPOSURE:
400 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
401 break;
402 case V4L2_CID_DO_WHITE_BALANCE:
403 err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
404 break;
405 case V4L2_CID_RED_BALANCE:
406 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
407 break;
408 case V4L2_CID_BLUE_BALANCE:
409 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
410 break;
411 case SN9C102_V4L2_CID_GREEN_BALANCE:
412 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
413 break;
414 case V4L2_CID_GAIN:
415 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
416 break;
417 case V4L2_CID_AUTOGAIN:
418 err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
419 (ctrl->value << 1));
420 break;
421 default:
422 return -EINVAL;
423 }
424
425 return err ? -EIO : 0;
426}
427
428
429static int ov7660_set_crop(struct sn9c102_device* cam,
430 const struct v4l2_rect* rect)
431{
432 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
433 int err = 0;
434 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
435 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
436
437 err += sn9c102_write_reg(cam, h_start, 0x12);
438 err += sn9c102_write_reg(cam, v_start, 0x13);
439
440 return err;
441}
442
443
444static int ov7660_set_pix_format(struct sn9c102_device* cam,
445 const struct v4l2_pix_format* pix)
446{
447 int r0, err = 0;
448
449 r0 = sn9c102_pread_reg(cam, 0x01);
450
451 if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
452 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
453 err += sn9c102_write_reg(cam, 0xa2, 0x17);
454 err += sn9c102_i2c_write(cam, 0x11, 0x00);
455 } else {
456 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
457 err += sn9c102_write_reg(cam, 0xa2, 0x17);
458 err += sn9c102_i2c_write(cam, 0x11, 0x0d);
459 }
460
461 return err;
462}
463
464
465static struct sn9c102_sensor ov7660 = {
466 .name = "OV7660",
467 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
468 .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
469 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
470 .frequency = SN9C102_I2C_100KHZ,
471 .interface = SN9C102_I2C_2WIRES,
472 .i2c_slave_id = 0x21,
473 .init = &ov7660_init,
474 .qctrl = {
475 {
476 .id = V4L2_CID_GAIN,
477 .type = V4L2_CTRL_TYPE_INTEGER,
478 .name = "global gain",
479 .minimum = 0x00,
480 .maximum = 0x7f,
481 .step = 0x01,
482 .default_value = 0x0a,
483 .flags = 0,
484 },
485 {
486 .id = V4L2_CID_EXPOSURE,
487 .type = V4L2_CTRL_TYPE_INTEGER,
488 .name = "exposure",
489 .minimum = 0x00,
490 .maximum = 0xff,
491 .step = 0x01,
492 .default_value = 0x50,
493 .flags = 0,
494 },
495 {
496 .id = V4L2_CID_DO_WHITE_BALANCE,
497 .type = V4L2_CTRL_TYPE_BOOLEAN,
498 .name = "night mode",
499 .minimum = 0x00,
500 .maximum = 0x01,
501 .step = 0x01,
502 .default_value = 0x00,
503 .flags = 0,
504 },
505 {
506 .id = V4L2_CID_RED_BALANCE,
507 .type = V4L2_CTRL_TYPE_INTEGER,
508 .name = "red balance",
509 .minimum = 0x00,
510 .maximum = 0x7f,
511 .step = 0x01,
512 .default_value = 0x1f,
513 .flags = 0,
514 },
515 {
516 .id = V4L2_CID_BLUE_BALANCE,
517 .type = V4L2_CTRL_TYPE_INTEGER,
518 .name = "blue balance",
519 .minimum = 0x00,
520 .maximum = 0x7f,
521 .step = 0x01,
522 .default_value = 0x1e,
523 .flags = 0,
524 },
525 {
526 .id = V4L2_CID_AUTOGAIN,
527 .type = V4L2_CTRL_TYPE_BOOLEAN,
528 .name = "auto adjust",
529 .minimum = 0x00,
530 .maximum = 0x01,
531 .step = 0x01,
532 .default_value = 0x00,
533 .flags = 0,
534 },
535 {
536 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
537 .type = V4L2_CTRL_TYPE_INTEGER,
538 .name = "green balance",
539 .minimum = 0x00,
540 .maximum = 0x7f,
541 .step = 0x01,
542 .default_value = 0x20,
543 .flags = 0,
544 },
545 },
546 .get_ctrl = &ov7660_get_ctrl,
547 .set_ctrl = &ov7660_set_ctrl,
548 .cropcap = {
549 .bounds = {
550 .left = 0,
551 .top = 0,
552 .width = 640,
553 .height = 480,
554 },
555 .defrect = {
556 .left = 0,
557 .top = 0,
558 .width = 640,
559 .height = 480,
560 },
561 },
562 .set_crop = &ov7660_set_crop,
563 .pix_format = {
564 .width = 640,
565 .height = 480,
566 .pixelformat = V4L2_PIX_FMT_JPEG,
567 .priv = 8,
568 },
569 .set_pix_format = &ov7660_set_pix_format
570};
571
572
573int sn9c102_probe_ov7660(struct sn9c102_device* cam)
574{
575 int pid, ver, err = 0;
576
577 err += sn9c102_write_reg(cam, 0x01, 0xf1);
578 err += sn9c102_write_reg(cam, 0x00, 0xf1);
579 err += sn9c102_write_reg(cam, 0x01, 0x01);
580 err += sn9c102_write_reg(cam, 0x00, 0x01);
581 err += sn9c102_write_reg(cam, 0x28, 0x17);
582
583 pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
584 ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
585 if (err || pid < 0 || ver < 0)
586 return -EIO;
587 if (pid != 0x76 || ver != 0x60)
588 return -ENODEV;
589 sn9c102_attach_sensor(cam, &ov7660);
590
591 return 0;
592}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 9915944235e8..8d79a5fae5de 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -143,7 +143,7 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
143static int pas106b_set_crop(struct sn9c102_device* cam, 143static int pas106b_set_crop(struct sn9c102_device* cam,
144 const struct v4l2_rect* rect) 144 const struct v4l2_rect* rect)
145{ 145{
146 struct sn9c102_sensor* s = &pas106b; 146 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
147 int err = 0; 147 int err = 0;
148 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, 148 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
149 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; 149 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
@@ -172,6 +172,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
172static struct sn9c102_sensor pas106b = { 172static struct sn9c102_sensor pas106b = {
173 .name = "PAS106B", 173 .name = "PAS106B",
174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
175 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
175 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 176 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
176 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 177 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
177 .interface = SN9C102_I2C_2WIRES, 178 .interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
deleted file mode 100644
index c8f1ae2152b8..000000000000
--- a/drivers/media/video/sn9c102/sn9c102_pas202bca.c
+++ /dev/null
@@ -1,238 +0,0 @@
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/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index e3c1178e339c..7894f01b56e8 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -1,13 +1,13 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * 5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
6 * <medaglia@undl.org.br> * 6 * <medaglia@undl.org.br> *
7 * http://cadu.homelinux.com:8080/ * 7 * http://cadu.homelinux.com:8080/ *
8 * * 8 * *
9 * DAC Magnitude, exposure and green gain controls added by * 9 * Support for SN9C103, DAC Magnitude, exposure and green gain controls *
10 * Luca Risolia <luca.risolia@studio.unibo.it> * 10 * added by Luca Risolia <luca.risolia@studio.unibo.it> *
11 * * 11 * *
12 * This program is free software; you can redistribute it and/or modify * 12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by * 13 * it under the terms of the GNU General Public License as published by *
@@ -35,12 +35,54 @@ static int pas202bcb_init(struct sn9c102_device* cam)
35{ 35{
36 int err = 0; 36 int err = 0;
37 37
38 switch (sn9c102_get_bridge(cam)) {
39 case BRIDGE_SN9C101:
40 case BRIDGE_SN9C102:
38 err += sn9c102_write_reg(cam, 0x00, 0x10); 41 err += sn9c102_write_reg(cam, 0x00, 0x10);
39 err += sn9c102_write_reg(cam, 0x00, 0x11); 42 err += sn9c102_write_reg(cam, 0x00, 0x11);
40 err += sn9c102_write_reg(cam, 0x00, 0x14); 43 err += sn9c102_write_reg(cam, 0x00, 0x14);
41 err += sn9c102_write_reg(cam, 0x20, 0x17); 44 err += sn9c102_write_reg(cam, 0x20, 0x17);
42 err += sn9c102_write_reg(cam, 0x30, 0x19); 45 err += sn9c102_write_reg(cam, 0x30, 0x19);
43 err += sn9c102_write_reg(cam, 0x09, 0x18); 46 err += sn9c102_write_reg(cam, 0x09, 0x18);
47 break;
48 case BRIDGE_SN9C103:
49 err += sn9c102_write_reg(cam, 0x00, 0x02);
50 err += sn9c102_write_reg(cam, 0x00, 0x03);
51 err += sn9c102_write_reg(cam, 0x1a, 0x04);
52 err += sn9c102_write_reg(cam, 0x20, 0x05);
53 err += sn9c102_write_reg(cam, 0x20, 0x06);
54 err += sn9c102_write_reg(cam, 0x20, 0x07);
55 err += sn9c102_write_reg(cam, 0x00, 0x10);
56 err += sn9c102_write_reg(cam, 0x00, 0x11);
57 err += sn9c102_write_reg(cam, 0x00, 0x14);
58 err += sn9c102_write_reg(cam, 0x20, 0x17);
59 err += sn9c102_write_reg(cam, 0x30, 0x19);
60 err += sn9c102_write_reg(cam, 0x09, 0x18);
61 err += sn9c102_write_reg(cam, 0x02, 0x1c);
62 err += sn9c102_write_reg(cam, 0x03, 0x1d);
63 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
64 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
65 err += sn9c102_write_reg(cam, 0x00, 0x20);
66 err += sn9c102_write_reg(cam, 0x10, 0x21);
67 err += sn9c102_write_reg(cam, 0x20, 0x22);
68 err += sn9c102_write_reg(cam, 0x30, 0x23);
69 err += sn9c102_write_reg(cam, 0x40, 0x24);
70 err += sn9c102_write_reg(cam, 0x50, 0x25);
71 err += sn9c102_write_reg(cam, 0x60, 0x26);
72 err += sn9c102_write_reg(cam, 0x70, 0x27);
73 err += sn9c102_write_reg(cam, 0x80, 0x28);
74 err += sn9c102_write_reg(cam, 0x90, 0x29);
75 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
76 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
77 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
78 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
79 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
80 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
81 err += sn9c102_write_reg(cam, 0xff, 0x30);
82 break;
83 default:
84 break;
85 }
44 86
45 err += sn9c102_i2c_write(cam, 0x02, 0x14); 87 err += sn9c102_i2c_write(cam, 0x02, 0x14);
46 err += sn9c102_i2c_write(cam, 0x03, 0x40); 88 err += sn9c102_i2c_write(cam, 0x03, 0x40);
@@ -107,7 +149,7 @@ static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
107 int err = 0; 149 int err = 0;
108 150
109 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 151 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
110 err += sn9c102_write_reg(cam, 0x24, 0x17); 152 err += sn9c102_write_reg(cam, 0x28, 0x17);
111 else 153 else
112 err += sn9c102_write_reg(cam, 0x20, 0x17); 154 err += sn9c102_write_reg(cam, 0x20, 0x17);
113 155
@@ -152,11 +194,23 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
152static int pas202bcb_set_crop(struct sn9c102_device* cam, 194static int pas202bcb_set_crop(struct sn9c102_device* cam,
153 const struct v4l2_rect* rect) 195 const struct v4l2_rect* rect)
154{ 196{
155 struct sn9c102_sensor* s = &pas202bcb; 197 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
156 int err = 0; 198 int err = 0;
157 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, 199 u8 h_start = 0,
158 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; 200 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
159 201
202 switch (sn9c102_get_bridge(cam)) {
203 case BRIDGE_SN9C101:
204 case BRIDGE_SN9C102:
205 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
206 break;
207 case BRIDGE_SN9C103:
208 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
209 break;
210 default:
211 break;
212 }
213
160 err += sn9c102_write_reg(cam, h_start, 0x12); 214 err += sn9c102_write_reg(cam, h_start, 0x12);
161 err += sn9c102_write_reg(cam, v_start, 0x13); 215 err += sn9c102_write_reg(cam, v_start, 0x13);
162 216
@@ -166,8 +220,8 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
166 220
167static struct sn9c102_sensor pas202bcb = { 221static struct sn9c102_sensor pas202bcb = {
168 .name = "PAS202BCB", 222 .name = "PAS202BCB",
169 .maintainer = "Carlos Eduardo Medaglia Dyonisio " 223 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
170 "<medaglia@undl.org.br>", 224 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
171 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 225 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
172 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 226 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
173 .interface = SN9C102_I2C_2WIRES, 227 .interface = SN9C102_I2C_2WIRES,
@@ -191,7 +245,7 @@ static struct sn9c102_sensor pas202bcb = {
191 .minimum = 0x00, 245 .minimum = 0x00,
192 .maximum = 0x1f, 246 .maximum = 0x1f,
193 .step = 0x01, 247 .step = 0x01,
194 .default_value = 0x0c, 248 .default_value = 0x0b,
195 .flags = 0, 249 .flags = 0,
196 }, 250 },
197 { 251 {
@@ -201,7 +255,7 @@ static struct sn9c102_sensor pas202bcb = {
201 .minimum = 0x00, 255 .minimum = 0x00,
202 .maximum = 0x0f, 256 .maximum = 0x0f,
203 .step = 0x01, 257 .step = 0x01,
204 .default_value = 0x01, 258 .default_value = 0x00,
205 .flags = 0, 259 .flags = 0,
206 }, 260 },
207 { 261 {
@@ -271,16 +325,27 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
271 * Minimal initialization to enable the I2C communication 325 * Minimal initialization to enable the I2C communication
272 * NOTE: do NOT change the values! 326 * NOTE: do NOT change the values!
273 */ 327 */
274 err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ 328 switch (sn9c102_get_bridge(cam)) {
275 err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ 329 case BRIDGE_SN9C101:
276 err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ 330 case BRIDGE_SN9C102:
277 if (err) 331 err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */
278 return -EIO; 332 err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */
333 err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */
334 break;
335 case BRIDGE_SN9C103: /* do _not_ change anything! */
336 err += sn9c102_write_reg(cam, 0x09, 0x01);
337 err += sn9c102_write_reg(cam, 0x44, 0x01);
338 err += sn9c102_write_reg(cam, 0x44, 0x02);
339 err += sn9c102_write_reg(cam, 0x29, 0x17);
340 break;
341 default:
342 break;
343 }
279 344
280 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); 345 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
281 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); 346 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
282 347
283 if (r0 < 0 || r1 < 0) 348 if (err || r0 < 0 || r1 < 0)
284 return -EIO; 349 return -EIO;
285 350
286 pid = (r0 << 4) | ((r1 & 0xf0) >> 4); 351 pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 2a874ee6f9f5..05f2942639c3 100644
--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -1,7 +1,7 @@
1/*************************************************************************** 1/***************************************************************************
2 * API for image sensors connected to the SN9C10x PC Camera Controllers * 2 * API for image sensors connected to the SN9C1xx PC Camera Controllers *
3 * * 3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 4 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * * 5 * *
6 * This program is free software; you can redistribute it and/or modify * 6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by * 7 * it under the terms of the GNU General Public License as published by *
@@ -36,14 +36,13 @@ struct sn9c102_sensor;
36/* 36/*
37 OVERVIEW. 37 OVERVIEW.
38 This is a small interface that allows you to add support for any CCD/CMOS 38 This is a small interface that allows you to add support for any CCD/CMOS
39 image sensors connected to the SN9C10X bridges. The entire API is documented 39 image sensors connected to the SN9C1XX bridges. The entire API is documented
40 below. In the most general case, to support a sensor there are three steps 40 below. In the most general case, to support a sensor there are three steps
41 you have to follow: 41 you have to follow:
42 1) define the main "sn9c102_sensor" structure by setting the basic fields; 42 1) define the main "sn9c102_sensor" structure by setting the basic fields;
43 2) write a probing function to be called by the core module when the USB 43 2) write a probing function to be called by the core module when the USB
44 camera is recognized, then add both the USB ids and the name of that 44 camera is recognized, then add both the USB ids and the name of that
45 function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see 45 function to the two corresponding tables in sn9c102_devtable.h;
46 below);
47 3) implement the methods that you want/need (and fill the rest of the main 46 3) implement the methods that you want/need (and fill the rest of the main
48 structure accordingly). 47 structure accordingly).
49 "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do 48 "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
@@ -54,42 +53,21 @@ struct sn9c102_sensor;
54 53
55/*****************************************************************************/ 54/*****************************************************************************/
56 55
57/* 56enum sn9c102_bridge {
58 Probing functions: on success, you must attach the sensor to the camera 57 BRIDGE_SN9C101 = 0x01,
59 by calling sn9c102_attach_sensor() provided below. 58 BRIDGE_SN9C102 = 0x02,
60 To enable the I2C communication, you might need to perform a really basic 59 BRIDGE_SN9C103 = 0x04,
61 initialization of the SN9C10X chip by using the write function declared 60 BRIDGE_SN9C105 = 0x08,
62 ahead. 61 BRIDGE_SN9C120 = 0x10,
63 Functions must return 0 on success, the appropriate error otherwise.
64*/
65extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
67extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
68extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
69extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
70extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
71extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
72extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
73
74/*
75 Add the above entries to this table. Be sure to add the entry in the right
76 place, since, on failure, the next probing routine is called according to
77 the order of the list below, from top to bottom.
78*/
79#define SN9C102_SENSOR_TABLE \
80static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \
81 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \
82 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
83 &sn9c102_probe_pas202bcb, /* 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 */ \
86 &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \
87 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
88 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
89 NULL, \
90}; 62};
91 63
92/* Device identification */ 64/* Return the bridge name */
65enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam);
66
67/* Return a pointer the sensor struct attached to the camera */
68struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam);
69
70/* Identify a device */
93extern struct sn9c102_device* 71extern struct sn9c102_device*
94sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); 72sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
95 73
@@ -99,68 +77,8 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
99 struct sn9c102_sensor* sensor); 77 struct sn9c102_sensor* sensor);
100 78
101/* 79/*
102 Each SN9C10x camera has proper PID/VID identifiers.
103 SN9C103 supports multiple interfaces, but we only handle the video class
104 interface.
105*/
106#define SN9C102_USB_DEVICE(vend, prod, intclass) \
107 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
108 USB_DEVICE_ID_MATCH_INT_CLASS, \
109 .idVendor = (vend), \
110 .idProduct = (prod), \
111 .bInterfaceClass = (intclass)
112
113#define SN9C102_ID_TABLE \
114static const struct usb_device_id sn9c102_id_table[] = { \
115 { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \
116 { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \
117 { USB_DEVICE(0x0c45, 0x6007), }, \
118 { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \
119 { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \
120 { USB_DEVICE(0x0c45, 0x6024), }, \
121 { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \
122 { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \
123 { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \
124 { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \
125 { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
126 { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \
127 { USB_DEVICE(0x0c45, 0x602d), }, \
128 { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \
129 { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
130 { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \
131 { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \
132 { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \
133 { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \
134 { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \
135 { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \
136 { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \
137 { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \
138 { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \
139 { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \
140 { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \
141 { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \
142 { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \
143 { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \
144 { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \
145 { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \
146 { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \
147 { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \
148 { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \
149 { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \
150 { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \
151 { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \
152 { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \
153 { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \
154 { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \
155 { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \
156 { } \
157};
158
159/*****************************************************************************/
160
161/*
162 Read/write routines: they always return -1 on error, 0 or the read value 80 Read/write routines: they always return -1 on error, 0 or the read value
163 otherwise. NOTE that a real read operation is not supported by the SN9C10X 81 otherwise. NOTE that a real read operation is not supported by the SN9C1XX
164 chip for some of its registers. To work around this problem, a pseudo-read 82 chip for some of its registers. To work around this problem, a pseudo-read
165 call is provided instead: it returns the last successfully written value 83 call is provided instead: it returns the last successfully written value
166 on the register (0 if it has never been written), the usual -1 on error. 84 on the register (0 if it has never been written), the usual -1 on error.
@@ -176,7 +94,7 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
176 These must be used if and only if the sensor doesn't implement the standard 94 These must be used if and only if the sensor doesn't implement the standard
177 I2C protocol. There are a number of good reasons why you must use the 95 I2C protocol. There are a number of good reasons why you must use the
178 single-byte versions of these functions: do not abuse. The first function 96 single-byte versions of these functions: do not abuse. The first function
179 writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X 97 writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
180 chip. The second one programs the registers 0x09 and 0x10 with data0 and 98 chip. The second one programs the registers 0x09 and 0x10 with data0 and
181 data1, and places the n bytes read from the sensor register table in the 99 data1, and places the n bytes read from the sensor register table in the
182 buffer pointed by 'buffer'. Both the functions return -1 on error; the write 100 buffer pointed by 'buffer'. Both the functions return -1 on error; the write
@@ -200,16 +118,6 @@ extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
200extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); 118extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
201extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); 119extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
202 120
203/*
204 NOTE: there are no exported debugging functions. To uniform the output you
205 must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
206 already included here, the argument being the struct device '&usbdev->dev'
207 of the sensor structure. Do NOT use these macros before the sensor is
208 attached or the kernel will crash! However, you should not need to notify
209 the user about common errors or other messages, since this is done by the
210 master module.
211*/
212
213/*****************************************************************************/ 121/*****************************************************************************/
214 122
215enum sn9c102_i2c_sysfs_ops { 123enum sn9c102_i2c_sysfs_ops {
@@ -227,17 +135,19 @@ enum sn9c102_i2c_interface {
227 SN9C102_I2C_3WIRES, 135 SN9C102_I2C_3WIRES,
228}; 136};
229 137
230#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 138#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
231 139
232struct sn9c102_sensor { 140struct sn9c102_sensor {
233 char name[32], /* sensor name */ 141 char name[32], /* sensor name */
234 maintainer[64]; /* name of the mantainer <email> */ 142 maintainer[64]; /* name of the mantainer <email> */
235 143
144 enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
145
236 /* Supported operations through the 'sysfs' interface */ 146 /* Supported operations through the 'sysfs' interface */
237 enum sn9c102_i2c_sysfs_ops sysfs_ops; 147 enum sn9c102_i2c_sysfs_ops sysfs_ops;
238 148
239 /* 149 /*
240 These sensor capabilities must be provided if the SN9C10X controller 150 These sensor capabilities must be provided if the SN9C1XX controller
241 needs to communicate through the sensor serial interface by using 151 needs to communicate through the sensor serial interface by using
242 at least one of the i2c functions available. 152 at least one of the i2c functions available.
243 */ 153 */
@@ -260,7 +170,7 @@ struct sn9c102_sensor {
260 /* 170 /*
261 This function will be called after the sensor has been attached. 171 This function will be called after the sensor has been attached.
262 It should be used to initialize the sensor only, but may also 172 It should be used to initialize the sensor only, but may also
263 configure part of the SN9C10X chip if necessary. You don't need to 173 configure part of the SN9C1XX chip if necessary. You don't need to
264 setup picture settings like brightness, contrast, etc.. here, if 174 setup picture settings like brightness, contrast, etc.. here, if
265 the corrisponding controls are implemented (see below), since 175 the corrisponding controls are implemented (see below), since
266 they are adjusted in the core driver by calling the set_ctrl() 176 they are adjusted in the core driver by calling the set_ctrl()
@@ -300,7 +210,7 @@ struct sn9c102_sensor {
300 It is not always true that the largest achievable active window can 210 It is not always true that the largest achievable active window can
301 cover the whole array of pixels. The V4L2 API defines another 211 cover the whole array of pixels. The V4L2 API defines another
302 area called "source rectangle", which, in turn, is a subrectangle of 212 area called "source rectangle", which, in turn, is a subrectangle of
303 the active window. The SN9C10X chip is always programmed to read the 213 the active window. The SN9C1XX chip is always programmed to read the
304 source rectangle. 214 source rectangle.
305 The bounds of both the active window and the source rectangle are 215 The bounds of both the active window and the source rectangle are
306 specified in the cropcap substructures 'bounds' and 'defrect'. 216 specified in the cropcap substructures 'bounds' and 'defrect'.
@@ -326,13 +236,13 @@ struct sn9c102_sensor {
326 const struct v4l2_rect* rect); 236 const struct v4l2_rect* rect);
327 /* 237 /*
328 To be called on VIDIOC_C_SETCROP. The core module always calls a 238 To be called on VIDIOC_C_SETCROP. The core module always calls a
329 default routine which configures the appropriate SN9C10X regs (also 239 default routine which configures the appropriate SN9C1XX regs (also
330 scaling), but you may need to override/adjust specific stuff. 240 scaling), but you may need to override/adjust specific stuff.
331 'rect' contains width and height values that are multiple of 16: in 241 'rect' contains width and height values that are multiple of 16: in
332 case you override the default function, you always have to program 242 case you override the default function, you always have to program
333 the chip to match those values; on error return the corresponding 243 the chip to match those values; on error return the corresponding
334 error code without rolling back. 244 error code without rolling back.
335 NOTE: in case, you must program the SN9C10X chip to get rid of 245 NOTE: in case, you must program the SN9C1XX chip to get rid of
336 blank pixels or blank lines at the _start_ of each line or 246 blank pixels or blank lines at the _start_ of each line or
337 frame after each HSYNC or VSYNC, so that the image starts with 247 frame after each HSYNC or VSYNC, so that the image starts with
338 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, 248 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
@@ -344,16 +254,16 @@ struct sn9c102_sensor {
344 /* 254 /*
345 What you have to define here are: 1) initial 'width' and 'height' of 255 What you have to define here are: 1) initial 'width' and 'height' of
346 the target rectangle 2) the initial 'pixelformat', which can be 256 the target rectangle 2) the initial 'pixelformat', which can be
347 either V4L2_PIX_FMT_SN9C10X (for compressed video) or 257 either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
348 V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the 258 or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
349 number of bits per pixel for uncompressed video, 8 or 9 (despite the 259 the number of bits per pixel for uncompressed video, 8 or 9 (despite
350 current value of 'pixelformat'). 260 the current value of 'pixelformat').
351 NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 261 NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
352 of cropcap.defrect.width and cropcap.defrect.height. I 262 of cropcap.defrect.width and cropcap.defrect.height. I
353 suggest 1/1. 263 suggest 1/1.
354 NOTE 2: The initial compression quality is defined by the first bit 264 NOTE 2: The initial compression quality is defined by the first bit
355 of reg 0x17 during the initialization of the image sensor. 265 of reg 0x17 during the initialization of the image sensor.
356 NOTE 3: as said above, you have to program the SN9C10X chip to get 266 NOTE 3: as said above, you have to program the SN9C1XX chip to get
357 rid of any blank pixels, so that the output of the sensor 267 rid of any blank pixels, so that the output of the sensor
358 matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). 268 matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
359 */ 269 */
@@ -378,12 +288,12 @@ struct sn9c102_sensor {
378/*****************************************************************************/ 288/*****************************************************************************/
379 289
380/* Private ioctl's for control settings supported by some image sensors */ 290/* Private ioctl's for control settings supported by some image sensors */
381#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE 291#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
382#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 292#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
383#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 293#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
384#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 294#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
385#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4 295#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
386#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5 296#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
387#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6 297#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
388 298
389#endif /* _SN9C102_SENSOR_H_ */ 299#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 294eb02fbd88..90023ad63adc 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -64,7 +64,7 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
64static int tas5110c1b_set_crop(struct sn9c102_device* cam, 64static int tas5110c1b_set_crop(struct sn9c102_device* cam,
65 const struct v4l2_rect* rect) 65 const struct v4l2_rect* rect)
66{ 66{
67 struct sn9c102_sensor* s = &tas5110c1b; 67 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
68 int err = 0; 68 int err = 0;
69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, 69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; 70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
@@ -98,6 +98,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
98static struct sn9c102_sensor tas5110c1b = { 98static struct sn9c102_sensor tas5110c1b = {
99 .name = "TAS5110C1B", 99 .name = "TAS5110C1B",
100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
101 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
101 .sysfs_ops = SN9C102_I2C_WRITE, 102 .sysfs_ops = SN9C102_I2C_WRITE,
102 .frequency = SN9C102_I2C_100KHZ, 103 .frequency = SN9C102_I2C_100KHZ,
103 .interface = SN9C102_I2C_3WIRES, 104 .interface = SN9C102_I2C_3WIRES,
@@ -145,6 +146,7 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
145 const struct usb_device_id tas5110c1b_id_table[] = { 146 const struct usb_device_id tas5110c1b_id_table[] = {
146 { USB_DEVICE(0x0c45, 0x6001), }, 147 { USB_DEVICE(0x0c45, 0x6001), },
147 { USB_DEVICE(0x0c45, 0x6005), }, 148 { USB_DEVICE(0x0c45, 0x6005), },
149 { USB_DEVICE(0x0c45, 0x6007), },
148 { USB_DEVICE(0x0c45, 0x60ab), }, 150 { USB_DEVICE(0x0c45, 0x60ab), },
149 { } 151 { }
150 }; 152 };
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index 9ecb09032b68..cb1b318bc1ff 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -1,8 +1,8 @@
1/*************************************************************************** 1/***************************************************************************
2 * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * 2 * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers * 3 * Controllers *
4 * * 4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * * 6 * *
7 * This program is free software; you can redistribute it and/or modify * 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 * 8 * it under the terms of the GNU General Public License as published by *
@@ -65,7 +65,7 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
65static int tas5130d1b_set_crop(struct sn9c102_device* cam, 65static int tas5130d1b_set_crop(struct sn9c102_device* cam,
66 const struct v4l2_rect* rect) 66 const struct v4l2_rect* rect)
67{ 67{
68 struct sn9c102_sensor* s = &tas5130d1b; 68 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, 69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; 70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
71 int err = 0; 71 int err = 0;
@@ -99,6 +99,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
99static struct sn9c102_sensor tas5130d1b = { 99static struct sn9c102_sensor tas5130d1b = {
100 .name = "TAS5130D1B", 100 .name = "TAS5130D1B",
101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
102 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
102 .sysfs_ops = SN9C102_I2C_WRITE, 103 .sysfs_ops = SN9C102_I2C_WRITE,
103 .frequency = SN9C102_I2C_100KHZ, 104 .frequency = SN9C102_I2C_100KHZ,
104 .interface = SN9C102_I2C_3WIRES, 105 .interface = SN9C102_I2C_3WIRES,
@@ -154,6 +155,7 @@ static struct sn9c102_sensor tas5130d1b = {
154int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) 155int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
155{ 156{
156 const struct usb_device_id tas5130d1b_id_table[] = { 157 const struct usb_device_id tas5130d1b_id_table[] = {
158 { USB_DEVICE(0x0c45, 0x6024), },
157 { USB_DEVICE(0x0c45, 0x6025), }, 159 { USB_DEVICE(0x0c45, 0x6025), },
158 { USB_DEVICE(0x0c45, 0x60aa), }, 160 { USB_DEVICE(0x0c45, 0x60aa), },
159 { } 161 { }