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