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