blob: 013d593b0c678979faff6075900bdac237d08508 [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 Moine739570b2008-07-14 09:38:29 -030028#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29static const char version[] = "2.1.7";
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[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055 {
56 {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
59 .name = "Brightness",
60 .minimum = 0,
61 .maximum = 255,
62 .step = 1,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030063#define BRIGHTNESS_DEF 0xd4
64 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030065 },
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
68 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030069 {
70 {
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Contrast",
74 .minimum = 0x0a,
75 .maximum = 0x1f,
76 .step = 1,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030077#define CONTRAST_DEF 0x0c
78 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030079 },
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
82 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 {
84 {
85 .id = V4L2_CID_SATURATION,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Color",
88 .minimum = 0,
89 .maximum = 7,
90 .step = 1,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030091#define COLOR_DEF 3
92 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093 },
94 .set = sd_setcolors,
95 .get = sd_getcolors,
96 },
97};
98
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030099static struct v4l2_pix_format vga_mode[] = {
100 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
101 .bytesperline = 176,
102 .sizeimage = 176 * 144 * 3 / 8 + 590,
103 .colorspace = V4L2_COLORSPACE_JPEG,
104 .priv = 3},
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
109 .priv = 2},
110 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
111 .bytesperline = 352,
112 .sizeimage = 352 * 288 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
114 .priv = 1},
115 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
116 .bytesperline = 640,
117 .sizeimage = 640 * 480 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
119 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300120};
121
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300122/* the read bytes are found in gspca_dev->usb_buf */
123static void reg_r(struct gspca_dev *gspca_dev,
124 __u16 index,
125 __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300127 struct usb_device *dev = gspca_dev->dev;
128
129#ifdef CONFIG_VIDEO_ADV_DEBUG
130 if (len > sizeof gspca_dev->usb_buf) {
131 err("reg_r: buffer overflow");
132 return;
133 }
134#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300135 usb_control_msg(dev,
136 usb_rcvctrlpipe(dev, 0),
137 0,
138 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
139 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300140 index, gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300141 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300142 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
143 index, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300144}
145
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300146/* the bytes to write are in gspca_dev->usb_buf */
147static void reg_w_val(struct gspca_dev *gspca_dev,
148 __u16 index,
149 __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300151 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300152
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300153 gspca_dev->usb_buf[0] = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154 usb_control_msg(dev,
155 usb_sndctrlpipe(dev, 0),
156 0,
157 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
158 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300159 index, gspca_dev->usb_buf, 1, 500);
160}
161
162static void reg_w(struct gspca_dev *gspca_dev,
163 __u16 index,
164 const __u8 *buffer,
165 __u16 len)
166{
167 struct usb_device *dev = gspca_dev->dev;
168
169#ifdef CONFIG_VIDEO_ADV_DEBUG
170 if (len > sizeof gspca_dev->usb_buf) {
171 err("reg_w: buffer overflow");
172 return;
173 }
174 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
175#endif
176 memcpy(gspca_dev->usb_buf, buffer, len);
177 usb_control_msg(dev,
178 usb_sndctrlpipe(dev, 0),
179 0,
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
181 0,
182 index, gspca_dev->usb_buf, len, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183}
184
185static const __u8 cx_sensor_init[][4] = {
186 {0x88, 0x11, 0x01, 0x01},
187 {0x88, 0x12, 0x70, 0x01},
188 {0x88, 0x0f, 0x00, 0x01},
189 {0x88, 0x05, 0x01, 0x01},
190 {}
191};
192
193static const __u8 cx11646_fw1[][3] = {
194 {0x00, 0x02, 0x00},
195 {0x01, 0x43, 0x00},
196 {0x02, 0xA7, 0x00},
197 {0x03, 0x8B, 0x01},
198 {0x04, 0xE9, 0x02},
199 {0x05, 0x08, 0x04},
200 {0x06, 0x08, 0x05},
201 {0x07, 0x07, 0x06},
202 {0x08, 0xE7, 0x06},
203 {0x09, 0xC6, 0x07},
204 {0x0A, 0x86, 0x08},
205 {0x0B, 0x46, 0x09},
206 {0x0C, 0x05, 0x0A},
207 {0x0D, 0xA5, 0x0A},
208 {0x0E, 0x45, 0x0B},
209 {0x0F, 0xE5, 0x0B},
210 {0x10, 0x85, 0x0C},
211 {0x11, 0x25, 0x0D},
212 {0x12, 0xC4, 0x0D},
213 {0x13, 0x45, 0x0E},
214 {0x14, 0xE4, 0x0E},
215 {0x15, 0x64, 0x0F},
216 {0x16, 0xE4, 0x0F},
217 {0x17, 0x64, 0x10},
218 {0x18, 0xE4, 0x10},
219 {0x19, 0x64, 0x11},
220 {0x1A, 0xE4, 0x11},
221 {0x1B, 0x64, 0x12},
222 {0x1C, 0xE3, 0x12},
223 {0x1D, 0x44, 0x13},
224 {0x1E, 0xC3, 0x13},
225 {0x1F, 0x24, 0x14},
226 {0x20, 0xA3, 0x14},
227 {0x21, 0x04, 0x15},
228 {0x22, 0x83, 0x15},
229 {0x23, 0xE3, 0x15},
230 {0x24, 0x43, 0x16},
231 {0x25, 0xA4, 0x16},
232 {0x26, 0x23, 0x17},
233 {0x27, 0x83, 0x17},
234 {0x28, 0xE3, 0x17},
235 {0x29, 0x43, 0x18},
236 {0x2A, 0xA3, 0x18},
237 {0x2B, 0x03, 0x19},
238 {0x2C, 0x63, 0x19},
239 {0x2D, 0xC3, 0x19},
240 {0x2E, 0x22, 0x1A},
241 {0x2F, 0x63, 0x1A},
242 {0x30, 0xC3, 0x1A},
243 {0x31, 0x23, 0x1B},
244 {0x32, 0x83, 0x1B},
245 {0x33, 0xE2, 0x1B},
246 {0x34, 0x23, 0x1C},
247 {0x35, 0x83, 0x1C},
248 {0x36, 0xE2, 0x1C},
249 {0x37, 0x23, 0x1D},
250 {0x38, 0x83, 0x1D},
251 {0x39, 0xE2, 0x1D},
252 {0x3A, 0x23, 0x1E},
253 {0x3B, 0x82, 0x1E},
254 {0x3C, 0xC3, 0x1E},
255 {0x3D, 0x22, 0x1F},
256 {0x3E, 0x63, 0x1F},
257 {0x3F, 0xC1, 0x1F},
258 {}
259};
260static void cx11646_fw(struct gspca_dev*gspca_dev)
261{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300262 int i = 0;
263
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300264 reg_w_val(gspca_dev, 0x006a, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265 while (cx11646_fw1[i][1]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300266 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300267 i++;
268 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300269 reg_w_val(gspca_dev, 0x006a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300270}
271
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300272static const __u8 cxsensor[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300273 0x88, 0x12, 0x70, 0x01,
274 0x88, 0x0d, 0x02, 0x01,
275 0x88, 0x0f, 0x00, 0x01,
276 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
277 0x88, 0x02, 0x10, 0x01,
278 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
279 0x88, 0x0B, 0x00, 0x01,
280 0x88, 0x0A, 0x0A, 0x01,
281 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
282 0x88, 0x05, 0x01, 0x01,
283 0xA1, 0x18, 0x00, 0x01,
284 0x00
285};
286
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300287static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
288static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
289static const __u8 reg10[] = { 0xb1, 0xb1 };
290static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
291static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300292 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300293static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300294 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300295static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
296static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297
298static void cx_sensor(struct gspca_dev*gspca_dev)
299{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300300 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300301 int length;
302 const __u8 *ptsensor = cxsensor;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300303
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300304 reg_w(gspca_dev, 0x0020, reg20, 8);
305 reg_w(gspca_dev, 0x0028, reg28, 8);
306 reg_w(gspca_dev, 0x0010, reg10, 8);
307 reg_w_val(gspca_dev, 0x0092, 0x03);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300308
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300309 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300310 case 0:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300311 reg_w(gspca_dev, 0x0071, reg71a, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312 break;
313 case 1:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300314 reg_w(gspca_dev, 0x0071, reg71b, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300315 break;
316 default:
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300317/* case 2: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300318 reg_w(gspca_dev, 0x0071, reg71c, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300319 break;
320 case 3:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300321 reg_w(gspca_dev, 0x0071, reg71d, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300322 break;
323 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300324 reg_w(gspca_dev, 0x007b, reg7b, 6);
325 reg_w_val(gspca_dev, 0x00f8, 0x00);
326 reg_w(gspca_dev, 0x0010, reg10, 8);
327 reg_w_val(gspca_dev, 0x0098, 0x41);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300328 for (i = 0; i < 11; i++) {
329 if (i == 3 || i == 5 || i == 8)
330 length = 8;
331 else
332 length = 4;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300333 reg_w(gspca_dev, 0x00e5, ptsensor, length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 if (length == 4)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300335 reg_r(gspca_dev, 0x00e8, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300337 reg_r(gspca_dev, 0x00e8, length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338 ptsensor += length;
339 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300340 reg_r(gspca_dev, 0x00e7, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300341}
342
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300343static const __u8 cx_inits_176[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
345 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
346 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
347 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
348 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
349 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
350 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300352static const __u8 cx_inits_320[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300353 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
354 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
355 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
356 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
357 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
358 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
359 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
360};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300361static const __u8 cx_inits_352[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
363 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
364 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
365 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
366 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
367 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
368 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
369};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300370static const __u8 cx_inits_640[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
372 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
373 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
374 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
375 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
376 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
377 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
378};
379
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300380static void cx11646_initsize(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300382 const __u8 *cxinit;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
384 static const __u8 reg17[] =
385 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
386
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300387 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388 case 0:
389 cxinit = cx_inits_640;
390 break;
391 case 1:
392 cxinit = cx_inits_352;
393 break;
394 default:
395/* case 2: */
396 cxinit = cx_inits_320;
397 break;
398 case 3:
399 cxinit = cx_inits_176;
400 break;
401 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300402 reg_w_val(gspca_dev, 0x009a, 0x01);
403 reg_w_val(gspca_dev, 0x0010, 0x10);
404 reg_w(gspca_dev, 0x0012, reg12, 5);
405 reg_w(gspca_dev, 0x0017, reg17, 8);
406 reg_w_val(gspca_dev, 0x00c0, 0x00);
407 reg_w_val(gspca_dev, 0x00c1, 0x04);
408 reg_w_val(gspca_dev, 0x00c2, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300409
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300410 reg_w(gspca_dev, 0x0061, cxinit, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300412 reg_w(gspca_dev, 0x00ca, cxinit, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300413 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300414 reg_w(gspca_dev, 0x00d2, cxinit, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300415 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300416 reg_w(gspca_dev, 0x00da, cxinit, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300418 reg_w(gspca_dev, 0x0041, cxinit, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300419 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300420 reg_w(gspca_dev, 0x0049, cxinit, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300421 cxinit += 8;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300422 reg_w(gspca_dev, 0x0051, cxinit, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300423
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300424 reg_r(gspca_dev, 0x0010, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425}
426
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300427static const __u8 cx_jpeg_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300428 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
429 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
430 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
431 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
432 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
433 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
434 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
435 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
436 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
437 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
438 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
439 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
440 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
441 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
442 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
443 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
444 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
445 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
446 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
448 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
449 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
450 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
451 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
452 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
453 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
454 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
455 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
456 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
457 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
458 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
459 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
460 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
461 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
462 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
463 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
464 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
465 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
466 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
467 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
468 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
469 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
470 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
471 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
472 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
473 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
474 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
475 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
476 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
477 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
478 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
479 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
480 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
481 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
482 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
483 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
484 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
485 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
486 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
487 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
488 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
489 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
490 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
491 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
492 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
493 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
494 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
495 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
496 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
497 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
498 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
499 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
500 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
501 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
502 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
503 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
504 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
505 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
506 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
507};
508
509
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300510static const __u8 cxjpeg_640[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
512 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
513 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
514 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
515 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
516 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
517 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
518 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
519 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
520 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
521 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
522 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
523 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
524 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
525 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
526 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
527 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
528 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
529 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
530 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
531 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
532 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
533 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
534 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
535 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
536 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
537 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
538};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300539static const __u8 cxjpeg_352[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
541 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
542 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
543 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
544 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
545 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
546 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
547 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
548 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
549 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
550 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
551 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
552 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
553 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
554 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
555 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
556 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
557 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
558 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
559 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
560 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
561 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
562 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
563 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
564 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
565 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
566 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
567};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300568static const __u8 cxjpeg_320[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300569 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
570 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
571 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
572 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
573 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
574 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
575 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
576 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
577 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
578 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
579 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
580 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
581 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
582 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
583 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
584 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
585 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
586 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
587 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
588 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
589 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
590 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
591 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
592 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
593 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
594 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
595 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
596};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300597static const __u8 cxjpeg_176[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
599 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
600 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
601 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
602 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
603 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
604 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
605 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
606 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
607 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
608 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
609 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
610 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
611 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
612 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
613 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
614 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
615 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
616 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
617 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
618 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
619 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
620 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
621 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
622 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
623 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
624 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
625};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300626/* 640 take with the zcx30x part */
627static const __u8 cxjpeg_qtable[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
629 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
630 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
631 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
632 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
633 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
634 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
635 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
636 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
637 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
638 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
639 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
640 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
646};
647
648
649static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
650{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 int i;
652 int length;
653
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300654 reg_w_val(gspca_dev, 0x00c0, 0x01);
655 reg_w_val(gspca_dev, 0x00c3, 0x00);
656 reg_w_val(gspca_dev, 0x00c0, 0x00);
657 reg_r(gspca_dev, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658 length = 8;
659 for (i = 0; i < 79; i++) {
660 if (i == 78)
661 length = 6;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300662 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300663 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300664 reg_r(gspca_dev, 0x0002, 1);
665 reg_w_val(gspca_dev, 0x0055, 0x14);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300666}
667
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300668static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
669static const __u8 regE5_8[] =
670 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
671static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
672static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
673static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
674static const __u8 reg51[] = { 0x77, 0x03 };
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300675#define reg70 0x03
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
677static void cx11646_jpeg(struct gspca_dev*gspca_dev)
678{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300680 int length;
681 __u8 Reg55;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300682 int retry;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300683
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300684 reg_w_val(gspca_dev, 0x00c0, 0x01);
685 reg_w_val(gspca_dev, 0x00c3, 0x00);
686 reg_w_val(gspca_dev, 0x00c0, 0x00);
687 reg_r(gspca_dev, 0x0001, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300688 length = 8;
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300689 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 case 0:
691 for (i = 0; i < 27; i++) {
692 if (i == 26)
693 length = 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300694 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 }
696 Reg55 = 0x28;
697 break;
698 case 1:
699 for (i = 0; i < 27; i++) {
700 if (i == 26)
701 length = 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300702 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 }
704 Reg55 = 0x16;
705 break;
706 default:
707/* case 2: */
708 for (i = 0; i < 27; i++) {
709 if (i == 26)
710 length = 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300711 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712 }
713 Reg55 = 0x14;
714 break;
715 case 3:
716 for (i = 0; i < 27; i++) {
717 if (i == 26)
718 length = 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300719 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720 }
721 Reg55 = 0x0B;
722 break;
723 }
724
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300725 reg_r(gspca_dev, 0x0002, 1);
726 reg_w_val(gspca_dev, 0x0055, Reg55);
727 reg_r(gspca_dev, 0x0002, 1);
728 reg_w(gspca_dev, 0x0010, reg10, 2);
729 reg_w_val(gspca_dev, 0x0054, 0x02);
730 reg_w_val(gspca_dev, 0x0054, 0x01);
731 reg_w_val(gspca_dev, 0x0000, 0x94);
732 reg_w_val(gspca_dev, 0x0053, 0xc0);
733 reg_w_val(gspca_dev, 0x00fc, 0xe1);
734 reg_w_val(gspca_dev, 0x0000, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735 /* wait for completion */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300736 retry = 50;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737 while (retry--) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300738 reg_r(gspca_dev, 0x0002, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739 /* 0x07 until 0x00 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300740 if (gspca_dev->usb_buf[0] == 0x00)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741 break;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300742 reg_w_val(gspca_dev, 0x0053, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743 }
744 if (retry == 0)
745 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
746 /* send the qtable now */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300747 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748 length = 8;
749 for (i = 0; i < 18; i++) {
750 if (i == 17)
751 length = 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300752 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753
754 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300755 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
756 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
757 reg_w_val(gspca_dev, 0x0054, 0x02);
758 reg_w_val(gspca_dev, 0x0054, 0x01);
759 reg_w_val(gspca_dev, 0x0000, 0x94);
760 reg_w_val(gspca_dev, 0x0053, 0xc0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300762 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
763 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
764 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
765 reg_w(gspca_dev, 0x0012, reg12, 5);
766 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
767 reg_r(gspca_dev, 0x00e8, 8);
768 reg_w(gspca_dev, 0x00e5, regE5a, 4);
769 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
770 reg_w_val(gspca_dev, 0x009a, 0x01);
771 reg_w(gspca_dev, 0x00e5, regE5b, 4);
772 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
773 reg_w(gspca_dev, 0x00e5, regE5c, 4);
774 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300776 reg_w(gspca_dev, 0x0051, reg51, 2);
777 reg_w(gspca_dev, 0x0010, reg10, 2);
778 reg_w_val(gspca_dev, 0x0070, reg70);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779}
780
781static void cx11646_init1(struct gspca_dev *gspca_dev)
782{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 int i = 0;
784
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300785 reg_w_val(gspca_dev, 0x0010, 0x00);
786 reg_w_val(gspca_dev, 0x0053, 0x00);
787 reg_w_val(gspca_dev, 0x0052, 0x00);
788 reg_w_val(gspca_dev, 0x009b, 0x2f);
789 reg_w_val(gspca_dev, 0x009c, 0x10);
790 reg_r(gspca_dev, 0x0098, 1);
791 reg_w_val(gspca_dev, 0x0098, 0x40);
792 reg_r(gspca_dev, 0x0099, 1);
793 reg_w_val(gspca_dev, 0x0099, 0x07);
794 reg_w_val(gspca_dev, 0x0039, 0x40);
795 reg_w_val(gspca_dev, 0x003c, 0xff);
796 reg_w_val(gspca_dev, 0x003f, 0x1f);
797 reg_w_val(gspca_dev, 0x003d, 0x40);
798/* reg_w_val(gspca_dev, 0x003d, 0x60); */
799 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800
801 while (cx_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300802 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
803 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804 if (i == 1) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300805 reg_w_val(gspca_dev, 0x00ed, 0x01);
806 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807 }
808 i++;
809 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300810 reg_w_val(gspca_dev, 0x00c3, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811}
812
813/* this function is called at probe time */
814static int sd_config(struct gspca_dev *gspca_dev,
815 const struct usb_device_id *id)
816{
817 struct sd *sd = (struct sd *) gspca_dev;
818 struct cam *cam;
819
820 cam = &gspca_dev->cam;
821 cam->dev_name = (char *) id->driver_info;
822 cam->epaddr = 0x01;
823 cam->cam_mode = vga_mode;
824 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
825
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300826 sd->qindex = 0; /* set the quantization */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300827 sd->brightness = BRIGHTNESS_DEF;
828 sd->contrast = CONTRAST_DEF;
829 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830 return 0;
831}
832
833/* this function is called at open time */
834static int sd_open(struct gspca_dev *gspca_dev)
835{
836 cx11646_init1(gspca_dev);
837 cx11646_initsize(gspca_dev);
838 cx11646_fw(gspca_dev);
839 cx_sensor(gspca_dev);
840 cx11646_jpegInit(gspca_dev);
841 return 0;
842}
843
844static void sd_start(struct gspca_dev *gspca_dev)
845{
846 cx11646_initsize(gspca_dev);
847 cx11646_fw(gspca_dev);
848 cx_sensor(gspca_dev);
849 cx11646_jpeg(gspca_dev);
850}
851
852static void sd_stopN(struct gspca_dev *gspca_dev)
853{
854}
855
856static void sd_stop0(struct gspca_dev *gspca_dev)
857{
858 int retry = 50;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300860 reg_w_val(gspca_dev, 0x0000, 0x00);
861 reg_r(gspca_dev, 0x0002, 1);
862 reg_w_val(gspca_dev, 0x0053, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863
864 while (retry--) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300865/* reg_r(gspca_dev, 0x0002, 1);*/
866 reg_r(gspca_dev, 0x0053, 1);
867 if (gspca_dev->usb_buf[0] == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 break;
869 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300870 reg_w_val(gspca_dev, 0x0000, 0x00);
871 reg_r(gspca_dev, 0x0002, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300873 reg_w_val(gspca_dev, 0x0010, 0x00);
874 reg_r(gspca_dev, 0x0033, 1);
875 reg_w_val(gspca_dev, 0x00fc, 0xe0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876}
877
878static void sd_close(struct gspca_dev *gspca_dev)
879{
880}
881
882static void sd_pkt_scan(struct gspca_dev *gspca_dev,
883 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300884 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 int len) /* iso packet length */
886{
887 if (data[0] == 0xff && data[1] == 0xd8) {
888
889 /* start of frame */
890 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
891 data, 0);
892
893 /* put the JPEG header in the new frame */
894 jpeg_put_header(gspca_dev, frame,
895 ((struct sd *) gspca_dev)->qindex,
896 0x22);
897 data += 2;
898 len -= 2;
899 }
900 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
901}
902
903static void setbrightness(struct gspca_dev*gspca_dev)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300907 __u8 reg51c[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 __u8 bright;
909 __u8 colors;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910
911 bright = sd->brightness;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 regE5cbx[2] = bright;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300913 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
914 reg_r(gspca_dev, 0x00e8, 8);
915 reg_w(gspca_dev, 0x00e5, regE5c, 4);
916 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300918 colors = sd->colors;
919 reg51c[0] = 0x77;
920 reg51c[1] = colors;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300921 reg_w(gspca_dev, 0x0051, reg51c, 2);
922 reg_w(gspca_dev, 0x0010, reg10, 2);
923 reg_w_val(gspca_dev, 0x0070, reg70);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924}
925
926static void setcontrast(struct gspca_dev*gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300930/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
931 __u8 reg51c[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 regE5acx[2] = sd->contrast;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300934 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
935 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300936 reg51c[0] = 0x77;
937 reg51c[1] = sd->colors;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300938 reg_w(gspca_dev, 0x0051, reg51c, 2);
939 reg_w(gspca_dev, 0x0010, reg10, 2);
940 reg_w_val(gspca_dev, 0x0070, reg70);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941}
942
943static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 sd->brightness = val;
948 if (gspca_dev->streaming)
949 setbrightness(gspca_dev);
950 return 0;
951}
952
953static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
956
957 *val = sd->brightness;
958 return 0;
959}
960
961static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
962{
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 sd->contrast = val;
966 if (gspca_dev->streaming)
967 setcontrast(gspca_dev);
968 return 0;
969}
970
971static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
974
975 *val = sd->contrast;
976 return 0;
977}
978
979static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
983 sd->colors = val;
984 if (gspca_dev->streaming) {
985 setbrightness(gspca_dev);
986 setcontrast(gspca_dev);
987 }
988 return 0;
989}
990
991static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 *val = sd->colors;
996 return 0;
997}
998
999/* sub-driver description */
1000static struct sd_desc sd_desc = {
1001 .name = MODULE_NAME,
1002 .ctrls = sd_ctrls,
1003 .nctrls = ARRAY_SIZE(sd_ctrls),
1004 .config = sd_config,
1005 .open = sd_open,
1006 .start = sd_start,
1007 .stopN = sd_stopN,
1008 .stop0 = sd_stop0,
1009 .close = sd_close,
1010 .pkt_scan = sd_pkt_scan,
1011};
1012
1013/* -- module initialisation -- */
1014#define DVNM(name) .driver_info = (kernel_ulong_t) name
1015static __devinitdata struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1017 {}
1018};
1019MODULE_DEVICE_TABLE(usb, device_table);
1020
1021/* -- device connect -- */
1022static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1024{
1025 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1026 THIS_MODULE);
1027}
1028
1029static struct usb_driver sd_driver = {
1030 .name = MODULE_NAME,
1031 .id_table = device_table,
1032 .probe = sd_probe,
1033 .disconnect = gspca_disconnect,
1034};
1035
1036/* -- module insert / remove -- */
1037static int __init sd_mod_init(void)
1038{
1039 if (usb_register(&sd_driver) < 0)
1040 return -1;
1041 PDEBUG(D_PROBE, "v%s registered", version);
1042 return 0;
1043}
1044static void __exit sd_mod_exit(void)
1045{
1046 usb_deregister(&sd_driver);
1047 PDEBUG(D_PROBE, "deregistered");
1048}
1049
1050module_init(sd_mod_init);
1051module_exit(sd_mod_exit);