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 */ |
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 | request: 0, |
71 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
72 | value: 0, |
73 | index, data: gspca_dev->usb_buf, size: len, |
74 | timeout: 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 */ |
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 | request: 0, |
90 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
91 | value: 0, |
92 | index, data: gspca_dev->usb_buf, size: 1, timeout: 500); |
93 | } |
94 | |
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 | request: 0, |
113 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
114 | value: 0, |
115 | index, data: gspca_dev->usb_buf, size: len, timeout: 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 | }; |
193 | static void cx11646_fw(struct gspca_dev*gspca_dev) |
194 | { |
195 | int i = 0; |
196 | |
197 | reg_w_val(gspca_dev, index: 0x006a, val: 0x02); |
198 | while (cx11646_fw1[i][1]) { |
199 | reg_w(gspca_dev, index: 0x006b, buffer: cx11646_fw1[i], len: 3); |
200 | i++; |
201 | } |
202 | reg_w_val(gspca_dev, index: 0x006a, val: 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 | |
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, index: 0x0020, buffer: reg20, len: 8); |
238 | reg_w(gspca_dev, index: 0x0028, buffer: reg28, len: 8); |
239 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
240 | reg_w_val(gspca_dev, index: 0x0092, val: 0x03); |
241 | |
242 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
243 | case 0: |
244 | reg_w(gspca_dev, index: 0x0071, buffer: reg71a, len: 4); |
245 | break; |
246 | case 1: |
247 | reg_w(gspca_dev, index: 0x0071, buffer: reg71b, len: 4); |
248 | break; |
249 | default: |
250 | /* case 2: */ |
251 | reg_w(gspca_dev, index: 0x0071, buffer: reg71c, len: 4); |
252 | break; |
253 | case 3: |
254 | reg_w(gspca_dev, index: 0x0071, buffer: reg71d, len: 4); |
255 | break; |
256 | } |
257 | reg_w(gspca_dev, index: 0x007b, buffer: reg7b, len: 6); |
258 | reg_w_val(gspca_dev, index: 0x00f8, val: 0x00); |
259 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
260 | reg_w_val(gspca_dev, index: 0x0098, val: 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, index: 0x00e5, buffer: ptsensor, len: length); |
267 | if (length == 4) |
268 | reg_r(gspca_dev, index: 0x00e8, len: 1); |
269 | else |
270 | reg_r(gspca_dev, index: 0x00e8, len: length); |
271 | ptsensor += length; |
272 | } |
273 | reg_r(gspca_dev, index: 0x00e7, len: 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 | |
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, index: 0x009a, val: 0x01); |
336 | reg_w_val(gspca_dev, index: 0x0010, val: 0x10); |
337 | reg_w(gspca_dev, index: 0x0012, buffer: reg12, len: 5); |
338 | reg_w(gspca_dev, index: 0x0017, buffer: reg17, len: 8); |
339 | reg_w_val(gspca_dev, index: 0x00c0, val: 0x00); |
340 | reg_w_val(gspca_dev, index: 0x00c1, val: 0x04); |
341 | reg_w_val(gspca_dev, index: 0x00c2, val: 0x04); |
342 | |
343 | reg_w(gspca_dev, index: 0x0061, buffer: cxinit, len: 8); |
344 | cxinit += 8; |
345 | reg_w(gspca_dev, index: 0x00ca, buffer: cxinit, len: 8); |
346 | cxinit += 8; |
347 | reg_w(gspca_dev, index: 0x00d2, buffer: cxinit, len: 8); |
348 | cxinit += 8; |
349 | reg_w(gspca_dev, index: 0x00da, buffer: cxinit, len: 6); |
350 | cxinit += 8; |
351 | reg_w(gspca_dev, index: 0x0041, buffer: cxinit, len: 8); |
352 | cxinit += 8; |
353 | reg_w(gspca_dev, index: 0x0049, buffer: cxinit, len: 8); |
354 | cxinit += 8; |
355 | reg_w(gspca_dev, index: 0x0051, buffer: cxinit, len: 2); |
356 | |
357 | reg_r(gspca_dev, index: 0x0010, len: 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 | |
582 | static void cx11646_jpegInit(struct gspca_dev*gspca_dev) |
583 | { |
584 | int i; |
585 | int length; |
586 | |
587 | reg_w_val(gspca_dev, index: 0x00c0, val: 0x01); |
588 | reg_w_val(gspca_dev, index: 0x00c3, val: 0x00); |
589 | reg_w_val(gspca_dev, index: 0x00c0, val: 0x00); |
590 | reg_r(gspca_dev, index: 0x0001, len: 1); |
591 | length = 8; |
592 | for (i = 0; i < 79; i++) { |
593 | if (i == 78) |
594 | length = 6; |
595 | reg_w(gspca_dev, index: 0x0008, buffer: cx_jpeg_init[i], len: length); |
596 | } |
597 | reg_r(gspca_dev, index: 0x0002, len: 1); |
598 | reg_w_val(gspca_dev, index: 0x0055, val: 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 | |
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, index: 0x00c0, val: 0x01); |
618 | reg_w_val(gspca_dev, index: 0x00c3, val: 0x00); |
619 | reg_w_val(gspca_dev, index: 0x00c0, val: 0x00); |
620 | reg_r(gspca_dev, index: 0x0001, len: 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, index: 0x0008, buffer: cxjpeg_640[i], len: 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, index: 0x0008, buffer: cxjpeg_352[i], len: 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, index: 0x0008, buffer: cxjpeg_320[i], len: 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, index: 0x0008, buffer: cxjpeg_176[i], len: length); |
653 | } |
654 | Reg55 = 0x0B; |
655 | break; |
656 | } |
657 | |
658 | reg_r(gspca_dev, index: 0x0002, len: 1); |
659 | reg_w_val(gspca_dev, index: 0x0055, val: Reg55); |
660 | reg_r(gspca_dev, index: 0x0002, len: 1); |
661 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
662 | reg_w_val(gspca_dev, index: 0x0054, val: 0x02); |
663 | reg_w_val(gspca_dev, index: 0x0054, val: 0x01); |
664 | reg_w_val(gspca_dev, index: 0x0000, val: 0x94); |
665 | reg_w_val(gspca_dev, index: 0x0053, val: 0xc0); |
666 | reg_w_val(gspca_dev, index: 0x00fc, val: 0xe1); |
667 | reg_w_val(gspca_dev, index: 0x0000, val: 0x00); |
668 | /* wait for completion */ |
669 | retry = 50; |
670 | do { |
671 | reg_r(gspca_dev, index: 0x0002, len: 1); |
672 | /* 0x07 until 0x00 */ |
673 | if (gspca_dev->usb_buf[0] == 0x00) |
674 | break; |
675 | reg_w_val(gspca_dev, index: 0x0053, val: 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, index: 0x0001, len: 1); /* -> 0x18 */ |
681 | length = 8; |
682 | for (i = 0; i < 18; i++) { |
683 | if (i == 17) |
684 | length = 2; |
685 | reg_w(gspca_dev, index: 0x0008, buffer: cxjpeg_qtable[i], len: length); |
686 | |
687 | } |
688 | reg_r(gspca_dev, index: 0x0002, len: 1); /* 0x00 */ |
689 | reg_r(gspca_dev, index: 0x0053, len: 1); /* 0x00 */ |
690 | reg_w_val(gspca_dev, index: 0x0054, val: 0x02); |
691 | reg_w_val(gspca_dev, index: 0x0054, val: 0x01); |
692 | reg_w_val(gspca_dev, index: 0x0000, val: 0x94); |
693 | reg_w_val(gspca_dev, index: 0x0053, val: 0xc0); |
694 | |
695 | reg_r(gspca_dev, index: 0x0038, len: 1); /* 0x40 */ |
696 | reg_r(gspca_dev, index: 0x0038, len: 1); /* 0x40 */ |
697 | reg_r(gspca_dev, index: 0x001f, len: 1); /* 0x38 */ |
698 | reg_w(gspca_dev, index: 0x0012, buffer: reg12, len: 5); |
699 | reg_w(gspca_dev, index: 0x00e5, buffer: regE5_8, len: 8); |
700 | reg_r(gspca_dev, index: 0x00e8, len: 8); |
701 | reg_w(gspca_dev, index: 0x00e5, buffer: regE5a, len: 4); |
702 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* 0x00 */ |
703 | reg_w_val(gspca_dev, index: 0x009a, val: 0x01); |
704 | reg_w(gspca_dev, index: 0x00e5, buffer: regE5b, len: 4); |
705 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* 0x00 */ |
706 | reg_w(gspca_dev, index: 0x00e5, buffer: regE5c, len: 4); |
707 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* 0x00 */ |
708 | |
709 | reg_w(gspca_dev, index: 0x0051, buffer: reg51, len: 2); |
710 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
711 | reg_w_val(gspca_dev, index: 0x0070, reg70); |
712 | } |
713 | |
714 | static void cx11646_init1(struct gspca_dev *gspca_dev) |
715 | { |
716 | int i = 0; |
717 | |
718 | reg_w_val(gspca_dev, index: 0x0010, val: 0x00); |
719 | reg_w_val(gspca_dev, index: 0x0053, val: 0x00); |
720 | reg_w_val(gspca_dev, index: 0x0052, val: 0x00); |
721 | reg_w_val(gspca_dev, index: 0x009b, val: 0x2f); |
722 | reg_w_val(gspca_dev, index: 0x009c, val: 0x10); |
723 | reg_r(gspca_dev, index: 0x0098, len: 1); |
724 | reg_w_val(gspca_dev, index: 0x0098, val: 0x40); |
725 | reg_r(gspca_dev, index: 0x0099, len: 1); |
726 | reg_w_val(gspca_dev, index: 0x0099, val: 0x07); |
727 | reg_w_val(gspca_dev, index: 0x0039, val: 0x40); |
728 | reg_w_val(gspca_dev, index: 0x003c, val: 0xff); |
729 | reg_w_val(gspca_dev, index: 0x003f, val: 0x1f); |
730 | reg_w_val(gspca_dev, index: 0x003d, val: 0x40); |
731 | /* reg_w_val(gspca_dev, 0x003d, 0x60); */ |
732 | reg_r(gspca_dev, index: 0x0099, len: 1); /* ->0x07 */ |
733 | |
734 | while (cx_sensor_init[i][0]) { |
735 | reg_w_val(gspca_dev, index: 0x00e5, val: cx_sensor_init[i][0]); |
736 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* -> 0x00 */ |
737 | if (i == 1) { |
738 | reg_w_val(gspca_dev, index: 0x00ed, val: 0x01); |
739 | reg_r(gspca_dev, index: 0x00ed, len: 1); /* -> 0x01 */ |
740 | } |
741 | i++; |
742 | } |
743 | reg_w_val(gspca_dev, index: 0x00c3, val: 0x00); |
744 | } |
745 | |
746 | /* this function is called at probe time */ |
747 | static int sd_config(struct gspca_dev *gspca_dev, |
748 | const struct usb_device_id *id) |
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 */ |
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 | |
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(jpeg_hdr: sd->jpeg_hdr, height: gspca_dev->pixfmt.height, |
775 | width: gspca_dev->pixfmt.width, |
776 | samplesY: 0x22); /* JPEG 411 */ |
777 | jpeg_set_qual(jpeg_hdr: 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 */ |
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, index: 0x0000, val: 0x00); |
794 | reg_r(gspca_dev, index: 0x0002, len: 1); |
795 | reg_w_val(gspca_dev, index: 0x0053, val: 0x00); |
796 | |
797 | while (retry--) { |
798 | /* reg_r(gspca_dev, 0x0002, 1);*/ |
799 | reg_r(gspca_dev, index: 0x0053, len: 1); |
800 | if (gspca_dev->usb_buf[0] == 0) |
801 | break; |
802 | } |
803 | reg_w_val(gspca_dev, index: 0x0000, val: 0x00); |
804 | reg_r(gspca_dev, index: 0x0002, len: 1); |
805 | |
806 | reg_w_val(gspca_dev, index: 0x0010, val: 0x00); |
807 | reg_r(gspca_dev, index: 0x0033, len: 1); |
808 | reg_w_val(gspca_dev, index: 0x00fc, val: 0xe0); |
809 | } |
810 | |
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, packet_type: LAST_PACKET, NULL, len: 0); |
821 | |
822 | /* put the JPEG header in the new frame */ |
823 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, |
824 | data: sd->jpeg_hdr, JPEG_HDR_SZ); |
825 | data += 2; |
826 | len -= 2; |
827 | } |
828 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len); |
829 | } |
830 | |
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, index: 0x00e5, buffer: regE5cbx, len: 8); |
838 | reg_r(gspca_dev, index: 0x00e8, len: 8); |
839 | reg_w(gspca_dev, index: 0x00e5, buffer: regE5c, len: 4); |
840 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* 0x00 */ |
841 | |
842 | reg51c[0] = 0x77; |
843 | reg51c[1] = sat; |
844 | reg_w(gspca_dev, index: 0x0051, buffer: reg51c, len: 2); |
845 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
846 | reg_w_val(gspca_dev, index: 0x0070, reg70); |
847 | } |
848 | |
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, index: 0x00e5, buffer: regE5acx, len: 4); |
857 | reg_r(gspca_dev, index: 0x00e8, len: 1); /* 0x00 */ |
858 | reg51c[0] = 0x77; |
859 | reg51c[1] = sat; |
860 | reg_w(gspca_dev, index: 0x0051, buffer: reg51c, len: 2); |
861 | reg_w(gspca_dev, index: 0x0010, buffer: reg10, len: 2); |
862 | reg_w_val(gspca_dev, index: 0x0070, reg70); |
863 | } |
864 | |
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, val: ctrl->val, sat: sd->sat->cur.val); |
879 | break; |
880 | case V4L2_CID_CONTRAST: |
881 | setcontrast(gspca_dev, val: ctrl->val, sat: sd->sat->cur.val); |
882 | break; |
883 | case V4L2_CID_SATURATION: |
884 | setbrightness(gspca_dev, val: sd->brightness->cur.val, sat: ctrl->val); |
885 | setcontrast(gspca_dev, val: sd->contrast->cur.val, sat: 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 | |
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, ops: &sd_ctrl_ops, |
903 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 0xd4); |
904 | sd->contrast = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
905 | V4L2_CID_CONTRAST, min: 0x0a, max: 0x1f, step: 1, def: 0x0c); |
906 | sd->sat = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
907 | V4L2_CID_SATURATION, min: 0, max: 7, step: 1, def: 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 -- */ |
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: &sd_desc, dev_size: 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 | |