Adding support for MOXA ART SoC. Testing port of linux-2.6.32.60-moxart.
[linux-3.6.7-moxart.git] / drivers / media / video / gspca / conex.c
blobc9052f20435ef00c2fc17cc2c870ebbfaedc0896
1 /*
2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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 * any later version.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24 #define MODULE_NAME "conex"
26 #include "gspca.h"
27 #define CONEX_CAM 1 /* special JPEG header */
28 #include "jpeg.h"
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
32 MODULE_LICENSE("GPL");
34 #define QUALITY 50
36 /* specific webcam descriptor */
37 struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39 struct v4l2_ctrl *brightness;
40 struct v4l2_ctrl *contrast;
41 struct v4l2_ctrl *sat;
43 u8 jpeg_hdr[JPEG_HDR_SZ];
46 static const struct v4l2_pix_format vga_mode[] = {
47 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
48 .bytesperline = 176,
49 .sizeimage = 176 * 144 * 3 / 8 + 590,
50 .colorspace = V4L2_COLORSPACE_JPEG,
51 .priv = 3},
52 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
53 .bytesperline = 320,
54 .sizeimage = 320 * 240 * 3 / 8 + 590,
55 .colorspace = V4L2_COLORSPACE_JPEG,
56 .priv = 2},
57 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
58 .bytesperline = 352,
59 .sizeimage = 352 * 288 * 3 / 8 + 590,
60 .colorspace = V4L2_COLORSPACE_JPEG,
61 .priv = 1},
62 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
63 .bytesperline = 640,
64 .sizeimage = 640 * 480 * 3 / 8 + 590,
65 .colorspace = V4L2_COLORSPACE_JPEG,
66 .priv = 0},
69 /* the read bytes are found in gspca_dev->usb_buf */
70 static void reg_r(struct gspca_dev *gspca_dev,
71 __u16 index,
72 __u16 len)
74 struct usb_device *dev = gspca_dev->dev;
76 #ifdef GSPCA_DEBUG
77 if (len > USB_BUF_SZ) {
78 pr_err("reg_r: buffer overflow\n");
79 return;
81 #endif
82 usb_control_msg(dev,
83 usb_rcvctrlpipe(dev, 0),
85 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
87 index, gspca_dev->usb_buf, len,
88 500);
89 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
90 index, gspca_dev->usb_buf[0]);
93 /* the bytes to write are in gspca_dev->usb_buf */
94 static void reg_w_val(struct gspca_dev *gspca_dev,
95 __u16 index,
96 __u8 val)
98 struct usb_device *dev = gspca_dev->dev;
100 gspca_dev->usb_buf[0] = val;
101 usb_control_msg(dev,
102 usb_sndctrlpipe(dev, 0),
104 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
106 index, gspca_dev->usb_buf, 1, 500);
109 static void reg_w(struct gspca_dev *gspca_dev,
110 __u16 index,
111 const __u8 *buffer,
112 __u16 len)
114 struct usb_device *dev = gspca_dev->dev;
116 #ifdef GSPCA_DEBUG
117 if (len > USB_BUF_SZ) {
118 pr_err("reg_w: buffer overflow\n");
119 return;
121 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
122 #endif
123 memcpy(gspca_dev->usb_buf, buffer, len);
124 usb_control_msg(dev,
125 usb_sndctrlpipe(dev, 0),
127 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
129 index, gspca_dev->usb_buf, len, 500);
132 static const __u8 cx_sensor_init[][4] = {
133 {0x88, 0x11, 0x01, 0x01},
134 {0x88, 0x12, 0x70, 0x01},
135 {0x88, 0x0f, 0x00, 0x01},
136 {0x88, 0x05, 0x01, 0x01},
140 static const __u8 cx11646_fw1[][3] = {
141 {0x00, 0x02, 0x00},
142 {0x01, 0x43, 0x00},
143 {0x02, 0xA7, 0x00},
144 {0x03, 0x8B, 0x01},
145 {0x04, 0xE9, 0x02},
146 {0x05, 0x08, 0x04},
147 {0x06, 0x08, 0x05},
148 {0x07, 0x07, 0x06},
149 {0x08, 0xE7, 0x06},
150 {0x09, 0xC6, 0x07},
151 {0x0A, 0x86, 0x08},
152 {0x0B, 0x46, 0x09},
153 {0x0C, 0x05, 0x0A},
154 {0x0D, 0xA5, 0x0A},
155 {0x0E, 0x45, 0x0B},
156 {0x0F, 0xE5, 0x0B},
157 {0x10, 0x85, 0x0C},
158 {0x11, 0x25, 0x0D},
159 {0x12, 0xC4, 0x0D},
160 {0x13, 0x45, 0x0E},
161 {0x14, 0xE4, 0x0E},
162 {0x15, 0x64, 0x0F},
163 {0x16, 0xE4, 0x0F},
164 {0x17, 0x64, 0x10},
165 {0x18, 0xE4, 0x10},
166 {0x19, 0x64, 0x11},
167 {0x1A, 0xE4, 0x11},
168 {0x1B, 0x64, 0x12},
169 {0x1C, 0xE3, 0x12},
170 {0x1D, 0x44, 0x13},
171 {0x1E, 0xC3, 0x13},
172 {0x1F, 0x24, 0x14},
173 {0x20, 0xA3, 0x14},
174 {0x21, 0x04, 0x15},
175 {0x22, 0x83, 0x15},
176 {0x23, 0xE3, 0x15},
177 {0x24, 0x43, 0x16},
178 {0x25, 0xA4, 0x16},
179 {0x26, 0x23, 0x17},
180 {0x27, 0x83, 0x17},
181 {0x28, 0xE3, 0x17},
182 {0x29, 0x43, 0x18},
183 {0x2A, 0xA3, 0x18},
184 {0x2B, 0x03, 0x19},
185 {0x2C, 0x63, 0x19},
186 {0x2D, 0xC3, 0x19},
187 {0x2E, 0x22, 0x1A},
188 {0x2F, 0x63, 0x1A},
189 {0x30, 0xC3, 0x1A},
190 {0x31, 0x23, 0x1B},
191 {0x32, 0x83, 0x1B},
192 {0x33, 0xE2, 0x1B},
193 {0x34, 0x23, 0x1C},
194 {0x35, 0x83, 0x1C},
195 {0x36, 0xE2, 0x1C},
196 {0x37, 0x23, 0x1D},
197 {0x38, 0x83, 0x1D},
198 {0x39, 0xE2, 0x1D},
199 {0x3A, 0x23, 0x1E},
200 {0x3B, 0x82, 0x1E},
201 {0x3C, 0xC3, 0x1E},
202 {0x3D, 0x22, 0x1F},
203 {0x3E, 0x63, 0x1F},
204 {0x3F, 0xC1, 0x1F},
207 static void cx11646_fw(struct gspca_dev*gspca_dev)
209 int i = 0;
211 reg_w_val(gspca_dev, 0x006a, 0x02);
212 while (cx11646_fw1[i][1]) {
213 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
214 i++;
216 reg_w_val(gspca_dev, 0x006a, 0x00);
219 static const __u8 cxsensor[] = {
220 0x88, 0x12, 0x70, 0x01,
221 0x88, 0x0d, 0x02, 0x01,
222 0x88, 0x0f, 0x00, 0x01,
223 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
224 0x88, 0x02, 0x10, 0x01,
225 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
226 0x88, 0x0B, 0x00, 0x01,
227 0x88, 0x0A, 0x0A, 0x01,
228 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
229 0x88, 0x05, 0x01, 0x01,
230 0xA1, 0x18, 0x00, 0x01,
231 0x00
234 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
235 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
236 static const __u8 reg10[] = { 0xb1, 0xb1 };
237 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
238 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
239 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
240 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
241 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
242 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
243 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
245 static void cx_sensor(struct gspca_dev*gspca_dev)
247 int i = 0;
248 int length;
249 const __u8 *ptsensor = cxsensor;
251 reg_w(gspca_dev, 0x0020, reg20, 8);
252 reg_w(gspca_dev, 0x0028, reg28, 8);
253 reg_w(gspca_dev, 0x0010, reg10, 2);
254 reg_w_val(gspca_dev, 0x0092, 0x03);
256 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
257 case 0:
258 reg_w(gspca_dev, 0x0071, reg71a, 4);
259 break;
260 case 1:
261 reg_w(gspca_dev, 0x0071, reg71b, 4);
262 break;
263 default:
264 /* case 2: */
265 reg_w(gspca_dev, 0x0071, reg71c, 4);
266 break;
267 case 3:
268 reg_w(gspca_dev, 0x0071, reg71d, 4);
269 break;
271 reg_w(gspca_dev, 0x007b, reg7b, 6);
272 reg_w_val(gspca_dev, 0x00f8, 0x00);
273 reg_w(gspca_dev, 0x0010, reg10, 2);
274 reg_w_val(gspca_dev, 0x0098, 0x41);
275 for (i = 0; i < 11; i++) {
276 if (i == 3 || i == 5 || i == 8)
277 length = 8;
278 else
279 length = 4;
280 reg_w(gspca_dev, 0x00e5, ptsensor, length);
281 if (length == 4)
282 reg_r(gspca_dev, 0x00e8, 1);
283 else
284 reg_r(gspca_dev, 0x00e8, length);
285 ptsensor += length;
287 reg_r(gspca_dev, 0x00e7, 8);
290 static const __u8 cx_inits_176[] = {
291 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
292 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
293 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
294 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
295 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
296 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
297 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
299 static const __u8 cx_inits_320[] = {
300 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
301 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
302 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
303 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
304 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
305 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
306 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
308 static const __u8 cx_inits_352[] = {
309 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
310 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
311 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
312 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
313 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
314 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
315 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
317 static const __u8 cx_inits_640[] = {
318 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
319 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
320 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
321 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
322 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
323 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
324 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
327 static void cx11646_initsize(struct gspca_dev *gspca_dev)
329 const __u8 *cxinit;
330 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
331 static const __u8 reg17[] =
332 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
334 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
335 case 0:
336 cxinit = cx_inits_640;
337 break;
338 case 1:
339 cxinit = cx_inits_352;
340 break;
341 default:
342 /* case 2: */
343 cxinit = cx_inits_320;
344 break;
345 case 3:
346 cxinit = cx_inits_176;
347 break;
349 reg_w_val(gspca_dev, 0x009a, 0x01);
350 reg_w_val(gspca_dev, 0x0010, 0x10);
351 reg_w(gspca_dev, 0x0012, reg12, 5);
352 reg_w(gspca_dev, 0x0017, reg17, 8);
353 reg_w_val(gspca_dev, 0x00c0, 0x00);
354 reg_w_val(gspca_dev, 0x00c1, 0x04);
355 reg_w_val(gspca_dev, 0x00c2, 0x04);
357 reg_w(gspca_dev, 0x0061, cxinit, 8);
358 cxinit += 8;
359 reg_w(gspca_dev, 0x00ca, cxinit, 8);
360 cxinit += 8;
361 reg_w(gspca_dev, 0x00d2, cxinit, 8);
362 cxinit += 8;
363 reg_w(gspca_dev, 0x00da, cxinit, 6);
364 cxinit += 8;
365 reg_w(gspca_dev, 0x0041, cxinit, 8);
366 cxinit += 8;
367 reg_w(gspca_dev, 0x0049, cxinit, 8);
368 cxinit += 8;
369 reg_w(gspca_dev, 0x0051, cxinit, 2);
371 reg_r(gspca_dev, 0x0010, 1);
374 static const __u8 cx_jpeg_init[][8] = {
375 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
376 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
377 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
378 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
379 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
380 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
381 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
382 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
383 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
384 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
385 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
386 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
387 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
388 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
389 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
390 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
391 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
392 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
393 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
394 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
395 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
396 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
397 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
398 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
399 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
400 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
401 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
402 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
403 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
404 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
405 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
406 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
407 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
408 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
409 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
410 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
411 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
412 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
413 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
414 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
415 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
416 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
417 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
418 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
419 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
420 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
421 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
422 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
423 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
424 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
425 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
426 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
427 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
428 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
429 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
430 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
431 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
432 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
433 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
434 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
435 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
436 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
437 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
438 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
439 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
440 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
441 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
442 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
443 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
444 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
445 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
446 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
447 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
448 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
449 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
450 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
451 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
452 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
453 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
457 static const __u8 cxjpeg_640[][8] = {
458 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
459 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
460 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
461 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
462 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
463 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
464 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
465 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
466 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
467 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
468 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
469 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
470 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
471 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
472 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
473 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
474 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
475 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
476 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
477 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
478 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
479 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
480 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
481 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
482 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
483 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
484 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
486 static const __u8 cxjpeg_352[][8] = {
487 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
488 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
489 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
490 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
491 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
492 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
493 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
494 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
495 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
496 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
497 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
498 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
499 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
500 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
501 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
502 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
503 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
504 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
505 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
506 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
507 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
508 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
509 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
510 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
511 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
512 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
513 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
515 static const __u8 cxjpeg_320[][8] = {
516 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
517 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
518 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
519 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
520 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
521 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
522 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
523 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
524 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
525 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
526 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
527 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
528 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
529 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
530 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
531 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
532 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
533 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
534 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
535 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
536 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
537 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
538 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
539 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
540 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
541 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
542 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
544 static const __u8 cxjpeg_176[][8] = {
545 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
546 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
547 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
548 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
549 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
550 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
551 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
552 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
553 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
554 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
555 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
556 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
557 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
558 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
559 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
560 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
561 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
562 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
563 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
564 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
565 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
566 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
567 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
568 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
569 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
570 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
571 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
573 /* 640 take with the zcx30x part */
574 static const __u8 cxjpeg_qtable[][8] = {
575 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
576 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
577 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
578 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
579 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
580 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
581 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
582 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
583 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
584 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
585 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
586 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
587 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
588 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
589 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
590 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
591 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
592 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
596 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
598 int i;
599 int length;
601 reg_w_val(gspca_dev, 0x00c0, 0x01);
602 reg_w_val(gspca_dev, 0x00c3, 0x00);
603 reg_w_val(gspca_dev, 0x00c0, 0x00);
604 reg_r(gspca_dev, 0x0001, 1);
605 length = 8;
606 for (i = 0; i < 79; i++) {
607 if (i == 78)
608 length = 6;
609 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
611 reg_r(gspca_dev, 0x0002, 1);
612 reg_w_val(gspca_dev, 0x0055, 0x14);
615 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
616 static const __u8 regE5_8[] =
617 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
618 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
619 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
620 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
621 static const __u8 reg51[] = { 0x77, 0x03 };
622 #define reg70 0x03
624 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
626 int i;
627 int length;
628 __u8 Reg55;
629 int retry;
631 reg_w_val(gspca_dev, 0x00c0, 0x01);
632 reg_w_val(gspca_dev, 0x00c3, 0x00);
633 reg_w_val(gspca_dev, 0x00c0, 0x00);
634 reg_r(gspca_dev, 0x0001, 1);
635 length = 8;
636 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
637 case 0:
638 for (i = 0; i < 27; i++) {
639 if (i == 26)
640 length = 2;
641 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
643 Reg55 = 0x28;
644 break;
645 case 1:
646 for (i = 0; i < 27; i++) {
647 if (i == 26)
648 length = 2;
649 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
651 Reg55 = 0x16;
652 break;
653 default:
654 /* case 2: */
655 for (i = 0; i < 27; i++) {
656 if (i == 26)
657 length = 2;
658 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
660 Reg55 = 0x14;
661 break;
662 case 3:
663 for (i = 0; i < 27; i++) {
664 if (i == 26)
665 length = 2;
666 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
668 Reg55 = 0x0B;
669 break;
672 reg_r(gspca_dev, 0x0002, 1);
673 reg_w_val(gspca_dev, 0x0055, Reg55);
674 reg_r(gspca_dev, 0x0002, 1);
675 reg_w(gspca_dev, 0x0010, reg10, 2);
676 reg_w_val(gspca_dev, 0x0054, 0x02);
677 reg_w_val(gspca_dev, 0x0054, 0x01);
678 reg_w_val(gspca_dev, 0x0000, 0x94);
679 reg_w_val(gspca_dev, 0x0053, 0xc0);
680 reg_w_val(gspca_dev, 0x00fc, 0xe1);
681 reg_w_val(gspca_dev, 0x0000, 0x00);
682 /* wait for completion */
683 retry = 50;
684 do {
685 reg_r(gspca_dev, 0x0002, 1);
686 /* 0x07 until 0x00 */
687 if (gspca_dev->usb_buf[0] == 0x00)
688 break;
689 reg_w_val(gspca_dev, 0x0053, 0x00);
690 } while (--retry);
691 if (retry == 0)
692 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
693 /* send the qtable now */
694 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
695 length = 8;
696 for (i = 0; i < 18; i++) {
697 if (i == 17)
698 length = 2;
699 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
702 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
703 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
704 reg_w_val(gspca_dev, 0x0054, 0x02);
705 reg_w_val(gspca_dev, 0x0054, 0x01);
706 reg_w_val(gspca_dev, 0x0000, 0x94);
707 reg_w_val(gspca_dev, 0x0053, 0xc0);
709 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
710 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
711 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
712 reg_w(gspca_dev, 0x0012, reg12, 5);
713 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
714 reg_r(gspca_dev, 0x00e8, 8);
715 reg_w(gspca_dev, 0x00e5, regE5a, 4);
716 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
717 reg_w_val(gspca_dev, 0x009a, 0x01);
718 reg_w(gspca_dev, 0x00e5, regE5b, 4);
719 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
720 reg_w(gspca_dev, 0x00e5, regE5c, 4);
721 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
723 reg_w(gspca_dev, 0x0051, reg51, 2);
724 reg_w(gspca_dev, 0x0010, reg10, 2);
725 reg_w_val(gspca_dev, 0x0070, reg70);
728 static void cx11646_init1(struct gspca_dev *gspca_dev)
730 int i = 0;
732 reg_w_val(gspca_dev, 0x0010, 0x00);
733 reg_w_val(gspca_dev, 0x0053, 0x00);
734 reg_w_val(gspca_dev, 0x0052, 0x00);
735 reg_w_val(gspca_dev, 0x009b, 0x2f);
736 reg_w_val(gspca_dev, 0x009c, 0x10);
737 reg_r(gspca_dev, 0x0098, 1);
738 reg_w_val(gspca_dev, 0x0098, 0x40);
739 reg_r(gspca_dev, 0x0099, 1);
740 reg_w_val(gspca_dev, 0x0099, 0x07);
741 reg_w_val(gspca_dev, 0x0039, 0x40);
742 reg_w_val(gspca_dev, 0x003c, 0xff);
743 reg_w_val(gspca_dev, 0x003f, 0x1f);
744 reg_w_val(gspca_dev, 0x003d, 0x40);
745 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
746 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
748 while (cx_sensor_init[i][0]) {
749 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
750 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
751 if (i == 1) {
752 reg_w_val(gspca_dev, 0x00ed, 0x01);
753 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
755 i++;
757 reg_w_val(gspca_dev, 0x00c3, 0x00);
760 /* this function is called at probe time */
761 static int sd_config(struct gspca_dev *gspca_dev,
762 const struct usb_device_id *id)
764 struct cam *cam;
766 cam = &gspca_dev->cam;
767 cam->cam_mode = vga_mode;
768 cam->nmodes = ARRAY_SIZE(vga_mode);
769 return 0;
772 /* this function is called at probe and resume time */
773 static int sd_init(struct gspca_dev *gspca_dev)
775 cx11646_init1(gspca_dev);
776 cx11646_initsize(gspca_dev);
777 cx11646_fw(gspca_dev);
778 cx_sensor(gspca_dev);
779 cx11646_jpegInit(gspca_dev);
780 return 0;
783 static int sd_start(struct gspca_dev *gspca_dev)
785 struct sd *sd = (struct sd *) gspca_dev;
787 /* create the JPEG header */
788 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
789 0x22); /* JPEG 411 */
790 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
792 cx11646_initsize(gspca_dev);
793 cx11646_fw(gspca_dev);
794 cx_sensor(gspca_dev);
795 cx11646_jpeg(gspca_dev);
796 return 0;
799 /* called on streamoff with alt 0 and on disconnect */
800 static void sd_stop0(struct gspca_dev *gspca_dev)
802 int retry = 50;
804 if (!gspca_dev->present)
805 return;
806 reg_w_val(gspca_dev, 0x0000, 0x00);
807 reg_r(gspca_dev, 0x0002, 1);
808 reg_w_val(gspca_dev, 0x0053, 0x00);
810 while (retry--) {
811 /* reg_r(gspca_dev, 0x0002, 1);*/
812 reg_r(gspca_dev, 0x0053, 1);
813 if (gspca_dev->usb_buf[0] == 0)
814 break;
816 reg_w_val(gspca_dev, 0x0000, 0x00);
817 reg_r(gspca_dev, 0x0002, 1);
819 reg_w_val(gspca_dev, 0x0010, 0x00);
820 reg_r(gspca_dev, 0x0033, 1);
821 reg_w_val(gspca_dev, 0x00fc, 0xe0);
824 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
825 u8 *data, /* isoc packet */
826 int len) /* iso packet length */
828 struct sd *sd = (struct sd *) gspca_dev;
830 if (data[0] == 0xff && data[1] == 0xd8) {
832 /* start of frame */
833 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
835 /* put the JPEG header in the new frame */
836 gspca_frame_add(gspca_dev, FIRST_PACKET,
837 sd->jpeg_hdr, JPEG_HDR_SZ);
838 data += 2;
839 len -= 2;
841 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
844 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
846 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
847 __u8 reg51c[2];
849 regE5cbx[2] = val;
850 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
851 reg_r(gspca_dev, 0x00e8, 8);
852 reg_w(gspca_dev, 0x00e5, regE5c, 4);
853 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
855 reg51c[0] = 0x77;
856 reg51c[1] = sat;
857 reg_w(gspca_dev, 0x0051, reg51c, 2);
858 reg_w(gspca_dev, 0x0010, reg10, 2);
859 reg_w_val(gspca_dev, 0x0070, reg70);
862 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
864 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
865 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
866 __u8 reg51c[2];
868 regE5acx[2] = val;
869 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
870 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
871 reg51c[0] = 0x77;
872 reg51c[1] = sat;
873 reg_w(gspca_dev, 0x0051, reg51c, 2);
874 reg_w(gspca_dev, 0x0010, reg10, 2);
875 reg_w_val(gspca_dev, 0x0070, reg70);
878 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
880 struct gspca_dev *gspca_dev =
881 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
882 struct sd *sd = (struct sd *)gspca_dev;
884 gspca_dev->usb_err = 0;
886 if (!gspca_dev->streaming)
887 return 0;
889 switch (ctrl->id) {
890 case V4L2_CID_BRIGHTNESS:
891 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
892 break;
893 case V4L2_CID_CONTRAST:
894 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
895 break;
896 case V4L2_CID_SATURATION:
897 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
898 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
899 break;
901 return gspca_dev->usb_err;
904 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
905 .s_ctrl = sd_s_ctrl,
908 static int sd_init_controls(struct gspca_dev *gspca_dev)
910 struct sd *sd = (struct sd *)gspca_dev;
911 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
913 gspca_dev->vdev.ctrl_handler = hdl;
914 v4l2_ctrl_handler_init(hdl, 3);
915 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
916 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
917 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
918 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
919 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
920 V4L2_CID_SATURATION, 0, 7, 1, 3);
921 if (hdl->error) {
922 pr_err("Could not initialize controls\n");
923 return hdl->error;
925 return 0;
928 /* sub-driver description */
929 static const struct sd_desc sd_desc = {
930 .name = MODULE_NAME,
931 .config = sd_config,
932 .init = sd_init,
933 .init_controls = sd_init_controls,
934 .start = sd_start,
935 .stop0 = sd_stop0,
936 .pkt_scan = sd_pkt_scan,
939 /* -- module initialisation -- */
940 static const struct usb_device_id device_table[] = {
941 {USB_DEVICE(0x0572, 0x0041)},
944 MODULE_DEVICE_TABLE(usb, device_table);
946 /* -- device connect -- */
947 static int sd_probe(struct usb_interface *intf,
948 const struct usb_device_id *id)
950 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
951 THIS_MODULE);
954 static struct usb_driver sd_driver = {
955 .name = MODULE_NAME,
956 .id_table = device_table,
957 .probe = sd_probe,
958 .disconnect = gspca_disconnect,
959 #ifdef CONFIG_PM
960 .suspend = gspca_suspend,
961 .resume = gspca_resume,
962 .reset_resume = gspca_resume,
963 #endif
966 module_usb_driver(sd_driver);