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