]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/video/gspca/spca500.c
V4L/DVB (8442): gspca: Remove the version from the subdrivers.
[mirror_ubuntu-artful-kernel.git] / drivers / media / video / gspca / spca500.c
CommitLineData
6a7eba24
JFM
1/*
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
6a7eba24
JFM
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
a5ae2062 35 __u8 packet[ISO_MAX_SIZE + 128];
6a7eba24
JFM
36 /* !! no more than 128 ff in an ISO packet */
37
38 unsigned char brightness;
39 unsigned char contrast;
40 unsigned char colors;
41
42 char qindex;
43 char subtype;
44#define AgfaCl20 0
45#define AiptekPocketDV 1
46#define BenqDC1016 2
47#define CreativePCCam300 3
48#define DLinkDSC350 4
49#define Gsmartmini 5
50#define IntelPocketPCCamera 6
51#define KodakEZ200 7
52#define LogitechClickSmart310 8
53#define LogitechClickSmart510 9
54#define LogitechTraveler 10
55#define MustekGsmart300 11
56#define Optimedia 12
57#define PalmPixDC85 13
58#define ToptroIndus 14
59};
60
61/* V4L2 controls supported by the driver */
62static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
68
69static struct ctrl sd_ctrls[] = {
6a7eba24
JFM
70 {
71 {
72 .id = V4L2_CID_BRIGHTNESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Brightness",
75 .minimum = 0,
a5ae2062 76 .maximum = 255,
6a7eba24 77 .step = 1,
a5ae2062
JFM
78#define BRIGHTNESS_DEF 127
79 .default_value = BRIGHTNESS_DEF,
6a7eba24
JFM
80 },
81 .set = sd_setbrightness,
82 .get = sd_getbrightness,
83 },
6a7eba24
JFM
84 {
85 {
86 .id = V4L2_CID_CONTRAST,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Contrast",
89 .minimum = 0,
a5ae2062 90 .maximum = 63,
6a7eba24 91 .step = 1,
a5ae2062
JFM
92#define CONTRAST_DEF 31
93 .default_value = CONTRAST_DEF,
6a7eba24
JFM
94 },
95 .set = sd_setcontrast,
96 .get = sd_getcontrast,
97 },
6a7eba24
JFM
98 {
99 {
100 .id = V4L2_CID_SATURATION,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Color",
103 .minimum = 0,
a5ae2062 104 .maximum = 63,
6a7eba24 105 .step = 1,
a5ae2062
JFM
106#define COLOR_DEF 31
107 .default_value = COLOR_DEF,
6a7eba24
JFM
108 },
109 .set = sd_setcolors,
110 .get = sd_getcolors,
111 },
112};
113
c2446b3e
JFM
114static struct v4l2_pix_format vga_mode[] = {
115 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
116 .bytesperline = 320,
117 .sizeimage = 320 * 240 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
119 .priv = 1},
120 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 640,
122 .sizeimage = 640 * 480 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 0},
6a7eba24
JFM
125};
126
c2446b3e
JFM
127static struct v4l2_pix_format sif_mode[] = {
128 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
129 .bytesperline = 176,
130 .sizeimage = 176 * 144 * 3 / 8 + 590,
131 .colorspace = V4L2_COLORSPACE_JPEG,
132 .priv = 1},
133 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .bytesperline = 352,
135 .sizeimage = 352 * 288 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
137 .priv = 0},
6a7eba24
JFM
138};
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
a5ae2062 155static const __u16 spca500_visual_defaults[][3] = {
6a7eba24
JFM
156 {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 */
a5ae2062 177 {}
6a7eba24 178};
a5ae2062 179static const __u16 Clicksmart510_defaults[][3] = {
6a7eba24
JFM
180 {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
a5ae2062 308static const __u8 qtable_creative_pccam[2][64] = {
6a7eba24
JFM
309 { /* 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
a5ae2062 329static const __u8 qtable_kodak_ez200[2][64] = {
6a7eba24
JFM
330 { /* 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
a5ae2062 350static const __u8 qtable_pocketdv[2][64] = {
956e42d2 351 { /* Q-table Y-components start registers 0x8800 */
6a7eba24
JFM
352 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 },
956e42d2 361 { /* Q-table C-components start registers 0x8840 */
6a7eba24
JFM
362 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
739570bb
JFM
372/* read 'len' bytes to gspca_dev->usb_buf */
373static void reg_r(struct gspca_dev *gspca_dev,
374 __u16 index,
375 __u16 length)
6a7eba24 376{
739570bb
JFM
377 usb_control_msg(gspca_dev->dev,
378 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
379 0,
380 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
381 0, /* value */
739570bb 382 index, gspca_dev->usb_buf, length, 500);
6a7eba24
JFM
383}
384
739570bb 385static int reg_w(struct gspca_dev *gspca_dev,
6a7eba24
JFM
386 __u16 req, __u16 index, __u16 value)
387{
388 int ret;
389
a5ae2062 390 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
739570bb
JFM
391 ret = usb_control_msg(gspca_dev->dev,
392 usb_sndctrlpipe(gspca_dev->dev, 0),
6a7eba24 393 req,
bf7f0b98 394 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6a7eba24 395 value, index, NULL, 0, 500);
6a7eba24
JFM
396 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 */
739570bb 402static int reg_r_12(struct gspca_dev *gspca_dev,
6a7eba24
JFM
403 __u16 req, /* bRequest */
404 __u16 index, /* wIndex */
405 __u16 length) /* wLength (1 or 2 only) */
406{
407 int ret;
6a7eba24 408
739570bb
JFM
409 gspca_dev->usb_buf[1] = 0;
410 ret = usb_control_msg(gspca_dev->dev,
411 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
412 req,
413 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
414 0, /* value */
415 index,
739570bb 416 gspca_dev->usb_buf, length,
6a7eba24
JFM
417 500); /* timeout */
418 if (ret < 0) {
a5ae2062 419 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
6a7eba24
JFM
420 return -1;
421 }
739570bb 422 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
6a7eba24
JFM
423}
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 */
739570bb 430static int reg_r_wait(struct gspca_dev *gspca_dev,
6a7eba24
JFM
431 __u16 reg, __u16 index, __u16 value)
432{
433 int ret, cnt = 20;
434
435 while (--cnt > 0) {
739570bb 436 ret = reg_r_12(gspca_dev, reg, index, 1);
6a7eba24
JFM
437 if (ret == value)
438 return 0;
439 msleep(50);
440 }
441 return -EIO;
442}
443
444static int write_vector(struct gspca_dev *gspca_dev,
a5ae2062 445 const __u16 data[][3])
6a7eba24 446{
6a7eba24
JFM
447 int ret, i = 0;
448
449 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
739570bb 450 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
6a7eba24
JFM
451 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,
a5ae2062 462 const __u8 qtable[2][64])
6a7eba24 463{
6a7eba24
JFM
464 int i, err;
465
466 /* loop over y components */
467 for (i = 0; i < 64; i++) {
739570bb 468 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
6a7eba24
JFM
469 if (err < 0)
470 return err;
471 }
472
473 /* loop over c components */
474 for (i = 0; i < 64; i++) {
739570bb 475 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
6a7eba24
JFM
476 if (err < 0)
477 return err;
478 }
479 return 0;
480}
481
482static void spca500_ping310(struct gspca_dev *gspca_dev)
483{
739570bb 484 reg_r(gspca_dev, 0x0d04, 2);
a5ae2062 485 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
739570bb 486 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
6a7eba24
JFM
487}
488
489static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
490{
739570bb 491 reg_r(gspca_dev, 0x0d05, 2);
a5ae2062 492 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
739570bb
JFM
493 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
494 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
6a7eba24
JFM
495 spca500_ping310(gspca_dev);
496
739570bb
JFM
497 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);
6a7eba24 507 /* 00 for adjust shutter */
739570bb
JFM
508 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
509 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
510 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
6a7eba24
JFM
511}
512
513static void spca500_setmode(struct gspca_dev *gspca_dev,
514 __u8 xmult, __u8 ymult)
515{
516 int mode;
517
518 /* set x multiplier */
739570bb 519 reg_w(gspca_dev, 0, 0x8001, xmult);
6a7eba24
JFM
520
521 /* set y multiplier */
739570bb 522 reg_w(gspca_dev, 0, 0x8002, ymult);
6a7eba24
JFM
523
524 /* use compressed mode, VGA, with mode specific subsample */
c2446b3e 525 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
739570bb 526 reg_w(gspca_dev, 0, 0x8003, mode << 4);
6a7eba24
JFM
527}
528
529static int spca500_full_reset(struct gspca_dev *gspca_dev)
530{
531 int err;
532
533 /* send the reset command */
739570bb 534 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
6a7eba24
JFM
535 if (err < 0)
536 return err;
537
538 /* wait for the reset to complete */
739570bb 539 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
6a7eba24
JFM
540 if (err < 0)
541 return err;
739570bb 542 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
6a7eba24
JFM
543 if (err < 0)
544 return err;
739570bb 545 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
6a7eba24 546 if (err < 0) {
a5ae2062 547 PDEBUG(D_ERR, "reg_r_wait() failed");
6a7eba24
JFM
548 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{
6a7eba24
JFM
562 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
739570bb 568 reg_r(gspca_dev, 0x0d00, 1);
6a7eba24
JFM
569
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
739570bb
JFM
592 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
593 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
594 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
6a7eba24
JFM
595
596 /* enable drop packet */
739570bb 597 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
598
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 */
739570bb 605 reg_w(gspca_dev, 0x00, 0x8880, 2);
6a7eba24 606 /* family cam Quicksmart stuff */
739570bb 607 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
6a7eba24 608 /* Set agc transfer: synced inbetween frames */
739570bb 609 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
6a7eba24 610 /* Init SDRAM - needed for SDRAM access */
739570bb 611 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24 612 /*Start init sequence or stream */
739570bb 613 reg_w(gspca_dev, 0, 0x8003, 0x00);
6a7eba24 614 /* switch to video camera mode */
739570bb 615 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 616 msleep(2000);
739570bb
JFM
617 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 }
6a7eba24
JFM
622}
623
624/* this function is called at probe time */
625static int sd_config(struct gspca_dev *gspca_dev,
626 const struct usb_device_id *id)
627{
628 struct sd *sd = (struct sd *) gspca_dev;
629 struct cam *cam;
630 __u16 vendor;
631 __u16 product;
632
633 vendor = id->idVendor;
634 product = id->idProduct;
635 switch (vendor) {
636 case 0x040a: /* Kodak cameras */
637/* switch (product) { */
638/* case 0x0300: */
639 sd->subtype = KodakEZ200;
640/* break; */
641/* } */
642 break;
643 case 0x041e: /* Creative cameras */
644/* switch (product) { */
645/* case 0x400a: */
646 sd->subtype = CreativePCCam300;
647/* break; */
648/* } */
649 break;
650 case 0x046d: /* Logitech Labtec */
651 switch (product) {
652 case 0x0890:
653 sd->subtype = LogitechTraveler;
654 break;
655 case 0x0900:
656 sd->subtype = LogitechClickSmart310;
657 break;
658 case 0x0901:
659 sd->subtype = LogitechClickSmart510;
660 break;
661 }
662 break;
663 case 0x04a5: /* Benq */
664/* switch (product) { */
665/* case 0x300c: */
666 sd->subtype = BenqDC1016;
667/* break; */
668/* } */
669 break;
670 case 0x04fc: /* SunPlus */
671/* switch (product) { */
672/* case 0x7333: */
673 sd->subtype = PalmPixDC85;
674/* break; */
675/* } */
676 break;
677 case 0x055f: /* Mustek cameras */
678 switch (product) {
679 case 0xc200:
680 sd->subtype = MustekGsmart300;
681 break;
682 case 0xc220:
683 sd->subtype = Gsmartmini;
684 break;
685 }
686 break;
687 case 0x06bd: /* Agfa Cl20 */
688/* switch (product) { */
689/* case 0x0404: */
690 sd->subtype = AgfaCl20;
691/* break; */
692/* } */
693 break;
694 case 0x06be: /* Optimedia */
695/* switch (product) { */
696/* case 0x0800: */
697 sd->subtype = Optimedia;
698/* break; */
699/* } */
700 break;
701 case 0x084d: /* D-Link / Minton */
702/* switch (product) { */
703/* case 0x0003: * DSC-350 / S-Cam F5 */
704 sd->subtype = DLinkDSC350;
705/* break; */
706/* } */
707 break;
708 case 0x08ca: /* Aiptek */
709/* switch (product) { */
710/* case 0x0103: */
711 sd->subtype = AiptekPocketDV;
712/* break; */
713/* } */
714 break;
715 case 0x2899: /* ToptroIndustrial */
716/* switch (product) { */
717/* case 0x012c: */
718 sd->subtype = ToptroIndus;
719/* break; */
720/* } */
721 break;
722 case 0x8086: /* Intel */
723/* switch (product) { */
724/* case 0x0630: * Pocket PC Camera */
725 sd->subtype = IntelPocketPCCamera;
726/* break; */
727/* } */
728 break;
729 }
730 cam = &gspca_dev->cam;
731 cam->dev_name = (char *) id->driver_info;
732 cam->epaddr = 0x01;
733 if (sd->subtype != LogitechClickSmart310) {
734 cam->cam_mode = vga_mode;
735 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
736 } else {
737 cam->cam_mode = sif_mode;
738 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
739 }
740 sd->qindex = 5;
a5ae2062
JFM
741 sd->brightness = BRIGHTNESS_DEF;
742 sd->contrast = CONTRAST_DEF;
743 sd->colors = COLOR_DEF;
6a7eba24
JFM
744 return 0;
745}
746
747/* this function is called at open time */
748static int sd_open(struct gspca_dev *gspca_dev)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 /* initialisation of spca500 based cameras is deferred */
753 PDEBUG(D_STREAM, "SPCA500 init");
754 if (sd->subtype == LogitechClickSmart310)
755 spca500_clksmart310_init(gspca_dev);
756/* else
757 spca500_initialise(gspca_dev); */
758 PDEBUG(D_STREAM, "SPCA500 init done");
759 return 0;
760}
761
762static void sd_start(struct gspca_dev *gspca_dev)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 int err;
766 __u8 Data;
767 __u8 xmult, ymult;
768
769 if (sd->subtype == LogitechClickSmart310) {
770 xmult = 0x16;
771 ymult = 0x12;
772 } else {
773 xmult = 0x28;
774 ymult = 0x1e;
775 }
776
777 /* is there a sensor here ? */
739570bb
JFM
778 reg_r(gspca_dev, 0x8a04, 1);
779 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
780 gspca_dev->usb_buf[0]);
781 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
6a7eba24
JFM
782 gspca_dev->curr_mode, xmult, ymult);
783
784 /* setup qtable */
785 switch (sd->subtype) {
786 case LogitechClickSmart310:
787 spca500_setmode(gspca_dev, xmult, ymult);
788
789 /* enable drop packet */
739570bb
JFM
790 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
791 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
792 err = spca50x_setup_qtable(gspca_dev,
793 0x00, 0x8800, 0x8840,
794 qtable_creative_pccam);
795 if (err < 0)
796 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
797 /* Init SDRAM - needed for SDRAM access */
739570bb 798 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
799
800 /* switch to video camera mode */
739570bb 801 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 802 msleep(500);
739570bb 803 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
a5ae2062 804 PDEBUG(D_ERR, "reg_r_wait() failed");
6a7eba24 805
739570bb
JFM
806 reg_r(gspca_dev, 0x816b, 1);
807 Data = gspca_dev->usb_buf[0];
808 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
809
810 spca500_synch310(gspca_dev);
811
812 write_vector(gspca_dev, spca500_visual_defaults);
813 spca500_setmode(gspca_dev, xmult, ymult);
814 /* enable drop packet */
739570bb 815 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24 816 PDEBUG(D_ERR, "failed to enable drop packet");
739570bb 817 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
818 err = spca50x_setup_qtable(gspca_dev,
819 0x00, 0x8800, 0x8840,
820 qtable_creative_pccam);
821 if (err < 0)
822 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
823
824 /* Init SDRAM - needed for SDRAM access */
739570bb 825 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
826
827 /* switch to video camera mode */
739570bb 828 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 829
739570bb 830 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
a5ae2062 831 PDEBUG(D_ERR, "reg_r_wait() failed");
6a7eba24 832
739570bb
JFM
833 reg_r(gspca_dev, 0x816b, 1);
834 Data = gspca_dev->usb_buf[0];
835 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
836 break;
837 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
838 case IntelPocketPCCamera: /* FIXME: Temporary fix for
839 * Intel Pocket PC Camera
840 * - NWG (Sat 29th March 2003) */
841
842 /* do a full reset */
956e42d2
JFM
843 err = spca500_full_reset(gspca_dev);
844 if (err < 0)
6a7eba24
JFM
845 PDEBUG(D_ERR, "spca500_full_reset failed");
846
847 /* enable drop packet */
739570bb 848 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
849 if (err < 0)
850 PDEBUG(D_ERR, "failed to enable drop packet");
739570bb 851 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
852 err = spca50x_setup_qtable(gspca_dev,
853 0x00, 0x8800, 0x8840,
854 qtable_creative_pccam);
855 if (err < 0)
856 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
857
858 spca500_setmode(gspca_dev, xmult, ymult);
739570bb 859 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
6a7eba24
JFM
860
861 /* switch to video camera mode */
739570bb 862 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 863
739570bb 864 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
a5ae2062 865 PDEBUG(D_ERR, "reg_r_wait() failed");
6a7eba24 866
739570bb
JFM
867 reg_r(gspca_dev, 0x816b, 1);
868 Data = gspca_dev->usb_buf[0];
869 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24 870
a5ae2062 871/* write_vector(gspca_dev, spca500_visual_defaults); */
6a7eba24
JFM
872 break;
873 case KodakEZ200: /* Kodak EZ200 */
874
875 /* do a full reset */
876 err = spca500_full_reset(gspca_dev);
877 if (err < 0)
878 PDEBUG(D_ERR, "spca500_full_reset failed");
879 /* enable drop packet */
739570bb
JFM
880 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
881 reg_w(gspca_dev, 0x00, 0x8880, 0);
6a7eba24
JFM
882 err = spca50x_setup_qtable(gspca_dev,
883 0x00, 0x8800, 0x8840,
884 qtable_kodak_ez200);
885 if (err < 0)
886 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
887 spca500_setmode(gspca_dev, xmult, ymult);
888
739570bb 889 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
6a7eba24
JFM
890
891 /* switch to video camera mode */
739570bb 892 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 893
739570bb 894 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
a5ae2062 895 PDEBUG(D_ERR, "reg_r_wait() failed");
6a7eba24 896
739570bb
JFM
897 reg_r(gspca_dev, 0x816b, 1);
898 Data = gspca_dev->usb_buf[0];
899 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24 900
a5ae2062 901/* write_vector(gspca_dev, spca500_visual_defaults); */
6a7eba24
JFM
902 break;
903
904 case BenqDC1016:
905 case DLinkDSC350: /* FamilyCam 300 */
906 case AiptekPocketDV: /* Aiptek PocketDV */
907 case Gsmartmini: /*Mustek Gsmart Mini */
908 case MustekGsmart300: /* Mustek Gsmart 300 */
909 case PalmPixDC85:
910 case Optimedia:
911 case ToptroIndus:
912 case AgfaCl20:
913 spca500_reinit(gspca_dev);
739570bb 914 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
6a7eba24 915 /* enable drop packet */
739570bb 916 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
917
918 err = spca50x_setup_qtable(gspca_dev,
919 0x00, 0x8800, 0x8840, qtable_pocketdv);
920 if (err < 0)
921 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
739570bb 922 reg_w(gspca_dev, 0x00, 0x8880, 2);
6a7eba24
JFM
923
924 /* familycam Quicksmart pocketDV stuff */
739570bb 925 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
6a7eba24 926 /* Set agc transfer: synced inbetween frames */
739570bb 927 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
6a7eba24 928 /* Init SDRAM - needed for SDRAM access */
739570bb 929 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24 930
956e42d2 931 spca500_setmode(gspca_dev, xmult, ymult);
6a7eba24 932 /* switch to video camera mode */
739570bb 933 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 934
739570bb 935 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
6a7eba24 936
739570bb
JFM
937 reg_r(gspca_dev, 0x816b, 1);
938 Data = gspca_dev->usb_buf[0];
939 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
940 break;
941 case LogitechTraveler:
942 case LogitechClickSmart510:
739570bb 943 reg_w(gspca_dev, 0x02, 0x00, 0x00);
6a7eba24 944 /* enable drop packet */
739570bb 945 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
946
947 err = spca50x_setup_qtable(gspca_dev,
948 0x00, 0x8800,
949 0x8840, qtable_creative_pccam);
950 if (err < 0)
951 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
739570bb
JFM
952 reg_w(gspca_dev, 0x00, 0x8880, 3);
953 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
6a7eba24 954 /* Init SDRAM - needed for SDRAM access */
739570bb 955 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
956
957 spca500_setmode(gspca_dev, xmult, ymult);
958
959 /* switch to video camera mode */
739570bb
JFM
960 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
961 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
6a7eba24 962
739570bb
JFM
963 reg_r(gspca_dev, 0x816b, 1);
964 Data = gspca_dev->usb_buf[0];
965 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
966 write_vector(gspca_dev, Clicksmart510_defaults);
967 break;
968 }
969}
970
971static void sd_stopN(struct gspca_dev *gspca_dev)
972{
739570bb 973 reg_w(gspca_dev, 0, 0x8003, 0x00);
6a7eba24
JFM
974
975 /* switch to video camera mode */
739570bb
JFM
976 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
977 reg_r(gspca_dev, 0x8000, 1);
978 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
979 gspca_dev->usb_buf[0]);
6a7eba24
JFM
980}
981
982static void sd_stop0(struct gspca_dev *gspca_dev)
983{
984}
985
986static void sd_close(struct gspca_dev *gspca_dev)
987{
988}
989
990static void sd_pkt_scan(struct gspca_dev *gspca_dev,
991 struct gspca_frame *frame, /* target */
a5ae2062 992 __u8 *data, /* isoc packet */
6a7eba24
JFM
993 int len) /* iso packet length */
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996 int i;
a5ae2062
JFM
997 __u8 *s, *d;
998 static __u8 ffd9[] = {0xff, 0xd9};
6a7eba24
JFM
999
1000/* frames are jpeg 4.1.1 without 0xff escape */
1001 if (data[0] == 0xff) {
1002 if (data[1] != 0x01) { /* drop packet */
1003/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1004 return;
1005 }
1006 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1007 ffd9, 2);
1008
1009 /* put the JPEG header in the new frame */
a5ae2062 1010 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
6a7eba24
JFM
1011
1012 data += SPCA500_OFFSET_DATA;
1013 len -= SPCA500_OFFSET_DATA;
1014 } else {
1015 data += 1;
1016 len -= 1;
1017 }
1018
1019 /* add 0x00 after 0xff */
1020 for (i = len; --i >= 0; )
1021 if (data[i] == 0xff)
1022 break;
1023 if (i < 0) { /* no 0xff */
1024 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1025 return;
1026 }
1027 s = data;
1028 d = sd->packet;
1029 for (i = 0; i < len; i++) {
1030 *d++ = *s++;
1031 if (s[-1] == 0xff)
1032 *d++ = 0x00;
1033 }
1034 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1035 sd->packet, d - sd->packet);
1036}
1037
1038static void setbrightness(struct gspca_dev *gspca_dev)
1039{
1040 struct sd *sd = (struct sd *) gspca_dev;
1041
739570bb 1042 reg_w(gspca_dev, 0x00, 0x8167,
6a7eba24
JFM
1043 (__u8) (sd->brightness - 128));
1044}
1045
1046static void getbrightness(struct gspca_dev *gspca_dev)
1047{
1048 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1049 int ret;
6a7eba24 1050
739570bb 1051 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
a5ae2062
JFM
1052 if (ret >= 0)
1053 sd->brightness = ret + 128;
6a7eba24
JFM
1054}
1055
1056static void setcontrast(struct gspca_dev *gspca_dev)
1057{
1058 struct sd *sd = (struct sd *) gspca_dev;
1059
739570bb 1060 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
6a7eba24
JFM
1061}
1062
1063static void getcontrast(struct gspca_dev *gspca_dev)
1064{
1065 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1066 int ret;
6a7eba24 1067
739570bb 1068 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
a5ae2062
JFM
1069 if (ret >= 0)
1070 sd->contrast = ret;
6a7eba24
JFM
1071}
1072
1073static void setcolors(struct gspca_dev *gspca_dev)
1074{
1075 struct sd *sd = (struct sd *) gspca_dev;
1076
739570bb 1077 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
6a7eba24
JFM
1078}
1079
1080static void getcolors(struct gspca_dev *gspca_dev)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1083 int ret;
6a7eba24 1084
739570bb 1085 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
a5ae2062
JFM
1086 if (ret >= 0)
1087 sd->colors = ret;
6a7eba24
JFM
1088}
1089
1090static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1091{
1092 struct sd *sd = (struct sd *) gspca_dev;
1093
1094 sd->brightness = val;
1095 if (gspca_dev->streaming)
1096 setbrightness(gspca_dev);
1097 return 0;
1098}
1099
1100static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 getbrightness(gspca_dev);
1105 *val = sd->brightness;
1106 return 0;
1107}
1108
1109static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1110{
1111 struct sd *sd = (struct sd *) gspca_dev;
1112
1113 sd->contrast = val;
1114 if (gspca_dev->streaming)
1115 setcontrast(gspca_dev);
1116 return 0;
1117}
1118
1119static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1120{
1121 struct sd *sd = (struct sd *) gspca_dev;
1122
1123 getcontrast(gspca_dev);
1124 *val = sd->contrast;
1125 return 0;
1126}
1127
1128static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1129{
1130 struct sd *sd = (struct sd *) gspca_dev;
1131
1132 sd->colors = val;
1133 if (gspca_dev->streaming)
1134 setcolors(gspca_dev);
1135 return 0;
1136}
1137
1138static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1139{
1140 struct sd *sd = (struct sd *) gspca_dev;
1141
1142 getcolors(gspca_dev);
1143 *val = sd->colors;
1144 return 0;
1145}
1146
1147/* sub-driver description */
1148static struct sd_desc sd_desc = {
1149 .name = MODULE_NAME,
1150 .ctrls = sd_ctrls,
a5ae2062 1151 .nctrls = ARRAY_SIZE(sd_ctrls),
6a7eba24
JFM
1152 .config = sd_config,
1153 .open = sd_open,
1154 .start = sd_start,
1155 .stopN = sd_stopN,
1156 .stop0 = sd_stop0,
1157 .close = sd_close,
1158 .pkt_scan = sd_pkt_scan,
1159};
1160
1161/* -- module initialisation -- */
1162#define DVNM(name) .driver_info = (kernel_ulong_t) name
a5ae2062 1163static const __devinitdata struct usb_device_id device_table[] = {
6a7eba24
JFM
1164 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1165 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1166 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1167 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1168 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1169 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1170 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1171 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1172 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1173 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1174 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1175 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1176 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1177 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1178 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1179 {}
1180};
1181MODULE_DEVICE_TABLE(usb, device_table);
1182
1183/* -- device connect -- */
1184static int sd_probe(struct usb_interface *intf,
1185 const struct usb_device_id *id)
1186{
1187 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1188 THIS_MODULE);
1189}
1190
1191static struct usb_driver sd_driver = {
1192 .name = MODULE_NAME,
1193 .id_table = device_table,
1194 .probe = sd_probe,
1195 .disconnect = gspca_disconnect,
1196};
1197
1198/* -- module insert / remove -- */
1199static int __init sd_mod_init(void)
1200{
1201 if (usb_register(&sd_driver) < 0)
1202 return -1;
10b0e96e 1203 PDEBUG(D_PROBE, "registered");
6a7eba24
JFM
1204 return 0;
1205}
1206static void __exit sd_mod_exit(void)
1207{
1208 usb_deregister(&sd_driver);
1209 PDEBUG(D_PROBE, "deregistered");
1210}
1211
1212module_init(sd_mod_init);
1213module_exit(sd_mod_exit);