blob: e00f3b53bdff6bed5ffd557522390f2e6a4376f5 [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"
Jean-Francois Moine36e819d2009-01-07 16:49:57 -030025#define QUANT_VAL 5 /* quantization table */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030026#include "jpeg.h"
27
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030028MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030036 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030037 /* !! no more than 128 ff in an ISO packet */
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043 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 Moinecc611b82008-12-29 07:49:41 -0300114static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300115 {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 Moinecc611b82008-12-29 07:49:41 -0300127static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300128 {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 Moine9d64fdb2008-07-25 08:53:03 -0300632 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633 if (sd->subtype != LogitechClickSmart310) {
634 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300635 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636 } else {
637 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300638 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300640 sd->brightness = BRIGHTNESS_DEF;
641 sd->contrast = CONTRAST_DEF;
642 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 return 0;
644}
645
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300646/* this function is called at probe and resume time */
647static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648{
649 struct sd *sd = (struct sd *) gspca_dev;
650
651 /* initialisation of spca500 based cameras is deferred */
652 PDEBUG(D_STREAM, "SPCA500 init");
653 if (sd->subtype == LogitechClickSmart310)
654 spca500_clksmart310_init(gspca_dev);
655/* else
656 spca500_initialise(gspca_dev); */
657 PDEBUG(D_STREAM, "SPCA500 init done");
658 return 0;
659}
660
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300661static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662{
663 struct sd *sd = (struct sd *) gspca_dev;
664 int err;
665 __u8 Data;
666 __u8 xmult, ymult;
667
668 if (sd->subtype == LogitechClickSmart310) {
669 xmult = 0x16;
670 ymult = 0x12;
671 } else {
672 xmult = 0x28;
673 ymult = 0x1e;
674 }
675
676 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300677 reg_r(gspca_dev, 0x8a04, 1);
678 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
679 gspca_dev->usb_buf[0]);
680 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681 gspca_dev->curr_mode, xmult, ymult);
682
683 /* setup qtable */
684 switch (sd->subtype) {
685 case LogitechClickSmart310:
686 spca500_setmode(gspca_dev, xmult, ymult);
687
688 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
690 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 err = spca50x_setup_qtable(gspca_dev,
692 0x00, 0x8800, 0x8840,
693 qtable_creative_pccam);
694 if (err < 0)
695 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
696 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300697 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698
699 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300702 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300703 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300705 reg_r(gspca_dev, 0x816b, 1);
706 Data = gspca_dev->usb_buf[0];
707 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708
709 spca500_synch310(gspca_dev);
710
711 write_vector(gspca_dev, spca500_visual_defaults);
712 spca500_setmode(gspca_dev, xmult, ymult);
713 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300715 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300716 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 err = spca50x_setup_qtable(gspca_dev,
718 0x00, 0x8800, 0x8840,
719 qtable_creative_pccam);
720 if (err < 0)
721 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
722
723 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300724 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725
726 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300727 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300729 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300730 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300732 reg_r(gspca_dev, 0x816b, 1);
733 Data = gspca_dev->usb_buf[0];
734 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735 break;
736 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
737 case IntelPocketPCCamera: /* FIXME: Temporary fix for
738 * Intel Pocket PC Camera
739 * - NWG (Sat 29th March 2003) */
740
741 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300742 err = spca500_full_reset(gspca_dev);
743 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744 PDEBUG(D_ERR, "spca500_full_reset failed");
745
746 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300747 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748 if (err < 0)
749 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300750 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 err = spca50x_setup_qtable(gspca_dev,
752 0x00, 0x8800, 0x8840,
753 qtable_creative_pccam);
754 if (err < 0)
755 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
756
757 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300758 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759
760 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300761 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300764 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300766 reg_r(gspca_dev, 0x816b, 1);
767 Data = gspca_dev->usb_buf[0];
768 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300770/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 break;
772 case KodakEZ200: /* Kodak EZ200 */
773
774 /* do a full reset */
775 err = spca500_full_reset(gspca_dev);
776 if (err < 0)
777 PDEBUG(D_ERR, "spca500_full_reset failed");
778 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300779 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
780 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 err = spca50x_setup_qtable(gspca_dev,
782 0x00, 0x8800, 0x8840,
783 qtable_kodak_ez200);
784 if (err < 0)
785 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
786 spca500_setmode(gspca_dev, xmult, ymult);
787
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300788 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789
790 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300791 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300793 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300794 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300795
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300796 reg_r(gspca_dev, 0x816b, 1);
797 Data = gspca_dev->usb_buf[0];
798 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300800/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801 break;
802
803 case BenqDC1016:
804 case DLinkDSC350: /* FamilyCam 300 */
805 case AiptekPocketDV: /* Aiptek PocketDV */
806 case Gsmartmini: /*Mustek Gsmart Mini */
807 case MustekGsmart300: /* Mustek Gsmart 300 */
808 case PalmPixDC85:
809 case Optimedia:
810 case ToptroIndus:
811 case AgfaCl20:
812 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300813 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814 /* 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
817 err = spca50x_setup_qtable(gspca_dev,
818 0x00, 0x8800, 0x8840, qtable_pocketdv);
819 if (err < 0)
820 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300821 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822
823 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300826 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300828 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300830 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300832 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300836 reg_r(gspca_dev, 0x816b, 1);
837 Data = gspca_dev->usb_buf[0];
838 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839 break;
840 case LogitechTraveler:
841 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300842 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845
846 err = spca50x_setup_qtable(gspca_dev,
847 0x00, 0x8800,
848 0x8840, qtable_creative_pccam);
849 if (err < 0)
850 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300851 reg_w(gspca_dev, 0x00, 0x8880, 3);
852 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300854 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855
856 spca500_setmode(gspca_dev, xmult, ymult);
857
858 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300859 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
860 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300861
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300862 reg_r(gspca_dev, 0x816b, 1);
863 Data = gspca_dev->usb_buf[0];
864 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 write_vector(gspca_dev, Clicksmart510_defaults);
866 break;
867 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300868 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869}
870
871static void sd_stopN(struct gspca_dev *gspca_dev)
872{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300873 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874
875 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300876 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
877 reg_r(gspca_dev, 0x8000, 1);
878 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
879 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880}
881
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882static void sd_pkt_scan(struct gspca_dev *gspca_dev,
883 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300884 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 int len) /* iso packet length */
886{
887 struct sd *sd = (struct sd *) gspca_dev;
888 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300889 __u8 *s, *d;
890 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300891
892/* frames are jpeg 4.1.1 without 0xff escape */
893 if (data[0] == 0xff) {
894 if (data[1] != 0x01) { /* drop packet */
895/* gspca_dev->last_packet_type = DISCARD_PACKET; */
896 return;
897 }
898 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
899 ffd9, 2);
900
901 /* put the JPEG header in the new frame */
Jean-Francois Moine36e819d2009-01-07 16:49:57 -0300902 jpeg_put_header(gspca_dev, frame, 0x22);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903
904 data += SPCA500_OFFSET_DATA;
905 len -= SPCA500_OFFSET_DATA;
906 } else {
907 data += 1;
908 len -= 1;
909 }
910
911 /* add 0x00 after 0xff */
912 for (i = len; --i >= 0; )
913 if (data[i] == 0xff)
914 break;
915 if (i < 0) { /* no 0xff */
916 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
917 return;
918 }
919 s = data;
920 d = sd->packet;
921 for (i = 0; i < len; i++) {
922 *d++ = *s++;
923 if (s[-1] == 0xff)
924 *d++ = 0x00;
925 }
926 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
927 sd->packet, d - sd->packet);
928}
929
930static void setbrightness(struct gspca_dev *gspca_dev)
931{
932 struct sd *sd = (struct sd *) gspca_dev;
933
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300934 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 (__u8) (sd->brightness - 128));
936}
937
938static void getbrightness(struct gspca_dev *gspca_dev)
939{
940 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300941 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300943 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300944 if (ret >= 0)
945 sd->brightness = ret + 128;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946}
947
948static void setcontrast(struct gspca_dev *gspca_dev)
949{
950 struct sd *sd = (struct sd *) gspca_dev;
951
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953}
954
955static void getcontrast(struct gspca_dev *gspca_dev)
956{
957 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300958 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300960 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300961 if (ret >= 0)
962 sd->contrast = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963}
964
965static void setcolors(struct gspca_dev *gspca_dev)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
968
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300969 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970}
971
972static void getcolors(struct gspca_dev *gspca_dev)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300975 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300977 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300978 if (ret >= 0)
979 sd->colors = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980}
981
982static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
985
986 sd->brightness = val;
987 if (gspca_dev->streaming)
988 setbrightness(gspca_dev);
989 return 0;
990}
991
992static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
993{
994 struct sd *sd = (struct sd *) gspca_dev;
995
996 getbrightness(gspca_dev);
997 *val = sd->brightness;
998 return 0;
999}
1000
1001static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1002{
1003 struct sd *sd = (struct sd *) gspca_dev;
1004
1005 sd->contrast = val;
1006 if (gspca_dev->streaming)
1007 setcontrast(gspca_dev);
1008 return 0;
1009}
1010
1011static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1012{
1013 struct sd *sd = (struct sd *) gspca_dev;
1014
1015 getcontrast(gspca_dev);
1016 *val = sd->contrast;
1017 return 0;
1018}
1019
1020static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1021{
1022 struct sd *sd = (struct sd *) gspca_dev;
1023
1024 sd->colors = val;
1025 if (gspca_dev->streaming)
1026 setcolors(gspca_dev);
1027 return 0;
1028}
1029
1030static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1031{
1032 struct sd *sd = (struct sd *) gspca_dev;
1033
1034 getcolors(gspca_dev);
1035 *val = sd->colors;
1036 return 0;
1037}
1038
1039/* sub-driver description */
1040static struct sd_desc sd_desc = {
1041 .name = MODULE_NAME,
1042 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001043 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001045 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 .start = sd_start,
1047 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001048 .pkt_scan = sd_pkt_scan,
1049};
1050
1051/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001052static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -03001053 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1054 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1055 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1056 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1057 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1058 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1059 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1060 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1061 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1062 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1063 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1064 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1065 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1066 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1067 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068 {}
1069};
1070MODULE_DEVICE_TABLE(usb, device_table);
1071
1072/* -- device connect -- */
1073static int sd_probe(struct usb_interface *intf,
1074 const struct usb_device_id *id)
1075{
1076 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1077 THIS_MODULE);
1078}
1079
1080static struct usb_driver sd_driver = {
1081 .name = MODULE_NAME,
1082 .id_table = device_table,
1083 .probe = sd_probe,
1084 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001085#ifdef CONFIG_PM
1086 .suspend = gspca_suspend,
1087 .resume = gspca_resume,
1088#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089};
1090
1091/* -- module insert / remove -- */
1092static int __init sd_mod_init(void)
1093{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001094 int ret;
1095 ret = usb_register(&sd_driver);
1096 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001097 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001098 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001099 return 0;
1100}
1101static void __exit sd_mod_exit(void)
1102{
1103 usb_deregister(&sd_driver);
1104 PDEBUG(D_PROBE, "deregistered");
1105}
1106
1107module_init(sd_mod_init);
1108module_exit(sd_mod_exit);