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