aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2005-06-25 10:30:24 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-07-12 14:52:56 -0400
commitb9df978f1974fea373741367b5d79a2ed3b7dcf9 (patch)
treee1eea703ac8af72697dc1e7c6df3ea61043ec590
parent8fd6db47b90c7ecac32e3211f771849e148bdb07 (diff)
[PATCH] USB: SN9C10x driver updates
SN9C10x driver updates. Changes: + new, - removed, * cleanup, @ bugfix @ Remove bad get_ctrl()'s * Documentation updates + Add 0x0c45/0x602d to the list of SN9C10x based devices + Add support for OV7630 image sensors Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/usb/sn9c102.txt4
-rw-r--r--drivers/usb/media/Makefile2
-rw-r--r--drivers/usb/media/sn9c102.h2
-rw-r--r--drivers/usb/media/sn9c102_core.c2
-rw-r--r--drivers/usb/media/sn9c102_ov7630.c394
-rw-r--r--drivers/usb/media/sn9c102_sensor.h16
-rw-r--r--drivers/usb/media/sn9c102_tas5110c1b.c21
-rw-r--r--drivers/usb/media/sn9c102_tas5130d1b.c27
8 files changed, 417 insertions, 51 deletions
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index cf9a1187edce..3f8a119db31b 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -297,6 +297,7 @@ Vendor ID Product ID
2970x0c45 0x602a 2970x0c45 0x602a
2980x0c45 0x602b 2980x0c45 0x602b
2990x0c45 0x602c 2990x0c45 0x602c
3000x0c45 0x602d
3000x0c45 0x6030 3010x0c45 0x6030
3010x0c45 0x6080 3020x0c45 0x6080
3020x0c45 0x6082 3030x0c45 0x6082
@@ -333,6 +334,7 @@ Model Manufacturer
333----- ------------ 334----- ------------
334HV7131D Hynix Semiconductor, Inc. 335HV7131D Hynix Semiconductor, Inc.
335MI-0343 Micron Technology, Inc. 336MI-0343 Micron Technology, Inc.
337OV7630 OmniVision Technologies, Inc.
336PAS106B PixArt Imaging, Inc. 338PAS106B PixArt Imaging, Inc.
337PAS202BCB PixArt Imaging, Inc. 339PAS202BCB PixArt Imaging, Inc.
338TAS5110C1B Taiwan Advanced Sensor Corporation 340TAS5110C1B Taiwan Advanced Sensor Corporation
@@ -470,9 +472,11 @@ order):
470- Luca Capello for the donation of a webcam; 472- Luca Capello for the donation of a webcam;
471- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the 473- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
472 donation of a webcam; 474 donation of a webcam;
475- Jon Hollstrom for the donation of a webcam;
473- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB 476- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
474 image sensor; 477 image sensor;
475- Stefano Mozzi, who donated 45 EU; 478- Stefano Mozzi, who donated 45 EU;
479- Andrew Pearce for the donation of a webcam;
476- Bertrik Sikken, who reverse-engineered and documented the Huffman compression 480- Bertrik Sikken, who reverse-engineered and documented the Huffman compression
477 algorithm used in the SN9C10x controllers and implemented the first decoder; 481 algorithm used in the SN9C10x controllers and implemented the first decoder;
478- Mizuno Takafumi for the donation of a webcam; 482- Mizuno Takafumi for the donation of a webcam;
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 2b76df7005fe..d83adffa925f 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -2,7 +2,7 @@
2# Makefile for USB Media drivers 2# Makefile for USB Media drivers
3# 3#
4 4
5sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o 5sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
6 6
7obj-$(CONFIG_USB_DABUSB) += dabusb.o 7obj-$(CONFIG_USB_DABUSB) += dabusb.o
8obj-$(CONFIG_USB_DSBR) += dsbr100.o 8obj-$(CONFIG_USB_DSBR) += dsbr100.o
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index 8b8a4c8743f8..e5cea0e2eb57 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -56,7 +56,7 @@
56#define SN9C102_MODULE_AUTHOR "(C) 2004-2005 Luca Risolia" 56#define SN9C102_MODULE_AUTHOR "(C) 2004-2005 Luca Risolia"
57#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 57#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
58#define SN9C102_MODULE_LICENSE "GPL" 58#define SN9C102_MODULE_LICENSE "GPL"
59#define SN9C102_MODULE_VERSION "1:1.24" 59#define SN9C102_MODULE_VERSION "1:1.24a"
60#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 24) 60#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 24)
61 61
62enum sn9c102_bridge { 62enum sn9c102_bridge {
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 31d57400d5be..cf8cfbabefde 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -429,7 +429,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
429} 429}
430 430
431 431
432static int 432int
433sn9c102_i2c_try_write(struct sn9c102_device* cam, 433sn9c102_i2c_try_write(struct sn9c102_device* cam,
434 struct sn9c102_sensor* sensor, u8 address, u8 value) 434 struct sn9c102_sensor* sensor, u8 address, u8 value)
435{ 435{
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c
new file mode 100644
index 000000000000..d27c5aedeaf8
--- /dev/null
+++ b/drivers/usb/media/sn9c102_ov7630.c
@@ -0,0 +1,394 @@
1/***************************************************************************
2 * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2005 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 ov7630;
26
27
28static int ov7630_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x00, 0x14);
33 err += sn9c102_write_reg(cam, 0x60, 0x17);
34 err += sn9c102_write_reg(cam, 0x0f, 0x18);
35 err += sn9c102_write_reg(cam, 0x50, 0x19);
36
37 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
38 err += sn9c102_i2c_write(cam, 0x11, 0x00);
39 err += sn9c102_i2c_write(cam, 0x15, 0x34);
40 err += sn9c102_i2c_write(cam, 0x16, 0x03);
41 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
42 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
43 err += sn9c102_i2c_write(cam, 0x19, 0x06);
44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
45 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
46 err += sn9c102_i2c_write(cam, 0x20, 0x44);
47 err += sn9c102_i2c_write(cam, 0x23, 0xee);
48 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
49 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
50 err += sn9c102_i2c_write(cam, 0x28, 0x20);
51 err += sn9c102_i2c_write(cam, 0x29, 0x30);
52 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
53 err += sn9c102_i2c_write(cam, 0x30, 0x24);
54 err += sn9c102_i2c_write(cam, 0x32, 0x86);
55 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
56 err += sn9c102_i2c_write(cam, 0x61, 0x42);
57 err += sn9c102_i2c_write(cam, 0x65, 0x00);
58 err += sn9c102_i2c_write(cam, 0x69, 0x38);
59 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
60 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
61 err += sn9c102_i2c_write(cam, 0x71, 0x00);
62 err += sn9c102_i2c_write(cam, 0x74, 0x21);
63 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
64
65 return err;
66}
67
68
69static int ov7630_set_ctrl(struct sn9c102_device* cam,
70 const struct v4l2_control* ctrl)
71{
72 int err = 0;
73
74 switch (ctrl->id) {
75 case V4L2_CID_EXPOSURE:
76 err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2);
77 err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03);
78 break;
79 case V4L2_CID_RED_BALANCE:
80 err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
81 break;
82 case V4L2_CID_BLUE_BALANCE:
83 err += sn9c102_i2c_write(cam, 0x03, ctrl->value);
84 break;
85 case V4L2_CID_GAIN:
86 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
87 break;
88 case V4L2_CID_CONTRAST:
89 err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
90 (ctrl->value-1) | 0x20)
91 : sn9c102_i2c_write(cam, 0x05, 0x00);
92 break;
93 case V4L2_CID_BRIGHTNESS:
94 err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
95 break;
96 case V4L2_CID_SATURATION:
97 err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4);
98 break;
99 case V4L2_CID_HUE:
100 err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
101 (ctrl->value-1) | 0x20)
102 : sn9c102_i2c_write(cam, 0x04, 0x00);
103 break;
104 case V4L2_CID_DO_WHITE_BALANCE:
105 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
106 break;
107 case V4L2_CID_WHITENESS:
108 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
109 break;
110 case V4L2_CID_AUTO_WHITE_BALANCE:
111 err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09);
112 break;
113 case V4L2_CID_AUTOGAIN:
114 err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
115 break;
116 case V4L2_CID_VFLIP:
117 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
118 break;
119 case V4L2_CID_BLACK_LEVEL:
120 err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
121 break;
122 case SN9C102_V4L2_CID_BRIGHT_LEVEL:
123 err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
124 break;
125 case SN9C102_V4L2_CID_GAMMA:
126 err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80);
127 break;
128 case SN9C102_V4L2_CID_BAND_FILTER:
129 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
130 break;
131 default:
132 return -EINVAL;
133 }
134
135 return err ? -EIO : 0;
136}
137
138
139static int ov7630_set_crop(struct sn9c102_device* cam,
140 const struct v4l2_rect* rect)
141{
142 struct sn9c102_sensor* s = &ov7630;
143 int err = 0;
144 u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
145
146 err += sn9c102_write_reg(cam, v_start, 0x13);
147
148 return err;
149}
150
151
152static int ov7630_set_pix_format(struct sn9c102_device* cam,
153 const struct v4l2_pix_format* pix)
154{
155 int err = 0;
156
157 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
158 err += sn9c102_write_reg(cam, 0x20, 0x19);
159 else
160 err += sn9c102_write_reg(cam, 0x50, 0x19);
161
162 return err;
163}
164
165
166static struct sn9c102_sensor ov7630 = {
167 .name = "OV7630",
168 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
169 .sysfs_ops = SN9C102_I2C_WRITE,
170 .frequency = SN9C102_I2C_100KHZ,
171 .interface = SN9C102_I2C_2WIRES,
172 .i2c_slave_id = 0x21,
173 .init = &ov7630_init,
174 .qctrl = {
175 {
176 .id = V4L2_CID_GAIN,
177 .type = V4L2_CTRL_TYPE_INTEGER,
178 .name = "global gain",
179 .minimum = 0x00,
180 .maximum = 0x3f,
181 .step = 0x01,
182 .default_value = 0x14,
183 .flags = 0,
184 },
185 {
186 .id = V4L2_CID_HUE,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "hue",
189 .minimum = 0x00,
190 .maximum = 0x1f+1,
191 .step = 0x01,
192 .default_value = 0x00,
193 .flags = 0,
194 },
195 {
196 .id = V4L2_CID_SATURATION,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "saturation",
199 .minimum = 0x00,
200 .maximum = 0x0f,
201 .step = 0x01,
202 .default_value = 0x08,
203 .flags = 0,
204 },
205 {
206 .id = V4L2_CID_CONTRAST,
207 .type = V4L2_CTRL_TYPE_INTEGER,
208 .name = "contrast",
209 .minimum = 0x00,
210 .maximum = 0x1f+1,
211 .step = 0x01,
212 .default_value = 0x00,
213 .flags = 0,
214 },
215 {
216 .id = V4L2_CID_EXPOSURE,
217 .type = V4L2_CTRL_TYPE_INTEGER,
218 .name = "exposure",
219 .minimum = 0x000,
220 .maximum = 0x3ff,
221 .step = 0x001,
222 .default_value = 0x83<<2,
223 .flags = 0,
224 },
225 {
226 .id = V4L2_CID_RED_BALANCE,
227 .type = V4L2_CTRL_TYPE_INTEGER,
228 .name = "red balance",
229 .minimum = 0x00,
230 .maximum = 0xff,
231 .step = 0x01,
232 .default_value = 0x3a,
233 .flags = 0,
234 },
235 {
236 .id = V4L2_CID_BLUE_BALANCE,
237 .type = V4L2_CTRL_TYPE_INTEGER,
238 .name = "blue balance",
239 .minimum = 0x00,
240 .maximum = 0xff,
241 .step = 0x01,
242 .default_value = 0x77,
243 .flags = 0,
244 },
245 {
246 .id = V4L2_CID_BRIGHTNESS,
247 .type = V4L2_CTRL_TYPE_INTEGER,
248 .name = "brightness",
249 .minimum = 0x00,
250 .maximum = 0xff,
251 .step = 0x01,
252 .default_value = 0xa0,
253 .flags = 0,
254 },
255 {
256 .id = V4L2_CID_DO_WHITE_BALANCE,
257 .type = V4L2_CTRL_TYPE_INTEGER,
258 .name = "white balance background: blue",
259 .minimum = 0x00,
260 .maximum = 0x3f,
261 .step = 0x01,
262 .default_value = 0x20,
263 .flags = 0,
264 },
265 {
266 .id = V4L2_CID_WHITENESS,
267 .type = V4L2_CTRL_TYPE_INTEGER,
268 .name = "white balance background: red",
269 .minimum = 0x00,
270 .maximum = 0x3f,
271 .step = 0x01,
272 .default_value = 0x20,
273 .flags = 0,
274 },
275 {
276 .id = V4L2_CID_AUTO_WHITE_BALANCE,
277 .type = V4L2_CTRL_TYPE_BOOLEAN,
278 .name = "auto white balance",
279 .minimum = 0x00,
280 .maximum = 0x01,
281 .step = 0x01,
282 .default_value = 0x01,
283 .flags = 0,
284 },
285 {
286 .id = V4L2_CID_AUTOGAIN,
287 .type = V4L2_CTRL_TYPE_INTEGER,
288 .name = "gain & exposure mode",
289 .minimum = 0x00,
290 .maximum = 0x03,
291 .step = 0x01,
292 .default_value = 0x00,
293 .flags = 0,
294 },
295 {
296 .id = V4L2_CID_VFLIP,
297 .type = V4L2_CTRL_TYPE_BOOLEAN,
298 .name = "vertical flip",
299 .minimum = 0x00,
300 .maximum = 0x01,
301 .step = 0x01,
302 .default_value = 0x01,
303 .flags = 0,
304 },
305 {
306 .id = V4L2_CID_BLACK_LEVEL,
307 .type = V4L2_CTRL_TYPE_INTEGER,
308 .name = "black pixel ratio",
309 .minimum = 0x01,
310 .maximum = 0x9a,
311 .step = 0x01,
312 .default_value = 0x8a,
313 .flags = 0,
314 },
315 {
316 .id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
317 .type = V4L2_CTRL_TYPE_INTEGER,
318 .name = "bright pixel ratio",
319 .minimum = 0x01,
320 .maximum = 0x9a,
321 .step = 0x01,
322 .default_value = 0x10,
323 .flags = 0,
324 },
325 {
326 .id = SN9C102_V4L2_CID_BAND_FILTER,
327 .type = V4L2_CTRL_TYPE_BOOLEAN,
328 .name = "band filter",
329 .minimum = 0x00,
330 .maximum = 0x01,
331 .step = 0x01,
332 .default_value = 0x00,
333 .flags = 0,
334 },
335 {
336 .id = SN9C102_V4L2_CID_GAMMA,
337 .type = V4L2_CTRL_TYPE_BOOLEAN,
338 .name = "rgb gamma",
339 .minimum = 0x00,
340 .maximum = 0x01,
341 .step = 0x01,
342 .default_value = 0x00,
343 .flags = 0,
344 },
345 },
346 .set_ctrl = &ov7630_set_ctrl,
347 .cropcap = {
348 .bounds = {
349 .left = 0,
350 .top = 0,
351 .width = 640,
352 .height = 480,
353 },
354 .defrect = {
355 .left = 0,
356 .top = 0,
357 .width = 640,
358 .height = 480,
359 },
360 },
361 .set_crop = &ov7630_set_crop,
362 .pix_format = {
363 .width = 640,
364 .height = 480,
365 .pixelformat = V4L2_PIX_FMT_SBGGR8,
366 .priv = 8,
367 },
368 .set_pix_format = &ov7630_set_pix_format
369};
370
371
372int sn9c102_probe_ov7630(struct sn9c102_device* cam)
373{
374 int err = 0;
375
376 sn9c102_attach_sensor(cam, &ov7630);
377
378 if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
379 le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c)
380 return -ENODEV;
381
382 err += sn9c102_write_reg(cam, 0x01, 0x01);
383 err += sn9c102_write_reg(cam, 0x00, 0x01);
384 err += sn9c102_write_reg(cam, 0x28, 0x17);
385
386 if (err)
387 return -EIO;
388
389 err += sn9c102_i2c_write(cam, 0x0b, 0);
390 if (err)
391 return -ENODEV;
392
393 return 0;
394}
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index 6a7adebcb4bf..a45166c3488c 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -64,6 +64,7 @@ struct sn9c102_sensor;
64*/ 64*/
65extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); 65extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
67extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
67extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 68extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
68extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); 69extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
69extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); 70extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
@@ -80,6 +81,7 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \
80 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ 81 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
81 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ 82 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \
82 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ 83 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \
84 &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \
83 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ 85 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
84 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ 86 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
85 NULL, \ 87 NULL, \
@@ -103,7 +105,8 @@ static const struct usb_device_id sn9c102_id_table[] = { \
103 { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ 105 { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \
104 { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \ 106 { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \
105 { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ 107 { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
106 { USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */ \ 108 { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \
109 { USB_DEVICE(0x0c45, 0x602d), }, \
107 { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ 110 { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
108 { USB_DEVICE(0x0c45, 0x6080), }, \ 111 { USB_DEVICE(0x0c45, 0x6080), }, \
109 { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */ \ 112 { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */ \
@@ -145,6 +148,8 @@ static const struct usb_device_id sn9c102_id_table[] = { \
145*/ 148*/
146 149
147/* The "try" I2C I/O versions are used when probing the sensor */ 150/* The "try" I2C I/O versions are used when probing the sensor */
151extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
152 u8 address, u8 value);
148extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, 153extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
149 u8 address); 154 u8 address);
150 155
@@ -201,6 +206,8 @@ enum sn9c102_i2c_interface {
201 SN9C102_I2C_3WIRES, 206 SN9C102_I2C_3WIRES,
202}; 207};
203 208
209#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
210
204struct sn9c102_sensor { 211struct sn9c102_sensor {
205 char name[32], /* sensor name */ 212 char name[32], /* sensor name */
206 maintainer[64]; /* name of the mantainer <email> */ 213 maintainer[64]; /* name of the mantainer <email> */
@@ -243,7 +250,7 @@ struct sn9c102_sensor {
243 sensor according to the default configuration structures below. 250 sensor according to the default configuration structures below.
244 */ 251 */
245 252
246 struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE]; 253 struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
247 /* 254 /*
248 Optional list of default controls, defined as indicated in the 255 Optional list of default controls, defined as indicated in the
249 V4L2 API. Menu type controls are not handled by this interface. 256 V4L2 API. Menu type controls are not handled by this interface.
@@ -356,7 +363,7 @@ struct sn9c102_sensor {
356 core module to store successfully updated values of the above 363 core module to store successfully updated values of the above
357 settings, for rollbacks..etc..in case of errors during atomic I/O 364 settings, for rollbacks..etc..in case of errors during atomic I/O
358 */ 365 */
359 struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE]; 366 struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
360 struct v4l2_rect _rect; 367 struct v4l2_rect _rect;
361}; 368};
362 369
@@ -367,5 +374,8 @@ struct sn9c102_sensor {
367#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 374#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
368#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 375#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
369#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 376#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
377#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4
378#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5
379#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6
370 380
371#endif /* _SN9C102_SENSOR_H_ */ 381#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 690d62192273..8775999b5aff 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -24,8 +24,6 @@
24 24
25static struct sn9c102_sensor tas5110c1b; 25static struct sn9c102_sensor tas5110c1b;
26 26
27static struct v4l2_control tas5110c1b_gain;
28
29 27
30static int tas5110c1b_init(struct sn9c102_device* cam) 28static int tas5110c1b_init(struct sn9c102_device* cam)
31{ 29{
@@ -46,21 +44,6 @@ static int tas5110c1b_init(struct sn9c102_device* cam)
46} 44}
47 45
48 46
49static int tas5110c1b_get_ctrl(struct sn9c102_device* cam,
50 struct v4l2_control* ctrl)
51{
52 switch (ctrl->id) {
53 case V4L2_CID_GAIN:
54 ctrl->value = tas5110c1b_gain.value;
55 break;
56 default:
57 return -EINVAL;
58 }
59
60 return 0;
61}
62
63
64static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 47static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
65 const struct v4l2_control* ctrl) 48 const struct v4l2_control* ctrl)
66{ 49{
@@ -68,8 +51,7 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
68 51
69 switch (ctrl->id) { 52 switch (ctrl->id) {
70 case V4L2_CID_GAIN: 53 case V4L2_CID_GAIN:
71 if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value))) 54 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
72 tas5110c1b_gain.value = ctrl->value;
73 break; 55 break;
74 default: 56 default:
75 return -EINVAL; 57 return -EINVAL;
@@ -147,7 +129,6 @@ static struct sn9c102_sensor tas5110c1b = {
147 .height = 288, 129 .height = 288,
148 }, 130 },
149 }, 131 },
150 .get_ctrl = &tas5110c1b_get_ctrl,
151 .set_crop = &tas5110c1b_set_crop, 132 .set_crop = &tas5110c1b_set_crop,
152 .pix_format = { 133 .pix_format = {
153 .width = 352, 134 .width = 352,
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index b378e941bbe8..927eafdd8c73 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -24,8 +24,6 @@
24 24
25static struct sn9c102_sensor tas5130d1b; 25static struct sn9c102_sensor tas5130d1b;
26 26
27static struct v4l2_control tas5130d1b_gain, tas5130d1b_exposure;
28
29 27
30static int tas5130d1b_init(struct sn9c102_device* cam) 28static int tas5130d1b_init(struct sn9c102_device* cam)
31{ 29{
@@ -44,24 +42,6 @@ static int tas5130d1b_init(struct sn9c102_device* cam)
44} 42}
45 43
46 44
47static int tas5130d1b_get_ctrl(struct sn9c102_device* cam,
48 struct v4l2_control* ctrl)
49{
50 switch (ctrl->id) {
51 case V4L2_CID_GAIN:
52 ctrl->value = tas5130d1b_gain.value;
53 break;
54 case V4L2_CID_EXPOSURE:
55 ctrl->value = tas5130d1b_exposure.value;
56 break;
57 default:
58 return -EINVAL;
59 }
60
61 return 0;
62}
63
64
65static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 45static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
66 const struct v4l2_control* ctrl) 46 const struct v4l2_control* ctrl)
67{ 47{
@@ -69,12 +49,10 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
69 49
70 switch (ctrl->id) { 50 switch (ctrl->id) {
71 case V4L2_CID_GAIN: 51 case V4L2_CID_GAIN:
72 if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value))) 52 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
73 tas5130d1b_gain.value = ctrl->value;
74 break; 53 break;
75 case V4L2_CID_EXPOSURE: 54 case V4L2_CID_EXPOSURE:
76 if (!(err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value))) 55 err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
77 tas5130d1b_exposure.value = ctrl->value;
78 break; 56 break;
79 default: 57 default:
80 return -EINVAL; 58 return -EINVAL;
@@ -147,7 +125,6 @@ static struct sn9c102_sensor tas5130d1b = {
147 .flags = 0, 125 .flags = 0,
148 }, 126 },
149 }, 127 },
150 .get_ctrl = &tas5130d1b_get_ctrl,
151 .set_ctrl = &tas5130d1b_set_ctrl, 128 .set_ctrl = &tas5130d1b_set_ctrl,
152 .cropcap = { 129 .cropcap = {
153 .bounds = { 130 .bounds = {