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