blob: 473bea750b5f533afae994be38995c9e9102c1be [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "conex"
23
24#include "gspca.h"
25#define CONEX_CAM 1 /* special JPEG header */
26#include "jpeg.h"
27
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -030028#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 3)
29static const char version[] = "2.1.3";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030
31MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42
43 unsigned char qindex;
44};
45
46/* V4L2 controls supported by the driver */
47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53
54static struct ctrl sd_ctrls[] = {
55#define SD_BRIGHTNESS 0
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 255,
63 .step = 1,
64 .default_value = 0xd4,
65 },
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
68 },
69#define SD_CONTRAST 1
70 {
71 {
72 .id = V4L2_CID_CONTRAST,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Contrast",
75 .minimum = 0x0a,
76 .maximum = 0x1f,
77 .step = 1,
78 .default_value = 0x0c,
79 },
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
82 },
83#define SD_COLOR 2
84 {
85 {
86 .id = V4L2_CID_SATURATION,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Color",
89 .minimum = 0,
90 .maximum = 7,
91 .step = 1,
92 .default_value = 3,
93 },
94 .set = sd_setcolors,
95 .get = sd_getcolors,
96 },
97};
98
99static struct cam_mode vga_mode[] = {
100 {V4L2_PIX_FMT_JPEG, 176, 144, 3},
101 {V4L2_PIX_FMT_JPEG, 320, 240, 2},
102 {V4L2_PIX_FMT_JPEG, 352, 288, 1},
103 {V4L2_PIX_FMT_JPEG, 640, 480, 0},
104};
105
106static void reg_r(struct usb_device *dev,
107 __u16 index,
108 __u8 *buffer, __u16 length)
109{
110 usb_control_msg(dev,
111 usb_rcvctrlpipe(dev, 0),
112 0,
113 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
114 0,
115 index, buffer, length,
116 500);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300117 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", index, *buffer);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300118}
119
120static void reg_w(struct usb_device *dev,
121 __u16 index,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300122 const __u8 *buffer, __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300123{
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300124 __u8 tmpbuf[8];
125
126#ifdef CONFIG_VIDEO_ADV_DEBUG
127 if (len > sizeof tmpbuf) {
128 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
129 return;
130 }
131 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
132#endif
133 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 usb_control_msg(dev,
135 usb_sndctrlpipe(dev, 0),
136 0,
137 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
138 0,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300139 index, tmpbuf, len, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140}
141
142static const __u8 cx_sensor_init[][4] = {
143 {0x88, 0x11, 0x01, 0x01},
144 {0x88, 0x12, 0x70, 0x01},
145 {0x88, 0x0f, 0x00, 0x01},
146 {0x88, 0x05, 0x01, 0x01},
147 {}
148};
149
150static const __u8 cx11646_fw1[][3] = {
151 {0x00, 0x02, 0x00},
152 {0x01, 0x43, 0x00},
153 {0x02, 0xA7, 0x00},
154 {0x03, 0x8B, 0x01},
155 {0x04, 0xE9, 0x02},
156 {0x05, 0x08, 0x04},
157 {0x06, 0x08, 0x05},
158 {0x07, 0x07, 0x06},
159 {0x08, 0xE7, 0x06},
160 {0x09, 0xC6, 0x07},
161 {0x0A, 0x86, 0x08},
162 {0x0B, 0x46, 0x09},
163 {0x0C, 0x05, 0x0A},
164 {0x0D, 0xA5, 0x0A},
165 {0x0E, 0x45, 0x0B},
166 {0x0F, 0xE5, 0x0B},
167 {0x10, 0x85, 0x0C},
168 {0x11, 0x25, 0x0D},
169 {0x12, 0xC4, 0x0D},
170 {0x13, 0x45, 0x0E},
171 {0x14, 0xE4, 0x0E},
172 {0x15, 0x64, 0x0F},
173 {0x16, 0xE4, 0x0F},
174 {0x17, 0x64, 0x10},
175 {0x18, 0xE4, 0x10},
176 {0x19, 0x64, 0x11},
177 {0x1A, 0xE4, 0x11},
178 {0x1B, 0x64, 0x12},
179 {0x1C, 0xE3, 0x12},
180 {0x1D, 0x44, 0x13},
181 {0x1E, 0xC3, 0x13},
182 {0x1F, 0x24, 0x14},
183 {0x20, 0xA3, 0x14},
184 {0x21, 0x04, 0x15},
185 {0x22, 0x83, 0x15},
186 {0x23, 0xE3, 0x15},
187 {0x24, 0x43, 0x16},
188 {0x25, 0xA4, 0x16},
189 {0x26, 0x23, 0x17},
190 {0x27, 0x83, 0x17},
191 {0x28, 0xE3, 0x17},
192 {0x29, 0x43, 0x18},
193 {0x2A, 0xA3, 0x18},
194 {0x2B, 0x03, 0x19},
195 {0x2C, 0x63, 0x19},
196 {0x2D, 0xC3, 0x19},
197 {0x2E, 0x22, 0x1A},
198 {0x2F, 0x63, 0x1A},
199 {0x30, 0xC3, 0x1A},
200 {0x31, 0x23, 0x1B},
201 {0x32, 0x83, 0x1B},
202 {0x33, 0xE2, 0x1B},
203 {0x34, 0x23, 0x1C},
204 {0x35, 0x83, 0x1C},
205 {0x36, 0xE2, 0x1C},
206 {0x37, 0x23, 0x1D},
207 {0x38, 0x83, 0x1D},
208 {0x39, 0xE2, 0x1D},
209 {0x3A, 0x23, 0x1E},
210 {0x3B, 0x82, 0x1E},
211 {0x3C, 0xC3, 0x1E},
212 {0x3D, 0x22, 0x1F},
213 {0x3E, 0x63, 0x1F},
214 {0x3F, 0xC1, 0x1F},
215 {}
216};
217static void cx11646_fw(struct gspca_dev*gspca_dev)
218{
219 __u8 val;
220 int i = 0;
221
222 val = 0x02;
223 reg_w(gspca_dev->dev, 0x006a, &val, 1);
224 while (cx11646_fw1[i][1]) {
225 reg_w(gspca_dev->dev, 0x006b, cx11646_fw1[i], 3);
226 i++;
227 }
228 val = 0x00;
229 reg_w(gspca_dev->dev, 0x006a, &val, 1);
230}
231
232static __u8 cxsensor[] = {
233 0x88, 0x12, 0x70, 0x01,
234 0x88, 0x0d, 0x02, 0x01,
235 0x88, 0x0f, 0x00, 0x01,
236 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
237 0x88, 0x02, 0x10, 0x01,
238 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
239 0x88, 0x0B, 0x00, 0x01,
240 0x88, 0x0A, 0x0A, 0x01,
241 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
242 0x88, 0x05, 0x01, 0x01,
243 0xA1, 0x18, 0x00, 0x01,
244 0x00
245};
246
247static __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
248static __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
249static __u8 reg10[] = { 0xb1, 0xb1 };
250static __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
251static __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
252 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
253static __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
254 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
255static __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
256static __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
257
258static void cx_sensor(struct gspca_dev*gspca_dev)
259{
260 __u8 val = 0;
261 int i = 0;
262 __u8 bufread[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
263 int length = 0;
264 __u8 *ptsensor = cxsensor;
265
266 reg_w(gspca_dev->dev, 0x0020, reg20, 8);
267 reg_w(gspca_dev->dev, 0x0028, reg28, 8);
268 reg_w(gspca_dev->dev, 0x0010, reg10, 8);
269 val = 0x03;
270 reg_w(gspca_dev->dev, 0x0092, &val, 1);
271
272 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
273 case 0:
274 reg_w(gspca_dev->dev, 0x0071, reg71a, 4);
275 break;
276 case 1:
277 reg_w(gspca_dev->dev, 0x0071, reg71b, 4);
278 break;
279 default:
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300280/* case 2: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281 reg_w(gspca_dev->dev, 0x0071, reg71c, 4);
282 break;
283 case 3:
284 reg_w(gspca_dev->dev, 0x0071, reg71d, 4);
285 break;
286 }
287 reg_w(gspca_dev->dev, 0x007b, reg7b, 6);
288 val = 0x00;
289 reg_w(gspca_dev->dev, 0x00f8, &val, 1);
290 reg_w(gspca_dev->dev, 0x0010, reg10, 8);
291 val = 0x41;
292 reg_w(gspca_dev->dev, 0x0098, &val, 1);
293 for (i = 0; i < 11; i++) {
294 if (i == 3 || i == 5 || i == 8)
295 length = 8;
296 else
297 length = 4;
298 reg_w(gspca_dev->dev, 0x00e5, ptsensor, length);
299 if (length == 4)
300 reg_r(gspca_dev->dev, 0x00e8, &val, 1);
301 else
302 reg_r(gspca_dev->dev, 0x00e8, bufread, length);
303 ptsensor += length;
304 }
305 reg_r(gspca_dev->dev, 0x00e7, bufread, 8);
306}
307
308static __u8 cx_inits_176[] = {
309 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
310 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
311 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
312 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
313 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
314 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
315 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
316};
317static __u8 cx_inits_320[] = {
318 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
319 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
320 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
321 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
322 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
323 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
324 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
325};
326static __u8 cx_inits_352[] = {
327 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
328 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
329 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
330 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
331 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
332 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
333 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
334};
335static __u8 cx_inits_640[] = {
336 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
337 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
338 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
339 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
340 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
341 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
342 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
343};
344
345static int cx11646_initsize(struct gspca_dev *gspca_dev)
346{
347 __u8 *cxinit;
348 __u8 val;
349 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
350 static const __u8 reg17[] =
351 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
352
353 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
354 case 0:
355 cxinit = cx_inits_640;
356 break;
357 case 1:
358 cxinit = cx_inits_352;
359 break;
360 default:
361/* case 2: */
362 cxinit = cx_inits_320;
363 break;
364 case 3:
365 cxinit = cx_inits_176;
366 break;
367 }
368 val = 0x01;
369 reg_w(gspca_dev->dev, 0x009a, &val, 1);
370 val = 0x10;
371 reg_w(gspca_dev->dev, 0x0010, &val, 1);
372 reg_w(gspca_dev->dev, 0x0012, reg12, 5);
373 reg_w(gspca_dev->dev, 0x0017, reg17, 8);
374 val = 0x00;
375 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
376 val = 0x04;
377 reg_w(gspca_dev->dev, 0x00c1, &val, 1);
378 val = 0x04;
379 reg_w(gspca_dev->dev, 0x00c2, &val, 1);
380
381 reg_w(gspca_dev->dev, 0x0061, cxinit, 8);
382 cxinit += 8;
383 reg_w(gspca_dev->dev, 0x00ca, cxinit, 8);
384 cxinit += 8;
385 reg_w(gspca_dev->dev, 0x00d2, cxinit, 8);
386 cxinit += 8;
387 reg_w(gspca_dev->dev, 0x00da, cxinit, 6);
388 cxinit += 8;
389 reg_w(gspca_dev->dev, 0x0041, cxinit, 8);
390 cxinit += 8;
391 reg_w(gspca_dev->dev, 0x0049, cxinit, 8);
392 cxinit += 8;
393 reg_w(gspca_dev->dev, 0x0051, cxinit, 2);
394
395 reg_r(gspca_dev->dev, 0x0010, &val, 1);
396 return val;
397}
398
399static __u8 cx_jpeg_init[][8] = {
400 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
401 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
402 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
403 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
404 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
405 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
406 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
407 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
408 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
409 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
410 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
411 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
412 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
413 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
414 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
415 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
416 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
417 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
418 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
419 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
420 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
421 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
422 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
423 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
424 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
425 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
426 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
427 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
428 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
429 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
430 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
431 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
432 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
433 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
434 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
435 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
436 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
437 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
438 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
439 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
440 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
441 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
442 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
443 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
444 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
445 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
446 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
447 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
448 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
449 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
450 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
451 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
452 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
453 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
454 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
455 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
456 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
457 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
458 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
459 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
460 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
461 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
462 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
463 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
464 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
465 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
466 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
467 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
468 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
469 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
470 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
471 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
472 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
473 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
474 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
475 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
476 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
477 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
478 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
479};
480
481
482static __u8 cxjpeg_640[][8] = {
483 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
484 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
485 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
486 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
487 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
488 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
489 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
490 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
491 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
492 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
493 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
494 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
495 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
496 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
497 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
498 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
499 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
500 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
501 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
502 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
503 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
504 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
505 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
506 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
507 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
508 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
509 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
510};
511static __u8 cxjpeg_352[][8] = {
512 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
513 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
514 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
515 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
516 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
517 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
518 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
519 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
520 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
521 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
522 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
523 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
524 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
525 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
526 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
527 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
528 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
529 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
530 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
531 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
532 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
533 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
534 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
535 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
536 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
537 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
538 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
539};
540static __u8 cxjpeg_320[][8] = {
541 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
542 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
543 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
544 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
545 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
546 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
547 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
548 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
549 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
550 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
551 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
552 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
553 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
554 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
555 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
556 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
557 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
558 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
559 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
560 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
561 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
562 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
563 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
564 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
565 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
566 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
567 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
568};
569static __u8 cxjpeg_176[][8] = {
570 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
571 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
572 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
573 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
574 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
575 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
576 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
577 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
578 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
579 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
580 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
581 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
582 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
583 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
584 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
585 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
586 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
587 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
588 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
589 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
590 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
591 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
592 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
593 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
594 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
595 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
596 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
597};
598static __u8 cxjpeg_qtable[][8] = { /* 640 take with the zcx30x part */
599 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
600 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
601 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
602 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
603 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
604 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
605 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
606 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
607 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
608 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
609 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
610 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
611 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
612 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
613 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
614 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
615 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
616 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
617};
618
619
620static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
621{
622 __u8 val;
623 int i;
624 int length;
625
626 val = 0x01;
627 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
628 val = 0x00;
629 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
630 val = 0x00;
631 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
632 reg_r(gspca_dev->dev, 0x0001, &val, 1);
633 length = 8;
634 for (i = 0; i < 79; i++) {
635 if (i == 78)
636 length = 6;
637 reg_w(gspca_dev->dev, 0x0008, cx_jpeg_init[i], length);
638 }
639 reg_r(gspca_dev->dev, 0x0002, &val, 1);
640 val = 0x14;
641 reg_w(gspca_dev->dev, 0x0055, &val, 1);
642}
643
644static __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
645static __u8 regE5_8[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
646static __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
647static __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
648static __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
649static __u8 reg51[] = { 0x77, 0x03 };
650static __u8 reg70 = 0x03;
651
652static void cx11646_jpeg(struct gspca_dev*gspca_dev)
653{
654 __u8 val;
655 int i;
656 int length = 8;
657 __u8 Reg55 = 0x14;
658 __u8 bufread[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
659 int retry = 50;
660
661 val = 0x01;
662 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
663 val = 0x00;
664 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
665 val = 0x00;
666 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
667 reg_r(gspca_dev->dev, 0x0001, &val, 1);
668 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
669 case 0:
670 for (i = 0; i < 27; i++) {
671 if (i == 26)
672 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300673 reg_w(gspca_dev->dev, 0x0008, cxjpeg_640[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300674 }
675 Reg55 = 0x28;
676 break;
677 case 1:
678 for (i = 0; i < 27; i++) {
679 if (i == 26)
680 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300681 reg_w(gspca_dev->dev, 0x0008, cxjpeg_352[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 }
683 Reg55 = 0x16;
684 break;
685 default:
686/* case 2: */
687 for (i = 0; i < 27; i++) {
688 if (i == 26)
689 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300690 reg_w(gspca_dev->dev, 0x0008, cxjpeg_320[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 }
692 Reg55 = 0x14;
693 break;
694 case 3:
695 for (i = 0; i < 27; i++) {
696 if (i == 26)
697 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300698 reg_w(gspca_dev->dev, 0x0008, cxjpeg_176[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699 }
700 Reg55 = 0x0B;
701 break;
702 }
703
704 reg_r(gspca_dev->dev, 0x0002, &val, 1);
705 val = Reg55;
706 reg_w(gspca_dev->dev, 0x0055, &val, 1);
707 reg_r(gspca_dev->dev, 0x0002, &val, 1);
708 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
709 val = 0x02;
710 reg_w(gspca_dev->dev, 0x0054, &val, 1);
711 val = 0x01;
712 reg_w(gspca_dev->dev, 0x0054, &val, 1);
713 val = 0x94;
714 reg_w(gspca_dev->dev, 0x0000, &val, 1);
715 val = 0xc0;
716 reg_w(gspca_dev->dev, 0x0053, &val, 1);
717 val = 0xe1;
718 reg_w(gspca_dev->dev, 0x00fc, &val, 1);
719 val = 0x00;
720 reg_w(gspca_dev->dev, 0x0000, &val, 1);
721 /* wait for completion */
722 while (retry--) {
723 reg_r(gspca_dev->dev, 0x0002, &val, 1);
724 /* 0x07 until 0x00 */
725 if (val == 0x00)
726 break;
727 val = 0x00;
728 reg_w(gspca_dev->dev, 0x0053, &val, 1);
729 }
730 if (retry == 0)
731 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
732 /* send the qtable now */
733 reg_r(gspca_dev->dev, 0x0001, &val, 1); /* -> 0x18 */
734 length = 8;
735 for (i = 0; i < 18; i++) {
736 if (i == 17)
737 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300738 reg_w(gspca_dev->dev, 0x0008, cxjpeg_qtable[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739
740 }
741 reg_r(gspca_dev->dev, 0x0002, &val, 1); /* 0x00 */
742 reg_r(gspca_dev->dev, 0x0053, &val, 1); /* 0x00 */
743 val = 0x02;
744 reg_w(gspca_dev->dev, 0x0054, &val, 1);
745 val = 0x01;
746 reg_w(gspca_dev->dev, 0x0054, &val, 1);
747 val = 0x94;
748 reg_w(gspca_dev->dev, 0x0000, &val, 1);
749 val = 0xc0;
750 reg_w(gspca_dev->dev, 0x0053, &val, 1);
751
752 reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
753 reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
754 reg_r(gspca_dev->dev, 0x001f, &val, 1); /* 0x38 */
755 reg_w(gspca_dev->dev, 0x0012, reg12, 5);
756 reg_w(gspca_dev->dev, 0x00e5, regE5_8, 8);
757 reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
758 reg_w(gspca_dev->dev, 0x00e5, regE5a, 4);
759 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
760 val = 0x01;
761 reg_w(gspca_dev->dev, 0x009a, &val, 1);
762 reg_w(gspca_dev->dev, 0x00e5, regE5b, 4);
763 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
764 reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
765 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
766
767 reg_w(gspca_dev->dev, 0x0051, reg51, 2);
768 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
769 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
770}
771
772static void cx11646_init1(struct gspca_dev *gspca_dev)
773{
774 __u8 val;
775 int i = 0;
776
777 val = 0;
778 reg_w(gspca_dev->dev, 0x0010, &val, 1);
779 reg_w(gspca_dev->dev, 0x0053, &val, 1);
780 reg_w(gspca_dev->dev, 0x0052, &val, 1);
781 val = 0x2f;
782 reg_w(gspca_dev->dev, 0x009b, &val, 1);
783 val = 0x10;
784 reg_w(gspca_dev->dev, 0x009c, &val, 1);
785 reg_r(gspca_dev->dev, 0x0098, &val, 1);
786 val = 0x40;
787 reg_w(gspca_dev->dev, 0x0098, &val, 1);
788 reg_r(gspca_dev->dev, 0x0099, &val, 1);
789 val = 0x07;
790 reg_w(gspca_dev->dev, 0x0099, &val, 1);
791 val = 0x40;
792 reg_w(gspca_dev->dev, 0x0039, &val, 1);
793 val = 0xff;
794 reg_w(gspca_dev->dev, 0x003c, &val, 1);
795 val = 0x1f;
796 reg_w(gspca_dev->dev, 0x003f, &val, 1);
797 val = 0x40;
798 reg_w(gspca_dev->dev, 0x003d, &val, 1);
799/* val= 0x60; */
800/* reg_w(gspca_dev->dev,0x00,0x00,0x003d,&val,1); */
801 reg_r(gspca_dev->dev, 0x0099, &val, 1); /* ->0x07 */
802
803 while (cx_sensor_init[i][0]) {
804 reg_w(gspca_dev->dev, 0x00e5, cx_sensor_init[i], 1);
805 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* -> 0x00 */
806 if (i == 1) {
807 val = 1;
808 reg_w(gspca_dev->dev, 0x00ed, &val, 1);
809 reg_r(gspca_dev->dev, 0x00ed, &val, 1); /* -> 0x01 */
810 }
811 i++;
812 }
813 val = 0x00;
814 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
815}
816
817/* this function is called at probe time */
818static int sd_config(struct gspca_dev *gspca_dev,
819 const struct usb_device_id *id)
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822 struct cam *cam;
823
824 cam = &gspca_dev->cam;
825 cam->dev_name = (char *) id->driver_info;
826 cam->epaddr = 0x01;
827 cam->cam_mode = vga_mode;
828 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
829
830 sd->qindex = 0; /* set the quantization table */
831 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
832 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
833 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
834 return 0;
835}
836
837/* this function is called at open time */
838static int sd_open(struct gspca_dev *gspca_dev)
839{
840 cx11646_init1(gspca_dev);
841 cx11646_initsize(gspca_dev);
842 cx11646_fw(gspca_dev);
843 cx_sensor(gspca_dev);
844 cx11646_jpegInit(gspca_dev);
845 return 0;
846}
847
848static void sd_start(struct gspca_dev *gspca_dev)
849{
850 cx11646_initsize(gspca_dev);
851 cx11646_fw(gspca_dev);
852 cx_sensor(gspca_dev);
853 cx11646_jpeg(gspca_dev);
854}
855
856static void sd_stopN(struct gspca_dev *gspca_dev)
857{
858}
859
860static void sd_stop0(struct gspca_dev *gspca_dev)
861{
862 int retry = 50;
863 __u8 val;
864
865 val = 0;
866 reg_w(gspca_dev->dev, 0x0000, &val, 1);
867 reg_r(gspca_dev->dev, 0x0002, &val, 1);
868 val = 0;
869 reg_w(gspca_dev->dev, 0x0053, &val, 1);
870
871 while (retry--) {
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300872/* reg_r(gspca_dev->dev, 0x0002, &val, 1);*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 reg_r(gspca_dev->dev, 0x0053, &val, 1);
874 if (val == 0)
875 break;
876 }
877 val = 0;
878 reg_w(gspca_dev->dev, 0x0000, &val, 1);
879 reg_r(gspca_dev->dev, 0x0002, &val, 1);
880
881 val = 0;
882 reg_w(gspca_dev->dev, 0x0010, &val, 1);
883 reg_r(gspca_dev->dev, 0x0033, &val, 1);
884 val = 0xe0;
885 reg_w(gspca_dev->dev, 0x00fc, &val, 1);
886}
887
888static void sd_close(struct gspca_dev *gspca_dev)
889{
890}
891
892static void sd_pkt_scan(struct gspca_dev *gspca_dev,
893 struct gspca_frame *frame, /* target */
894 unsigned char *data, /* isoc packet */
895 int len) /* iso packet length */
896{
897 if (data[0] == 0xff && data[1] == 0xd8) {
898
899 /* start of frame */
900 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
901 data, 0);
902
903 /* put the JPEG header in the new frame */
904 jpeg_put_header(gspca_dev, frame,
905 ((struct sd *) gspca_dev)->qindex,
906 0x22);
907 data += 2;
908 len -= 2;
909 }
910 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
911}
912
913static void setbrightness(struct gspca_dev*gspca_dev)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
917 __u8 reg51c[] = { 0x77, 0x03 };
918 __u8 bright;
919 __u8 colors;
920 __u8 val;
921 __u8 bufread[8];
922
923 bright = sd->brightness;
924 colors = sd->colors;
925 regE5cbx[2] = bright;
926 reg51c[1] = colors;
927 reg_w(gspca_dev->dev, 0x00e5, regE5cbx, 8);
928 reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
929 reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
930 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
931
932 reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
933 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
934 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
935}
936
937static void setcontrast(struct gspca_dev*gspca_dev)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
941 /* __u8 regE5bcx[]={0x88,0x0b,0x12,0x01}; // LSB */
942 __u8 reg51c[] = { 0x77, 0x03 };
943 __u8 val;
944
945 reg51c[1] = sd->colors;
946 regE5acx[2] = sd->contrast;
947 reg_w(gspca_dev->dev, 0x00e5, regE5acx, 4);
948 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
949 reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
950 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
951 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
952}
953
954static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
955{
956 struct sd *sd = (struct sd *) gspca_dev;
957
958 sd->brightness = val;
959 if (gspca_dev->streaming)
960 setbrightness(gspca_dev);
961 return 0;
962}
963
964static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
965{
966 struct sd *sd = (struct sd *) gspca_dev;
967
968 *val = sd->brightness;
969 return 0;
970}
971
972static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975
976 sd->contrast = val;
977 if (gspca_dev->streaming)
978 setcontrast(gspca_dev);
979 return 0;
980}
981
982static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
985
986 *val = sd->contrast;
987 return 0;
988}
989
990static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
991{
992 struct sd *sd = (struct sd *) gspca_dev;
993
994 sd->colors = val;
995 if (gspca_dev->streaming) {
996 setbrightness(gspca_dev);
997 setcontrast(gspca_dev);
998 }
999 return 0;
1000}
1001
1002static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1003{
1004 struct sd *sd = (struct sd *) gspca_dev;
1005
1006 *val = sd->colors;
1007 return 0;
1008}
1009
1010/* sub-driver description */
1011static struct sd_desc sd_desc = {
1012 .name = MODULE_NAME,
1013 .ctrls = sd_ctrls,
1014 .nctrls = ARRAY_SIZE(sd_ctrls),
1015 .config = sd_config,
1016 .open = sd_open,
1017 .start = sd_start,
1018 .stopN = sd_stopN,
1019 .stop0 = sd_stop0,
1020 .close = sd_close,
1021 .pkt_scan = sd_pkt_scan,
1022};
1023
1024/* -- module initialisation -- */
1025#define DVNM(name) .driver_info = (kernel_ulong_t) name
1026static __devinitdata struct usb_device_id device_table[] = {
1027 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1028 {}
1029};
1030MODULE_DEVICE_TABLE(usb, device_table);
1031
1032/* -- device connect -- */
1033static int sd_probe(struct usb_interface *intf,
1034 const struct usb_device_id *id)
1035{
1036 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1037 THIS_MODULE);
1038}
1039
1040static struct usb_driver sd_driver = {
1041 .name = MODULE_NAME,
1042 .id_table = device_table,
1043 .probe = sd_probe,
1044 .disconnect = gspca_disconnect,
1045};
1046
1047/* -- module insert / remove -- */
1048static int __init sd_mod_init(void)
1049{
1050 if (usb_register(&sd_driver) < 0)
1051 return -1;
1052 PDEBUG(D_PROBE, "v%s registered", version);
1053 return 0;
1054}
1055static void __exit sd_mod_exit(void)
1056{
1057 usb_deregister(&sd_driver);
1058 PDEBUG(D_PROBE, "deregistered");
1059}
1060
1061module_init(sd_mod_init);
1062module_exit(sd_mod_exit);