1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Connexant Cx11646 library
4 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #define MODULE_NAME "conex"
12
13 #include "gspca.h"
14 #define CONEX_CAM 1 /* special JPEG header */
15 #include "jpeg.h"
16
17 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
18 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
19 MODULE_LICENSE("GPL");
20
21 #define QUALITY 50
22
23 /* specific webcam descriptor */
24 struct sd {
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;
29
30 u8 jpeg_hdr[JPEG_HDR_SZ];
31 };
32
33 static const struct v4l2_pix_format vga_mode[] = {
34 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
35 .bytesperline = 176,
36 .sizeimage = 176 * 144 * 3 / 8 + 590,
37 .colorspace = V4L2_COLORSPACE_JPEG,
38 .priv = 3},
39 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
40 .bytesperline = 320,
41 .sizeimage = 320 * 240 * 3 / 8 + 590,
42 .colorspace = V4L2_COLORSPACE_JPEG,
43 .priv = 2},
44 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
45 .bytesperline = 352,
46 .sizeimage = 352 * 288 * 3 / 8 + 590,
47 .colorspace = V4L2_COLORSPACE_JPEG,
48 .priv = 1},
49 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
50 .bytesperline = 640,
51 .sizeimage = 640 * 480 * 3 / 8 + 590,
52 .colorspace = V4L2_COLORSPACE_JPEG,
53 .priv = 0},
54 };
55
56 /* the read bytes are found in gspca_dev->usb_buf */
reg_r(struct gspca_dev * gspca_dev,__u16 index,__u16 len)57 static void reg_r(struct gspca_dev *gspca_dev,
58 __u16 index,
59 __u16 len)
60 {
61 struct usb_device *dev = gspca_dev->dev;
62
63 if (len > USB_BUF_SZ) {
64 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
65 return;
66 }
67
68 usb_control_msg(dev,
69 usb_rcvctrlpipe(dev, 0),
70 0,
71 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
72 0,
73 index, gspca_dev->usb_buf, len,
74 500);
75 gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n",
76 index, gspca_dev->usb_buf[0]);
77 }
78
79 /* the bytes to write are in gspca_dev->usb_buf */
reg_w_val(struct gspca_dev * gspca_dev,__u16 index,__u8 val)80 static void reg_w_val(struct gspca_dev *gspca_dev,
81 __u16 index,
82 __u8 val)
83 {
84 struct usb_device *dev = gspca_dev->dev;
85
86 gspca_dev->usb_buf[0] = val;
87 usb_control_msg(dev,
88 usb_sndctrlpipe(dev, 0),
89 0,
90 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
91 0,
92 index, gspca_dev->usb_buf, 1, 500);
93 }
94
reg_w(struct gspca_dev * gspca_dev,__u16 index,const __u8 * buffer,__u16 len)95 static void reg_w(struct gspca_dev *gspca_dev,
96 __u16 index,
97 const __u8 *buffer,
98 __u16 len)
99 {
100 struct usb_device *dev = gspca_dev->dev;
101
102 if (len > USB_BUF_SZ) {
103 gspca_err(gspca_dev, "reg_w: buffer overflow\n");
104 return;
105 }
106 gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n",
107 index, *buffer);
108
109 memcpy(gspca_dev->usb_buf, buffer, len);
110 usb_control_msg(dev,
111 usb_sndctrlpipe(dev, 0),
112 0,
113 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
114 0,
115 index, gspca_dev->usb_buf, len, 500);
116 }
117
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},
123 {}
124 };
125
126 static const __u8 cx11646_fw1[][3] = {
127 {0x00, 0x02, 0x00},
128 {0x01, 0x43, 0x00},
129 {0x02, 0xA7, 0x00},
130 {0x03, 0x8B, 0x01},
131 {0x04, 0xE9, 0x02},
132 {0x05, 0x08, 0x04},
133 {0x06, 0x08, 0x05},
134 {0x07, 0x07, 0x06},
135 {0x08, 0xE7, 0x06},
136 {0x09, 0xC6, 0x07},
137 {0x0A, 0x86, 0x08},
138 {0x0B, 0x46, 0x09},
139 {0x0C, 0x05, 0x0A},
140 {0x0D, 0xA5, 0x0A},
141 {0x0E, 0x45, 0x0B},
142 {0x0F, 0xE5, 0x0B},
143 {0x10, 0x85, 0x0C},
144 {0x11, 0x25, 0x0D},
145 {0x12, 0xC4, 0x0D},
146 {0x13, 0x45, 0x0E},
147 {0x14, 0xE4, 0x0E},
148 {0x15, 0x64, 0x0F},
149 {0x16, 0xE4, 0x0F},
150 {0x17, 0x64, 0x10},
151 {0x18, 0xE4, 0x10},
152 {0x19, 0x64, 0x11},
153 {0x1A, 0xE4, 0x11},
154 {0x1B, 0x64, 0x12},
155 {0x1C, 0xE3, 0x12},
156 {0x1D, 0x44, 0x13},
157 {0x1E, 0xC3, 0x13},
158 {0x1F, 0x24, 0x14},
159 {0x20, 0xA3, 0x14},
160 {0x21, 0x04, 0x15},
161 {0x22, 0x83, 0x15},
162 {0x23, 0xE3, 0x15},
163 {0x24, 0x43, 0x16},
164 {0x25, 0xA4, 0x16},
165 {0x26, 0x23, 0x17},
166 {0x27, 0x83, 0x17},
167 {0x28, 0xE3, 0x17},
168 {0x29, 0x43, 0x18},
169 {0x2A, 0xA3, 0x18},
170 {0x2B, 0x03, 0x19},
171 {0x2C, 0x63, 0x19},
172 {0x2D, 0xC3, 0x19},
173 {0x2E, 0x22, 0x1A},
174 {0x2F, 0x63, 0x1A},
175 {0x30, 0xC3, 0x1A},
176 {0x31, 0x23, 0x1B},
177 {0x32, 0x83, 0x1B},
178 {0x33, 0xE2, 0x1B},
179 {0x34, 0x23, 0x1C},
180 {0x35, 0x83, 0x1C},
181 {0x36, 0xE2, 0x1C},
182 {0x37, 0x23, 0x1D},
183 {0x38, 0x83, 0x1D},
184 {0x39, 0xE2, 0x1D},
185 {0x3A, 0x23, 0x1E},
186 {0x3B, 0x82, 0x1E},
187 {0x3C, 0xC3, 0x1E},
188 {0x3D, 0x22, 0x1F},
189 {0x3E, 0x63, 0x1F},
190 {0x3F, 0xC1, 0x1F},
191 {}
192 };
cx11646_fw(struct gspca_dev * gspca_dev)193 static void cx11646_fw(struct gspca_dev*gspca_dev)
194 {
195 int i = 0;
196
197 reg_w_val(gspca_dev, 0x006a, 0x02);
198 while (cx11646_fw1[i][1]) {
199 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
200 i++;
201 }
202 reg_w_val(gspca_dev, 0x006a, 0x00);
203 }
204
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,
217 0x00
218 };
219
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 };
230
cx_sensor(struct gspca_dev * gspca_dev)231 static void cx_sensor(struct gspca_dev*gspca_dev)
232 {
233 int i = 0;
234 int length;
235 const __u8 *ptsensor = cxsensor;
236
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);
241
242 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
243 case 0:
244 reg_w(gspca_dev, 0x0071, reg71a, 4);
245 break;
246 case 1:
247 reg_w(gspca_dev, 0x0071, reg71b, 4);
248 break;
249 default:
250 /* case 2: */
251 reg_w(gspca_dev, 0x0071, reg71c, 4);
252 break;
253 case 3:
254 reg_w(gspca_dev, 0x0071, reg71d, 4);
255 break;
256 }
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)
263 length = 8;
264 else
265 length = 4;
266 reg_w(gspca_dev, 0x00e5, ptsensor, length);
267 if (length == 4)
268 reg_r(gspca_dev, 0x00e8, 1);
269 else
270 reg_r(gspca_dev, 0x00e8, length);
271 ptsensor += length;
272 }
273 reg_r(gspca_dev, 0x00e7, 8);
274 }
275
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
284 };
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
293 };
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
302 };
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
311 };
312
cx11646_initsize(struct gspca_dev * gspca_dev)313 static void cx11646_initsize(struct gspca_dev *gspca_dev)
314 {
315 const __u8 *cxinit;
316 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
317 static const __u8 reg17[] =
318 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
319
320 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
321 case 0:
322 cxinit = cx_inits_640;
323 break;
324 case 1:
325 cxinit = cx_inits_352;
326 break;
327 default:
328 /* case 2: */
329 cxinit = cx_inits_320;
330 break;
331 case 3:
332 cxinit = cx_inits_176;
333 break;
334 }
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);
342
343 reg_w(gspca_dev, 0x0061, cxinit, 8);
344 cxinit += 8;
345 reg_w(gspca_dev, 0x00ca, cxinit, 8);
346 cxinit += 8;
347 reg_w(gspca_dev, 0x00d2, cxinit, 8);
348 cxinit += 8;
349 reg_w(gspca_dev, 0x00da, cxinit, 6);
350 cxinit += 8;
351 reg_w(gspca_dev, 0x0041, cxinit, 8);
352 cxinit += 8;
353 reg_w(gspca_dev, 0x0049, cxinit, 8);
354 cxinit += 8;
355 reg_w(gspca_dev, 0x0051, cxinit, 2);
356
357 reg_r(gspca_dev, 0x0010, 1);
358 }
359
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 */
440 };
441
442
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 */
471 };
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}
500 };
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 */
529 };
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}
558 };
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 */
579 };
580
581
cx11646_jpegInit(struct gspca_dev * gspca_dev)582 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
583 {
584 int i;
585 int length;
586
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);
591 length = 8;
592 for (i = 0; i < 79; i++) {
593 if (i == 78)
594 length = 6;
595 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
596 }
597 reg_r(gspca_dev, 0x0002, 1);
598 reg_w_val(gspca_dev, 0x0055, 0x14);
599 }
600
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 };
608 #define reg70 0x03
609
cx11646_jpeg(struct gspca_dev * gspca_dev)610 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
611 {
612 int i;
613 int length;
614 __u8 Reg55;
615 int retry;
616
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);
621 length = 8;
622 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
623 case 0:
624 for (i = 0; i < 27; i++) {
625 if (i == 26)
626 length = 2;
627 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
628 }
629 Reg55 = 0x28;
630 break;
631 case 1:
632 for (i = 0; i < 27; i++) {
633 if (i == 26)
634 length = 2;
635 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
636 }
637 Reg55 = 0x16;
638 break;
639 default:
640 /* case 2: */
641 for (i = 0; i < 27; i++) {
642 if (i == 26)
643 length = 2;
644 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
645 }
646 Reg55 = 0x14;
647 break;
648 case 3:
649 for (i = 0; i < 27; i++) {
650 if (i == 26)
651 length = 2;
652 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
653 }
654 Reg55 = 0x0B;
655 break;
656 }
657
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 */
669 retry = 50;
670 do {
671 reg_r(gspca_dev, 0x0002, 1);
672 /* 0x07 until 0x00 */
673 if (gspca_dev->usb_buf[0] == 0x00)
674 break;
675 reg_w_val(gspca_dev, 0x0053, 0x00);
676 } while (--retry);
677 if (retry == 0)
678 gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n");
679 /* send the qtable now */
680 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
681 length = 8;
682 for (i = 0; i < 18; i++) {
683 if (i == 17)
684 length = 2;
685 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
686
687 }
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);
694
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 */
708
709 reg_w(gspca_dev, 0x0051, reg51, 2);
710 reg_w(gspca_dev, 0x0010, reg10, 2);
711 reg_w_val(gspca_dev, 0x0070, reg70);
712 }
713
cx11646_init1(struct gspca_dev * gspca_dev)714 static void cx11646_init1(struct gspca_dev *gspca_dev)
715 {
716 int i = 0;
717
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 */
733
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 */
737 if (i == 1) {
738 reg_w_val(gspca_dev, 0x00ed, 0x01);
739 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
740 }
741 i++;
742 }
743 reg_w_val(gspca_dev, 0x00c3, 0x00);
744 }
745
746 /* this function is called at probe time */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)747 static int sd_config(struct gspca_dev *gspca_dev,
748 const struct usb_device_id *id)
749 {
750 struct cam *cam;
751
752 cam = &gspca_dev->cam;
753 cam->cam_mode = vga_mode;
754 cam->nmodes = ARRAY_SIZE(vga_mode);
755 return 0;
756 }
757
758 /* this function is called at probe and resume time */
sd_init(struct gspca_dev * gspca_dev)759 static int sd_init(struct gspca_dev *gspca_dev)
760 {
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);
766 return 0;
767 }
768
sd_start(struct gspca_dev * gspca_dev)769 static int sd_start(struct gspca_dev *gspca_dev)
770 {
771 struct sd *sd = (struct sd *) gspca_dev;
772
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);
778
779 cx11646_initsize(gspca_dev);
780 cx11646_fw(gspca_dev);
781 cx_sensor(gspca_dev);
782 cx11646_jpeg(gspca_dev);
783 return 0;
784 }
785
786 /* called on streamoff with alt 0 and on disconnect */
sd_stop0(struct gspca_dev * gspca_dev)787 static void sd_stop0(struct gspca_dev *gspca_dev)
788 {
789 int retry = 50;
790
791 if (!gspca_dev->present)
792 return;
793 reg_w_val(gspca_dev, 0x0000, 0x00);
794 reg_r(gspca_dev, 0x0002, 1);
795 reg_w_val(gspca_dev, 0x0053, 0x00);
796
797 while (retry--) {
798 /* reg_r(gspca_dev, 0x0002, 1);*/
799 reg_r(gspca_dev, 0x0053, 1);
800 if (gspca_dev->usb_buf[0] == 0)
801 break;
802 }
803 reg_w_val(gspca_dev, 0x0000, 0x00);
804 reg_r(gspca_dev, 0x0002, 1);
805
806 reg_w_val(gspca_dev, 0x0010, 0x00);
807 reg_r(gspca_dev, 0x0033, 1);
808 reg_w_val(gspca_dev, 0x00fc, 0xe0);
809 }
810
sd_pkt_scan(struct gspca_dev * gspca_dev,u8 * data,int len)811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
812 u8 *data, /* isoc packet */
813 int len) /* iso packet length */
814 {
815 struct sd *sd = (struct sd *) gspca_dev;
816
817 if (data[0] == 0xff && data[1] == 0xd8) {
818
819 /* start of frame */
820 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
821
822 /* put the JPEG header in the new frame */
823 gspca_frame_add(gspca_dev, FIRST_PACKET,
824 sd->jpeg_hdr, JPEG_HDR_SZ);
825 data += 2;
826 len -= 2;
827 }
828 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
829 }
830
setbrightness(struct gspca_dev * gspca_dev,s32 val,s32 sat)831 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
832 {
833 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
834 __u8 reg51c[2];
835
836 regE5cbx[2] = val;
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 */
841
842 reg51c[0] = 0x77;
843 reg51c[1] = sat;
844 reg_w(gspca_dev, 0x0051, reg51c, 2);
845 reg_w(gspca_dev, 0x0010, reg10, 2);
846 reg_w_val(gspca_dev, 0x0070, reg70);
847 }
848
setcontrast(struct gspca_dev * gspca_dev,s32 val,s32 sat)849 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
850 {
851 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
852 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
853 __u8 reg51c[2];
854
855 regE5acx[2] = val;
856 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
857 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
858 reg51c[0] = 0x77;
859 reg51c[1] = sat;
860 reg_w(gspca_dev, 0x0051, reg51c, 2);
861 reg_w(gspca_dev, 0x0010, reg10, 2);
862 reg_w_val(gspca_dev, 0x0070, reg70);
863 }
864
sd_s_ctrl(struct v4l2_ctrl * ctrl)865 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
866 {
867 struct gspca_dev *gspca_dev =
868 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
869 struct sd *sd = (struct sd *)gspca_dev;
870
871 gspca_dev->usb_err = 0;
872
873 if (!gspca_dev->streaming)
874 return 0;
875
876 switch (ctrl->id) {
877 case V4L2_CID_BRIGHTNESS:
878 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
879 break;
880 case V4L2_CID_CONTRAST:
881 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
882 break;
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);
886 break;
887 }
888 return gspca_dev->usb_err;
889 }
890
891 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
892 .s_ctrl = sd_s_ctrl,
893 };
894
sd_init_controls(struct gspca_dev * gspca_dev)895 static int sd_init_controls(struct gspca_dev *gspca_dev)
896 {
897 struct sd *sd = (struct sd *)gspca_dev;
898 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
899
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);
908 if (hdl->error) {
909 pr_err("Could not initialize controls\n");
910 return hdl->error;
911 }
912 return 0;
913 }
914
915 /* sub-driver description */
916 static const struct sd_desc sd_desc = {
917 .name = MODULE_NAME,
918 .config = sd_config,
919 .init = sd_init,
920 .init_controls = sd_init_controls,
921 .start = sd_start,
922 .stop0 = sd_stop0,
923 .pkt_scan = sd_pkt_scan,
924 };
925
926 /* -- module initialisation -- */
927 static const struct usb_device_id device_table[] = {
928 {USB_DEVICE(0x0572, 0x0041)},
929 {}
930 };
931 MODULE_DEVICE_TABLE(usb, device_table);
932
933 /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)934 static int sd_probe(struct usb_interface *intf,
935 const struct usb_device_id *id)
936 {
937 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
938 THIS_MODULE);
939 }
940
941 static struct usb_driver sd_driver = {
942 .name = MODULE_NAME,
943 .id_table = device_table,
944 .probe = sd_probe,
945 .disconnect = gspca_disconnect,
946 #ifdef CONFIG_PM
947 .suspend = gspca_suspend,
948 .resume = gspca_resume,
949 .reset_resume = gspca_resume,
950 #endif
951 };
952
953 module_usb_driver(sd_driver);
954