1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * SPCA500 chip based cameras initialization data
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 */
7
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10#define MODULE_NAME "spca500"
11
12#include "gspca.h"
13#include "jpeg.h"
14
15MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
16MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
17MODULE_LICENSE("GPL");
18
19#define QUALITY 85
20
21/* specific webcam descriptor */
22struct sd {
23 struct gspca_dev gspca_dev; /* !! must be the first item */
24
25 char subtype;
26#define AgfaCl20 0
27#define AiptekPocketDV 1
28#define BenqDC1016 2
29#define CreativePCCam300 3
30#define DLinkDSC350 4
31#define Gsmartmini 5
32#define IntelPocketPCCamera 6
33#define KodakEZ200 7
34#define LogitechClickSmart310 8
35#define LogitechClickSmart510 9
36#define LogitechTraveler 10
37#define MustekGsmart300 11
38#define Optimedia 12
39#define PalmPixDC85 13
40#define ToptroIndus 14
41
42 u8 jpeg_hdr[JPEG_HDR_SZ];
43};
44
45static const struct v4l2_pix_format vga_mode[] = {
46 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
47 .bytesperline = 320,
48 .sizeimage = 320 * 240 * 3 / 8 + 590,
49 .colorspace = V4L2_COLORSPACE_JPEG,
50 .priv = 1},
51 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
52 .bytesperline = 640,
53 .sizeimage = 640 * 480 * 3 / 8 + 590,
54 .colorspace = V4L2_COLORSPACE_JPEG,
55 .priv = 0},
56};
57
58static const struct v4l2_pix_format sif_mode[] = {
59 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
60 .bytesperline = 176,
61 .sizeimage = 176 * 144 * 3 / 8 + 590,
62 .colorspace = V4L2_COLORSPACE_JPEG,
63 .priv = 1},
64 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
65 .bytesperline = 352,
66 .sizeimage = 352 * 288 * 3 / 8 + 590,
67 .colorspace = V4L2_COLORSPACE_JPEG,
68 .priv = 0},
69};
70
71/* Frame packet header offsets for the spca500 */
72#define SPCA500_OFFSET_PADDINGLB 2
73#define SPCA500_OFFSET_PADDINGHB 3
74#define SPCA500_OFFSET_MODE 4
75#define SPCA500_OFFSET_IMGWIDTH 5
76#define SPCA500_OFFSET_IMGHEIGHT 6
77#define SPCA500_OFFSET_IMGMODE 7
78#define SPCA500_OFFSET_QTBLINDEX 8
79#define SPCA500_OFFSET_FRAMSEQ 9
80#define SPCA500_OFFSET_CDSPINFO 10
81#define SPCA500_OFFSET_GPIO 11
82#define SPCA500_OFFSET_AUGPIO 12
83#define SPCA500_OFFSET_DATA 16
84
85
86static const __u16 spca500_visual_defaults[][3] = {
87 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
88 * hue (H byte) = 0,
89 * saturation/hue enable,
90 * brightness/contrast enable.
91 */
92 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
93 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
94 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
95 * hue (H byte) = 0, saturation/hue enable,
96 * brightness/contrast enable.
97 * was 0x0003, now 0x0000.
98 */
99 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
100 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
101 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
102 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
103 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
104 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
105 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
106 {0x0c, 0x0004, 0x0000},
107 /* set interface */
108 {}
109};
110static const __u16 Clicksmart510_defaults[][3] = {
111 {0x00, 0x00, 0x8211},
112 {0x00, 0x01, 0x82c0},
113 {0x00, 0x10, 0x82cb},
114 {0x00, 0x0f, 0x800d},
115 {0x00, 0x82, 0x8225},
116 {0x00, 0x21, 0x8228},
117 {0x00, 0x00, 0x8203},
118 {0x00, 0x00, 0x8204},
119 {0x00, 0x08, 0x8205},
120 {0x00, 0xf8, 0x8206},
121 {0x00, 0x28, 0x8207},
122 {0x00, 0xa0, 0x8208},
123 {0x00, 0x08, 0x824a},
124 {0x00, 0x08, 0x8214},
125 {0x00, 0x80, 0x82c1},
126 {0x00, 0x00, 0x82c2},
127 {0x00, 0x00, 0x82ca},
128 {0x00, 0x80, 0x82c1},
129 {0x00, 0x04, 0x82c2},
130 {0x00, 0x00, 0x82ca},
131 {0x00, 0xfc, 0x8100},
132 {0x00, 0xfc, 0x8105},
133 {0x00, 0x30, 0x8101},
134 {0x00, 0x00, 0x8102},
135 {0x00, 0x00, 0x8103},
136 {0x00, 0x66, 0x8107},
137 {0x00, 0x00, 0x816b},
138 {0x00, 0x00, 0x8155},
139 {0x00, 0x01, 0x8156},
140 {0x00, 0x60, 0x8157},
141 {0x00, 0x40, 0x8158},
142 {0x00, 0x0a, 0x8159},
143 {0x00, 0x06, 0x815a},
144 {0x00, 0x00, 0x813f},
145 {0x00, 0x00, 0x8200},
146 {0x00, 0x19, 0x8201},
147 {0x00, 0x00, 0x82c1},
148 {0x00, 0xa0, 0x82c2},
149 {0x00, 0x00, 0x82ca},
150 {0x00, 0x00, 0x8117},
151 {0x00, 0x00, 0x8118},
152 {0x00, 0x65, 0x8119},
153 {0x00, 0x00, 0x811a},
154 {0x00, 0x00, 0x811b},
155 {0x00, 0x55, 0x811c},
156 {0x00, 0x65, 0x811d},
157 {0x00, 0x55, 0x811e},
158 {0x00, 0x16, 0x811f},
159 {0x00, 0x19, 0x8120},
160 {0x00, 0x80, 0x8103},
161 {0x00, 0x83, 0x816b},
162 {0x00, 0x25, 0x8168},
163 {0x00, 0x01, 0x820f},
164 {0x00, 0xff, 0x8115},
165 {0x00, 0x48, 0x8116},
166 {0x00, 0x50, 0x8151},
167 {0x00, 0x40, 0x8152},
168 {0x00, 0x78, 0x8153},
169 {0x00, 0x40, 0x8154},
170 {0x00, 0x00, 0x8167},
171 {0x00, 0x20, 0x8168},
172 {0x00, 0x00, 0x816a},
173 {0x00, 0x03, 0x816b},
174 {0x00, 0x20, 0x8169},
175 {0x00, 0x60, 0x8157},
176 {0x00, 0x00, 0x8190},
177 {0x00, 0x00, 0x81a1},
178 {0x00, 0x00, 0x81b2},
179 {0x00, 0x27, 0x8191},
180 {0x00, 0x27, 0x81a2},
181 {0x00, 0x27, 0x81b3},
182 {0x00, 0x4b, 0x8192},
183 {0x00, 0x4b, 0x81a3},
184 {0x00, 0x4b, 0x81b4},
185 {0x00, 0x66, 0x8193},
186 {0x00, 0x66, 0x81a4},
187 {0x00, 0x66, 0x81b5},
188 {0x00, 0x79, 0x8194},
189 {0x00, 0x79, 0x81a5},
190 {0x00, 0x79, 0x81b6},
191 {0x00, 0x8a, 0x8195},
192 {0x00, 0x8a, 0x81a6},
193 {0x00, 0x8a, 0x81b7},
194 {0x00, 0x9b, 0x8196},
195 {0x00, 0x9b, 0x81a7},
196 {0x00, 0x9b, 0x81b8},
197 {0x00, 0xa6, 0x8197},
198 {0x00, 0xa6, 0x81a8},
199 {0x00, 0xa6, 0x81b9},
200 {0x00, 0xb2, 0x8198},
201 {0x00, 0xb2, 0x81a9},
202 {0x00, 0xb2, 0x81ba},
203 {0x00, 0xbe, 0x8199},
204 {0x00, 0xbe, 0x81aa},
205 {0x00, 0xbe, 0x81bb},
206 {0x00, 0xc8, 0x819a},
207 {0x00, 0xc8, 0x81ab},
208 {0x00, 0xc8, 0x81bc},
209 {0x00, 0xd2, 0x819b},
210 {0x00, 0xd2, 0x81ac},
211 {0x00, 0xd2, 0x81bd},
212 {0x00, 0xdb, 0x819c},
213 {0x00, 0xdb, 0x81ad},
214 {0x00, 0xdb, 0x81be},
215 {0x00, 0xe4, 0x819d},
216 {0x00, 0xe4, 0x81ae},
217 {0x00, 0xe4, 0x81bf},
218 {0x00, 0xed, 0x819e},
219 {0x00, 0xed, 0x81af},
220 {0x00, 0xed, 0x81c0},
221 {0x00, 0xf7, 0x819f},
222 {0x00, 0xf7, 0x81b0},
223 {0x00, 0xf7, 0x81c1},
224 {0x00, 0xff, 0x81a0},
225 {0x00, 0xff, 0x81b1},
226 {0x00, 0xff, 0x81c2},
227 {0x00, 0x03, 0x8156},
228 {0x00, 0x00, 0x8211},
229 {0x00, 0x20, 0x8168},
230 {0x00, 0x01, 0x8202},
231 {0x00, 0x30, 0x8101},
232 {0x00, 0x00, 0x8111},
233 {0x00, 0x00, 0x8112},
234 {0x00, 0x00, 0x8113},
235 {0x00, 0x00, 0x8114},
236 {}
237};
238
239static const __u8 qtable_creative_pccam[2][64] = {
240 { /* Q-table Y-components */
241 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
242 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
243 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
244 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
245 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
246 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
247 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
248 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
249 { /* Q-table C-components */
250 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
251 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
252 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
253 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
254 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
255 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
256 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
257 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
258};
259
260static const __u8 qtable_kodak_ez200[2][64] = {
261 { /* Q-table Y-components */
262 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
263 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
264 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
265 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
266 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
267 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
268 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
269 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
270 { /* Q-table C-components */
271 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
272 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
273 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
274 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
275 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
276 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
277 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
278 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
279};
280
281static const __u8 qtable_pocketdv[2][64] = {
282 { /* Q-table Y-components start registers 0x8800 */
283 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
284 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
285 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
286 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
287 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
288 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
289 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
290 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
291 },
292 { /* Q-table C-components start registers 0x8840 */
293 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
294 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
295 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
296 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
297 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
298 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
299 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
300 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
301};
302
303/* read 'len' bytes to gspca_dev->usb_buf */
304static void reg_r(struct gspca_dev *gspca_dev,
305 __u16 index,
306 __u16 length)
307{
308 usb_control_msg(dev: gspca_dev->dev,
309 usb_rcvctrlpipe(gspca_dev->dev, 0),
310 request: 0,
311 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312 value: 0, /* value */
313 index, data: gspca_dev->usb_buf, size: length, timeout: 500);
314}
315
316static int reg_w(struct gspca_dev *gspca_dev,
317 __u16 req, __u16 index, __u16 value)
318{
319 int ret;
320
321 gspca_dbg(gspca_dev, D_USBO, "reg write: [0x%02x] = 0x%02x\n",
322 index, value);
323 ret = usb_control_msg(dev: gspca_dev->dev,
324 usb_sndctrlpipe(gspca_dev->dev, 0),
325 request: req,
326 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
327 value, index, NULL, size: 0, timeout: 500);
328 if (ret < 0)
329 pr_err("reg write: error %d\n", ret);
330 return ret;
331}
332
333/* returns: negative is error, pos or zero is data */
334static int reg_r_12(struct gspca_dev *gspca_dev,
335 __u16 req, /* bRequest */
336 __u16 index, /* wIndex */
337 __u16 length) /* wLength (1 or 2 only) */
338{
339 int ret;
340
341 gspca_dev->usb_buf[1] = 0;
342 ret = usb_control_msg(dev: gspca_dev->dev,
343 usb_rcvctrlpipe(gspca_dev->dev, 0),
344 request: req,
345 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
346 value: 0, /* value */
347 index,
348 data: gspca_dev->usb_buf, size: length,
349 timeout: 500); /* timeout */
350 if (ret < 0) {
351 pr_err("reg_r_12 err %d\n", ret);
352 return ret;
353 }
354 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
355}
356
357/*
358 * Simple function to wait for a given 8-bit value to be returned from
359 * a reg_read call.
360 * Returns: negative is error or timeout, zero is success.
361 */
362static int reg_r_wait(struct gspca_dev *gspca_dev,
363 __u16 reg, __u16 index, __u16 value)
364{
365 int ret, cnt = 20;
366
367 while (--cnt > 0) {
368 ret = reg_r_12(gspca_dev, req: reg, index, length: 1);
369 if (ret == value)
370 return 0;
371 msleep(msecs: 50);
372 }
373 return -EIO;
374}
375
376static int write_vector(struct gspca_dev *gspca_dev,
377 const __u16 data[][3])
378{
379 int ret, i = 0;
380
381 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
382 ret = reg_w(gspca_dev, req: data[i][0], index: data[i][2], value: data[i][1]);
383 if (ret < 0)
384 return ret;
385 i++;
386 }
387 return 0;
388}
389
390static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
391 unsigned int request,
392 unsigned int ybase,
393 unsigned int cbase,
394 const __u8 qtable[2][64])
395{
396 int i, err;
397
398 /* loop over y components */
399 for (i = 0; i < 64; i++) {
400 err = reg_w(gspca_dev, req: request, index: ybase + i, value: qtable[0][i]);
401 if (err < 0)
402 return err;
403 }
404
405 /* loop over c components */
406 for (i = 0; i < 64; i++) {
407 err = reg_w(gspca_dev, req: request, index: cbase + i, value: qtable[1][i]);
408 if (err < 0)
409 return err;
410 }
411 return 0;
412}
413
414static void spca500_ping310(struct gspca_dev *gspca_dev)
415{
416 reg_r(gspca_dev, index: 0x0d04, length: 2);
417 gspca_dbg(gspca_dev, D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x\n",
418 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
419}
420
421static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
422{
423 reg_r(gspca_dev, index: 0x0d05, length: 2);
424 gspca_dbg(gspca_dev, D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x\n",
425 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
426 reg_w(gspca_dev, req: 0x00, index: 0x8167, value: 0x5a);
427 spca500_ping310(gspca_dev);
428
429 reg_w(gspca_dev, req: 0x00, index: 0x8168, value: 0x22);
430 reg_w(gspca_dev, req: 0x00, index: 0x816a, value: 0xc0);
431 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: 0x0b);
432 reg_w(gspca_dev, req: 0x00, index: 0x8169, value: 0x25);
433 reg_w(gspca_dev, req: 0x00, index: 0x8157, value: 0x5b);
434 reg_w(gspca_dev, req: 0x00, index: 0x8158, value: 0x5b);
435 reg_w(gspca_dev, req: 0x00, index: 0x813f, value: 0x03);
436 reg_w(gspca_dev, req: 0x00, index: 0x8151, value: 0x4a);
437 reg_w(gspca_dev, req: 0x00, index: 0x8153, value: 0x78);
438 reg_w(gspca_dev, req: 0x00, index: 0x0d01, value: 0x04);
439 /* 00 for adjust shutter */
440 reg_w(gspca_dev, req: 0x00, index: 0x0d02, value: 0x01);
441 reg_w(gspca_dev, req: 0x00, index: 0x8169, value: 0x25);
442 reg_w(gspca_dev, req: 0x00, index: 0x0d01, value: 0x02);
443}
444
445static void spca500_setmode(struct gspca_dev *gspca_dev,
446 __u8 xmult, __u8 ymult)
447{
448 int mode;
449
450 /* set x multiplier */
451 reg_w(gspca_dev, req: 0, index: 0x8001, value: xmult);
452
453 /* set y multiplier */
454 reg_w(gspca_dev, req: 0, index: 0x8002, value: ymult);
455
456 /* use compressed mode, VGA, with mode specific subsample */
457 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
458 reg_w(gspca_dev, req: 0, index: 0x8003, value: mode << 4);
459}
460
461static int spca500_full_reset(struct gspca_dev *gspca_dev)
462{
463 int err;
464
465 /* send the reset command */
466 err = reg_w(gspca_dev, req: 0xe0, index: 0x0001, value: 0x0000);
467 if (err < 0)
468 return err;
469
470 /* wait for the reset to complete */
471 err = reg_r_wait(gspca_dev, reg: 0x06, index: 0x0000, value: 0x0000);
472 if (err < 0)
473 return err;
474 err = reg_w(gspca_dev, req: 0xe0, index: 0x0000, value: 0x0000);
475 if (err < 0)
476 return err;
477 err = reg_r_wait(gspca_dev, reg: 0x06, index: 0, value: 0);
478 if (err < 0) {
479 gspca_err(gspca_dev, "reg_r_wait() failed\n");
480 return err;
481 }
482 /* all ok */
483 return 0;
484}
485
486/* Synchro the Bridge with sensor */
487/* Maybe that will work on all spca500 chip */
488/* because i only own a clicksmart310 try for that chip */
489/* using spca50x_set_packet_size() cause an Ooops here */
490/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
491/* up-port the same feature as in 2.4.x kernel */
492static int spca500_synch310(struct gspca_dev *gspca_dev)
493{
494 if (usb_set_interface(dev: gspca_dev->dev, ifnum: gspca_dev->iface, alternate: 0) < 0) {
495 gspca_err(gspca_dev, "Set packet size: set interface error\n");
496 goto error;
497 }
498 spca500_ping310(gspca_dev);
499
500 reg_r(gspca_dev, index: 0x0d00, length: 1);
501
502 /* need alt setting here */
503 gspca_dbg(gspca_dev, D_PACK, "ClickSmart310 sync alt: %d\n",
504 gspca_dev->alt);
505
506 /* Windoze use pipe with altsetting 6 why 7 here */
507 if (usb_set_interface(dev: gspca_dev->dev,
508 ifnum: gspca_dev->iface,
509 alternate: gspca_dev->alt) < 0) {
510 gspca_err(gspca_dev, "Set packet size: set interface error\n");
511 goto error;
512 }
513 return 0;
514error:
515 return -EBUSY;
516}
517
518static void spca500_reinit(struct gspca_dev *gspca_dev)
519{
520 int err;
521 __u8 Data;
522
523 /* some unknown command from Aiptek pocket dv and family300 */
524
525 reg_w(gspca_dev, req: 0x00, index: 0x0d01, value: 0x01);
526 reg_w(gspca_dev, req: 0x00, index: 0x0d03, value: 0x00);
527 reg_w(gspca_dev, req: 0x00, index: 0x0d02, value: 0x01);
528
529 /* enable drop packet */
530 reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
531
532 err = spca50x_setup_qtable(gspca_dev, request: 0x00, ybase: 0x8800, cbase: 0x8840,
533 qtable: qtable_pocketdv);
534 if (err < 0)
535 gspca_err(gspca_dev, "spca50x_setup_qtable failed on init\n");
536
537 /* set qtable index */
538 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 2);
539 /* family cam Quicksmart stuff */
540 reg_w(gspca_dev, req: 0x00, index: 0x800a, value: 0x00);
541 /* Set agc transfer: synced between frames */
542 reg_w(gspca_dev, req: 0x00, index: 0x820f, value: 0x01);
543 /* Init SDRAM - needed for SDRAM access */
544 reg_w(gspca_dev, req: 0x00, index: 0x870a, value: 0x04);
545 /*Start init sequence or stream */
546 reg_w(gspca_dev, req: 0, index: 0x8003, value: 0x00);
547 /* switch to video camera mode */
548 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
549 msleep(msecs: 2000);
550 if (reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44) != 0) {
551 reg_r(gspca_dev, index: 0x816b, length: 1);
552 Data = gspca_dev->usb_buf[0];
553 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
554 }
555}
556
557/* this function is called at probe time */
558static int sd_config(struct gspca_dev *gspca_dev,
559 const struct usb_device_id *id)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 struct cam *cam;
563
564 cam = &gspca_dev->cam;
565 sd->subtype = id->driver_info;
566 if (sd->subtype != LogitechClickSmart310) {
567 cam->cam_mode = vga_mode;
568 cam->nmodes = ARRAY_SIZE(vga_mode);
569 } else {
570 cam->cam_mode = sif_mode;
571 cam->nmodes = ARRAY_SIZE(sif_mode);
572 }
573 return 0;
574}
575
576/* this function is called at probe and resume time */
577static int sd_init(struct gspca_dev *gspca_dev)
578{
579 struct sd *sd = (struct sd *) gspca_dev;
580
581 /* initialisation of spca500 based cameras is deferred */
582 gspca_dbg(gspca_dev, D_STREAM, "SPCA500 init\n");
583 if (sd->subtype == LogitechClickSmart310)
584 spca500_clksmart310_init(gspca_dev);
585/* else
586 spca500_initialise(gspca_dev); */
587 gspca_dbg(gspca_dev, D_STREAM, "SPCA500 init done\n");
588 return 0;
589}
590
591static int sd_start(struct gspca_dev *gspca_dev)
592{
593 struct sd *sd = (struct sd *) gspca_dev;
594 int err;
595 __u8 Data;
596 __u8 xmult, ymult;
597
598 /* create the JPEG header */
599 jpeg_define(jpeg_hdr: sd->jpeg_hdr, height: gspca_dev->pixfmt.height,
600 width: gspca_dev->pixfmt.width,
601 samplesY: 0x22); /* JPEG 411 */
602 jpeg_set_qual(jpeg_hdr: sd->jpeg_hdr, QUALITY);
603
604 if (sd->subtype == LogitechClickSmart310) {
605 xmult = 0x16;
606 ymult = 0x12;
607 } else {
608 xmult = 0x28;
609 ymult = 0x1e;
610 }
611
612 /* is there a sensor here ? */
613 reg_r(gspca_dev, index: 0x8a04, length: 1);
614 gspca_dbg(gspca_dev, D_STREAM, "Spca500 Sensor Address 0x%02x\n",
615 gspca_dev->usb_buf[0]);
616 gspca_dbg(gspca_dev, D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
617 gspca_dev->curr_mode, xmult, ymult);
618
619 /* setup qtable */
620 switch (sd->subtype) {
621 case LogitechClickSmart310:
622 spca500_setmode(gspca_dev, xmult, ymult);
623
624 /* enable drop packet */
625 reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
626 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 3);
627 err = spca50x_setup_qtable(gspca_dev,
628 request: 0x00, ybase: 0x8800, cbase: 0x8840,
629 qtable: qtable_creative_pccam);
630 if (err < 0)
631 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
632 /* Init SDRAM - needed for SDRAM access */
633 reg_w(gspca_dev, req: 0x00, index: 0x870a, value: 0x04);
634
635 /* switch to video camera mode */
636 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
637 msleep(msecs: 500);
638 if (reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44) != 0)
639 gspca_err(gspca_dev, "reg_r_wait() failed\n");
640
641 reg_r(gspca_dev, index: 0x816b, length: 1);
642 Data = gspca_dev->usb_buf[0];
643 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
644
645 spca500_synch310(gspca_dev);
646
647 write_vector(gspca_dev, data: spca500_visual_defaults);
648 spca500_setmode(gspca_dev, xmult, ymult);
649 /* enable drop packet */
650 err = reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
651 if (err < 0)
652 gspca_err(gspca_dev, "failed to enable drop packet\n");
653 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 3);
654 err = spca50x_setup_qtable(gspca_dev,
655 request: 0x00, ybase: 0x8800, cbase: 0x8840,
656 qtable: qtable_creative_pccam);
657 if (err < 0)
658 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
659
660 /* Init SDRAM - needed for SDRAM access */
661 reg_w(gspca_dev, req: 0x00, index: 0x870a, value: 0x04);
662
663 /* switch to video camera mode */
664 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
665
666 if (reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44) != 0)
667 gspca_err(gspca_dev, "reg_r_wait() failed\n");
668
669 reg_r(gspca_dev, index: 0x816b, length: 1);
670 Data = gspca_dev->usb_buf[0];
671 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
672 break;
673 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
674 case IntelPocketPCCamera: /* FIXME: Temporary fix for
675 * Intel Pocket PC Camera
676 * - NWG (Sat 29th March 2003) */
677
678 /* do a full reset */
679 err = spca500_full_reset(gspca_dev);
680 if (err < 0)
681 gspca_err(gspca_dev, "spca500_full_reset failed\n");
682
683 /* enable drop packet */
684 err = reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
685 if (err < 0)
686 gspca_err(gspca_dev, "failed to enable drop packet\n");
687 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 3);
688 err = spca50x_setup_qtable(gspca_dev,
689 request: 0x00, ybase: 0x8800, cbase: 0x8840,
690 qtable: qtable_creative_pccam);
691 if (err < 0)
692 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
693
694 spca500_setmode(gspca_dev, xmult, ymult);
695 reg_w(gspca_dev, req: 0x20, index: 0x0001, value: 0x0004);
696
697 /* switch to video camera mode */
698 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
699
700 if (reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44) != 0)
701 gspca_err(gspca_dev, "reg_r_wait() failed\n");
702
703 reg_r(gspca_dev, index: 0x816b, length: 1);
704 Data = gspca_dev->usb_buf[0];
705 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
706
707/* write_vector(gspca_dev, spca500_visual_defaults); */
708 break;
709 case KodakEZ200: /* Kodak EZ200 */
710
711 /* do a full reset */
712 err = spca500_full_reset(gspca_dev);
713 if (err < 0)
714 gspca_err(gspca_dev, "spca500_full_reset failed\n");
715 /* enable drop packet */
716 reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
717 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 0);
718 err = spca50x_setup_qtable(gspca_dev,
719 request: 0x00, ybase: 0x8800, cbase: 0x8840,
720 qtable: qtable_kodak_ez200);
721 if (err < 0)
722 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
723 spca500_setmode(gspca_dev, xmult, ymult);
724
725 reg_w(gspca_dev, req: 0x20, index: 0x0001, value: 0x0004);
726
727 /* switch to video camera mode */
728 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
729
730 if (reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44) != 0)
731 gspca_err(gspca_dev, "reg_r_wait() failed\n");
732
733 reg_r(gspca_dev, index: 0x816b, length: 1);
734 Data = gspca_dev->usb_buf[0];
735 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
736
737/* write_vector(gspca_dev, spca500_visual_defaults); */
738 break;
739
740 case BenqDC1016:
741 case DLinkDSC350: /* FamilyCam 300 */
742 case AiptekPocketDV: /* Aiptek PocketDV */
743 case Gsmartmini: /*Mustek Gsmart Mini */
744 case MustekGsmart300: /* Mustek Gsmart 300 */
745 case PalmPixDC85:
746 case Optimedia:
747 case ToptroIndus:
748 case AgfaCl20:
749 spca500_reinit(gspca_dev);
750 reg_w(gspca_dev, req: 0x00, index: 0x0d01, value: 0x01);
751 /* enable drop packet */
752 reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
753
754 err = spca50x_setup_qtable(gspca_dev,
755 request: 0x00, ybase: 0x8800, cbase: 0x8840, qtable: qtable_pocketdv);
756 if (err < 0)
757 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
758 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 2);
759
760 /* familycam Quicksmart pocketDV stuff */
761 reg_w(gspca_dev, req: 0x00, index: 0x800a, value: 0x00);
762 /* Set agc transfer: synced between frames */
763 reg_w(gspca_dev, req: 0x00, index: 0x820f, value: 0x01);
764 /* Init SDRAM - needed for SDRAM access */
765 reg_w(gspca_dev, req: 0x00, index: 0x870a, value: 0x04);
766
767 spca500_setmode(gspca_dev, xmult, ymult);
768 /* switch to video camera mode */
769 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
770
771 reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44);
772
773 reg_r(gspca_dev, index: 0x816b, length: 1);
774 Data = gspca_dev->usb_buf[0];
775 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
776 break;
777 case LogitechTraveler:
778 case LogitechClickSmart510:
779 reg_w(gspca_dev, req: 0x02, index: 0x00, value: 0x00);
780 /* enable drop packet */
781 reg_w(gspca_dev, req: 0x00, index: 0x850a, value: 0x0001);
782
783 err = spca50x_setup_qtable(gspca_dev,
784 request: 0x00, ybase: 0x8800,
785 cbase: 0x8840, qtable: qtable_creative_pccam);
786 if (err < 0)
787 gspca_err(gspca_dev, "spca50x_setup_qtable failed\n");
788 reg_w(gspca_dev, req: 0x00, index: 0x8880, value: 3);
789 reg_w(gspca_dev, req: 0x00, index: 0x800a, value: 0x00);
790 /* Init SDRAM - needed for SDRAM access */
791 reg_w(gspca_dev, req: 0x00, index: 0x870a, value: 0x04);
792
793 spca500_setmode(gspca_dev, xmult, ymult);
794
795 /* switch to video camera mode */
796 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
797 reg_r_wait(gspca_dev, reg: 0, index: 0x8000, value: 0x44);
798
799 reg_r(gspca_dev, index: 0x816b, length: 1);
800 Data = gspca_dev->usb_buf[0];
801 reg_w(gspca_dev, req: 0x00, index: 0x816b, value: Data);
802 write_vector(gspca_dev, data: Clicksmart510_defaults);
803 break;
804 }
805 return 0;
806}
807
808static void sd_stopN(struct gspca_dev *gspca_dev)
809{
810 reg_w(gspca_dev, req: 0, index: 0x8003, value: 0x00);
811
812 /* switch to video camera mode */
813 reg_w(gspca_dev, req: 0x00, index: 0x8000, value: 0x0004);
814 reg_r(gspca_dev, index: 0x8000, length: 1);
815 gspca_dbg(gspca_dev, D_STREAM, "stop SPCA500 done reg8000: 0x%2x\n",
816 gspca_dev->usb_buf[0]);
817}
818
819static void sd_pkt_scan(struct gspca_dev *gspca_dev,
820 u8 *data, /* isoc packet */
821 int len) /* iso packet length */
822{
823 struct sd *sd = (struct sd *) gspca_dev;
824 int i;
825 static __u8 ffd9[] = {0xff, 0xd9};
826
827/* frames are jpeg 4.1.1 without 0xff escape */
828 if (data[0] == 0xff) {
829 if (data[1] != 0x01) { /* drop packet */
830/* gspca_dev->last_packet_type = DISCARD_PACKET; */
831 return;
832 }
833 gspca_frame_add(gspca_dev, packet_type: LAST_PACKET,
834 data: ffd9, len: 2);
835
836 /* put the JPEG header in the new frame */
837 gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET,
838 data: sd->jpeg_hdr, JPEG_HDR_SZ);
839
840 data += SPCA500_OFFSET_DATA;
841 len -= SPCA500_OFFSET_DATA;
842 } else {
843 data += 1;
844 len -= 1;
845 }
846
847 /* add 0x00 after 0xff */
848 i = 0;
849 do {
850 if (data[i] == 0xff) {
851 gspca_frame_add(gspca_dev, packet_type: INTER_PACKET,
852 data, len: i + 1);
853 len -= i;
854 data += i;
855 *data = 0x00;
856 i = 0;
857 }
858 i++;
859 } while (i < len);
860 gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len);
861}
862
863static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
864{
865 reg_w(gspca_dev, req: 0x00, index: 0x8167,
866 value: (__u8) (val - 128));
867}
868
869static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
870{
871 reg_w(gspca_dev, req: 0x00, index: 0x8168, value: val);
872}
873
874static void setcolors(struct gspca_dev *gspca_dev, s32 val)
875{
876 reg_w(gspca_dev, req: 0x00, index: 0x8169, value: val);
877}
878
879static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
880{
881 struct gspca_dev *gspca_dev =
882 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
883
884 gspca_dev->usb_err = 0;
885
886 if (!gspca_dev->streaming)
887 return 0;
888
889 switch (ctrl->id) {
890 case V4L2_CID_BRIGHTNESS:
891 setbrightness(gspca_dev, val: ctrl->val);
892 break;
893 case V4L2_CID_CONTRAST:
894 setcontrast(gspca_dev, val: ctrl->val);
895 break;
896 case V4L2_CID_SATURATION:
897 setcolors(gspca_dev, val: ctrl->val);
898 break;
899 }
900 return gspca_dev->usb_err;
901}
902
903static const struct v4l2_ctrl_ops sd_ctrl_ops = {
904 .s_ctrl = sd_s_ctrl,
905};
906
907static int sd_init_controls(struct gspca_dev *gspca_dev)
908{
909 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
910
911 gspca_dev->vdev.ctrl_handler = hdl;
912 v4l2_ctrl_handler_init(hdl, 3);
913 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
914 V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 127);
915 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
916 V4L2_CID_CONTRAST, min: 0, max: 63, step: 1, def: 31);
917 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
918 V4L2_CID_SATURATION, min: 0, max: 63, step: 1, def: 31);
919
920 if (hdl->error) {
921 pr_err("Could not initialize controls\n");
922 return hdl->error;
923 }
924 return 0;
925}
926
927/* sub-driver description */
928static const struct sd_desc sd_desc = {
929 .name = MODULE_NAME,
930 .config = sd_config,
931 .init = sd_init,
932 .init_controls = sd_init_controls,
933 .start = sd_start,
934 .stopN = sd_stopN,
935 .pkt_scan = sd_pkt_scan,
936};
937
938/* -- module initialisation -- */
939static const struct usb_device_id device_table[] = {
940 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
941 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
942 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
943 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
944 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
945 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
946 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
947 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
948 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
949 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
950 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
951 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
952 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
953 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
954 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
955 {}
956};
957MODULE_DEVICE_TABLE(usb, device_table);
958
959/* -- device connect -- */
960static int sd_probe(struct usb_interface *intf,
961 const struct usb_device_id *id)
962{
963 return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd),
964 THIS_MODULE);
965}
966
967static struct usb_driver sd_driver = {
968 .name = MODULE_NAME,
969 .id_table = device_table,
970 .probe = sd_probe,
971 .disconnect = gspca_disconnect,
972#ifdef CONFIG_PM
973 .suspend = gspca_suspend,
974 .resume = gspca_resume,
975 .reset_resume = gspca_resume,
976#endif
977};
978
979module_usb_driver(sd_driver);
980

source code of linux/drivers/media/usb/gspca/spca500.c