Dino lite pro is a mt9m111
[microdia.git] / sn9c20x-bridge.c
blob2cfc4a7ce6e04479edfe91749865ab1cb1ee0bb0
1 /**
2 * @file sn9c20x-bridge.c
3 * @author Dave Neuer
4 * @date 2008-03-02
6 * @brief Common functions and data for the Sonix SN9C20x webcam bridge chips.
8 * @note Copyright (C) Dave Neuer
10 * @par Licences
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
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/delay.h>
28 #include <linux/errno.h>
29 #include <linux/string.h>
30 #include "sn9c20x.h"
31 #include "sn9c20x-bridge.h"
35 /**
36 * @var RX
37 * Coordinate X aray for eliptic HSV corrections, conditionaly Red pixel
39 static const int RX[] = {
40 41, 44, 46, 48, 50, 52, 54, 56,
41 58, 60, 62, 64, 66, 68, 70, 72,
42 74, 76, 78, 80, 81, 83, 85, 87,
43 88, 90, 92, 93, 95, 97, 98, 100,
44 101, 102, 104, 105, 107, 108, 109, 110,
45 112, 113, 114, 115, 116, 117, 118, 119,
46 120, 121, 122, 123, 123, 124, 125, 125,
47 126, 127, 127, 128, 128, 129, 129, 129,
48 130, 130, 130, 130, 131, 131, 131, 131,
49 131, 131, 131, 131, 130, 130, 130, 130,
50 129, 129, 129, 128, 128, 127, 127, 126,
51 125, 125, 124, 123, 122, 122, 121, 120,
52 119, 118, 117, 116, 115, 114, 112, 111,
53 110, 109, 107, 106, 105, 103, 102, 101,
54 99, 98, 96, 94, 93, 91, 90, 88,
55 86, 84, 83, 81, 79, 77, 75, 74,
56 72, 70, 68, 66, 64, 62, 60, 58,
57 56, 54, 52, 49, 47, 45, 43, 41,
58 39, 36, 34, 32, 30, 28, 25, 23,
59 21, 19, 16, 14, 12, 9, 7, 5,
60 3, 0, -1, -3, -6, -8, -10, -12,
61 -15, -17, -19, -22, -24, -26, -28, -30,
62 -33, -35, -37, -39, -41, -44, -46, -48,
63 -50, -52, -54, -56, -58, -60, -62, -64,
64 -66, -68, -70, -72, -74, -76, -78, -80,
65 -81, -83, -85, -87, -88, -90, -92, -93,
66 -95, -97, -98, -100, -101, -102, -104, -105,
67 -107, -108, -109, -110, -112, -113, -114, -115,
68 -116, -117, -118, -119, -120, -121, -122, -123,
69 -123, -124, -125, -125, -126, -127, -127, -128,
70 -128, -128, -128, -128, -128, -128, -128, -128,
71 -128, -128, -128, -128, -128, -128, -128, -128,
72 -128, -128, -128, -128, -128, -128, -128, -128,
73 -128, -127, -127, -126, -125, -125, -124, -123,
74 -122, -122, -121, -120, -119, -118, -117, -116,
75 -115, -114, -112, -111, -110, -109, -107, -106,
76 -105, -103, -102, -101, -99, -98, -96, -94,
77 -93, -91, -90, -88, -86, -84, -83, -81,
78 -79, -77, -75, -74, -72, -70, -68, -66,
79 -64, -62, -60, -58, -56, -54, -52, -49,
80 -47, -45, -43, -41, -39, -36, -34, -32,
81 -30, -28, -25, -23, -21, -19, -16, -14,
82 -12, -9, -7, -5, -3, 0, 1, 3,
83 6, 8, 10, 12, 15, 17, 19, 22,
84 24, 26, 28, 30, 33, 35, 37, 39, 41
86 /**
87 * @var RY
88 * Coordinate Y aray for eliptic HSV corrections, conditionaly Red pixel
90 static const int RY[] = {
91 82, 80, 78, 76, 74, 73, 71, 69,
92 67, 65, 63, 61, 58, 56, 54, 52,
93 50, 48, 46, 44, 41, 39, 37, 35,
94 32, 30, 28, 26, 23, 21, 19, 16,
95 14, 12, 10, 7, 5, 3, 0, -1,
96 -3, -6, -8, -10, -13, -15, -17, -19,
97 -22, -24, -26, -29, -31, -33, -35, -38,
98 -40, -42, -44, -46, -48, -51, -53, -55,
99 -57, -59, -61, -63, -65, -67, -69, -71,
100 -73, -75, -77, -79, -81, -82, -84, -86,
101 -88, -89, -91, -93, -94, -96, -98, -99,
102 -101, -102, -104, -105, -106, -108, -109, -110,
103 -112, -113, -114, -115, -116, -117, -119, -120,
104 -120, -121, -122, -123, -124, -125, -126, -126,
105 -127, -128, -128, -128, -128, -128, -128, -128,
106 -128, -128, -128, -128, -128, -128, -128, -128,
107 -128, -128, -128, -128, -128, -128, -128, -128,
108 -128, -128, -128, -128, -128, -128, -128, -128,
109 -127, -127, -126, -125, -125, -124, -123, -122,
110 -121, -120, -119, -118, -117, -116, -115, -114,
111 -113, -111, -110, -109, -107, -106, -105, -103,
112 -102, -100, -99, -97, -96, -94, -92, -91,
113 -89, -87, -85, -84, -82, -80, -78, -76,
114 -74, -73, -71, -69, -67, -65, -63, -61,
115 -58, -56, -54, -52, -50, -48, -46, -44,
116 -41, -39, -37, -35, -32, -30, -28, -26,
117 -23, -21, -19, -16, -14, -12, -10, -7,
118 -5, -3, 0, 1, 3, 6, 8, 10,
119 13, 15, 17, 19, 22, 24, 26, 29,
120 31, 33, 35, 38, 40, 42, 44, 46,
121 48, 51, 53, 55, 57, 59, 61, 63,
122 65, 67, 69, 71, 73, 75, 77, 79,
123 81, 82, 84, 86, 88, 89, 91, 93,
124 94, 96, 98, 99, 101, 102, 104, 105,
125 106, 108, 109, 110, 112, 113, 114, 115,
126 116, 117, 119, 120, 120, 121, 122, 123,
127 124, 125, 126, 126, 127, 128, 128, 129,
128 129, 130, 130, 131, 131, 131, 131, 132,
129 132, 132, 132, 132, 132, 132, 132, 132,
130 132, 132, 132, 131, 131, 131, 130, 130,
131 130, 129, 129, 128, 127, 127, 126, 125,
132 125, 124, 123, 122, 121, 120, 119, 118,
133 117, 116, 115, 114, 113, 111, 110, 109,
134 107, 106, 105, 103, 102, 100, 99, 97,
135 96, 94, 92, 91, 89, 87, 85, 84, 82
139 * @var GX
140 * Coordinate X aray for eliptic HSV corrections, conditionaly Green pixel
142 static const int GX[] = {
143 -124, -124, -125, -125, -125, -125, -125, -125,
144 -125, -126, -126, -125, -125, -125, -125, -125,
145 -125, -124, -124, -124, -123, -123, -122, -122,
146 -121, -121, -120, -120, -119, -118, -117, -117,
147 -116, -115, -114, -113, -112, -111, -110, -109,
148 -108, -107, -105, -104, -103, -102, -100, -99,
149 -98, -96, -95, -93, -92, -91, -89, -87,
150 -86, -84, -83, -81, -79, -77, -76, -74,
151 -72, -70, -69, -67, -65, -63, -61, -59,
152 -57, -55, -53, -51, -49, -47, -45, -43,
153 -41, -39, -37, -35, -33, -30, -28, -26,
154 -24, -22, -20, -18, -15, -13, -11, -9,
155 -7, -4, -2, 0, 1, 3, 6, 8,
156 10, 12, 14, 17, 19, 21, 23, 25,
157 27, 29, 32, 34, 36, 38, 40, 42,
158 44, 46, 48, 50, 52, 54, 56, 58,
159 60, 62, 64, 66, 68, 70, 71, 73,
160 75, 77, 78, 80, 82, 83, 85, 87,
161 88, 90, 91, 93, 94, 96, 97, 98,
162 100, 101, 102, 104, 105, 106, 107, 108,
163 109, 111, 112, 113, 113, 114, 115, 116,
164 117, 118, 118, 119, 120, 120, 121, 122,
165 122, 123, 123, 124, 124, 124, 125, 125,
166 125, 125, 125, 125, 125, 126, 126, 125,
167 125, 125, 125, 125, 125, 124, 124, 124,
168 123, 123, 122, 122, 121, 121, 120, 120,
169 119, 118, 117, 117, 116, 115, 114, 113,
170 112, 111, 110, 109, 108, 107, 105, 104,
171 103, 102, 100, 99, 98, 96, 95, 93,
172 92, 91, 89, 87, 86, 84, 83, 81,
173 79, 77, 76, 74, 72, 70, 69, 67,
174 65, 63, 61, 59, 57, 55, 53, 51,
175 49, 47, 45, 43, 41, 39, 37, 35,
176 33, 30, 28, 26, 24, 22, 20, 18,
177 15, 13, 11, 9, 7, 4, 2, 0,
178 -1, -3, -6, -8, -10, -12, -14, -17,
179 -19, -21, -23, -25, -27, -29, -32, -34,
180 -36, -38, -40, -42, -44, -46, -48, -50,
181 -52, -54, -56, -58, -60, -62, -64, -66,
182 -68, -70, -71, -73, -75, -77, -78, -80,
183 -82, -83, -85, -87, -88, -90, -91, -93,
184 -94, -96, -97, -98, -100, -101, -102, -104,
185 -105, -106, -107, -108, -109, -111, -112, -113,
186 -113, -114, -115, -116, -117, -118, -118, -119,
187 -120, -120, -121, -122, -122, -123, -123, -124, -124
191 * @var GY
192 * Coordinate Y aray for eliptic HSV corrections, conditionaly Green pixel
194 static const int GY[] = {
195 -100, -99, -98, -97, -95, -94, -93, -91,
196 -90, -89, -87, -86, -84, -83, -81, -80,
197 -78, -76, -75, -73, -71, -70, -68, -66,
198 -64, -63, -61, -59, -57, -55, -53, -51,
199 -49, -48, -46, -44, -42, -40, -38, -36,
200 -34, -32, -30, -27, -25, -23, -21, -19,
201 -17, -15, -13, -11, -9, -7, -4, -2,
202 0, 1, 3, 5, 7, 9, 11, 14,
203 16, 18, 20, 22, 24, 26, 28, 30,
204 32, 34, 36, 38, 40, 42, 44, 46,
205 48, 50, 52, 54, 56, 58, 59, 61,
206 63, 65, 67, 68, 70, 72, 74, 75,
207 77, 78, 80, 82, 83, 85, 86, 88,
208 89, 90, 92, 93, 95, 96, 97, 98,
209 100, 101, 102, 103, 104, 105, 106, 107,
210 108, 109, 110, 111, 112, 112, 113, 114,
211 115, 115, 116, 116, 117, 117, 118, 118,
212 119, 119, 119, 120, 120, 120, 120, 120,
213 121, 121, 121, 121, 121, 121, 120, 120,
214 120, 120, 120, 119, 119, 119, 118, 118,
215 117, 117, 116, 116, 115, 114, 114, 113,
216 112, 111, 111, 110, 109, 108, 107, 106,
217 105, 104, 103, 102, 100, 99, 98, 97,
218 95, 94, 93, 91, 90, 89, 87, 86,
219 84, 83, 81, 80, 78, 76, 75, 73,
220 71, 70, 68, 66, 64, 63, 61, 59,
221 57, 55, 53, 51, 49, 48, 46, 44,
222 42, 40, 38, 36, 34, 32, 30, 27,
223 25, 23, 21, 19, 17, 15, 13, 11,
224 9, 7, 4, 2, 0, -1, -3, -5,
225 -7, -9, -11, -14, -16, -18, -20, -22,
226 -24, -26, -28, -30, -32, -34, -36, -38,
227 -40, -42, -44, -46, -48, -50, -52, -54,
228 -56, -58, -59, -61, -63, -65, -67, -68,
229 -70, -72, -74, -75, -77, -78, -80, -82,
230 -83, -85, -86, -88, -89, -90, -92, -93,
231 -95, -96, -97, -98, -100, -101, -102, -103,
232 -104, -105, -106, -107, -108, -109, -110, -111,
233 -112, -112, -113, -114, -115, -115, -116, -116,
234 -117, -117, -118, -118, -119, -119, -119, -120,
235 -120, -120, -120, -120, -121, -121, -121, -121,
236 -121, -121, -120, -120, -120, -120, -120, -119,
237 -119, -119, -118, -118, -117, -117, -116, -116,
238 -115, -114, -114, -113, -112, -111, -111, -110,
239 -109, -108, -107, -106, -105, -104, -103, -102, -100
243 * @var BX
244 * Coordinate X aray for eliptic HSV corrections, conditionaly Blue pixel
246 static const int BX[] = {
247 112, 113, 114, 114, 115, 116, 117, 117,
248 118, 118, 119, 119, 120, 120, 120, 121,
249 121, 121, 122, 122, 122, 122, 122, 122,
250 122, 122, 122, 122, 122, 122, 121, 121,
251 121, 120, 120, 120, 119, 119, 118, 118,
252 117, 116, 116, 115, 114, 113, 113, 112,
253 111, 110, 109, 108, 107, 106, 105, 104,
254 103, 102, 100, 99, 98, 97, 95, 94,
255 93, 91, 90, 88, 87, 85, 84, 82,
256 80, 79, 77, 76, 74, 72, 70, 69,
257 67, 65, 63, 61, 60, 58, 56, 54,
258 52, 50, 48, 46, 44, 42, 40, 38,
259 36, 34, 32, 30, 28, 26, 24, 22,
260 19, 17, 15, 13, 11, 9, 7, 5,
261 2, 0, -1, -3, -5, -7, -9, -12,
262 -14, -16, -18, -20, -22, -24, -26, -28,
263 -31, -33, -35, -37, -39, -41, -43, -45,
264 -47, -49, -51, -53, -54, -56, -58, -60,
265 -62, -64, -66, -67, -69, -71, -73, -74,
266 -76, -78, -79, -81, -83, -84, -86, -87,
267 -89, -90, -92, -93, -94, -96, -97, -98,
268 -99, -101, -102, -103, -104, -105, -106, -107,
269 -108, -109, -110, -111, -112, -113, -114, -114,
270 -115, -116, -117, -117, -118, -118, -119, -119,
271 -120, -120, -120, -121, -121, -121, -122, -122,
272 -122, -122, -122, -122, -122, -122, -122, -122,
273 -122, -122, -121, -121, -121, -120, -120, -120,
274 -119, -119, -118, -118, -117, -116, -116, -115,
275 -114, -113, -113, -112, -111, -110, -109, -108,
276 -107, -106, -105, -104, -103, -102, -100, -99,
277 -98, -97, -95, -94, -93, -91, -90, -88,
278 -87, -85, -84, -82, -80, -79, -77, -76,
279 -74, -72, -70, -69, -67, -65, -63, -61,
280 -60, -58, -56, -54, -52, -50, -48, -46,
281 -44, -42, -40, -38, -36, -34, -32, -30,
282 -28, -26, -24, -22, -19, -17, -15, -13,
283 -11, -9, -7, -5, -2, 0, 1, 3,
284 5, 7, 9, 12, 14, 16, 18, 20,
285 22, 24, 26, 28, 31, 33, 35, 37,
286 39, 41, 43, 45, 47, 49, 51, 53,
287 54, 56, 58, 60, 62, 64, 66, 67,
288 69, 71, 73, 74, 76, 78, 79, 81,
289 83, 84, 86, 87, 89, 90, 92, 93,
290 94, 96, 97, 98, 99, 101, 102, 103,
291 104, 105, 106, 107, 108, 109, 110, 111, 112
295 * @var BY
296 * Coordinate Y aray for eliptic HSV corrections, conditionaly Blue pixel
298 static const int BY[] = {
299 -11, -13, -15, -17, -19, -21, -23, -25,
300 -27, -29, -31, -33, -35, -37, -39, -41,
301 -43, -45, -46, -48, -50, -52, -54, -55,
302 -57, -59, -61, -62, -64, -66, -67, -69,
303 -71, -72, -74, -75, -77, -78, -80, -81,
304 -83, -84, -86, -87, -88, -90, -91, -92,
305 -93, -95, -96, -97, -98, -99, -100, -101,
306 -102, -103, -104, -105, -106, -106, -107, -108,
307 -109, -109, -110, -111, -111, -112, -112, -113,
308 -113, -114, -114, -114, -115, -115, -115, -115,
309 -116, -116, -116, -116, -116, -116, -116, -116,
310 -116, -115, -115, -115, -115, -114, -114, -114,
311 -113, -113, -112, -112, -111, -111, -110, -110,
312 -109, -108, -108, -107, -106, -105, -104, -103,
313 -102, -101, -100, -99, -98, -97, -96, -95,
314 -94, -93, -91, -90, -89, -88, -86, -85,
315 -84, -82, -81, -79, -78, -76, -75, -73,
316 -71, -70, -68, -67, -65, -63, -62, -60,
317 -58, -56, -55, -53, -51, -49, -47, -45,
318 -44, -42, -40, -38, -36, -34, -32, -30,
319 -28, -26, -24, -22, -20, -18, -16, -14,
320 -12, -10, -8, -6, -4, -2, 0, 1,
321 3, 5, 7, 9, 11, 13, 15, 17,
322 19, 21, 23, 25, 27, 29, 31, 33,
323 35, 37, 39, 41, 43, 45, 46, 48,
324 50, 52, 54, 55, 57, 59, 61, 62,
325 64, 66, 67, 69, 71, 72, 74, 75,
326 77, 78, 80, 81, 83, 84, 86, 87,
327 88, 90, 91, 92, 93, 95, 96, 97,
328 98, 99, 100, 101, 102, 103, 104, 105,
329 106, 106, 107, 108, 109, 109, 110, 111,
330 111, 112, 112, 113, 113, 114, 114, 114,
331 115, 115, 115, 115, 116, 116, 116, 116,
332 116, 116, 116, 116, 116, 115, 115, 115,
333 115, 114, 114, 114, 113, 113, 112, 112,
334 111, 111, 110, 110, 109, 108, 108, 107,
335 106, 105, 104, 103, 102, 101, 100, 99,
336 98, 97, 96, 95, 94, 93, 91, 90,
337 89, 88, 86, 85, 84, 82, 81, 79,
338 78, 76, 75, 73, 71, 70, 68, 67,
339 65, 63, 62, 60, 58, 56, 55, 53,
340 51, 49, 47, 45, 44, 42, 40, 38,
341 36, 34, 32, 30, 28, 26, 24, 22,
342 20, 18, 16, 14, 12, 10, 8, 6,
343 4, 2, 0, -1, -3, -5, -7, -9, -11
347 int sn9c20x_set_camera_control(struct usb_sn9c20x *dev,
348 __u32 control, __s32 value)
350 int ret = -EINVAL;
351 switch (control) {
352 case V4L2_CID_CONTRAST:
353 if (dev->camera.set_contrast) {
354 dev->vsettings.contrast = value;
355 ret = dev->camera.set_contrast(dev);
357 break;
358 case V4L2_CID_BRIGHTNESS:
359 if (dev->camera.set_brightness) {
360 dev->vsettings.brightness = value;
361 ret = dev->camera.set_brightness(dev);
363 break;
364 case V4L2_CID_GAMMA:
365 if (dev->camera.set_gamma) {
366 dev->vsettings.gamma = value;
367 ret = dev->camera.set_gamma(dev);
369 break;
370 case V4L2_CID_SATURATION:
371 if (dev->camera.set_saturation) {
372 dev->vsettings.colour = value;
373 ret = dev->camera.set_saturation(dev);
375 break;
376 case V4L2_CID_HUE:
377 if (dev->camera.set_hue) {
378 dev->vsettings.hue = value;
379 ret = dev->camera.set_hue(dev);
381 break;
382 case V4L2_CID_SHARPNESS:
383 if (dev->camera.set_sharpness) {
384 dev->vsettings.sharpness = value;
385 ret = dev->camera.set_sharpness(dev);
387 break;
388 case V4L2_CID_RED_BALANCE:
389 if (dev->camera.set_red_gain) {
390 dev->vsettings.red_gain = value & 0x7f;
391 ret = dev->camera.set_red_gain(dev);
393 break;
394 case V4L2_CID_BLUE_BALANCE:
395 if (dev->camera.set_blue_gain) {
396 dev->vsettings.blue_gain = value & 0x7f;
397 ret = dev->camera.set_blue_gain(dev);
399 break;
400 case V4L2_CID_HFLIP:
401 if (dev->camera.set_hvflip) {
402 dev->vsettings.hflip = value;
403 ret = dev->camera.set_hvflip(dev);
405 break;
406 case V4L2_CID_VFLIP:
407 if (dev->camera.set_hvflip) {
408 dev->vsettings.vflip = value;
409 ret = dev->camera.set_hvflip(dev);
411 break;
412 case V4L2_CID_AUTOGAIN:
413 if (dev->camera.set_auto_gain) {
414 dev->vsettings.auto_gain = value;
415 ret = dev->camera.set_auto_gain(dev);
417 break;
418 case V4L2_CID_EXPOSURE:
419 if (dev->camera.set_exposure) {
420 dev->vsettings.exposure = value;
421 ret = dev->camera.set_exposure(dev);
423 break;
424 case V4L2_CID_GAIN:
425 if (dev->camera.set_gain) {
426 dev->vsettings.gain = value;
427 ret = dev->camera.set_gain(dev);
429 break;
430 case V4L2_CID_AUTO_WHITE_BALANCE:
431 if (dev->camera.set_auto_whitebalance) {
432 dev->vsettings.auto_whitebalance = value;
433 ret = dev->camera.set_auto_whitebalance(dev);
435 break;
436 case V4L2_CID_EXPOSURE_AUTO:
437 dev->vsettings.auto_exposure = value;
438 ret = 0;
439 if (dev->camera.set_auto_exposure)
440 ret = dev->camera.set_auto_exposure(dev);
441 break;
443 return ret;
447 * @brief Switch Video stream on and off
449 * @param dev Pointer to device structure
450 * @param enable On or off
452 * @author Brian Johnson
454 * @return 0 or negative error code
457 int sn9c20x_enable_video(struct usb_sn9c20x *dev, int enable)
459 __u8 value;
460 int ret;
462 ret = usb_sn9c20x_control_read(dev, 0x1061, &value, 1);
463 if (ret < 0)
464 return ret;
466 if (enable) {
467 value |= 0x02;
468 ret = usb_sn9c20x_control_write(dev, 0x1061, &value, 1);
469 } else {
470 value &= ~0x02;
471 ret = usb_sn9c20x_control_write(dev, 0x1061, &value, 1);
474 sn9c20x_set_LEDs(dev, enable);
476 return ret;
480 * @brief Switch LEDs on and off
482 * @param dev Pointer to device structure
483 * @param enable On or off
485 * @author Josua Grawitter
487 * @return 0 or negative error code
490 int sn9c20x_set_LEDs(struct usb_sn9c20x *dev, int enable)
492 int ret;
493 __u8 led[2];
495 int sensor = dev->camera.sensor;
497 if (enable) {
498 switch (sensor) {
499 case MT9M001_SENSOR:
500 case HV7131R_SENSOR:
501 case SOI968_SENSOR:
502 led[0] = 0x80;
503 led[1] = 0xa0;
504 break;
505 case MT9V011_SENSOR:
506 case OV7660_SENSOR:
507 led[0] = 0x40;
508 led[1] = 0x60;
509 break;
510 case MT9M111_SENSOR:
511 led[0] = 0x00;
512 led[1] = 0x60;
513 break;
514 case MT9V111_SENSOR:
515 led[0] = 0xc0;
516 led[1] = 0xe0;
517 break;
518 default:
519 led[0] = 0x00;
520 led[1] = 0x20;
522 } else {
523 switch (sensor) {
524 case HV7131R_SENSOR:
525 case MT9M001_SENSOR:
526 case MT9V011_SENSOR:
527 led[0] = 0xa0;
528 led[1] = 0xa0;
529 break;
530 case MT9M111_SENSOR:
531 case OV7660_SENSOR:
532 led[0] = 0x20;
533 led[1] = 0x60;
534 break;
535 case MT9V111_SENSOR:
536 led[0] = 0x80;
537 led[1] = 0xe0;
538 break;
539 default:
540 led[0] = 0x20;
541 led[1] = 0x20;
545 ret = usb_sn9c20x_control_write(dev, 0x1006, led, 2);
547 return ret;
551 * @brief Initializes Micro-Controller's I2C interface
553 * @author Neekhil
555 * @param dev Pointer to the device
557 * @return Zero (success) or negative (USB-error value)
560 int sn9c20x_i2c_initialize(struct usb_sn9c20x *dev)
562 __u8 buf[9];
563 int ret;
565 dev->camera.i2c_flags = SN9C20X_I2C_2WIRE;
567 buf[0] = dev->camera.i2c_flags;
568 buf[1] = dev->camera.address;
569 buf[2] = 0x00;
570 buf[3] = 0x00;
571 buf[4] = 0x00;
572 buf[5] = 0x00;
573 buf[6] = 0x00;
574 buf[7] = 0x00;
575 buf[8] = 0x03;
576 /* Initialize I2C registers to avoid getting no ACK at first I2C operation: */
577 /* Get green diagonal bands w/o this dummy write, Bridge does not know sensor address ? */
578 ret = usb_sn9c20x_control_write(dev, 0x10c0, buf, 9);
579 if (ret < 0)
580 return ret;
581 else
582 return 0;
586 * @brief Wait until the I2C slave is ready for the next operation
588 * @param dev Pointer to the device
589 * @param highspeed
590 * @param slave_error
592 * @return Zero for success or a negative error value
595 int sn9c20x_i2c_ack_wait(struct usb_sn9c20x *dev, bool highspeed, bool *slave_error)
597 int ret, i;
598 __u8 readbuf;
599 int delay = highspeed ? 100 : 400;
601 for (i = 0; i < 5; i++) {
602 ret = usb_sn9c20x_control_read(dev, 0x10c0, &readbuf, 1);
604 if (unlikely(ret < 0))
605 return ret;
606 else if (readbuf & SN9C20X_I2C_ERROR) {
607 *slave_error = 1;
608 /* probably should come up w/ an error value and
609 * return it via the error return */
610 return 0;
611 } else if (readbuf & SN9C20X_I2C_READY)
612 return 0;
613 else
614 udelay(delay);
616 return -EBUSY;
620 * @brief Read up to 5 bytes of data from an I2C slave
622 * @param dev Pointer to the device
623 * @param nbytes Number of bytes to read
624 * @param address The address of the register on the slave to read
625 * @param result A pointer to the location at which the result should be stored
627 * @return Zero for success or a negative error value
630 int sn9c20x_read_i2c_data(struct usb_sn9c20x *dev, __u8 nbytes,
631 __u8 address, __u8 *result)
633 int ret, i, j;
634 __u8 row[5];
636 if (!dev || nbytes > 4)
637 return -EINVAL;
639 /* first, we must do a dummy write of just the address */
640 ret = sn9c20x_write_i2c_data(dev, 0, address, NULL);
641 if (unlikely(ret < 0))
642 return ret;
644 memset(row, 0, 5);
645 /* now we issue the same command but with the read bit set
646 * and no slave register address */
647 dev->camera.i2c_flags |= SN9C20X_I2C_READ;
648 ret = sn9c20x_write_i2c_data(dev, nbytes - 1, 0, row);
649 dev->camera.i2c_flags &= ~SN9C20X_I2C_READ;
650 if (unlikely(ret < 0))
651 return ret;
653 /* finally, ask the bridge for the data */
654 ret = usb_sn9c20x_control_read(dev, 0x10c2, row, 5);
655 if (unlikely(ret < 0))
656 return ret;
658 UDIA_DEBUG("I2C read: %02x %02x %02x %02x %02x %02x\n",
659 address, row[0], row[1], row[2], row[3], row[4]);
661 for (i = 0, j = 5 - nbytes; i < nbytes; i++, j++)
662 result[i] = row[j];
664 return 0;
668 * @brief Read up to 4 bytes of data from an I2C slave an return them as 16bit values
670 * @param dev Pointer to the device
671 * @param datalen Number of 16bit values to read
672 * @param address The address of the register on the slave to read
673 * @param result A pointer to the location at which the result should be stored
675 * @return Zero for success or a negative error value
678 int sn9c20x_read_i2c_data16(struct usb_sn9c20x *dev, __u8 datalen,
679 __u8 address, __u16 *result)
681 __u8 result8[4];
682 __u8 k;
683 int ret;
685 if (datalen > 2)
686 return -EINVAL;
687 ret = sn9c20x_read_i2c_data(dev, 2*datalen, address, result8);
688 for (k = 0; k < datalen; k++)
689 result[k] = (result8[k*2] << 8) | result8[k*2+1];
690 return ret;
693 static const char *wasread = "read from";
694 static const char *waswrite = "write to";
697 * @brief Write up to 5 bytes of data to an I2C slave
699 * @param dev Pointer to the device
700 * @param nbytes The number of bytes of data
701 * @param address The address of the register on the slave to write
702 * @param data An array containing the data to write
703 * @param last_byte The byte to be sent as last byte of control sequence
705 * @return Zero for success or a negative error value
708 int sn9c20x_write_i2c_data_ext(struct usb_sn9c20x *dev, __u8 nbytes,
709 __u8 address, const __u8 data[nbytes], __u8 last_byte)
711 int ret, i;
712 __u8 row[8];
713 bool slave_error = 0;
715 if (!dev || (nbytes > 0 && !data) || nbytes > 4)
716 return -EINVAL;
718 /* from the point of view of the bridge, the length
719 * includes the address */
720 row[0] = dev->camera.i2c_flags | ((nbytes + 1) << 4);
721 row[1] = dev->camera.address;
722 row[2] = address;
723 row[7] = last_byte;
725 for (i = 0; i < 4; i++)
726 row[i + 3] = i < nbytes ? data[i] : 0;
728 UDIA_DEBUG("I2C %s %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
729 (dev->camera.i2c_flags & SN9C20X_I2C_READ ? wasread : waswrite),
730 address, row[0], row[1], row[2], row[3], row[4], row[5], row[6],
731 row[7]);
733 ret = usb_sn9c20x_control_write(dev, 0x10c0, row, 8);
734 if (likely(ret >= 0))
735 ret = sn9c20x_i2c_ack_wait(dev,
736 dev->camera.i2c_flags & SN9C20X_I2C_400KHZ,
737 &slave_error);
739 if (slave_error) {
740 UDIA_ERROR("I2C slave 0x%02x returned error during %s address 0x%02x\n",
741 dev->camera.address, (dev->camera.i2c_flags &
742 SN9C20X_I2C_READ ? wasread : waswrite), address);
743 return -1000;
744 /* there should be no interference with USB errors */
747 if (ret < 0) {
748 /* we got no ack */
749 UDIA_ERROR("No ack from I2C slave 0x%02x for %s address 0x%02x\n",
750 dev->camera.address, (dev->camera.i2c_flags &
751 SN9C20X_I2C_READ ? wasread : waswrite), address);
752 return ret;
755 return 0;
759 * @brief Write up to 2 16bit values als single bytes to an I2C slave
761 * @param dev Pointer to the device
762 * @param datalen The number of 16bit data values to write
763 * @param address The address of the register on the slave to write
764 * @param data An array containing the data to write
766 * @return Zero for success or a negative error value
769 int sn9c20x_write_i2c_data16(struct usb_sn9c20x *dev, __u8 datalen,
770 __u8 address, const __u16 data[datalen])
772 __u8 data8[4];
773 __u8 k;
774 int ret;
776 if (datalen > 2)
777 return -EINVAL;
778 for (k = 0; k < datalen; k++) {
779 data8[k*2] = data[k] >> 8;
780 data8[k*2+1] = data[k] & 0xff;
782 ret = sn9c20x_write_i2c_data(dev, 2*datalen, address, data8);
783 return ret;
786 int sn9c20x_write_i2c_array(struct usb_sn9c20x *dev,
787 struct sn9c20x_i2c_regs *regs, int bits16)
789 int i;
790 int ret = 0;
791 __u16 value16;
792 __u8 value8;
793 for (i = 0;; i++) {
794 if (regs[i].address == 0xff)
795 break;
796 if (bits16) {
797 value16 = regs[i].value;
798 ret = sn9c20x_write_i2c_data16(dev, 1,
799 regs[i].address, &value16);
800 } else {
801 value8 = (__u8)regs[i].value;
802 ret = sn9c20x_write_i2c_data(dev, 1,
803 regs[i].address, &value8);
805 if (unlikely(ret < 0))
806 return ret;
808 return ret;
812 * @brief Calculate and set hue/sat
814 * @author Comer352l, Boris Borisov
816 * @param dev Pointer to the device
818 * @return Zero (success) or negative (USB-error value)
821 int sn9c20x_set_color(struct usb_sn9c20x *dev)
823 __s16 value;
824 long tmp_coordinate;
825 __u8 *cmatrix = dev->vsettings.cmatrix;
827 if (dev->vsettings.hue < -179)
828 dev->vsettings.hue = -180;
830 if (dev->vsettings.hue > 179)
831 dev->vsettings.hue = 180;
833 value = 180 + dev->vsettings.hue;
835 /* Calculate HUE and SATURATION */
836 tmp_coordinate = (long)(RX[value]);
837 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
838 cmatrix[6] = (unsigned char)(tmp_coordinate & 0xff);
839 cmatrix[7] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
841 tmp_coordinate = (long)(RY[value]);
842 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
843 cmatrix[8] = (unsigned char)(tmp_coordinate & 0xff);
844 cmatrix[9] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
846 tmp_coordinate = (long)(GX[value]);
847 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
848 cmatrix[10] = (unsigned char)(tmp_coordinate & 0xff);
849 cmatrix[11] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
851 tmp_coordinate = (long)(GY[value]);
852 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
853 cmatrix[12] = (unsigned char)(tmp_coordinate & 0xff);
854 cmatrix[13] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
856 tmp_coordinate = (long)(BX[value]);
857 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
858 cmatrix[14] = (unsigned char)(tmp_coordinate & 0xff);
859 cmatrix[15] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
861 tmp_coordinate = (long)(BY[value]);
862 tmp_coordinate = (tmp_coordinate * dev->vsettings.colour) >> 8;
863 cmatrix[16] = (unsigned char)(tmp_coordinate & 0xff);
864 cmatrix[17] = (unsigned char)((tmp_coordinate >> 8) & 0x0f);
867 return usb_sn9c20x_control_write(dev, 0x10e1, cmatrix, 21);
871 * @brief Set contrast inside sn9c20x chip
873 * @author Comer352l
875 * @param dev Pointer to the device
877 * @return Zero (success) or negative (USB-error value)
880 int sn9c20x_set_contrast(struct usb_sn9c20x *dev)
882 __u8 *cmatrix = dev->vsettings.cmatrix;
883 __u8 contrast_val = (dev->vsettings.contrast) * 0x25 / 0x100;
885 contrast_val += 0x26;
886 cmatrix[2] = contrast_val;
887 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
888 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
890 return usb_sn9c20x_control_write(dev, 0x10e1, cmatrix, 21);
894 * @brief Set brightness inside sn9c20x chip
896 * @author Comer352l
898 * @param dev Pointer to the device
900 * @return Zero (success) or negative (USB-error value)
902 * Wrapper for sn9c20x_set_contrast
905 int sn9c20x_set_brightness(struct usb_sn9c20x *dev)
907 __u8 *cmatrix = dev->vsettings.cmatrix;
909 cmatrix[18] = dev->vsettings.brightness - 0x80;
911 return usb_sn9c20x_control_write(dev, 0x10e1, cmatrix, 21);
915 * @brief Set gamma inside sn9c20x chip
917 * @author Comer352l
919 * @param dev Pointer to the device
921 * @return Zero (success) or negative (USB-error value)
924 int sn9c20x_set_gamma(struct usb_sn9c20x *dev)
926 int value = (dev->vsettings.gamma) * 0xb8 / 0x100;
927 int r = 0;
929 __u8 gamma_val[17] = {0x0a, 0x13, 0x25, 0x37, 0x45, 0x55, 0x65, 0x74,
930 0x83, 0x92, 0xa1, 0xb0, 0xbf, 0xce, 0xdf, 0xea, 0xf5};
932 gamma_val[0] = 0x0a;
933 gamma_val[1] = 0x13 + (value * (0xcb - 0x13) / 0xb8);
934 gamma_val[2] = 0x25 + (value * (0xee - 0x25) / 0xb8);
935 gamma_val[3] = 0x37 + (value * (0xfa - 0x37) / 0xb8);
936 gamma_val[4] = 0x45 + (value * (0xfc - 0x45) / 0xb8);
937 gamma_val[5] = 0x55 + (value * (0xfb - 0x55) / 0xb8);
938 gamma_val[6] = 0x65 + (value * (0xfc - 0x65) / 0xb8);
939 gamma_val[7] = 0x74 + (value * (0xfd - 0x74) / 0xb8);
940 gamma_val[8] = 0x83 + (value * (0xfe - 0x83) / 0xb8);
941 gamma_val[9] = 0x92 + (value * (0xfc - 0x92) / 0xb8);
942 gamma_val[10] = 0xa1 + (value * (0xfc - 0xa1) / 0xb8);
943 gamma_val[11] = 0xb0 + (value * (0xfc - 0xb0) / 0xb8);
944 gamma_val[12] = 0xbf + (value * (0xfb - 0xbf) / 0xb8);
945 gamma_val[13] = 0xce + (value * (0xfb - 0xce) / 0xb8);
946 gamma_val[14] = 0xdf + (value * (0xfd - 0xdf) / 0xb8);
947 gamma_val[15] = 0xea + (value * (0xf9 - 0xea) / 0xb8);
948 gamma_val[16] = 0xf5;
950 r = usb_sn9c20x_control_write(dev, 0x1190, gamma_val, 17);
952 return r;
956 * @brief Set sharpness inside sn9c20x chip
958 * @author Comer352l
960 * @param dev Pointer to the device
962 * @return Zero (success) or negative (USB-error value)
965 int sn9c20x_set_sharpness(struct usb_sn9c20x *dev)
967 __u8 val[1];
968 int ret;
970 ret = usb_sn9c20x_control_read(dev, SN9C20X_SHARPNESS, val, 1);
971 if (ret < 0)
972 return ret;
973 val[0] = (val[0] & 0xc0) | (dev->vsettings.sharpness & 0x3f);
974 ret = usb_sn9c20x_control_write(dev, SN9C20X_SHARPNESS, val, 1);
975 if (ret < 0)
976 return ret;
977 else
978 return 0;
982 * @brief Set red gain inside sn9c20x chip
984 * @author Brian Johnson
986 * @param dev Pointer to the device
988 * @return Zero (success) or negative (USB-error value)
991 int sn9c20x_set_red_gain(struct usb_sn9c20x *dev)
993 __u8 val;
994 int ret;
996 val = dev->vsettings.red_gain;
997 ret = usb_sn9c20x_control_write(dev, SN9C20X_RED_GAIN, &val, 1);
998 if (ret < 0)
999 return ret;
1000 else
1001 return 0;
1005 * @brief Set blue gain inside sn9c20x chip
1007 * @author Brian Johnson
1009 * @param dev Pointer to the device
1011 * @return Zero (success) or negative (USB-error value)
1014 int sn9c20x_set_blue_gain(struct usb_sn9c20x *dev)
1016 __u8 val;
1017 int ret;
1019 val = dev->vsettings.blue_gain;
1020 ret = usb_sn9c20x_control_write(dev, SN9C20X_BLUE_GAIN, &val, 1);
1021 if (ret < 0)
1022 return ret;
1023 else
1024 return 0;
1029 * @brief Calculate closest resolution to input from application
1031 * @author Brian Johnson
1033 * @param dev Pointer to the device structure
1034 * @param width Requested width of video stream
1035 * @param height Requested height of video stream
1037 * @retval width Closest possible width of video stream
1038 * @retval height Closest possible height of video stream
1040 * @return Number of the
1043 int sn9c20x_get_closest_resolution(struct usb_sn9c20x *dev,
1044 int *width, int *height)
1046 int i;
1048 for (i = SN9C20X_N_MODES - 1; i >= 0; i--) {
1049 if (*width >= sn9c20x_modes[i].width
1050 && *height >= sn9c20x_modes[i].height)
1051 break;
1054 *width = sn9c20x_modes[i].width;
1055 *height = sn9c20x_modes[i].height;
1057 return i;
1061 * @brief Set resolution inside sn9c20x chip
1063 * @author Brian Johnson
1065 * @param dev Pointer to the device
1066 * @param width Width
1067 * @param height Height
1069 * @return 0
1072 int sn9c20x_set_resolution(struct usb_sn9c20x *dev,
1073 int width, int height)
1075 int ret;
1076 __u8 scale;
1077 __u8 window[6];
1078 __u8 clrwindow[5];
1079 struct sn9c20x_video_mode *mode;
1081 ret = sn9c20x_get_closest_resolution(dev, &width, &height);
1083 mode = &sn9c20x_modes[ret];
1085 dev->vsettings.format.width = mode->width;
1086 dev->vsettings.format.height = mode->height;
1088 clrwindow[0] = 0;
1089 clrwindow[1] = mode->width >> 2;
1090 clrwindow[2] = 0;
1091 clrwindow[3] = mode->height >> 1;
1092 clrwindow[4] = ((mode->width >> 10) & 0x01) |
1093 ((mode->height >> 8) & 0x06);
1095 scale = mode->scale;
1097 window[0] = (mode->window[0] + dev->camera.hstart) & 0xff;
1098 window[1] = (mode->window[0] + dev->camera.hstart) >> 8;
1099 window[2] = (mode->window[1] + dev->camera.vstart) & 0xff;
1100 window[3] = (mode->window[1] + dev->camera.vstart) >> 8;
1101 window[4] = mode->window[2] >> 4;
1102 window[5] = mode->window[3] >> 3;
1104 usb_sn9c20x_control_write(dev, 0x10fb, clrwindow, 5);
1105 usb_sn9c20x_control_write(dev, 0x1180, window, 6);
1106 usb_sn9c20x_control_write(dev, SN9C20X_SCALE, &scale, 1);
1108 UDIA_DEBUG("Set mode [%dx%d]\n", mode->width, mode->height);
1110 return 0;
1114 int sn9c20x_set_format(struct usb_sn9c20x *dev, __u32 format)
1116 int i;
1117 int ret = -EINVAL;
1118 for (i = 0; i < SN9C20X_N_FMTS; i++) {
1119 if (sn9c20x_fmts[i].pix_fmt == format) {
1120 dev->vsettings.format.bytesperline =
1121 dev->vsettings.format.width *
1122 sn9c20x_fmts[i].depth / 8;
1123 dev->vsettings.format.sizeimage =
1124 dev->vsettings.format.height *
1125 dev->vsettings.format.bytesperline;
1126 dev->vsettings.format.pixelformat = format;
1127 dev->vsettings.format.colorspace = V4L2_COLORSPACE_SRGB;
1128 dev->vsettings.format.priv = 0;
1129 sn9c20x_fmts[i].set_format(dev);
1130 ret = 0;
1131 break;
1134 return ret;
1137 void sn9c20x_set_raw(struct usb_sn9c20x *dev)
1139 __u8 value;
1140 value = 0x2d;
1141 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1142 UDIA_INFO("Using raw output format\n");
1145 void sn9c20x_set_jpeg(struct usb_sn9c20x *dev)
1147 __u8 value;
1148 value = 0x2c;
1149 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1150 UDIA_INFO("Using jpeg output format\n");
1153 void sn9c20x_set_yuv420(struct usb_sn9c20x *dev)
1155 __u8 value;
1156 value = 0x2f;
1157 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1158 UDIA_INFO("Using yuv420 output format\n");
1161 void sn9c20x_set_yuv422(struct usb_sn9c20x *dev)
1163 __u8 value;
1164 value = 0x2e;
1165 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1166 UDIA_INFO("Using yuv422 output format\n");
1170 * @brief This function initializes the SN9C20x bridge,
1171 * these are the bare minimum writes that must be done for
1172 * the bridge to work correctly.
1174 * @author Neekhil
1176 * @param dev Pointer to the device
1178 * @return Zero for success or error value
1181 int sn9c20x_initialize(struct usb_sn9c20x *dev)
1183 int ret, i;
1185 __u16 reg;
1186 __u8 value;
1188 __u16 regs[][2] = {
1189 {0x1000, 0x78},
1190 {0x1001, 0x40},
1191 {0x1002, 0x1c},
1192 {0x1020, 0x80},
1193 {0x1061, 0x01},
1194 {0x1067, 0x40},
1195 {0x1068, 0x30},
1196 {0x1069, 0x20},
1197 {0x106a, 0x10},
1198 {0x106b, 0x08},
1199 {0x1188, 0x87},
1200 {0x11a1, 0x00},
1201 {0x11a2, 0x00},
1202 {0x11a3, 0x6a},
1203 {0x11a4, 0x50},
1204 {0x11ab, 0x00},
1205 {0x11ac, 0x00},
1206 {0x11ad, 0x50},
1207 {0x11ae, 0x3c},
1208 {0x118a, 0x04},
1209 {0x0395, 0x04},
1210 {0x11b8, 0x3a},
1211 {0x118b, 0x0e},
1212 {0x10f7, 0x05},
1213 {0x10f8, 0x14},
1214 {0x10fa, 0xff},
1215 {0x10f9, 0x00},
1216 {0x11ba, 0x0a},
1217 {0x11a5, 0x2d},
1218 {0x11a6, 0x2d},
1219 {0x11a7, 0x3a},
1220 {0x11a8, 0x05},
1221 {0x11a9, 0x04},
1222 {0x11aa, 0x3f},
1223 {0x11af, 0x28},
1224 {0x11b0, 0xd8},
1225 {0x11b1, 0x14},
1226 {0x11b2, 0xec},
1227 {0x11b3, 0x32},
1228 {0x11b4, 0xdd},
1229 {0x11b5, 0x32},
1230 {0x11b6, 0xdd},
1231 {0x10e0, 0x2c},
1232 {0x11bc, 0x40},
1233 {0x11bd, 0x01},
1234 {0x11be, 0xf0},
1235 {0x11bf, 0x00},
1236 {0x118c, 0x1f},
1237 {0x118d, 0x1f},
1238 {0x118e, 0x1f},
1239 {0x118f, 0x1f},
1240 {0x1180, 0x01},
1241 {0x1181, 0x00},
1242 {0x1182, 0x01},
1243 {0x1183, 0x00},
1244 {0x1184, 0x50},
1245 {0x1185, 0x80},
1248 __u8 qtable1[64] = {
1249 0x0d, 0x08, 0x08, 0x0d, 0x08, 0x08, 0x0d, 0x0d,
1250 0x0d, 0x0d, 0x11, 0x0d, 0x0d, 0x11, 0x15, 0x21,
1251 0x15, 0x15, 0x11, 0x11, 0x15, 0x2a, 0x1d, 0x1d,
1252 0x19, 0x21, 0x32, 0x2a, 0x32, 0x32, 0x2e, 0x2a,
1253 0x2e, 0x2e, 0x36, 0x3a, 0x4b, 0x43, 0x36, 0x3a,
1254 0x47, 0x3a, 0x2e, 0x2e, 0x43, 0x5c, 0x43, 0x47,
1255 0x4f, 0x54, 0x58, 0x58, 0x58, 0x32, 0x3f, 0x60,
1256 0x64, 0x5c, 0x54, 0x64, 0x4b, 0x54, 0x58, 0x54
1259 __u8 qtable2[64] = {
1260 0x0d, 0x11, 0x11, 0x15, 0x11, 0x15, 0x26, 0x15,
1261 0x15, 0x26, 0x54, 0x36, 0x2e, 0x36, 0x54, 0x54,
1262 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1263 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1264 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1265 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1266 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1267 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54
1270 for (i = 0; i < ARRAY_SIZE(regs); i++) {
1271 reg = regs[i][0];
1272 value = regs[i][1];
1273 ret = usb_sn9c20x_control_write(dev, reg, &value, 1);
1274 if (unlikely(ret < 0)) {
1275 UDIA_INFO("Bridge Init Error (%d). line %d\n", ret, i);
1276 goto err;
1280 ret = usb_sn9c20x_control_write(dev, 0x1100, qtable1, 64);
1281 if (ret < 0)
1282 goto err;
1284 ret = usb_sn9c20x_control_write(dev, 0x1140, qtable2, 64);
1285 if (ret < 0)
1286 goto err;
1288 #ifdef CONFIG_SN9C20X_EVDEV
1289 ret = usb_sn9c20x_control_read(dev, 0x1005, &dev->input_gpio, 1);
1290 if (ret < 0)
1291 goto err;
1293 dev->input_gpio = ~dev->input_gpio;
1294 #endif
1296 dev->camera.set_contrast = sn9c20x_set_contrast;
1297 dev->camera.set_brightness = sn9c20x_set_brightness;
1298 dev->camera.set_hue = sn9c20x_set_color;
1299 dev->camera.set_saturation = sn9c20x_set_color;
1300 dev->camera.set_gamma = sn9c20x_set_gamma;
1301 dev->camera.set_sharpness = sn9c20x_set_sharpness;
1302 dev->camera.set_red_gain = sn9c20x_set_red_gain;
1303 dev->camera.set_blue_gain = sn9c20x_set_blue_gain;
1305 ret = sn9c20x_i2c_initialize(dev);
1306 if (ret < 0)
1307 goto err;
1309 ret = sn9c20x_initialize_sensor(dev);
1310 return ret;
1312 err:
1313 UDIA_ERROR("Device Init failed (%d)!\n", ret);
1314 return ret;
1317 int sn9c20x_reset_device(struct usb_sn9c20x *dev)
1319 if (sn9c20x_initialize(dev) < 0)
1320 return -EINVAL;
1322 sn9c20x_set_camera_control(dev, V4L2_CID_HFLIP,
1323 dev->vsettings.hflip);
1324 sn9c20x_set_camera_control(dev, V4L2_CID_VFLIP,
1325 dev->vsettings.vflip);
1326 sn9c20x_set_camera_control(dev, V4L2_CID_GAIN,
1327 dev->vsettings.gain);
1328 sn9c20x_set_camera_control(dev, V4L2_CID_BRIGHTNESS,
1329 dev->vsettings.brightness);
1330 sn9c20x_set_camera_control(dev, V4L2_CID_CONTRAST,
1331 dev->vsettings.contrast);
1332 sn9c20x_set_camera_control(dev, V4L2_CID_HUE,
1333 dev->vsettings.hue);
1334 sn9c20x_set_camera_control(dev, V4L2_CID_SATURATION,
1335 dev->vsettings.colour);
1336 sn9c20x_set_camera_control(dev, V4L2_CID_GAMMA,
1337 dev->vsettings.gamma);
1338 sn9c20x_set_camera_control(dev, V4L2_CID_SHARPNESS,
1339 dev->vsettings.sharpness);
1340 sn9c20x_set_camera_control(dev, V4L2_CID_RED_BALANCE,
1341 dev->vsettings.red_gain);
1342 sn9c20x_set_camera_control(dev, V4L2_CID_BLUE_BALANCE,
1343 dev->vsettings.blue_gain);
1344 sn9c20x_set_camera_control(dev, V4L2_CID_EXPOSURE_AUTO,
1345 dev->vsettings.auto_exposure);
1346 sn9c20x_set_camera_control(dev, V4L2_CID_AUTOGAIN,
1347 dev->vsettings.auto_gain);
1348 sn9c20x_set_camera_control(dev, V4L2_CID_AUTO_WHITE_BALANCE,
1349 dev->vsettings.auto_whitebalance);
1350 sn9c20x_set_camera_control(dev, V4L2_CID_EXPOSURE,
1351 dev->vsettings.exposure);
1353 sn9c20x_set_resolution(dev, dev->vsettings.format.width,
1354 dev->vsettings.format.height);
1356 sn9c20x_set_format(dev, dev->vsettings.format.pixelformat);
1358 return 0;