blob: 17fe2c2a440d8f222f434c4c2692db093ef4e50d [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030035 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 /* !! no more than 128 ff in an ISO packet */
37
38 unsigned char brightness;
39 unsigned char contrast;
40 unsigned char colors;
41
42 char qindex;
43 char subtype;
44#define AgfaCl20 0
45#define AiptekPocketDV 1
46#define BenqDC1016 2
47#define CreativePCCam300 3
48#define DLinkDSC350 4
49#define Gsmartmini 5
50#define IntelPocketPCCamera 6
51#define KodakEZ200 7
52#define LogitechClickSmart310 8
53#define LogitechClickSmart510 9
54#define LogitechTraveler 10
55#define MustekGsmart300 11
56#define Optimedia 12
57#define PalmPixDC85 13
58#define ToptroIndus 14
59};
60
61/* V4L2 controls supported by the driver */
62static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
68
69static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030070 {
71 {
72 .id = V4L2_CID_BRIGHTNESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Brightness",
75 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030076 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030077 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030078#define BRIGHTNESS_DEF 127
79 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030080 },
81 .set = sd_setbrightness,
82 .get = sd_getbrightness,
83 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030084 {
85 {
86 .id = V4L2_CID_CONTRAST,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Contrast",
89 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030090 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030092#define CONTRAST_DEF 31
93 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030094 },
95 .set = sd_setcontrast,
96 .get = sd_getcontrast,
97 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 {
99 {
100 .id = V4L2_CID_SATURATION,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Color",
103 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300104 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300106#define COLOR_DEF 31
107 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108 },
109 .set = sd_setcolors,
110 .get = sd_getcolors,
111 },
112};
113
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300114static struct v4l2_pix_format vga_mode[] = {
115 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
116 .bytesperline = 320,
117 .sizeimage = 320 * 240 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
119 .priv = 1},
120 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 640,
122 .sizeimage = 640 * 480 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125};
126
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300127static struct v4l2_pix_format sif_mode[] = {
128 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
129 .bytesperline = 176,
130 .sizeimage = 176 * 144 * 3 / 8 + 590,
131 .colorspace = V4L2_COLORSPACE_JPEG,
132 .priv = 1},
133 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .bytesperline = 352,
135 .sizeimage = 352 * 288 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
137 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300138};
139
140/* Frame packet header offsets for the spca500 */
141#define SPCA500_OFFSET_PADDINGLB 2
142#define SPCA500_OFFSET_PADDINGHB 3
143#define SPCA500_OFFSET_MODE 4
144#define SPCA500_OFFSET_IMGWIDTH 5
145#define SPCA500_OFFSET_IMGHEIGHT 6
146#define SPCA500_OFFSET_IMGMODE 7
147#define SPCA500_OFFSET_QTBLINDEX 8
148#define SPCA500_OFFSET_FRAMSEQ 9
149#define SPCA500_OFFSET_CDSPINFO 10
150#define SPCA500_OFFSET_GPIO 11
151#define SPCA500_OFFSET_AUGPIO 12
152#define SPCA500_OFFSET_DATA 16
153
154
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300155static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
157 * hue (H byte) = 0,
158 * saturation/hue enable,
159 * brightness/contrast enable.
160 */
161 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
162 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
163 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
164 * hue (H byte) = 0, saturation/hue enable,
165 * brightness/contrast enable.
166 * was 0x0003, now 0x0000.
167 */
168 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
169 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
170 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
171 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
172 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
173 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
174 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
175 {0x0c, 0x0004, 0x0000},
176 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300177 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300179static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180 {0x00, 0x00, 0x8211},
181 {0x00, 0x01, 0x82c0},
182 {0x00, 0x10, 0x82cb},
183 {0x00, 0x0f, 0x800d},
184 {0x00, 0x82, 0x8225},
185 {0x00, 0x21, 0x8228},
186 {0x00, 0x00, 0x8203},
187 {0x00, 0x00, 0x8204},
188 {0x00, 0x08, 0x8205},
189 {0x00, 0xf8, 0x8206},
190 {0x00, 0x28, 0x8207},
191 {0x00, 0xa0, 0x8208},
192 {0x00, 0x08, 0x824a},
193 {0x00, 0x08, 0x8214},
194 {0x00, 0x80, 0x82c1},
195 {0x00, 0x00, 0x82c2},
196 {0x00, 0x00, 0x82ca},
197 {0x00, 0x80, 0x82c1},
198 {0x00, 0x04, 0x82c2},
199 {0x00, 0x00, 0x82ca},
200 {0x00, 0xfc, 0x8100},
201 {0x00, 0xfc, 0x8105},
202 {0x00, 0x30, 0x8101},
203 {0x00, 0x00, 0x8102},
204 {0x00, 0x00, 0x8103},
205 {0x00, 0x66, 0x8107},
206 {0x00, 0x00, 0x816b},
207 {0x00, 0x00, 0x8155},
208 {0x00, 0x01, 0x8156},
209 {0x00, 0x60, 0x8157},
210 {0x00, 0x40, 0x8158},
211 {0x00, 0x0a, 0x8159},
212 {0x00, 0x06, 0x815a},
213 {0x00, 0x00, 0x813f},
214 {0x00, 0x00, 0x8200},
215 {0x00, 0x19, 0x8201},
216 {0x00, 0x00, 0x82c1},
217 {0x00, 0xa0, 0x82c2},
218 {0x00, 0x00, 0x82ca},
219 {0x00, 0x00, 0x8117},
220 {0x00, 0x00, 0x8118},
221 {0x00, 0x65, 0x8119},
222 {0x00, 0x00, 0x811a},
223 {0x00, 0x00, 0x811b},
224 {0x00, 0x55, 0x811c},
225 {0x00, 0x65, 0x811d},
226 {0x00, 0x55, 0x811e},
227 {0x00, 0x16, 0x811f},
228 {0x00, 0x19, 0x8120},
229 {0x00, 0x80, 0x8103},
230 {0x00, 0x83, 0x816b},
231 {0x00, 0x25, 0x8168},
232 {0x00, 0x01, 0x820f},
233 {0x00, 0xff, 0x8115},
234 {0x00, 0x48, 0x8116},
235 {0x00, 0x50, 0x8151},
236 {0x00, 0x40, 0x8152},
237 {0x00, 0x78, 0x8153},
238 {0x00, 0x40, 0x8154},
239 {0x00, 0x00, 0x8167},
240 {0x00, 0x20, 0x8168},
241 {0x00, 0x00, 0x816a},
242 {0x00, 0x03, 0x816b},
243 {0x00, 0x20, 0x8169},
244 {0x00, 0x60, 0x8157},
245 {0x00, 0x00, 0x8190},
246 {0x00, 0x00, 0x81a1},
247 {0x00, 0x00, 0x81b2},
248 {0x00, 0x27, 0x8191},
249 {0x00, 0x27, 0x81a2},
250 {0x00, 0x27, 0x81b3},
251 {0x00, 0x4b, 0x8192},
252 {0x00, 0x4b, 0x81a3},
253 {0x00, 0x4b, 0x81b4},
254 {0x00, 0x66, 0x8193},
255 {0x00, 0x66, 0x81a4},
256 {0x00, 0x66, 0x81b5},
257 {0x00, 0x79, 0x8194},
258 {0x00, 0x79, 0x81a5},
259 {0x00, 0x79, 0x81b6},
260 {0x00, 0x8a, 0x8195},
261 {0x00, 0x8a, 0x81a6},
262 {0x00, 0x8a, 0x81b7},
263 {0x00, 0x9b, 0x8196},
264 {0x00, 0x9b, 0x81a7},
265 {0x00, 0x9b, 0x81b8},
266 {0x00, 0xa6, 0x8197},
267 {0x00, 0xa6, 0x81a8},
268 {0x00, 0xa6, 0x81b9},
269 {0x00, 0xb2, 0x8198},
270 {0x00, 0xb2, 0x81a9},
271 {0x00, 0xb2, 0x81ba},
272 {0x00, 0xbe, 0x8199},
273 {0x00, 0xbe, 0x81aa},
274 {0x00, 0xbe, 0x81bb},
275 {0x00, 0xc8, 0x819a},
276 {0x00, 0xc8, 0x81ab},
277 {0x00, 0xc8, 0x81bc},
278 {0x00, 0xd2, 0x819b},
279 {0x00, 0xd2, 0x81ac},
280 {0x00, 0xd2, 0x81bd},
281 {0x00, 0xdb, 0x819c},
282 {0x00, 0xdb, 0x81ad},
283 {0x00, 0xdb, 0x81be},
284 {0x00, 0xe4, 0x819d},
285 {0x00, 0xe4, 0x81ae},
286 {0x00, 0xe4, 0x81bf},
287 {0x00, 0xed, 0x819e},
288 {0x00, 0xed, 0x81af},
289 {0x00, 0xed, 0x81c0},
290 {0x00, 0xf7, 0x819f},
291 {0x00, 0xf7, 0x81b0},
292 {0x00, 0xf7, 0x81c1},
293 {0x00, 0xff, 0x81a0},
294 {0x00, 0xff, 0x81b1},
295 {0x00, 0xff, 0x81c2},
296 {0x00, 0x03, 0x8156},
297 {0x00, 0x00, 0x8211},
298 {0x00, 0x20, 0x8168},
299 {0x00, 0x01, 0x8202},
300 {0x00, 0x30, 0x8101},
301 {0x00, 0x00, 0x8111},
302 {0x00, 0x00, 0x8112},
303 {0x00, 0x00, 0x8113},
304 {0x00, 0x00, 0x8114},
305 {}
306};
307
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300308static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 { /* Q-table Y-components */
310 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
311 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
312 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
313 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
314 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
315 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
316 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
317 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
318 { /* Q-table C-components */
319 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
320 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
321 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
322 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
327};
328
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300329static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300330 { /* Q-table Y-components */
331 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
332 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
333 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
334 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
335 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
336 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
337 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
338 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
339 { /* Q-table C-components */
340 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
341 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
342 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
343 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
348};
349
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300350static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300351 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300352 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
353 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
354 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
355 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
356 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
357 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
358 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
359 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
360 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300361 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
363 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
364 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
365 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
366 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
367 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
370};
371
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300372/* read 'len' bytes to gspca_dev->usb_buf */
373static void reg_r(struct gspca_dev *gspca_dev,
374 __u16 index,
375 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300377 usb_control_msg(gspca_dev->dev,
378 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379 0,
380 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
381 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300382 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383}
384
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300385static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386 __u16 req, __u16 index, __u16 value)
387{
388 int ret;
389
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300390 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300391 ret = usb_control_msg(gspca_dev->dev,
392 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300394 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396 if (ret < 0)
397 PDEBUG(D_ERR, "reg write: error %d", ret);
398 return ret;
399}
400
401/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300402static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300403 __u16 req, /* bRequest */
404 __u16 index, /* wIndex */
405 __u16 length) /* wLength (1 or 2 only) */
406{
407 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300408
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300409 gspca_dev->usb_buf[1] = 0;
410 ret = usb_control_msg(gspca_dev->dev,
411 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300412 req,
413 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
414 0, /* value */
415 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300416 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 500); /* timeout */
418 if (ret < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300419 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300420 return -1;
421 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300422 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300423}
424
425/*
426 * Simple function to wait for a given 8-bit value to be returned from
427 * a reg_read call.
428 * Returns: negative is error or timeout, zero is success.
429 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300430static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300431 __u16 reg, __u16 index, __u16 value)
432{
433 int ret, cnt = 20;
434
435 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300436 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300437 if (ret == value)
438 return 0;
439 msleep(50);
440 }
441 return -EIO;
442}
443
444static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300445 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300446{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447 int ret, i = 0;
448
449 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300450 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451 if (ret < 0)
452 return ret;
453 i++;
454 }
455 return 0;
456}
457
458static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
459 unsigned int request,
460 unsigned int ybase,
461 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300462 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464 int i, err;
465
466 /* loop over y components */
467 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300468 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469 if (err < 0)
470 return err;
471 }
472
473 /* loop over c components */
474 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300475 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300476 if (err < 0)
477 return err;
478 }
479 return 0;
480}
481
482static void spca500_ping310(struct gspca_dev *gspca_dev)
483{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300484 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300485 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300486 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300487}
488
489static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
490{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300491 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300492 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300493 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
494 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300495 spca500_ping310(gspca_dev);
496
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300497 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
498 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
499 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
500 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
501 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
502 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
503 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
504 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
505 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
506 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300508 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
509 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
510 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511}
512
513static void spca500_setmode(struct gspca_dev *gspca_dev,
514 __u8 xmult, __u8 ymult)
515{
516 int mode;
517
518 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300519 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520
521 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300522 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300523
524 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300525 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300526 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300527}
528
529static int spca500_full_reset(struct gspca_dev *gspca_dev)
530{
531 int err;
532
533 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 if (err < 0)
536 return err;
537
538 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300539 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540 if (err < 0)
541 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543 if (err < 0)
544 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300547 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 return err;
549 }
550 /* all ok */
551 return 0;
552}
553
554/* Synchro the Bridge with sensor */
555/* Maybe that will work on all spca500 chip */
556/* because i only own a clicksmart310 try for that chip */
557/* using spca50x_set_packet_size() cause an Ooops here */
558/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
559/* up-port the same feature as in 2.4.x kernel */
560static int spca500_synch310(struct gspca_dev *gspca_dev)
561{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
563 PDEBUG(D_ERR, "Set packet size: set interface error");
564 goto error;
565 }
566 spca500_ping310(gspca_dev);
567
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300568 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300569
570 /* need alt setting here */
571 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
572
573 /* Windoze use pipe with altsetting 6 why 7 here */
574 if (usb_set_interface(gspca_dev->dev,
575 gspca_dev->iface,
576 gspca_dev->alt) < 0) {
577 PDEBUG(D_ERR, "Set packet size: set interface error");
578 goto error;
579 }
580 return 0;
581error:
582 return -EBUSY;
583}
584
585static void spca500_reinit(struct gspca_dev *gspca_dev)
586{
587 int err;
588 __u8 Data;
589
590 /* some unknow command from Aiptek pocket dv and family300 */
591
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300592 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
593 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
594 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595
596 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598
599 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
600 qtable_pocketdv);
601 if (err < 0)
602 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
603
604 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300605 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300606 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300607 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300609 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300611 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300613 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
618 reg_r(gspca_dev, 0x816b, 1);
619 Data = gspca_dev->usb_buf[0];
620 reg_w(gspca_dev, 0x00, 0x816b, Data);
621 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622}
623
624/* this function is called at probe time */
625static int sd_config(struct gspca_dev *gspca_dev,
626 const struct usb_device_id *id)
627{
628 struct sd *sd = (struct sd *) gspca_dev;
629 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 cam->epaddr = 0x01;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300633 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 if (sd->subtype != LogitechClickSmart310) {
635 cam->cam_mode = vga_mode;
636 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
637 } else {
638 cam->cam_mode = sif_mode;
639 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
640 }
641 sd->qindex = 5;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300642 sd->brightness = BRIGHTNESS_DEF;
643 sd->contrast = CONTRAST_DEF;
644 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 return 0;
646}
647
648/* this function is called at open time */
649static int sd_open(struct gspca_dev *gspca_dev)
650{
651 struct sd *sd = (struct sd *) gspca_dev;
652
653 /* initialisation of spca500 based cameras is deferred */
654 PDEBUG(D_STREAM, "SPCA500 init");
655 if (sd->subtype == LogitechClickSmart310)
656 spca500_clksmart310_init(gspca_dev);
657/* else
658 spca500_initialise(gspca_dev); */
659 PDEBUG(D_STREAM, "SPCA500 init done");
660 return 0;
661}
662
663static void sd_start(struct gspca_dev *gspca_dev)
664{
665 struct sd *sd = (struct sd *) gspca_dev;
666 int err;
667 __u8 Data;
668 __u8 xmult, ymult;
669
670 if (sd->subtype == LogitechClickSmart310) {
671 xmult = 0x16;
672 ymult = 0x12;
673 } else {
674 xmult = 0x28;
675 ymult = 0x1e;
676 }
677
678 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300679 reg_r(gspca_dev, 0x8a04, 1);
680 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
681 gspca_dev->usb_buf[0]);
682 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300683 gspca_dev->curr_mode, xmult, ymult);
684
685 /* setup qtable */
686 switch (sd->subtype) {
687 case LogitechClickSmart310:
688 spca500_setmode(gspca_dev, xmult, ymult);
689
690 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300691 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
692 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 err = spca50x_setup_qtable(gspca_dev,
694 0x00, 0x8800, 0x8840,
695 qtable_creative_pccam);
696 if (err < 0)
697 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
698 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300699 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700
701 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300702 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300704 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300705 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300707 reg_r(gspca_dev, 0x816b, 1);
708 Data = gspca_dev->usb_buf[0];
709 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
711 spca500_synch310(gspca_dev);
712
713 write_vector(gspca_dev, spca500_visual_defaults);
714 spca500_setmode(gspca_dev, xmult, ymult);
715 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300716 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300718 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 err = spca50x_setup_qtable(gspca_dev,
720 0x00, 0x8800, 0x8840,
721 qtable_creative_pccam);
722 if (err < 0)
723 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
724
725 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300726 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727
728 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300729 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300731 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300732 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300733
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300734 reg_r(gspca_dev, 0x816b, 1);
735 Data = gspca_dev->usb_buf[0];
736 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737 break;
738 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
739 case IntelPocketPCCamera: /* FIXME: Temporary fix for
740 * Intel Pocket PC Camera
741 * - NWG (Sat 29th March 2003) */
742
743 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300744 err = spca500_full_reset(gspca_dev);
745 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 PDEBUG(D_ERR, "spca500_full_reset failed");
747
748 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300749 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750 if (err < 0)
751 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300752 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753 err = spca50x_setup_qtable(gspca_dev,
754 0x00, 0x8800, 0x8840,
755 qtable_creative_pccam);
756 if (err < 0)
757 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
758
759 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761
762 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300765 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300766 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300768 reg_r(gspca_dev, 0x816b, 1);
769 Data = gspca_dev->usb_buf[0];
770 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300772/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773 break;
774 case KodakEZ200: /* Kodak EZ200 */
775
776 /* do a full reset */
777 err = spca500_full_reset(gspca_dev);
778 if (err < 0)
779 PDEBUG(D_ERR, "spca500_full_reset failed");
780 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300781 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
782 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 err = spca50x_setup_qtable(gspca_dev,
784 0x00, 0x8800, 0x8840,
785 qtable_kodak_ez200);
786 if (err < 0)
787 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
788 spca500_setmode(gspca_dev, xmult, ymult);
789
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791
792 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300793 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300795 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300796 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300797
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300798 reg_r(gspca_dev, 0x816b, 1);
799 Data = gspca_dev->usb_buf[0];
800 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300802/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 break;
804
805 case BenqDC1016:
806 case DLinkDSC350: /* FamilyCam 300 */
807 case AiptekPocketDV: /* Aiptek PocketDV */
808 case Gsmartmini: /*Mustek Gsmart Mini */
809 case MustekGsmart300: /* Mustek Gsmart 300 */
810 case PalmPixDC85:
811 case Optimedia:
812 case ToptroIndus:
813 case AgfaCl20:
814 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300815 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300816 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300817 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818
819 err = spca50x_setup_qtable(gspca_dev,
820 0x00, 0x8800, 0x8840, qtable_pocketdv);
821 if (err < 0)
822 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300823 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824
825 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300826 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300828 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300830 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300832 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300836 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300838 reg_r(gspca_dev, 0x816b, 1);
839 Data = gspca_dev->usb_buf[0];
840 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300841 break;
842 case LogitechTraveler:
843 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300846 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847
848 err = spca50x_setup_qtable(gspca_dev,
849 0x00, 0x8800,
850 0x8840, qtable_creative_pccam);
851 if (err < 0)
852 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300853 reg_w(gspca_dev, 0x00, 0x8880, 3);
854 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300856 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857
858 spca500_setmode(gspca_dev, xmult, ymult);
859
860 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300861 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
862 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300864 reg_r(gspca_dev, 0x816b, 1);
865 Data = gspca_dev->usb_buf[0];
866 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867 write_vector(gspca_dev, Clicksmart510_defaults);
868 break;
869 }
870}
871
872static void sd_stopN(struct gspca_dev *gspca_dev)
873{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300874 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875
876 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300877 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
878 reg_r(gspca_dev, 0x8000, 1);
879 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
880 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881}
882
883static void sd_stop0(struct gspca_dev *gspca_dev)
884{
885}
886
887static void sd_close(struct gspca_dev *gspca_dev)
888{
889}
890
891static void sd_pkt_scan(struct gspca_dev *gspca_dev,
892 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300893 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 int len) /* iso packet length */
895{
896 struct sd *sd = (struct sd *) gspca_dev;
897 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300898 __u8 *s, *d;
899 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900
901/* frames are jpeg 4.1.1 without 0xff escape */
902 if (data[0] == 0xff) {
903 if (data[1] != 0x01) { /* drop packet */
904/* gspca_dev->last_packet_type = DISCARD_PACKET; */
905 return;
906 }
907 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
908 ffd9, 2);
909
910 /* put the JPEG header in the new frame */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300911 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912
913 data += SPCA500_OFFSET_DATA;
914 len -= SPCA500_OFFSET_DATA;
915 } else {
916 data += 1;
917 len -= 1;
918 }
919
920 /* add 0x00 after 0xff */
921 for (i = len; --i >= 0; )
922 if (data[i] == 0xff)
923 break;
924 if (i < 0) { /* no 0xff */
925 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
926 return;
927 }
928 s = data;
929 d = sd->packet;
930 for (i = 0; i < len; i++) {
931 *d++ = *s++;
932 if (s[-1] == 0xff)
933 *d++ = 0x00;
934 }
935 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
936 sd->packet, d - sd->packet);
937}
938
939static void setbrightness(struct gspca_dev *gspca_dev)
940{
941 struct sd *sd = (struct sd *) gspca_dev;
942
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300943 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 (__u8) (sd->brightness - 128));
945}
946
947static void getbrightness(struct gspca_dev *gspca_dev)
948{
949 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300950 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300953 if (ret >= 0)
954 sd->brightness = ret + 128;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955}
956
957static void setcontrast(struct gspca_dev *gspca_dev)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300961 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962}
963
964static void getcontrast(struct gspca_dev *gspca_dev)
965{
966 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300967 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300969 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300970 if (ret >= 0)
971 sd->contrast = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300972}
973
974static void setcolors(struct gspca_dev *gspca_dev)
975{
976 struct sd *sd = (struct sd *) gspca_dev;
977
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300978 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979}
980
981static void getcolors(struct gspca_dev *gspca_dev)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300984 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300986 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300987 if (ret >= 0)
988 sd->colors = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989}
990
991static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 sd->brightness = val;
996 if (gspca_dev->streaming)
997 setbrightness(gspca_dev);
998 return 0;
999}
1000
1001static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1002{
1003 struct sd *sd = (struct sd *) gspca_dev;
1004
1005 getbrightness(gspca_dev);
1006 *val = sd->brightness;
1007 return 0;
1008}
1009
1010static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1011{
1012 struct sd *sd = (struct sd *) gspca_dev;
1013
1014 sd->contrast = val;
1015 if (gspca_dev->streaming)
1016 setcontrast(gspca_dev);
1017 return 0;
1018}
1019
1020static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1021{
1022 struct sd *sd = (struct sd *) gspca_dev;
1023
1024 getcontrast(gspca_dev);
1025 *val = sd->contrast;
1026 return 0;
1027}
1028
1029static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1030{
1031 struct sd *sd = (struct sd *) gspca_dev;
1032
1033 sd->colors = val;
1034 if (gspca_dev->streaming)
1035 setcolors(gspca_dev);
1036 return 0;
1037}
1038
1039static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1040{
1041 struct sd *sd = (struct sd *) gspca_dev;
1042
1043 getcolors(gspca_dev);
1044 *val = sd->colors;
1045 return 0;
1046}
1047
1048/* sub-driver description */
1049static struct sd_desc sd_desc = {
1050 .name = MODULE_NAME,
1051 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001052 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 .config = sd_config,
1054 .open = sd_open,
1055 .start = sd_start,
1056 .stopN = sd_stopN,
1057 .stop0 = sd_stop0,
1058 .close = sd_close,
1059 .pkt_scan = sd_pkt_scan,
1060};
1061
1062/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001063static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -03001064 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1065 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1066 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1067 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1068 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1069 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1070 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1071 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1072 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1073 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1074 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1075 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1076 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1077 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1078 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001079 {}
1080};
1081MODULE_DEVICE_TABLE(usb, device_table);
1082
1083/* -- device connect -- */
1084static int sd_probe(struct usb_interface *intf,
1085 const struct usb_device_id *id)
1086{
1087 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1088 THIS_MODULE);
1089}
1090
1091static struct usb_driver sd_driver = {
1092 .name = MODULE_NAME,
1093 .id_table = device_table,
1094 .probe = sd_probe,
1095 .disconnect = gspca_disconnect,
1096};
1097
1098/* -- module insert / remove -- */
1099static int __init sd_mod_init(void)
1100{
1101 if (usb_register(&sd_driver) < 0)
1102 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001103 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001104 return 0;
1105}
1106static void __exit sd_mod_exit(void)
1107{
1108 usb_deregister(&sd_driver);
1109 PDEBUG(D_PROBE, "deregistered");
1110}
1111
1112module_init(sd_mod_init);
1113module_exit(sd_mod_exit);