blob: 8c83823745f05e7f0496c0260e311cbe44866fd0 [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;
630 __u16 vendor;
631 __u16 product;
632
633 vendor = id->idVendor;
634 product = id->idProduct;
635 switch (vendor) {
636 case 0x040a: /* Kodak cameras */
637/* switch (product) { */
638/* case 0x0300: */
639 sd->subtype = KodakEZ200;
640/* break; */
641/* } */
642 break;
643 case 0x041e: /* Creative cameras */
644/* switch (product) { */
645/* case 0x400a: */
646 sd->subtype = CreativePCCam300;
647/* break; */
648/* } */
649 break;
650 case 0x046d: /* Logitech Labtec */
651 switch (product) {
652 case 0x0890:
653 sd->subtype = LogitechTraveler;
654 break;
655 case 0x0900:
656 sd->subtype = LogitechClickSmart310;
657 break;
658 case 0x0901:
659 sd->subtype = LogitechClickSmart510;
660 break;
661 }
662 break;
663 case 0x04a5: /* Benq */
664/* switch (product) { */
665/* case 0x300c: */
666 sd->subtype = BenqDC1016;
667/* break; */
668/* } */
669 break;
670 case 0x04fc: /* SunPlus */
671/* switch (product) { */
672/* case 0x7333: */
673 sd->subtype = PalmPixDC85;
674/* break; */
675/* } */
676 break;
677 case 0x055f: /* Mustek cameras */
678 switch (product) {
679 case 0xc200:
680 sd->subtype = MustekGsmart300;
681 break;
682 case 0xc220:
683 sd->subtype = Gsmartmini;
684 break;
685 }
686 break;
687 case 0x06bd: /* Agfa Cl20 */
688/* switch (product) { */
689/* case 0x0404: */
690 sd->subtype = AgfaCl20;
691/* break; */
692/* } */
693 break;
694 case 0x06be: /* Optimedia */
695/* switch (product) { */
696/* case 0x0800: */
697 sd->subtype = Optimedia;
698/* break; */
699/* } */
700 break;
701 case 0x084d: /* D-Link / Minton */
702/* switch (product) { */
703/* case 0x0003: * DSC-350 / S-Cam F5 */
704 sd->subtype = DLinkDSC350;
705/* break; */
706/* } */
707 break;
708 case 0x08ca: /* Aiptek */
709/* switch (product) { */
710/* case 0x0103: */
711 sd->subtype = AiptekPocketDV;
712/* break; */
713/* } */
714 break;
715 case 0x2899: /* ToptroIndustrial */
716/* switch (product) { */
717/* case 0x012c: */
718 sd->subtype = ToptroIndus;
719/* break; */
720/* } */
721 break;
722 case 0x8086: /* Intel */
723/* switch (product) { */
724/* case 0x0630: * Pocket PC Camera */
725 sd->subtype = IntelPocketPCCamera;
726/* break; */
727/* } */
728 break;
729 }
730 cam = &gspca_dev->cam;
731 cam->dev_name = (char *) id->driver_info;
732 cam->epaddr = 0x01;
733 if (sd->subtype != LogitechClickSmart310) {
734 cam->cam_mode = vga_mode;
735 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
736 } else {
737 cam->cam_mode = sif_mode;
738 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
739 }
740 sd->qindex = 5;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300741 sd->brightness = BRIGHTNESS_DEF;
742 sd->contrast = CONTRAST_DEF;
743 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744 return 0;
745}
746
747/* this function is called at open time */
748static int sd_open(struct gspca_dev *gspca_dev)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 /* initialisation of spca500 based cameras is deferred */
753 PDEBUG(D_STREAM, "SPCA500 init");
754 if (sd->subtype == LogitechClickSmart310)
755 spca500_clksmart310_init(gspca_dev);
756/* else
757 spca500_initialise(gspca_dev); */
758 PDEBUG(D_STREAM, "SPCA500 init done");
759 return 0;
760}
761
762static void sd_start(struct gspca_dev *gspca_dev)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 int err;
766 __u8 Data;
767 __u8 xmult, ymult;
768
769 if (sd->subtype == LogitechClickSmart310) {
770 xmult = 0x16;
771 ymult = 0x12;
772 } else {
773 xmult = 0x28;
774 ymult = 0x1e;
775 }
776
777 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300778 reg_r(gspca_dev, 0x8a04, 1);
779 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
780 gspca_dev->usb_buf[0]);
781 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 gspca_dev->curr_mode, xmult, ymult);
783
784 /* setup qtable */
785 switch (sd->subtype) {
786 case LogitechClickSmart310:
787 spca500_setmode(gspca_dev, xmult, ymult);
788
789 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
791 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 err = spca50x_setup_qtable(gspca_dev,
793 0x00, 0x8800, 0x8840,
794 qtable_creative_pccam);
795 if (err < 0)
796 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
797 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300798 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799
800 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300801 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300802 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300803 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300804 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300806 reg_r(gspca_dev, 0x816b, 1);
807 Data = gspca_dev->usb_buf[0];
808 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809
810 spca500_synch310(gspca_dev);
811
812 write_vector(gspca_dev, spca500_visual_defaults);
813 spca500_setmode(gspca_dev, xmult, ymult);
814 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300815 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300816 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300817 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 err = spca50x_setup_qtable(gspca_dev,
819 0x00, 0x8800, 0x8840,
820 qtable_creative_pccam);
821 if (err < 0)
822 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
823
824 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300825 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826
827 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300828 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300830 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300831 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300833 reg_r(gspca_dev, 0x816b, 1);
834 Data = gspca_dev->usb_buf[0];
835 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300836 break;
837 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
838 case IntelPocketPCCamera: /* FIXME: Temporary fix for
839 * Intel Pocket PC Camera
840 * - NWG (Sat 29th March 2003) */
841
842 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300843 err = spca500_full_reset(gspca_dev);
844 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 PDEBUG(D_ERR, "spca500_full_reset failed");
846
847 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300848 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 if (err < 0)
850 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300851 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 err = spca50x_setup_qtable(gspca_dev,
853 0x00, 0x8800, 0x8840,
854 qtable_creative_pccam);
855 if (err < 0)
856 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
857
858 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300859 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860
861 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300862 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300864 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300865 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300867 reg_r(gspca_dev, 0x816b, 1);
868 Data = gspca_dev->usb_buf[0];
869 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300871/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872 break;
873 case KodakEZ200: /* Kodak EZ200 */
874
875 /* do a full reset */
876 err = spca500_full_reset(gspca_dev);
877 if (err < 0)
878 PDEBUG(D_ERR, "spca500_full_reset failed");
879 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300880 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
881 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882 err = spca50x_setup_qtable(gspca_dev,
883 0x00, 0x8800, 0x8840,
884 qtable_kodak_ez200);
885 if (err < 0)
886 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
887 spca500_setmode(gspca_dev, xmult, ymult);
888
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300889 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890
891 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300892 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300894 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300895 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300897 reg_r(gspca_dev, 0x816b, 1);
898 Data = gspca_dev->usb_buf[0];
899 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300901/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902 break;
903
904 case BenqDC1016:
905 case DLinkDSC350: /* FamilyCam 300 */
906 case AiptekPocketDV: /* Aiptek PocketDV */
907 case Gsmartmini: /*Mustek Gsmart Mini */
908 case MustekGsmart300: /* Mustek Gsmart 300 */
909 case PalmPixDC85:
910 case Optimedia:
911 case ToptroIndus:
912 case AgfaCl20:
913 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300914 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300916 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917
918 err = spca50x_setup_qtable(gspca_dev,
919 0x00, 0x8800, 0x8840, qtable_pocketdv);
920 if (err < 0)
921 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300922 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923
924 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300925 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300927 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300929 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300931 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300933 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300935 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300937 reg_r(gspca_dev, 0x816b, 1);
938 Data = gspca_dev->usb_buf[0];
939 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 break;
941 case LogitechTraveler:
942 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300943 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300945 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946
947 err = spca50x_setup_qtable(gspca_dev,
948 0x00, 0x8800,
949 0x8840, qtable_creative_pccam);
950 if (err < 0)
951 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 reg_w(gspca_dev, 0x00, 0x8880, 3);
953 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300954 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300955 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956
957 spca500_setmode(gspca_dev, xmult, ymult);
958
959 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300960 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
961 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300963 reg_r(gspca_dev, 0x816b, 1);
964 Data = gspca_dev->usb_buf[0];
965 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 write_vector(gspca_dev, Clicksmart510_defaults);
967 break;
968 }
969}
970
971static void sd_stopN(struct gspca_dev *gspca_dev)
972{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300973 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300974
975 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300976 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
977 reg_r(gspca_dev, 0x8000, 1);
978 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
979 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980}
981
982static void sd_stop0(struct gspca_dev *gspca_dev)
983{
984}
985
986static void sd_close(struct gspca_dev *gspca_dev)
987{
988}
989
990static void sd_pkt_scan(struct gspca_dev *gspca_dev,
991 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300992 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 int len) /* iso packet length */
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300997 __u8 *s, *d;
998 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999
1000/* frames are jpeg 4.1.1 without 0xff escape */
1001 if (data[0] == 0xff) {
1002 if (data[1] != 0x01) { /* drop packet */
1003/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1004 return;
1005 }
1006 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1007 ffd9, 2);
1008
1009 /* put the JPEG header in the new frame */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001010 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011
1012 data += SPCA500_OFFSET_DATA;
1013 len -= SPCA500_OFFSET_DATA;
1014 } else {
1015 data += 1;
1016 len -= 1;
1017 }
1018
1019 /* add 0x00 after 0xff */
1020 for (i = len; --i >= 0; )
1021 if (data[i] == 0xff)
1022 break;
1023 if (i < 0) { /* no 0xff */
1024 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1025 return;
1026 }
1027 s = data;
1028 d = sd->packet;
1029 for (i = 0; i < len; i++) {
1030 *d++ = *s++;
1031 if (s[-1] == 0xff)
1032 *d++ = 0x00;
1033 }
1034 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1035 sd->packet, d - sd->packet);
1036}
1037
1038static void setbrightness(struct gspca_dev *gspca_dev)
1039{
1040 struct sd *sd = (struct sd *) gspca_dev;
1041
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001042 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001043 (__u8) (sd->brightness - 128));
1044}
1045
1046static void getbrightness(struct gspca_dev *gspca_dev)
1047{
1048 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001049 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001051 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001052 if (ret >= 0)
1053 sd->brightness = ret + 128;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054}
1055
1056static void setcontrast(struct gspca_dev *gspca_dev)
1057{
1058 struct sd *sd = (struct sd *) gspca_dev;
1059
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001060 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001061}
1062
1063static void getcontrast(struct gspca_dev *gspca_dev)
1064{
1065 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001066 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001067
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001068 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001069 if (ret >= 0)
1070 sd->contrast = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071}
1072
1073static void setcolors(struct gspca_dev *gspca_dev)
1074{
1075 struct sd *sd = (struct sd *) gspca_dev;
1076
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001077 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001078}
1079
1080static void getcolors(struct gspca_dev *gspca_dev)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001083 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001084
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001085 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001086 if (ret >= 0)
1087 sd->colors = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001088}
1089
1090static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1091{
1092 struct sd *sd = (struct sd *) gspca_dev;
1093
1094 sd->brightness = val;
1095 if (gspca_dev->streaming)
1096 setbrightness(gspca_dev);
1097 return 0;
1098}
1099
1100static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 getbrightness(gspca_dev);
1105 *val = sd->brightness;
1106 return 0;
1107}
1108
1109static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1110{
1111 struct sd *sd = (struct sd *) gspca_dev;
1112
1113 sd->contrast = val;
1114 if (gspca_dev->streaming)
1115 setcontrast(gspca_dev);
1116 return 0;
1117}
1118
1119static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1120{
1121 struct sd *sd = (struct sd *) gspca_dev;
1122
1123 getcontrast(gspca_dev);
1124 *val = sd->contrast;
1125 return 0;
1126}
1127
1128static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1129{
1130 struct sd *sd = (struct sd *) gspca_dev;
1131
1132 sd->colors = val;
1133 if (gspca_dev->streaming)
1134 setcolors(gspca_dev);
1135 return 0;
1136}
1137
1138static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1139{
1140 struct sd *sd = (struct sd *) gspca_dev;
1141
1142 getcolors(gspca_dev);
1143 *val = sd->colors;
1144 return 0;
1145}
1146
1147/* sub-driver description */
1148static struct sd_desc sd_desc = {
1149 .name = MODULE_NAME,
1150 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001151 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001152 .config = sd_config,
1153 .open = sd_open,
1154 .start = sd_start,
1155 .stopN = sd_stopN,
1156 .stop0 = sd_stop0,
1157 .close = sd_close,
1158 .pkt_scan = sd_pkt_scan,
1159};
1160
1161/* -- module initialisation -- */
1162#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001163static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001164 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1165 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1166 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1167 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1168 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1169 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1170 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1171 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1172 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1173 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1174 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1175 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1176 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1177 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1178 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1179 {}
1180};
1181MODULE_DEVICE_TABLE(usb, device_table);
1182
1183/* -- device connect -- */
1184static int sd_probe(struct usb_interface *intf,
1185 const struct usb_device_id *id)
1186{
1187 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1188 THIS_MODULE);
1189}
1190
1191static struct usb_driver sd_driver = {
1192 .name = MODULE_NAME,
1193 .id_table = device_table,
1194 .probe = sd_probe,
1195 .disconnect = gspca_disconnect,
1196};
1197
1198/* -- module insert / remove -- */
1199static int __init sd_mod_init(void)
1200{
1201 if (usb_register(&sd_driver) < 0)
1202 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001203 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001204 return 0;
1205}
1206static void __exit sd_mod_exit(void)
1207{
1208 usb_deregister(&sd_driver);
1209 PDEBUG(D_PROBE, "deregistered");
1210}
1211
1212module_init(sd_mod_init);
1213module_exit(sd_mod_exit);