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