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