Fix SXGA support to enforce bayer format
[microdia.git] / sn9c20x-bridge.c
blob381442db22062fd64861922c50922bf5407e55a7
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] = 0xa0;
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 if (*width < sn9c20x_modes[0].width)
1049 *width = sn9c20x_modes[0].width;
1051 if (*height < sn9c20x_modes[0].height)
1052 *height = sn9c20x_modes[0].height;
1054 if (dev->camera.set_sxga_mode == NULL) {
1055 if (*width > 640)
1056 *width = 640;
1058 if (*height > 480)
1059 *height = 480;
1062 for (i = SN9C20X_N_MODES - 1; i >= 0; i--) {
1063 if (*width >= sn9c20x_modes[i].width
1064 && *height >= sn9c20x_modes[i].height)
1065 break;
1068 *width = sn9c20x_modes[i].width;
1069 *height = sn9c20x_modes[i].height;
1070 return i;
1074 * @brief Set resolution inside sn9c20x chip
1076 * @author Brian Johnson
1078 * @param dev Pointer to the device
1079 * @param width Width
1080 * @param height Height
1082 * @return 0
1085 int sn9c20x_set_resolution(struct usb_sn9c20x *dev,
1086 int width, int height)
1088 int ret;
1089 __u8 scale;
1090 __u8 window[6];
1091 __u8 clrwindow[5];
1092 struct sn9c20x_video_mode *mode;
1094 ret = sn9c20x_get_closest_resolution(dev, &width, &height);
1096 mode = &sn9c20x_modes[ret];
1098 dev->vsettings.format.width = mode->width;
1099 dev->vsettings.format.height = mode->height;
1101 clrwindow[0] = 0;
1102 clrwindow[1] = mode->width >> 2;
1103 clrwindow[2] = 0;
1104 clrwindow[3] = mode->height >> 1;
1105 clrwindow[4] = ((mode->width >> 10) & 0x01) |
1106 ((mode->height >> 8) & 0x06);
1108 scale = mode->scale;
1110 window[0] = (mode->window[0] + dev->camera.hstart) & 0xff;
1111 window[1] = (mode->window[0] + dev->camera.hstart) >> 8;
1112 window[2] = (mode->window[1] + dev->camera.vstart) & 0xff;
1113 window[3] = (mode->window[1] + dev->camera.vstart) >> 8;
1114 window[4] = mode->window[2] >> 4;
1115 window[5] = mode->window[3] >> 3;
1117 if (dev->camera.set_sxga_mode) {
1118 if (width > 640 && height > 480) {
1119 dev->camera.set_sxga_mode(dev, true);
1120 scale |= 0xc0;
1121 UDIA_DEBUG("Set Sensor to SXGA\n");
1122 } else {
1123 dev->camera.set_sxga_mode(dev, false);
1124 scale |= 0x80;
1125 UDIA_DEBUG("Set Sensor to VGA\n");
1129 usb_sn9c20x_control_write(dev, 0x10fb, clrwindow, 5);
1130 usb_sn9c20x_control_write(dev, 0x1180, window, 6);
1131 usb_sn9c20x_control_write(dev, SN9C20X_SCALE, &scale, 1);
1133 UDIA_DEBUG("Set mode [%dx%d]\n", mode->width, mode->height);
1135 return 0;
1139 int sn9c20x_set_format(struct usb_sn9c20x *dev, __u32 format)
1141 int i;
1142 int ret = -EINVAL;
1143 for (i = 0; i < SN9C20X_N_FMTS; i++) {
1144 if (sn9c20x_fmts[i].pix_fmt == format) {
1145 dev->vsettings.format.bytesperline =
1146 dev->vsettings.format.width *
1147 sn9c20x_fmts[i].depth / 8;
1148 dev->vsettings.format.sizeimage =
1149 dev->vsettings.format.height *
1150 dev->vsettings.format.bytesperline;
1151 dev->vsettings.format.pixelformat = format;
1152 dev->vsettings.format.colorspace = V4L2_COLORSPACE_SRGB;
1153 dev->vsettings.format.priv = 0;
1154 sn9c20x_fmts[i].set_format(dev);
1155 ret = 0;
1156 break;
1159 return ret;
1162 void sn9c20x_set_raw(struct usb_sn9c20x *dev)
1164 __u8 value;
1165 value = 0x2d;
1166 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1167 UDIA_INFO("Using raw output format\n");
1170 void sn9c20x_set_jpeg(struct usb_sn9c20x *dev)
1172 __u8 value;
1173 value = 0x2c;
1174 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1175 UDIA_INFO("Using jpeg output format\n");
1178 void sn9c20x_set_yuv420(struct usb_sn9c20x *dev)
1180 __u8 value;
1181 value = 0x2f;
1182 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1183 UDIA_INFO("Using yuv420 output format\n");
1186 void sn9c20x_set_yuv422(struct usb_sn9c20x *dev)
1188 __u8 value;
1189 value = 0x2e;
1190 usb_sn9c20x_control_write(dev, 0x10e0, &value, 1);
1191 UDIA_INFO("Using yuv422 output format\n");
1195 * @brief This function initializes the SN9C20x bridge,
1196 * these are the bare minimum writes that must be done for
1197 * the bridge to work correctly.
1199 * @author Neekhil
1201 * @param dev Pointer to the device
1203 * @return Zero for success or error value
1206 int sn9c20x_initialize(struct usb_sn9c20x *dev)
1208 int ret, i;
1210 __u16 reg;
1211 __u8 value;
1213 __u16 regs[][2] = {
1214 {0x1000, 0x78},
1215 {0x1001, 0x40},
1216 {0x1002, 0x1c},
1217 {0x1020, 0x80},
1218 {0x1061, 0x01},
1219 {0x1067, 0x40},
1220 {0x1068, 0x30},
1221 {0x1069, 0x20},
1222 {0x106a, 0x10},
1223 {0x106b, 0x08},
1224 {0x1188, 0x87},
1225 {0x11a1, 0x00},
1226 {0x11a2, 0x00},
1227 {0x11a3, 0x6a},
1228 {0x11a4, 0x50},
1229 {0x11ab, 0x00},
1230 {0x11ac, 0x00},
1231 {0x11ad, 0x50},
1232 {0x11ae, 0x3c},
1233 {0x118a, 0x04},
1234 {0x0395, 0x04},
1235 {0x11b8, 0x3a},
1236 {0x118b, 0x0e},
1237 {0x10f7, 0x05},
1238 {0x10f8, 0x14},
1239 {0x10fa, 0xff},
1240 {0x10f9, 0x00},
1241 {0x11ba, 0x0a},
1242 {0x11a5, 0x2d},
1243 {0x11a6, 0x2d},
1244 {0x11a7, 0x3a},
1245 {0x11a8, 0x05},
1246 {0x11a9, 0x04},
1247 {0x11aa, 0x3f},
1248 {0x11af, 0x28},
1249 {0x11b0, 0xd8},
1250 {0x11b1, 0x14},
1251 {0x11b2, 0xec},
1252 {0x11b3, 0x32},
1253 {0x11b4, 0xdd},
1254 {0x11b5, 0x32},
1255 {0x11b6, 0xdd},
1256 {0x10e0, 0x2c},
1257 {0x11bc, 0x40},
1258 {0x11bd, 0x01},
1259 {0x11be, 0xf0},
1260 {0x11bf, 0x00},
1261 {0x118c, 0x1f},
1262 {0x118d, 0x1f},
1263 {0x118e, 0x1f},
1264 {0x118f, 0x1f},
1265 {0x1180, 0x01},
1266 {0x1181, 0x00},
1267 {0x1182, 0x01},
1268 {0x1183, 0x00},
1269 {0x1184, 0x50},
1270 {0x1185, 0x80},
1273 __u8 qtable1[64] = {
1274 0x0d, 0x08, 0x08, 0x0d, 0x08, 0x08, 0x0d, 0x0d,
1275 0x0d, 0x0d, 0x11, 0x0d, 0x0d, 0x11, 0x15, 0x21,
1276 0x15, 0x15, 0x11, 0x11, 0x15, 0x2a, 0x1d, 0x1d,
1277 0x19, 0x21, 0x32, 0x2a, 0x32, 0x32, 0x2e, 0x2a,
1278 0x2e, 0x2e, 0x36, 0x3a, 0x4b, 0x43, 0x36, 0x3a,
1279 0x47, 0x3a, 0x2e, 0x2e, 0x43, 0x5c, 0x43, 0x47,
1280 0x4f, 0x54, 0x58, 0x58, 0x58, 0x32, 0x3f, 0x60,
1281 0x64, 0x5c, 0x54, 0x64, 0x4b, 0x54, 0x58, 0x54
1284 __u8 qtable2[64] = {
1285 0x0d, 0x11, 0x11, 0x15, 0x11, 0x15, 0x26, 0x15,
1286 0x15, 0x26, 0x54, 0x36, 0x2e, 0x36, 0x54, 0x54,
1287 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1288 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1289 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1290 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1291 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1292 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54
1295 for (i = 0; i < ARRAY_SIZE(regs); i++) {
1296 reg = regs[i][0];
1297 value = regs[i][1];
1298 ret = usb_sn9c20x_control_write(dev, reg, &value, 1);
1299 if (unlikely(ret < 0)) {
1300 UDIA_INFO("Bridge Init Error (%d). line %d\n", ret, i);
1301 goto err;
1305 ret = usb_sn9c20x_control_write(dev, 0x1100, qtable1, 64);
1306 if (ret < 0)
1307 goto err;
1309 ret = usb_sn9c20x_control_write(dev, 0x1140, qtable2, 64);
1310 if (ret < 0)
1311 goto err;
1313 #ifdef CONFIG_SN9C20X_EVDEV
1314 ret = usb_sn9c20x_control_read(dev, 0x1005, &dev->input_gpio, 1);
1315 if (ret < 0)
1316 goto err;
1318 dev->input_gpio = ~dev->input_gpio;
1319 #endif
1321 dev->camera.set_contrast = sn9c20x_set_contrast;
1322 dev->camera.set_brightness = sn9c20x_set_brightness;
1323 dev->camera.set_hue = sn9c20x_set_color;
1324 dev->camera.set_saturation = sn9c20x_set_color;
1325 dev->camera.set_gamma = sn9c20x_set_gamma;
1326 dev->camera.set_sharpness = sn9c20x_set_sharpness;
1327 dev->camera.set_red_gain = sn9c20x_set_red_gain;
1328 dev->camera.set_blue_gain = sn9c20x_set_blue_gain;
1330 ret = sn9c20x_i2c_initialize(dev);
1331 if (ret < 0)
1332 goto err;
1334 ret = sn9c20x_initialize_sensor(dev);
1335 return ret;
1337 err:
1338 UDIA_ERROR("Device Init failed (%d)!\n", ret);
1339 return ret;
1342 int sn9c20x_reset_device(struct usb_sn9c20x *dev)
1344 if (sn9c20x_initialize(dev) < 0)
1345 return -EINVAL;
1347 sn9c20x_set_camera_control(dev, V4L2_CID_HFLIP,
1348 dev->vsettings.hflip);
1349 sn9c20x_set_camera_control(dev, V4L2_CID_VFLIP,
1350 dev->vsettings.vflip);
1351 sn9c20x_set_camera_control(dev, V4L2_CID_GAIN,
1352 dev->vsettings.gain);
1353 sn9c20x_set_camera_control(dev, V4L2_CID_BRIGHTNESS,
1354 dev->vsettings.brightness);
1355 sn9c20x_set_camera_control(dev, V4L2_CID_CONTRAST,
1356 dev->vsettings.contrast);
1357 sn9c20x_set_camera_control(dev, V4L2_CID_HUE,
1358 dev->vsettings.hue);
1359 sn9c20x_set_camera_control(dev, V4L2_CID_SATURATION,
1360 dev->vsettings.colour);
1361 sn9c20x_set_camera_control(dev, V4L2_CID_GAMMA,
1362 dev->vsettings.gamma);
1363 sn9c20x_set_camera_control(dev, V4L2_CID_SHARPNESS,
1364 dev->vsettings.sharpness);
1365 sn9c20x_set_camera_control(dev, V4L2_CID_RED_BALANCE,
1366 dev->vsettings.red_gain);
1367 sn9c20x_set_camera_control(dev, V4L2_CID_BLUE_BALANCE,
1368 dev->vsettings.blue_gain);
1369 sn9c20x_set_camera_control(dev, V4L2_CID_EXPOSURE_AUTO,
1370 dev->vsettings.auto_exposure);
1371 sn9c20x_set_camera_control(dev, V4L2_CID_AUTOGAIN,
1372 dev->vsettings.auto_gain);
1373 sn9c20x_set_camera_control(dev, V4L2_CID_AUTO_WHITE_BALANCE,
1374 dev->vsettings.auto_whitebalance);
1375 sn9c20x_set_camera_control(dev, V4L2_CID_EXPOSURE,
1376 dev->vsettings.exposure);
1378 sn9c20x_set_resolution(dev, dev->vsettings.format.width,
1379 dev->vsettings.format.height);
1381 sn9c20x_set_format(dev, dev->vsettings.format.pixelformat);
1383 return 0;