1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Connexant Cx11646 library
4 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #define MODULE_NAME "conex"
14 #define CONEX_CAM 1 /* special JPEG header */
17 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
18 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
19 MODULE_LICENSE("GPL");
23 /* specific webcam descriptor */
25 struct gspca_dev gspca_dev; /* !! must be the first item */
26 struct v4l2_ctrl *brightness;
27 struct v4l2_ctrl *contrast;
28 struct v4l2_ctrl *sat;
30 u8 jpeg_hdr[JPEG_HDR_SZ];
33 static const struct v4l2_pix_format vga_mode[] = {
34 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
36 .sizeimage = 176 * 144 * 3 / 8 + 590,
37 .colorspace = V4L2_COLORSPACE_JPEG,
39 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
41 .sizeimage = 320 * 240 * 3 / 8 + 590,
42 .colorspace = V4L2_COLORSPACE_JPEG,
44 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
46 .sizeimage = 352 * 288 * 3 / 8 + 590,
47 .colorspace = V4L2_COLORSPACE_JPEG,
49 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
51 .sizeimage = 640 * 480 * 3 / 8 + 590,
52 .colorspace = V4L2_COLORSPACE_JPEG,
56 /* the read bytes are found in gspca_dev->usb_buf */
57 static void reg_r(struct gspca_dev *gspca_dev,
61 struct usb_device *dev = gspca_dev->dev;
63 if (len > USB_BUF_SZ) {
64 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
69 usb_rcvctrlpipe(dev, 0),
71 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
73 index, gspca_dev->usb_buf, len,
75 gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n",
76 index, gspca_dev->usb_buf[0]);
79 /* the bytes to write are in gspca_dev->usb_buf */
80 static void reg_w_val(struct gspca_dev *gspca_dev,
84 struct usb_device *dev = gspca_dev->dev;
86 gspca_dev->usb_buf[0] = val;
88 usb_sndctrlpipe(dev, 0),
90 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
92 index, gspca_dev->usb_buf, 1, 500);
95 static void reg_w(struct gspca_dev *gspca_dev,
100 struct usb_device *dev = gspca_dev->dev;
102 if (len > USB_BUF_SZ) {
103 gspca_err(gspca_dev, "reg_w: buffer overflow\n");
106 gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n",
109 memcpy(gspca_dev->usb_buf, buffer, len);
111 usb_sndctrlpipe(dev, 0),
113 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
115 index, gspca_dev->usb_buf, len, 500);
118 static const __u8 cx_sensor_init[][4] = {
119 {0x88, 0x11, 0x01, 0x01},
120 {0x88, 0x12, 0x70, 0x01},
121 {0x88, 0x0f, 0x00, 0x01},
122 {0x88, 0x05, 0x01, 0x01},
126 static const __u8 cx11646_fw1[][3] = {
193 static void cx11646_fw(struct gspca_dev*gspca_dev)
197 reg_w_val(gspca_dev, 0x006a, 0x02);
198 while (cx11646_fw1[i][1]) {
199 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
202 reg_w_val(gspca_dev, 0x006a, 0x00);
205 static const __u8 cxsensor[] = {
206 0x88, 0x12, 0x70, 0x01,
207 0x88, 0x0d, 0x02, 0x01,
208 0x88, 0x0f, 0x00, 0x01,
209 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
210 0x88, 0x02, 0x10, 0x01,
211 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
212 0x88, 0x0B, 0x00, 0x01,
213 0x88, 0x0A, 0x0A, 0x01,
214 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
215 0x88, 0x05, 0x01, 0x01,
216 0xA1, 0x18, 0x00, 0x01,
220 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
221 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
222 static const __u8 reg10[] = { 0xb1, 0xb1 };
223 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
224 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
225 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
226 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
227 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
228 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
229 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
231 static void cx_sensor(struct gspca_dev*gspca_dev)
235 const __u8 *ptsensor = cxsensor;
237 reg_w(gspca_dev, 0x0020, reg20, 8);
238 reg_w(gspca_dev, 0x0028, reg28, 8);
239 reg_w(gspca_dev, 0x0010, reg10, 2);
240 reg_w_val(gspca_dev, 0x0092, 0x03);
242 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
244 reg_w(gspca_dev, 0x0071, reg71a, 4);
247 reg_w(gspca_dev, 0x0071, reg71b, 4);
251 reg_w(gspca_dev, 0x0071, reg71c, 4);
254 reg_w(gspca_dev, 0x0071, reg71d, 4);
257 reg_w(gspca_dev, 0x007b, reg7b, 6);
258 reg_w_val(gspca_dev, 0x00f8, 0x00);
259 reg_w(gspca_dev, 0x0010, reg10, 2);
260 reg_w_val(gspca_dev, 0x0098, 0x41);
261 for (i = 0; i < 11; i++) {
262 if (i == 3 || i == 5 || i == 8)
266 reg_w(gspca_dev, 0x00e5, ptsensor, length);
268 reg_r(gspca_dev, 0x00e8, 1);
270 reg_r(gspca_dev, 0x00e8, length);
273 reg_r(gspca_dev, 0x00e7, 8);
276 static const __u8 cx_inits_176[] = {
277 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
278 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
279 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
280 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
281 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
282 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
283 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
285 static const __u8 cx_inits_320[] = {
286 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
287 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
288 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
289 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
290 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
291 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
292 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
294 static const __u8 cx_inits_352[] = {
295 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
296 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
297 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
298 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
299 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
300 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
301 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
303 static const __u8 cx_inits_640[] = {
304 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
305 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
306 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
307 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
308 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
309 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
310 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
313 static void cx11646_initsize(struct gspca_dev *gspca_dev)
316 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
317 static const __u8 reg17[] =
318 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
320 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
322 cxinit = cx_inits_640;
325 cxinit = cx_inits_352;
329 cxinit = cx_inits_320;
332 cxinit = cx_inits_176;
335 reg_w_val(gspca_dev, 0x009a, 0x01);
336 reg_w_val(gspca_dev, 0x0010, 0x10);
337 reg_w(gspca_dev, 0x0012, reg12, 5);
338 reg_w(gspca_dev, 0x0017, reg17, 8);
339 reg_w_val(gspca_dev, 0x00c0, 0x00);
340 reg_w_val(gspca_dev, 0x00c1, 0x04);
341 reg_w_val(gspca_dev, 0x00c2, 0x04);
343 reg_w(gspca_dev, 0x0061, cxinit, 8);
345 reg_w(gspca_dev, 0x00ca, cxinit, 8);
347 reg_w(gspca_dev, 0x00d2, cxinit, 8);
349 reg_w(gspca_dev, 0x00da, cxinit, 6);
351 reg_w(gspca_dev, 0x0041, cxinit, 8);
353 reg_w(gspca_dev, 0x0049, cxinit, 8);
355 reg_w(gspca_dev, 0x0051, cxinit, 2);
357 reg_r(gspca_dev, 0x0010, 1);
360 static const __u8 cx_jpeg_init[][8] = {
361 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
362 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
363 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
364 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
365 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
366 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
367 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
368 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
369 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
370 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
371 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
372 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
373 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
374 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
375 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
376 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
377 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
378 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
379 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
380 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
381 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
382 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
383 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
384 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
385 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
386 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
387 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
388 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
389 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
390 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
391 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
392 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
393 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
394 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
395 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
396 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
397 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
398 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
399 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
400 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
401 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
402 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
403 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
404 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
405 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
406 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
407 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
408 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
409 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
410 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
411 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
412 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
413 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
414 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
415 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
416 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
417 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
418 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
419 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
420 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
421 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
422 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
423 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
424 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
425 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
426 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
427 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
428 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
429 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
430 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
431 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
432 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
433 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
434 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
435 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
436 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
437 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
438 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
439 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
443 static const __u8 cxjpeg_640[][8] = {
444 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
445 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
446 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
447 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
448 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
449 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
450 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
451 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
452 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
453 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
454 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
455 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
456 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
457 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
458 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
459 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
460 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
461 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
462 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
463 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
464 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
465 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
466 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
467 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
468 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
469 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
470 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
472 static const __u8 cxjpeg_352[][8] = {
473 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
474 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
475 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
476 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
477 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
478 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
479 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
480 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
481 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
482 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
483 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
484 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
485 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
486 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
487 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
488 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
489 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
490 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
491 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
492 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
493 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
494 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
495 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
496 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
497 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
498 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
499 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
501 static const __u8 cxjpeg_320[][8] = {
502 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
503 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
504 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
505 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
506 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
507 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
508 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
509 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
510 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
511 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
512 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
513 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
514 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
515 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
516 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
517 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
518 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
519 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
520 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
521 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
522 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
523 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
524 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
525 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
526 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
527 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
528 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
530 static const __u8 cxjpeg_176[][8] = {
531 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
532 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
533 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
534 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
535 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
536 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
537 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
538 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
539 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
540 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
541 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
542 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
543 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
544 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
545 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
546 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
547 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
548 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
549 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
550 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
551 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
552 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
553 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
554 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
555 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
556 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
557 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
559 /* 640 take with the zcx30x part */
560 static const __u8 cxjpeg_qtable[][8] = {
561 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
562 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
563 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
564 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
565 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
566 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
567 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
568 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
569 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
570 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
571 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
572 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
573 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
574 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
575 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
576 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
577 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
578 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
582 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
587 reg_w_val(gspca_dev, 0x00c0, 0x01);
588 reg_w_val(gspca_dev, 0x00c3, 0x00);
589 reg_w_val(gspca_dev, 0x00c0, 0x00);
590 reg_r(gspca_dev, 0x0001, 1);
592 for (i = 0; i < 79; i++) {
595 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
597 reg_r(gspca_dev, 0x0002, 1);
598 reg_w_val(gspca_dev, 0x0055, 0x14);
601 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
602 static const __u8 regE5_8[] =
603 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
604 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
605 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
606 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
607 static const __u8 reg51[] = { 0x77, 0x03 };
610 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
617 reg_w_val(gspca_dev, 0x00c0, 0x01);
618 reg_w_val(gspca_dev, 0x00c3, 0x00);
619 reg_w_val(gspca_dev, 0x00c0, 0x00);
620 reg_r(gspca_dev, 0x0001, 1);
622 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
624 for (i = 0; i < 27; i++) {
627 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
632 for (i = 0; i < 27; i++) {
635 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
641 for (i = 0; i < 27; i++) {
644 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
649 for (i = 0; i < 27; i++) {
652 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
658 reg_r(gspca_dev, 0x0002, 1);
659 reg_w_val(gspca_dev, 0x0055, Reg55);
660 reg_r(gspca_dev, 0x0002, 1);
661 reg_w(gspca_dev, 0x0010, reg10, 2);
662 reg_w_val(gspca_dev, 0x0054, 0x02);
663 reg_w_val(gspca_dev, 0x0054, 0x01);
664 reg_w_val(gspca_dev, 0x0000, 0x94);
665 reg_w_val(gspca_dev, 0x0053, 0xc0);
666 reg_w_val(gspca_dev, 0x00fc, 0xe1);
667 reg_w_val(gspca_dev, 0x0000, 0x00);
668 /* wait for completion */
671 reg_r(gspca_dev, 0x0002, 1);
672 /* 0x07 until 0x00 */
673 if (gspca_dev->usb_buf[0] == 0x00)
675 reg_w_val(gspca_dev, 0x0053, 0x00);
678 gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n");
679 /* send the qtable now */
680 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
682 for (i = 0; i < 18; i++) {
685 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
688 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
689 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
690 reg_w_val(gspca_dev, 0x0054, 0x02);
691 reg_w_val(gspca_dev, 0x0054, 0x01);
692 reg_w_val(gspca_dev, 0x0000, 0x94);
693 reg_w_val(gspca_dev, 0x0053, 0xc0);
695 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
696 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
697 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
698 reg_w(gspca_dev, 0x0012, reg12, 5);
699 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
700 reg_r(gspca_dev, 0x00e8, 8);
701 reg_w(gspca_dev, 0x00e5, regE5a, 4);
702 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
703 reg_w_val(gspca_dev, 0x009a, 0x01);
704 reg_w(gspca_dev, 0x00e5, regE5b, 4);
705 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
706 reg_w(gspca_dev, 0x00e5, regE5c, 4);
707 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
709 reg_w(gspca_dev, 0x0051, reg51, 2);
710 reg_w(gspca_dev, 0x0010, reg10, 2);
711 reg_w_val(gspca_dev, 0x0070, reg70);
714 static void cx11646_init1(struct gspca_dev *gspca_dev)
718 reg_w_val(gspca_dev, 0x0010, 0x00);
719 reg_w_val(gspca_dev, 0x0053, 0x00);
720 reg_w_val(gspca_dev, 0x0052, 0x00);
721 reg_w_val(gspca_dev, 0x009b, 0x2f);
722 reg_w_val(gspca_dev, 0x009c, 0x10);
723 reg_r(gspca_dev, 0x0098, 1);
724 reg_w_val(gspca_dev, 0x0098, 0x40);
725 reg_r(gspca_dev, 0x0099, 1);
726 reg_w_val(gspca_dev, 0x0099, 0x07);
727 reg_w_val(gspca_dev, 0x0039, 0x40);
728 reg_w_val(gspca_dev, 0x003c, 0xff);
729 reg_w_val(gspca_dev, 0x003f, 0x1f);
730 reg_w_val(gspca_dev, 0x003d, 0x40);
731 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
732 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
734 while (cx_sensor_init[i][0]) {
735 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
736 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
738 reg_w_val(gspca_dev, 0x00ed, 0x01);
739 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
743 reg_w_val(gspca_dev, 0x00c3, 0x00);
746 /* this function is called at probe time */
747 static int sd_config(struct gspca_dev *gspca_dev,
748 const struct usb_device_id *id)
752 cam = &gspca_dev->cam;
753 cam->cam_mode = vga_mode;
754 cam->nmodes = ARRAY_SIZE(vga_mode);
758 /* this function is called at probe and resume time */
759 static int sd_init(struct gspca_dev *gspca_dev)
761 cx11646_init1(gspca_dev);
762 cx11646_initsize(gspca_dev);
763 cx11646_fw(gspca_dev);
764 cx_sensor(gspca_dev);
765 cx11646_jpegInit(gspca_dev);
769 static int sd_start(struct gspca_dev *gspca_dev)
771 struct sd *sd = (struct sd *) gspca_dev;
773 /* create the JPEG header */
774 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
775 gspca_dev->pixfmt.width,
776 0x22); /* JPEG 411 */
777 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
779 cx11646_initsize(gspca_dev);
780 cx11646_fw(gspca_dev);
781 cx_sensor(gspca_dev);
782 cx11646_jpeg(gspca_dev);
786 /* called on streamoff with alt 0 and on disconnect */
787 static void sd_stop0(struct gspca_dev *gspca_dev)
791 if (!gspca_dev->present)
793 reg_w_val(gspca_dev, 0x0000, 0x00);
794 reg_r(gspca_dev, 0x0002, 1);
795 reg_w_val(gspca_dev, 0x0053, 0x00);
798 /* reg_r(gspca_dev, 0x0002, 1);*/
799 reg_r(gspca_dev, 0x0053, 1);
800 if (gspca_dev->usb_buf[0] == 0)
803 reg_w_val(gspca_dev, 0x0000, 0x00);
804 reg_r(gspca_dev, 0x0002, 1);
806 reg_w_val(gspca_dev, 0x0010, 0x00);
807 reg_r(gspca_dev, 0x0033, 1);
808 reg_w_val(gspca_dev, 0x00fc, 0xe0);
811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
812 u8 *data, /* isoc packet */
813 int len) /* iso packet length */
815 struct sd *sd = (struct sd *) gspca_dev;
817 if (data[0] == 0xff && data[1] == 0xd8) {
820 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
822 /* put the JPEG header in the new frame */
823 gspca_frame_add(gspca_dev, FIRST_PACKET,
824 sd->jpeg_hdr, JPEG_HDR_SZ);
828 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
831 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
833 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
837 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
838 reg_r(gspca_dev, 0x00e8, 8);
839 reg_w(gspca_dev, 0x00e5, regE5c, 4);
840 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
844 reg_w(gspca_dev, 0x0051, reg51c, 2);
845 reg_w(gspca_dev, 0x0010, reg10, 2);
846 reg_w_val(gspca_dev, 0x0070, reg70);
849 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
851 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
852 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
856 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
857 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
860 reg_w(gspca_dev, 0x0051, reg51c, 2);
861 reg_w(gspca_dev, 0x0010, reg10, 2);
862 reg_w_val(gspca_dev, 0x0070, reg70);
865 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
867 struct gspca_dev *gspca_dev =
868 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
869 struct sd *sd = (struct sd *)gspca_dev;
871 gspca_dev->usb_err = 0;
873 if (!gspca_dev->streaming)
877 case V4L2_CID_BRIGHTNESS:
878 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
880 case V4L2_CID_CONTRAST:
881 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
883 case V4L2_CID_SATURATION:
884 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
885 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
888 return gspca_dev->usb_err;
891 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
895 static int sd_init_controls(struct gspca_dev *gspca_dev)
897 struct sd *sd = (struct sd *)gspca_dev;
898 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
900 gspca_dev->vdev.ctrl_handler = hdl;
901 v4l2_ctrl_handler_init(hdl, 3);
902 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
903 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
904 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
905 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
906 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
907 V4L2_CID_SATURATION, 0, 7, 1, 3);
909 pr_err("Could not initialize controls\n");
915 /* sub-driver description */
916 static const struct sd_desc sd_desc = {
920 .init_controls = sd_init_controls,
923 .pkt_scan = sd_pkt_scan,
926 /* -- module initialisation -- */
927 static const struct usb_device_id device_table[] = {
928 {USB_DEVICE(0x0572, 0x0041)},
931 MODULE_DEVICE_TABLE(usb, device_table);
933 /* -- device connect -- */
934 static int sd_probe(struct usb_interface *intf,
935 const struct usb_device_id *id)
937 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
941 static struct usb_driver sd_driver = {
943 .id_table = device_table,
945 .disconnect = gspca_disconnect,
947 .suspend = gspca_suspend,
948 .resume = gspca_resume,
949 .reset_resume = gspca_resume,
953 module_usb_driver(sd_driver);