blob: 6d50247b7ad227796f0560c978dd6b49cb38e6ff [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 Moinea5ae2062008-07-04 11:16:16 -030028#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4)
29static const char version[] = "2.1.4";
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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300232static const __u8 cxsensor[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300233 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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300247static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
248static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
249static const __u8 reg10[] = { 0xb1, 0xb1 };
250static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
251static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300253static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300255static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
256static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300257
258static void cx_sensor(struct gspca_dev*gspca_dev)
259{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300260 __u8 val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300261 int i = 0;
262 __u8 bufread[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300263 int length;
264 const __u8 *ptsensor = cxsensor;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265
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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300308static const __u8 cx_inits_176[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300317static const __u8 cx_inits_320[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300318 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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300326static const __u8 cx_inits_352[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327 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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300335static const __u8 cx_inits_640[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336 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{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300347 const __u8 *cxinit;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348 __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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300399static const __u8 cx_jpeg_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300400 {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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300482static const __u8 cxjpeg_640[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300483 {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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300511static const __u8 cxjpeg_352[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512 {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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300540static const __u8 cxjpeg_320[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 {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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569static const __u8 cxjpeg_176[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570 {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};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300598/* 640 take with the zcx30x part */
599static const __u8 cxjpeg_qtable[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
601 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
602 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
603 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
604 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
605 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
606 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
607 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
608 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
609 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
610 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 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 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
617 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
618};
619
620
621static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
622{
623 __u8 val;
624 int i;
625 int length;
626
627 val = 0x01;
628 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
629 val = 0x00;
630 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
631 val = 0x00;
632 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
633 reg_r(gspca_dev->dev, 0x0001, &val, 1);
634 length = 8;
635 for (i = 0; i < 79; i++) {
636 if (i == 78)
637 length = 6;
638 reg_w(gspca_dev->dev, 0x0008, cx_jpeg_init[i], length);
639 }
640 reg_r(gspca_dev->dev, 0x0002, &val, 1);
641 val = 0x14;
642 reg_w(gspca_dev->dev, 0x0055, &val, 1);
643}
644
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300645static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
646static const __u8 regE5_8[] =
647 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
648static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
649static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
650static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
651static const __u8 reg51[] = { 0x77, 0x03 };
652static const __u8 reg70 = 0x03;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300653
654static void cx11646_jpeg(struct gspca_dev*gspca_dev)
655{
656 __u8 val;
657 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300658 int length;
659 __u8 Reg55;
660 __u8 bufread[8];
661 int retry;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662
663 val = 0x01;
664 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
665 val = 0x00;
666 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
667 val = 0x00;
668 reg_w(gspca_dev->dev, 0x00c0, &val, 1);
669 reg_r(gspca_dev->dev, 0x0001, &val, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300670 length = 8;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300671 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
672 case 0:
673 for (i = 0; i < 27; i++) {
674 if (i == 26)
675 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300676 reg_w(gspca_dev->dev, 0x0008, cxjpeg_640[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 }
678 Reg55 = 0x28;
679 break;
680 case 1:
681 for (i = 0; i < 27; i++) {
682 if (i == 26)
683 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300684 reg_w(gspca_dev->dev, 0x0008, cxjpeg_352[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685 }
686 Reg55 = 0x16;
687 break;
688 default:
689/* case 2: */
690 for (i = 0; i < 27; i++) {
691 if (i == 26)
692 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300693 reg_w(gspca_dev->dev, 0x0008, cxjpeg_320[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 }
695 Reg55 = 0x14;
696 break;
697 case 3:
698 for (i = 0; i < 27; i++) {
699 if (i == 26)
700 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300701 reg_w(gspca_dev->dev, 0x0008, cxjpeg_176[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702 }
703 Reg55 = 0x0B;
704 break;
705 }
706
707 reg_r(gspca_dev->dev, 0x0002, &val, 1);
708 val = Reg55;
709 reg_w(gspca_dev->dev, 0x0055, &val, 1);
710 reg_r(gspca_dev->dev, 0x0002, &val, 1);
711 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
712 val = 0x02;
713 reg_w(gspca_dev->dev, 0x0054, &val, 1);
714 val = 0x01;
715 reg_w(gspca_dev->dev, 0x0054, &val, 1);
716 val = 0x94;
717 reg_w(gspca_dev->dev, 0x0000, &val, 1);
718 val = 0xc0;
719 reg_w(gspca_dev->dev, 0x0053, &val, 1);
720 val = 0xe1;
721 reg_w(gspca_dev->dev, 0x00fc, &val, 1);
722 val = 0x00;
723 reg_w(gspca_dev->dev, 0x0000, &val, 1);
724 /* wait for completion */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300725 retry = 50;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726 while (retry--) {
727 reg_r(gspca_dev->dev, 0x0002, &val, 1);
728 /* 0x07 until 0x00 */
729 if (val == 0x00)
730 break;
731 val = 0x00;
732 reg_w(gspca_dev->dev, 0x0053, &val, 1);
733 }
734 if (retry == 0)
735 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
736 /* send the qtable now */
737 reg_r(gspca_dev->dev, 0x0001, &val, 1); /* -> 0x18 */
738 length = 8;
739 for (i = 0; i < 18; i++) {
740 if (i == 17)
741 length = 2;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300742 reg_w(gspca_dev->dev, 0x0008, cxjpeg_qtable[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743
744 }
745 reg_r(gspca_dev->dev, 0x0002, &val, 1); /* 0x00 */
746 reg_r(gspca_dev->dev, 0x0053, &val, 1); /* 0x00 */
747 val = 0x02;
748 reg_w(gspca_dev->dev, 0x0054, &val, 1);
749 val = 0x01;
750 reg_w(gspca_dev->dev, 0x0054, &val, 1);
751 val = 0x94;
752 reg_w(gspca_dev->dev, 0x0000, &val, 1);
753 val = 0xc0;
754 reg_w(gspca_dev->dev, 0x0053, &val, 1);
755
756 reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
757 reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
758 reg_r(gspca_dev->dev, 0x001f, &val, 1); /* 0x38 */
759 reg_w(gspca_dev->dev, 0x0012, reg12, 5);
760 reg_w(gspca_dev->dev, 0x00e5, regE5_8, 8);
761 reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
762 reg_w(gspca_dev->dev, 0x00e5, regE5a, 4);
763 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
764 val = 0x01;
765 reg_w(gspca_dev->dev, 0x009a, &val, 1);
766 reg_w(gspca_dev->dev, 0x00e5, regE5b, 4);
767 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
768 reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
769 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
770
771 reg_w(gspca_dev->dev, 0x0051, reg51, 2);
772 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
773 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
774}
775
776static void cx11646_init1(struct gspca_dev *gspca_dev)
777{
778 __u8 val;
779 int i = 0;
780
781 val = 0;
782 reg_w(gspca_dev->dev, 0x0010, &val, 1);
783 reg_w(gspca_dev->dev, 0x0053, &val, 1);
784 reg_w(gspca_dev->dev, 0x0052, &val, 1);
785 val = 0x2f;
786 reg_w(gspca_dev->dev, 0x009b, &val, 1);
787 val = 0x10;
788 reg_w(gspca_dev->dev, 0x009c, &val, 1);
789 reg_r(gspca_dev->dev, 0x0098, &val, 1);
790 val = 0x40;
791 reg_w(gspca_dev->dev, 0x0098, &val, 1);
792 reg_r(gspca_dev->dev, 0x0099, &val, 1);
793 val = 0x07;
794 reg_w(gspca_dev->dev, 0x0099, &val, 1);
795 val = 0x40;
796 reg_w(gspca_dev->dev, 0x0039, &val, 1);
797 val = 0xff;
798 reg_w(gspca_dev->dev, 0x003c, &val, 1);
799 val = 0x1f;
800 reg_w(gspca_dev->dev, 0x003f, &val, 1);
801 val = 0x40;
802 reg_w(gspca_dev->dev, 0x003d, &val, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300803/* val= 0x60; */
804/* reg_w(gspca_dev->dev, 0x00, 0x00, 0x003d, &val, 1); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805 reg_r(gspca_dev->dev, 0x0099, &val, 1); /* ->0x07 */
806
807 while (cx_sensor_init[i][0]) {
808 reg_w(gspca_dev->dev, 0x00e5, cx_sensor_init[i], 1);
809 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* -> 0x00 */
810 if (i == 1) {
811 val = 1;
812 reg_w(gspca_dev->dev, 0x00ed, &val, 1);
813 reg_r(gspca_dev->dev, 0x00ed, &val, 1); /* -> 0x01 */
814 }
815 i++;
816 }
817 val = 0x00;
818 reg_w(gspca_dev->dev, 0x00c3, &val, 1);
819}
820
821/* this function is called at probe time */
822static int sd_config(struct gspca_dev *gspca_dev,
823 const struct usb_device_id *id)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826 struct cam *cam;
827
828 cam = &gspca_dev->cam;
829 cam->dev_name = (char *) id->driver_info;
830 cam->epaddr = 0x01;
831 cam->cam_mode = vga_mode;
832 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
833
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300834 sd->qindex = 0; /* set the quantization */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
836 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
837 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
838 return 0;
839}
840
841/* this function is called at open time */
842static int sd_open(struct gspca_dev *gspca_dev)
843{
844 cx11646_init1(gspca_dev);
845 cx11646_initsize(gspca_dev);
846 cx11646_fw(gspca_dev);
847 cx_sensor(gspca_dev);
848 cx11646_jpegInit(gspca_dev);
849 return 0;
850}
851
852static void sd_start(struct gspca_dev *gspca_dev)
853{
854 cx11646_initsize(gspca_dev);
855 cx11646_fw(gspca_dev);
856 cx_sensor(gspca_dev);
857 cx11646_jpeg(gspca_dev);
858}
859
860static void sd_stopN(struct gspca_dev *gspca_dev)
861{
862}
863
864static void sd_stop0(struct gspca_dev *gspca_dev)
865{
866 int retry = 50;
867 __u8 val;
868
869 val = 0;
870 reg_w(gspca_dev->dev, 0x0000, &val, 1);
871 reg_r(gspca_dev->dev, 0x0002, &val, 1);
872 val = 0;
873 reg_w(gspca_dev->dev, 0x0053, &val, 1);
874
875 while (retry--) {
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300876/* reg_r(gspca_dev->dev, 0x0002, &val, 1);*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 reg_r(gspca_dev->dev, 0x0053, &val, 1);
878 if (val == 0)
879 break;
880 }
881 val = 0;
882 reg_w(gspca_dev->dev, 0x0000, &val, 1);
883 reg_r(gspca_dev->dev, 0x0002, &val, 1);
884
885 val = 0;
886 reg_w(gspca_dev->dev, 0x0010, &val, 1);
887 reg_r(gspca_dev->dev, 0x0033, &val, 1);
888 val = 0xe0;
889 reg_w(gspca_dev->dev, 0x00fc, &val, 1);
890}
891
892static void sd_close(struct gspca_dev *gspca_dev)
893{
894}
895
896static void sd_pkt_scan(struct gspca_dev *gspca_dev,
897 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300898 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 int len) /* iso packet length */
900{
901 if (data[0] == 0xff && data[1] == 0xd8) {
902
903 /* start of frame */
904 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
905 data, 0);
906
907 /* put the JPEG header in the new frame */
908 jpeg_put_header(gspca_dev, frame,
909 ((struct sd *) gspca_dev)->qindex,
910 0x22);
911 data += 2;
912 len -= 2;
913 }
914 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
915}
916
917static void setbrightness(struct gspca_dev*gspca_dev)
918{
919 struct sd *sd = (struct sd *) gspca_dev;
920 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300921 __u8 reg51c[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 __u8 bright;
923 __u8 colors;
924 __u8 val;
925 __u8 bufread[8];
926
927 bright = sd->brightness;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 regE5cbx[2] = bright;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929 reg_w(gspca_dev->dev, 0x00e5, regE5cbx, 8);
930 reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
931 reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
932 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
933
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300934 colors = sd->colors;
935 reg51c[0] = 0x77;
936 reg51c[1] = colors;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
938 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
939 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
940}
941
942static void setcontrast(struct gspca_dev*gspca_dev)
943{
944 struct sd *sd = (struct sd *) gspca_dev;
945 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300946/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
947 __u8 reg51c[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 __u8 val;
949
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950 regE5acx[2] = sd->contrast;
951 reg_w(gspca_dev->dev, 0x00e5, regE5acx, 4);
952 reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300953 reg51c[0] = 0x77;
954 reg51c[1] = sd->colors;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
956 reg_w(gspca_dev->dev, 0x0010, reg10, 2);
957 reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
958}
959
960static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
961{
962 struct sd *sd = (struct sd *) gspca_dev;
963
964 sd->brightness = val;
965 if (gspca_dev->streaming)
966 setbrightness(gspca_dev);
967 return 0;
968}
969
970static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
971{
972 struct sd *sd = (struct sd *) gspca_dev;
973
974 *val = sd->brightness;
975 return 0;
976}
977
978static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 sd->contrast = val;
983 if (gspca_dev->streaming)
984 setcontrast(gspca_dev);
985 return 0;
986}
987
988static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
989{
990 struct sd *sd = (struct sd *) gspca_dev;
991
992 *val = sd->contrast;
993 return 0;
994}
995
996static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 sd->colors = val;
1001 if (gspca_dev->streaming) {
1002 setbrightness(gspca_dev);
1003 setcontrast(gspca_dev);
1004 }
1005 return 0;
1006}
1007
1008static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1009{
1010 struct sd *sd = (struct sd *) gspca_dev;
1011
1012 *val = sd->colors;
1013 return 0;
1014}
1015
1016/* sub-driver description */
1017static struct sd_desc sd_desc = {
1018 .name = MODULE_NAME,
1019 .ctrls = sd_ctrls,
1020 .nctrls = ARRAY_SIZE(sd_ctrls),
1021 .config = sd_config,
1022 .open = sd_open,
1023 .start = sd_start,
1024 .stopN = sd_stopN,
1025 .stop0 = sd_stop0,
1026 .close = sd_close,
1027 .pkt_scan = sd_pkt_scan,
1028};
1029
1030/* -- module initialisation -- */
1031#define DVNM(name) .driver_info = (kernel_ulong_t) name
1032static __devinitdata struct usb_device_id device_table[] = {
1033 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1034 {}
1035};
1036MODULE_DEVICE_TABLE(usb, device_table);
1037
1038/* -- device connect -- */
1039static int sd_probe(struct usb_interface *intf,
1040 const struct usb_device_id *id)
1041{
1042 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1043 THIS_MODULE);
1044}
1045
1046static struct usb_driver sd_driver = {
1047 .name = MODULE_NAME,
1048 .id_table = device_table,
1049 .probe = sd_probe,
1050 .disconnect = gspca_disconnect,
1051};
1052
1053/* -- module insert / remove -- */
1054static int __init sd_mod_init(void)
1055{
1056 if (usb_register(&sd_driver) < 0)
1057 return -1;
1058 PDEBUG(D_PROBE, "v%s registered", version);
1059 return 0;
1060}
1061static void __exit sd_mod_exit(void)
1062{
1063 usb_deregister(&sd_driver);
1064 PDEBUG(D_PROBE, "deregistered");
1065}
1066
1067module_init(sd_mod_init);
1068module_exit(sd_mod_exit);