blob: d00f0f76e0e3cd1bd24559b917a7da598893e373 [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 Moinec2446b32008-07-05 11:49:20 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
28static const char version[] = "2.1.5";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030038 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030039 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44
45 char qindex;
46 char subtype;
47#define AgfaCl20 0
48#define AiptekPocketDV 1
49#define BenqDC1016 2
50#define CreativePCCam300 3
51#define DLinkDSC350 4
52#define Gsmartmini 5
53#define IntelPocketPCCamera 6
54#define KodakEZ200 7
55#define LogitechClickSmart310 8
56#define LogitechClickSmart510 9
57#define LogitechTraveler 10
58#define MustekGsmart300 11
59#define Optimedia 12
60#define PalmPixDC85 13
61#define ToptroIndus 14
62};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030079 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030080 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081#define BRIGHTNESS_DEF 127
82 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030093 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030094 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095#define CONTRAST_DEF 31
96 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300107 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109#define COLOR_DEF 31
110 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115};
116
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240 * 3 / 8 + 590,
121 .colorspace = V4L2_COLORSPACE_JPEG,
122 .priv = 1},
123 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480 * 3 / 8 + 590,
126 .colorspace = V4L2_COLORSPACE_JPEG,
127 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300128};
129
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144 * 3 / 8 + 590,
134 .colorspace = V4L2_COLORSPACE_JPEG,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
140 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300141};
142
143/* Frame packet header offsets for the spca500 */
144#define SPCA500_OFFSET_PADDINGLB 2
145#define SPCA500_OFFSET_PADDINGHB 3
146#define SPCA500_OFFSET_MODE 4
147#define SPCA500_OFFSET_IMGWIDTH 5
148#define SPCA500_OFFSET_IMGHEIGHT 6
149#define SPCA500_OFFSET_IMGMODE 7
150#define SPCA500_OFFSET_QTBLINDEX 8
151#define SPCA500_OFFSET_FRAMSEQ 9
152#define SPCA500_OFFSET_CDSPINFO 10
153#define SPCA500_OFFSET_GPIO 11
154#define SPCA500_OFFSET_AUGPIO 12
155#define SPCA500_OFFSET_DATA 16
156
157
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300158static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300159 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
160 * hue (H byte) = 0,
161 * saturation/hue enable,
162 * brightness/contrast enable.
163 */
164 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
165 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
166 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
167 * hue (H byte) = 0, saturation/hue enable,
168 * brightness/contrast enable.
169 * was 0x0003, now 0x0000.
170 */
171 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
172 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
173 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
174 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
175 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
176 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
177 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
178 {0x0c, 0x0004, 0x0000},
179 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300180 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300182static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183 {0x00, 0x00, 0x8211},
184 {0x00, 0x01, 0x82c0},
185 {0x00, 0x10, 0x82cb},
186 {0x00, 0x0f, 0x800d},
187 {0x00, 0x82, 0x8225},
188 {0x00, 0x21, 0x8228},
189 {0x00, 0x00, 0x8203},
190 {0x00, 0x00, 0x8204},
191 {0x00, 0x08, 0x8205},
192 {0x00, 0xf8, 0x8206},
193 {0x00, 0x28, 0x8207},
194 {0x00, 0xa0, 0x8208},
195 {0x00, 0x08, 0x824a},
196 {0x00, 0x08, 0x8214},
197 {0x00, 0x80, 0x82c1},
198 {0x00, 0x00, 0x82c2},
199 {0x00, 0x00, 0x82ca},
200 {0x00, 0x80, 0x82c1},
201 {0x00, 0x04, 0x82c2},
202 {0x00, 0x00, 0x82ca},
203 {0x00, 0xfc, 0x8100},
204 {0x00, 0xfc, 0x8105},
205 {0x00, 0x30, 0x8101},
206 {0x00, 0x00, 0x8102},
207 {0x00, 0x00, 0x8103},
208 {0x00, 0x66, 0x8107},
209 {0x00, 0x00, 0x816b},
210 {0x00, 0x00, 0x8155},
211 {0x00, 0x01, 0x8156},
212 {0x00, 0x60, 0x8157},
213 {0x00, 0x40, 0x8158},
214 {0x00, 0x0a, 0x8159},
215 {0x00, 0x06, 0x815a},
216 {0x00, 0x00, 0x813f},
217 {0x00, 0x00, 0x8200},
218 {0x00, 0x19, 0x8201},
219 {0x00, 0x00, 0x82c1},
220 {0x00, 0xa0, 0x82c2},
221 {0x00, 0x00, 0x82ca},
222 {0x00, 0x00, 0x8117},
223 {0x00, 0x00, 0x8118},
224 {0x00, 0x65, 0x8119},
225 {0x00, 0x00, 0x811a},
226 {0x00, 0x00, 0x811b},
227 {0x00, 0x55, 0x811c},
228 {0x00, 0x65, 0x811d},
229 {0x00, 0x55, 0x811e},
230 {0x00, 0x16, 0x811f},
231 {0x00, 0x19, 0x8120},
232 {0x00, 0x80, 0x8103},
233 {0x00, 0x83, 0x816b},
234 {0x00, 0x25, 0x8168},
235 {0x00, 0x01, 0x820f},
236 {0x00, 0xff, 0x8115},
237 {0x00, 0x48, 0x8116},
238 {0x00, 0x50, 0x8151},
239 {0x00, 0x40, 0x8152},
240 {0x00, 0x78, 0x8153},
241 {0x00, 0x40, 0x8154},
242 {0x00, 0x00, 0x8167},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x00, 0x816a},
245 {0x00, 0x03, 0x816b},
246 {0x00, 0x20, 0x8169},
247 {0x00, 0x60, 0x8157},
248 {0x00, 0x00, 0x8190},
249 {0x00, 0x00, 0x81a1},
250 {0x00, 0x00, 0x81b2},
251 {0x00, 0x27, 0x8191},
252 {0x00, 0x27, 0x81a2},
253 {0x00, 0x27, 0x81b3},
254 {0x00, 0x4b, 0x8192},
255 {0x00, 0x4b, 0x81a3},
256 {0x00, 0x4b, 0x81b4},
257 {0x00, 0x66, 0x8193},
258 {0x00, 0x66, 0x81a4},
259 {0x00, 0x66, 0x81b5},
260 {0x00, 0x79, 0x8194},
261 {0x00, 0x79, 0x81a5},
262 {0x00, 0x79, 0x81b6},
263 {0x00, 0x8a, 0x8195},
264 {0x00, 0x8a, 0x81a6},
265 {0x00, 0x8a, 0x81b7},
266 {0x00, 0x9b, 0x8196},
267 {0x00, 0x9b, 0x81a7},
268 {0x00, 0x9b, 0x81b8},
269 {0x00, 0xa6, 0x8197},
270 {0x00, 0xa6, 0x81a8},
271 {0x00, 0xa6, 0x81b9},
272 {0x00, 0xb2, 0x8198},
273 {0x00, 0xb2, 0x81a9},
274 {0x00, 0xb2, 0x81ba},
275 {0x00, 0xbe, 0x8199},
276 {0x00, 0xbe, 0x81aa},
277 {0x00, 0xbe, 0x81bb},
278 {0x00, 0xc8, 0x819a},
279 {0x00, 0xc8, 0x81ab},
280 {0x00, 0xc8, 0x81bc},
281 {0x00, 0xd2, 0x819b},
282 {0x00, 0xd2, 0x81ac},
283 {0x00, 0xd2, 0x81bd},
284 {0x00, 0xdb, 0x819c},
285 {0x00, 0xdb, 0x81ad},
286 {0x00, 0xdb, 0x81be},
287 {0x00, 0xe4, 0x819d},
288 {0x00, 0xe4, 0x81ae},
289 {0x00, 0xe4, 0x81bf},
290 {0x00, 0xed, 0x819e},
291 {0x00, 0xed, 0x81af},
292 {0x00, 0xed, 0x81c0},
293 {0x00, 0xf7, 0x819f},
294 {0x00, 0xf7, 0x81b0},
295 {0x00, 0xf7, 0x81c1},
296 {0x00, 0xff, 0x81a0},
297 {0x00, 0xff, 0x81b1},
298 {0x00, 0xff, 0x81c2},
299 {0x00, 0x03, 0x8156},
300 {0x00, 0x00, 0x8211},
301 {0x00, 0x20, 0x8168},
302 {0x00, 0x01, 0x8202},
303 {0x00, 0x30, 0x8101},
304 {0x00, 0x00, 0x8111},
305 {0x00, 0x00, 0x8112},
306 {0x00, 0x00, 0x8113},
307 {0x00, 0x00, 0x8114},
308 {}
309};
310
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300311static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312 { /* Q-table Y-components */
313 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
314 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
315 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
316 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
317 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
318 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
319 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
320 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
321 { /* Q-table C-components */
322 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
329 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
330};
331
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300332static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300333 { /* Q-table Y-components */
334 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
335 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
336 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
337 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
338 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
339 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
340 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
341 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
342 { /* Q-table C-components */
343 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
350 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
351};
352
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300353static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300354 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300355 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
356 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
357 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
358 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
359 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
360 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
361 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
362 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
363 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300364 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300365 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
366 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
367 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
372 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
373};
374
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300375static void reg_r(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376 __u16 index,
377 __u8 *buffer, __u16 length)
378{
379 usb_control_msg(dev,
380 usb_rcvctrlpipe(dev, 0),
381 0,
382 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
383 0, /* value */
384 index, buffer, length, 500);
385}
386
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300387static int reg_w(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388 __u16 req, __u16 index, __u16 value)
389{
390 int ret;
391
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300392 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393 ret = usb_control_msg(dev,
394 usb_sndctrlpipe(dev, 0),
395 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300396 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300397 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300398 if (ret < 0)
399 PDEBUG(D_ERR, "reg write: error %d", ret);
400 return ret;
401}
402
403/* returns: negative is error, pos or zero is data */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300404static int reg_r_12(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300405 __u16 req, /* bRequest */
406 __u16 index, /* wIndex */
407 __u16 length) /* wLength (1 or 2 only) */
408{
409 int ret;
410 __u8 buf[2];
411
412 buf[1] = 0;
413 ret = usb_control_msg(dev,
414 usb_rcvctrlpipe(dev, 0),
415 req,
416 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
417 0, /* value */
418 index,
419 buf, length,
420 500); /* timeout */
421 if (ret < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300422 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300423 return -1;
424 }
425 return (buf[1] << 8) + buf[0];
426}
427
428/*
429 * Simple function to wait for a given 8-bit value to be returned from
430 * a reg_read call.
431 * Returns: negative is error or timeout, zero is success.
432 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300433static int reg_r_wait(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300434 __u16 reg, __u16 index, __u16 value)
435{
436 int ret, cnt = 20;
437
438 while (--cnt > 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300439 ret = reg_r_12(dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300440 if (ret == value)
441 return 0;
442 msleep(50);
443 }
444 return -EIO;
445}
446
447static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300448 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300449{
450 struct usb_device *dev = gspca_dev->dev;
451 int ret, i = 0;
452
453 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300454 ret = reg_w(dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 if (ret < 0)
456 return ret;
457 i++;
458 }
459 return 0;
460}
461
462static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
463 unsigned int request,
464 unsigned int ybase,
465 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300466 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467{
468 struct usb_device *dev = gspca_dev->dev;
469 int i, err;
470
471 /* loop over y components */
472 for (i = 0; i < 64; i++) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300473 err = reg_w(dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300474 if (err < 0)
475 return err;
476 }
477
478 /* loop over c components */
479 for (i = 0; i < 64; i++) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300480 err = reg_w(dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300481 if (err < 0)
482 return err;
483 }
484 return 0;
485}
486
487static void spca500_ping310(struct gspca_dev *gspca_dev)
488{
489 __u8 Data[2];
490
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300491 reg_r(gspca_dev->dev, 0x0d04, Data, 2);
492 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493 Data[0], Data[1]);
494}
495
496static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
497{
498 __u8 Data[2];
499
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300500 reg_r(gspca_dev->dev, 0x0d05, Data, 2);
501 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
502 Data[0], Data[1]);
503 reg_w(gspca_dev->dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 spca500_ping310(gspca_dev);
505
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300506 reg_w(gspca_dev->dev, 0x00, 0x8168, 0x22);
507 reg_w(gspca_dev->dev, 0x00, 0x816a, 0xc0);
508 reg_w(gspca_dev->dev, 0x00, 0x816b, 0x0b);
509 reg_w(gspca_dev->dev, 0x00, 0x8169, 0x25);
510 reg_w(gspca_dev->dev, 0x00, 0x8157, 0x5b);
511 reg_w(gspca_dev->dev, 0x00, 0x8158, 0x5b);
512 reg_w(gspca_dev->dev, 0x00, 0x813f, 0x03);
513 reg_w(gspca_dev->dev, 0x00, 0x8151, 0x4a);
514 reg_w(gspca_dev->dev, 0x00, 0x8153, 0x78);
515 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516 /* 00 for adjust shutter */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300517 reg_w(gspca_dev->dev, 0x00, 0x0d02, 0x01);
518 reg_w(gspca_dev->dev, 0x00, 0x8169, 0x25);
519 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520}
521
522static void spca500_setmode(struct gspca_dev *gspca_dev,
523 __u8 xmult, __u8 ymult)
524{
525 int mode;
526
527 /* set x multiplier */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300528 reg_w(gspca_dev->dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529
530 /* set y multiplier */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300531 reg_w(gspca_dev->dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532
533 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300534 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300535 reg_w(gspca_dev->dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536}
537
538static int spca500_full_reset(struct gspca_dev *gspca_dev)
539{
540 int err;
541
542 /* send the reset command */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300543 err = reg_w(gspca_dev->dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544 if (err < 0)
545 return err;
546
547 /* wait for the reset to complete */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300548 err = reg_r_wait(gspca_dev->dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549 if (err < 0)
550 return err;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300551 err = reg_w(gspca_dev->dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300552 if (err < 0)
553 return err;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300554 err = reg_r_wait(gspca_dev->dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300556 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 return err;
558 }
559 /* all ok */
560 return 0;
561}
562
563/* Synchro the Bridge with sensor */
564/* Maybe that will work on all spca500 chip */
565/* because i only own a clicksmart310 try for that chip */
566/* using spca50x_set_packet_size() cause an Ooops here */
567/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
568/* up-port the same feature as in 2.4.x kernel */
569static int spca500_synch310(struct gspca_dev *gspca_dev)
570{
571 __u8 Data;
572
573 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
574 PDEBUG(D_ERR, "Set packet size: set interface error");
575 goto error;
576 }
577 spca500_ping310(gspca_dev);
578
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300579 reg_r(gspca_dev->dev, 0x0d00, &Data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580
581 /* need alt setting here */
582 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
583
584 /* Windoze use pipe with altsetting 6 why 7 here */
585 if (usb_set_interface(gspca_dev->dev,
586 gspca_dev->iface,
587 gspca_dev->alt) < 0) {
588 PDEBUG(D_ERR, "Set packet size: set interface error");
589 goto error;
590 }
591 return 0;
592error:
593 return -EBUSY;
594}
595
596static void spca500_reinit(struct gspca_dev *gspca_dev)
597{
598 int err;
599 __u8 Data;
600
601 /* some unknow command from Aiptek pocket dv and family300 */
602
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300603 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x01);
604 reg_w(gspca_dev->dev, 0x00, 0x0d03, 0x00);
605 reg_w(gspca_dev->dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300606
607 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300608 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300609
610 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
611 qtable_pocketdv);
612 if (err < 0)
613 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
614
615 /* set qtable index */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300616 reg_w(gspca_dev->dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 /* family cam Quicksmart stuff */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300618 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300620 reg_w(gspca_dev->dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300622 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623 /*Start init sequence or stream */
624
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300625 reg_w(gspca_dev->dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300627 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 msleep(2000);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300629 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
630 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
631 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632}
633
634/* this function is called at probe time */
635static int sd_config(struct gspca_dev *gspca_dev,
636 const struct usb_device_id *id)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 struct cam *cam;
640 __u16 vendor;
641 __u16 product;
642
643 vendor = id->idVendor;
644 product = id->idProduct;
645 switch (vendor) {
646 case 0x040a: /* Kodak cameras */
647/* switch (product) { */
648/* case 0x0300: */
649 sd->subtype = KodakEZ200;
650/* break; */
651/* } */
652 break;
653 case 0x041e: /* Creative cameras */
654/* switch (product) { */
655/* case 0x400a: */
656 sd->subtype = CreativePCCam300;
657/* break; */
658/* } */
659 break;
660 case 0x046d: /* Logitech Labtec */
661 switch (product) {
662 case 0x0890:
663 sd->subtype = LogitechTraveler;
664 break;
665 case 0x0900:
666 sd->subtype = LogitechClickSmart310;
667 break;
668 case 0x0901:
669 sd->subtype = LogitechClickSmart510;
670 break;
671 }
672 break;
673 case 0x04a5: /* Benq */
674/* switch (product) { */
675/* case 0x300c: */
676 sd->subtype = BenqDC1016;
677/* break; */
678/* } */
679 break;
680 case 0x04fc: /* SunPlus */
681/* switch (product) { */
682/* case 0x7333: */
683 sd->subtype = PalmPixDC85;
684/* break; */
685/* } */
686 break;
687 case 0x055f: /* Mustek cameras */
688 switch (product) {
689 case 0xc200:
690 sd->subtype = MustekGsmart300;
691 break;
692 case 0xc220:
693 sd->subtype = Gsmartmini;
694 break;
695 }
696 break;
697 case 0x06bd: /* Agfa Cl20 */
698/* switch (product) { */
699/* case 0x0404: */
700 sd->subtype = AgfaCl20;
701/* break; */
702/* } */
703 break;
704 case 0x06be: /* Optimedia */
705/* switch (product) { */
706/* case 0x0800: */
707 sd->subtype = Optimedia;
708/* break; */
709/* } */
710 break;
711 case 0x084d: /* D-Link / Minton */
712/* switch (product) { */
713/* case 0x0003: * DSC-350 / S-Cam F5 */
714 sd->subtype = DLinkDSC350;
715/* break; */
716/* } */
717 break;
718 case 0x08ca: /* Aiptek */
719/* switch (product) { */
720/* case 0x0103: */
721 sd->subtype = AiptekPocketDV;
722/* break; */
723/* } */
724 break;
725 case 0x2899: /* ToptroIndustrial */
726/* switch (product) { */
727/* case 0x012c: */
728 sd->subtype = ToptroIndus;
729/* break; */
730/* } */
731 break;
732 case 0x8086: /* Intel */
733/* switch (product) { */
734/* case 0x0630: * Pocket PC Camera */
735 sd->subtype = IntelPocketPCCamera;
736/* break; */
737/* } */
738 break;
739 }
740 cam = &gspca_dev->cam;
741 cam->dev_name = (char *) id->driver_info;
742 cam->epaddr = 0x01;
743 if (sd->subtype != LogitechClickSmart310) {
744 cam->cam_mode = vga_mode;
745 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
746 } else {
747 cam->cam_mode = sif_mode;
748 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
749 }
750 sd->qindex = 5;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300751 sd->brightness = BRIGHTNESS_DEF;
752 sd->contrast = CONTRAST_DEF;
753 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300754 return 0;
755}
756
757/* this function is called at open time */
758static int sd_open(struct gspca_dev *gspca_dev)
759{
760 struct sd *sd = (struct sd *) gspca_dev;
761
762 /* initialisation of spca500 based cameras is deferred */
763 PDEBUG(D_STREAM, "SPCA500 init");
764 if (sd->subtype == LogitechClickSmart310)
765 spca500_clksmart310_init(gspca_dev);
766/* else
767 spca500_initialise(gspca_dev); */
768 PDEBUG(D_STREAM, "SPCA500 init done");
769 return 0;
770}
771
772static void sd_start(struct gspca_dev *gspca_dev)
773{
774 struct sd *sd = (struct sd *) gspca_dev;
775 int err;
776 __u8 Data;
777 __u8 xmult, ymult;
778
779 if (sd->subtype == LogitechClickSmart310) {
780 xmult = 0x16;
781 ymult = 0x12;
782 } else {
783 xmult = 0x28;
784 ymult = 0x1e;
785 }
786
787 /* is there a sensor here ? */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300788 reg_r(gspca_dev->dev, 0x8a04, &Data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02X", Data);
790 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02X, Ymult: 0x%02X",
791 gspca_dev->curr_mode, xmult, ymult);
792
793 /* setup qtable */
794 switch (sd->subtype) {
795 case LogitechClickSmart310:
796 spca500_setmode(gspca_dev, xmult, ymult);
797
798 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300799 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
800 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801 err = spca50x_setup_qtable(gspca_dev,
802 0x00, 0x8800, 0x8840,
803 qtable_creative_pccam);
804 if (err < 0)
805 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
806 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300807 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808
809 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300810 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 msleep(500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300812 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
813 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300815 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
816 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817
818 spca500_synch310(gspca_dev);
819
820 write_vector(gspca_dev, spca500_visual_defaults);
821 spca500_setmode(gspca_dev, xmult, ymult);
822 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300823 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300825 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826 err = spca50x_setup_qtable(gspca_dev,
827 0x00, 0x8800, 0x8840,
828 qtable_creative_pccam);
829 if (err < 0)
830 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
831
832 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300833 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834
835 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300836 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300838 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
839 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300841 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
842 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 break;
844 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
845 case IntelPocketPCCamera: /* FIXME: Temporary fix for
846 * Intel Pocket PC Camera
847 * - NWG (Sat 29th March 2003) */
848
849 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300850 err = spca500_full_reset(gspca_dev);
851 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 PDEBUG(D_ERR, "spca500_full_reset failed");
853
854 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300855 err = reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856 if (err < 0)
857 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300858 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859 err = spca50x_setup_qtable(gspca_dev,
860 0x00, 0x8800, 0x8840,
861 qtable_creative_pccam);
862 if (err < 0)
863 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
864
865 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300866 reg_w(gspca_dev->dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867
868 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300869 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300871 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
872 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300874 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
875 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300877/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878 break;
879 case KodakEZ200: /* Kodak EZ200 */
880
881 /* do a full reset */
882 err = spca500_full_reset(gspca_dev);
883 if (err < 0)
884 PDEBUG(D_ERR, "spca500_full_reset failed");
885 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300886 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
887 reg_w(gspca_dev->dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 err = spca50x_setup_qtable(gspca_dev,
889 0x00, 0x8800, 0x8840,
890 qtable_kodak_ez200);
891 if (err < 0)
892 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
893 spca500_setmode(gspca_dev, xmult, ymult);
894
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300895 reg_w(gspca_dev->dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896
897 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300898 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300900 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
901 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300903 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
904 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300906/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 break;
908
909 case BenqDC1016:
910 case DLinkDSC350: /* FamilyCam 300 */
911 case AiptekPocketDV: /* Aiptek PocketDV */
912 case Gsmartmini: /*Mustek Gsmart Mini */
913 case MustekGsmart300: /* Mustek Gsmart 300 */
914 case PalmPixDC85:
915 case Optimedia:
916 case ToptroIndus:
917 case AgfaCl20:
918 spca500_reinit(gspca_dev);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300919 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300921 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922
923 err = spca50x_setup_qtable(gspca_dev,
924 0x00, 0x8800, 0x8840, qtable_pocketdv);
925 if (err < 0)
926 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300927 reg_w(gspca_dev->dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928
929 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300930 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300932 reg_w(gspca_dev->dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300934 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300936 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300938 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300940 reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300942 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
943 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 break;
945 case LogitechTraveler:
946 case LogitechClickSmart510:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300947 reg_w(gspca_dev->dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300949 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950
951 err = spca50x_setup_qtable(gspca_dev,
952 0x00, 0x8800,
953 0x8840, qtable_creative_pccam);
954 if (err < 0)
955 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300956 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
957 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300959 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960
961 spca500_setmode(gspca_dev, xmult, ymult);
962
963 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300964 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
965 reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300967 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
968 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 write_vector(gspca_dev, Clicksmart510_defaults);
970 break;
971 }
972}
973
974static void sd_stopN(struct gspca_dev *gspca_dev)
975{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300976 __u8 data;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300978 reg_w(gspca_dev->dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979
980 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300981 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
982 reg_r(gspca_dev->dev, 0x8000, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x", data);
984}
985
986static void sd_stop0(struct gspca_dev *gspca_dev)
987{
988}
989
990static void sd_close(struct gspca_dev *gspca_dev)
991{
992}
993
994static void sd_pkt_scan(struct gspca_dev *gspca_dev,
995 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300996 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997 int len) /* iso packet length */
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001001 __u8 *s, *d;
1002 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001003
1004/* frames are jpeg 4.1.1 without 0xff escape */
1005 if (data[0] == 0xff) {
1006 if (data[1] != 0x01) { /* drop packet */
1007/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1008 return;
1009 }
1010 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1011 ffd9, 2);
1012
1013 /* put the JPEG header in the new frame */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001014 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015
1016 data += SPCA500_OFFSET_DATA;
1017 len -= SPCA500_OFFSET_DATA;
1018 } else {
1019 data += 1;
1020 len -= 1;
1021 }
1022
1023 /* add 0x00 after 0xff */
1024 for (i = len; --i >= 0; )
1025 if (data[i] == 0xff)
1026 break;
1027 if (i < 0) { /* no 0xff */
1028 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1029 return;
1030 }
1031 s = data;
1032 d = sd->packet;
1033 for (i = 0; i < len; i++) {
1034 *d++ = *s++;
1035 if (s[-1] == 0xff)
1036 *d++ = 0x00;
1037 }
1038 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1039 sd->packet, d - sd->packet);
1040}
1041
1042static void setbrightness(struct gspca_dev *gspca_dev)
1043{
1044 struct sd *sd = (struct sd *) gspca_dev;
1045
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001046 reg_w(gspca_dev->dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047 (__u8) (sd->brightness - 128));
1048}
1049
1050static void getbrightness(struct gspca_dev *gspca_dev)
1051{
1052 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001053 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001055 ret = reg_r_12(gspca_dev->dev, 0x00, 0x8167, 1);
1056 if (ret >= 0)
1057 sd->brightness = ret + 128;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001058}
1059
1060static void setcontrast(struct gspca_dev *gspca_dev)
1061{
1062 struct sd *sd = (struct sd *) gspca_dev;
1063
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001064 reg_w(gspca_dev->dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001065}
1066
1067static void getcontrast(struct gspca_dev *gspca_dev)
1068{
1069 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001070 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001072 ret = reg_r_12(gspca_dev->dev, 0x0, 0x8168, 1);
1073 if (ret >= 0)
1074 sd->contrast = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075}
1076
1077static void setcolors(struct gspca_dev *gspca_dev)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001081 reg_w(gspca_dev->dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001082}
1083
1084static void getcolors(struct gspca_dev *gspca_dev)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001087 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001088
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001089 ret = reg_r_12(gspca_dev->dev, 0x0, 0x8169, 1);
1090 if (ret >= 0)
1091 sd->colors = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001092}
1093
1094static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1095{
1096 struct sd *sd = (struct sd *) gspca_dev;
1097
1098 sd->brightness = val;
1099 if (gspca_dev->streaming)
1100 setbrightness(gspca_dev);
1101 return 0;
1102}
1103
1104static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1105{
1106 struct sd *sd = (struct sd *) gspca_dev;
1107
1108 getbrightness(gspca_dev);
1109 *val = sd->brightness;
1110 return 0;
1111}
1112
1113static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1114{
1115 struct sd *sd = (struct sd *) gspca_dev;
1116
1117 sd->contrast = val;
1118 if (gspca_dev->streaming)
1119 setcontrast(gspca_dev);
1120 return 0;
1121}
1122
1123static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1124{
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
1127 getcontrast(gspca_dev);
1128 *val = sd->contrast;
1129 return 0;
1130}
1131
1132static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1133{
1134 struct sd *sd = (struct sd *) gspca_dev;
1135
1136 sd->colors = val;
1137 if (gspca_dev->streaming)
1138 setcolors(gspca_dev);
1139 return 0;
1140}
1141
1142static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1143{
1144 struct sd *sd = (struct sd *) gspca_dev;
1145
1146 getcolors(gspca_dev);
1147 *val = sd->colors;
1148 return 0;
1149}
1150
1151/* sub-driver description */
1152static struct sd_desc sd_desc = {
1153 .name = MODULE_NAME,
1154 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001155 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001156 .config = sd_config,
1157 .open = sd_open,
1158 .start = sd_start,
1159 .stopN = sd_stopN,
1160 .stop0 = sd_stop0,
1161 .close = sd_close,
1162 .pkt_scan = sd_pkt_scan,
1163};
1164
1165/* -- module initialisation -- */
1166#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001167static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001168 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1169 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1170 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1171 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1172 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1173 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1174 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1175 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1176 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1177 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1178 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1179 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1180 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1181 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1182 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1183 {}
1184};
1185MODULE_DEVICE_TABLE(usb, device_table);
1186
1187/* -- device connect -- */
1188static int sd_probe(struct usb_interface *intf,
1189 const struct usb_device_id *id)
1190{
1191 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1192 THIS_MODULE);
1193}
1194
1195static struct usb_driver sd_driver = {
1196 .name = MODULE_NAME,
1197 .id_table = device_table,
1198 .probe = sd_probe,
1199 .disconnect = gspca_disconnect,
1200};
1201
1202/* -- module insert / remove -- */
1203static int __init sd_mod_init(void)
1204{
1205 if (usb_register(&sd_driver) < 0)
1206 return -1;
1207 PDEBUG(D_PROBE, "v%s registered", version);
1208 return 0;
1209}
1210static void __exit sd_mod_exit(void)
1211{
1212 usb_deregister(&sd_driver);
1213 PDEBUG(D_PROBE, "deregistered");
1214}
1215
1216module_init(sd_mod_init);
1217module_exit(sd_mod_exit);