blob: 6f38fa6d86b6ac7a03d9035d247d49a3d4b6e7eb [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030035 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 /* !! no more than 128 ff in an ISO packet */
37
38 unsigned char brightness;
39 unsigned char contrast;
40 unsigned char colors;
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030041 u8 quality;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -030042#define QUALITY_MIN 70
43#define QUALITY_MAX 95
44#define QUALITY_DEF 85
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030046 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
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030062
63 u8 *jpeg_hdr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064};
65
66/* V4L2 controls supported by the driver */
67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73
74static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030075 {
76 {
77 .id = V4L2_CID_BRIGHTNESS,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Brightness",
80 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030082 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030083#define BRIGHTNESS_DEF 127
84 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030085 },
86 .set = sd_setbrightness,
87 .get = sd_getbrightness,
88 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 {
90 {
91 .id = V4L2_CID_CONTRAST,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Contrast",
94 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030096 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030097#define CONTRAST_DEF 31
98 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030099 },
100 .set = sd_setcontrast,
101 .get = sd_getcontrast,
102 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300103 {
104 {
105 .id = V4L2_CID_SATURATION,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Color",
108 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300111#define COLOR_DEF 31
112 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300113 },
114 .set = sd_setcolors,
115 .get = sd_getcolors,
116 },
117};
118
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300119static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300120 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 320,
122 .sizeimage = 320 * 240 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 1},
125 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
126 .bytesperline = 640,
127 .sizeimage = 640 * 480 * 3 / 8 + 590,
128 .colorspace = V4L2_COLORSPACE_JPEG,
129 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130};
131
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300132static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300133 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .bytesperline = 176,
135 .sizeimage = 176 * 144 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
137 .priv = 1},
138 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .bytesperline = 352,
140 .sizeimage = 352 * 288 * 3 / 8 + 590,
141 .colorspace = V4L2_COLORSPACE_JPEG,
142 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143};
144
145/* Frame packet header offsets for the spca500 */
146#define SPCA500_OFFSET_PADDINGLB 2
147#define SPCA500_OFFSET_PADDINGHB 3
148#define SPCA500_OFFSET_MODE 4
149#define SPCA500_OFFSET_IMGWIDTH 5
150#define SPCA500_OFFSET_IMGHEIGHT 6
151#define SPCA500_OFFSET_IMGMODE 7
152#define SPCA500_OFFSET_QTBLINDEX 8
153#define SPCA500_OFFSET_FRAMSEQ 9
154#define SPCA500_OFFSET_CDSPINFO 10
155#define SPCA500_OFFSET_GPIO 11
156#define SPCA500_OFFSET_AUGPIO 12
157#define SPCA500_OFFSET_DATA 16
158
159
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300160static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300161 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
162 * hue (H byte) = 0,
163 * saturation/hue enable,
164 * brightness/contrast enable.
165 */
166 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
167 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
168 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
169 * hue (H byte) = 0, saturation/hue enable,
170 * brightness/contrast enable.
171 * was 0x0003, now 0x0000.
172 */
173 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
174 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
175 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
176 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
177 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
178 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
179 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
180 {0x0c, 0x0004, 0x0000},
181 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300182 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300184static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300185 {0x00, 0x00, 0x8211},
186 {0x00, 0x01, 0x82c0},
187 {0x00, 0x10, 0x82cb},
188 {0x00, 0x0f, 0x800d},
189 {0x00, 0x82, 0x8225},
190 {0x00, 0x21, 0x8228},
191 {0x00, 0x00, 0x8203},
192 {0x00, 0x00, 0x8204},
193 {0x00, 0x08, 0x8205},
194 {0x00, 0xf8, 0x8206},
195 {0x00, 0x28, 0x8207},
196 {0x00, 0xa0, 0x8208},
197 {0x00, 0x08, 0x824a},
198 {0x00, 0x08, 0x8214},
199 {0x00, 0x80, 0x82c1},
200 {0x00, 0x00, 0x82c2},
201 {0x00, 0x00, 0x82ca},
202 {0x00, 0x80, 0x82c1},
203 {0x00, 0x04, 0x82c2},
204 {0x00, 0x00, 0x82ca},
205 {0x00, 0xfc, 0x8100},
206 {0x00, 0xfc, 0x8105},
207 {0x00, 0x30, 0x8101},
208 {0x00, 0x00, 0x8102},
209 {0x00, 0x00, 0x8103},
210 {0x00, 0x66, 0x8107},
211 {0x00, 0x00, 0x816b},
212 {0x00, 0x00, 0x8155},
213 {0x00, 0x01, 0x8156},
214 {0x00, 0x60, 0x8157},
215 {0x00, 0x40, 0x8158},
216 {0x00, 0x0a, 0x8159},
217 {0x00, 0x06, 0x815a},
218 {0x00, 0x00, 0x813f},
219 {0x00, 0x00, 0x8200},
220 {0x00, 0x19, 0x8201},
221 {0x00, 0x00, 0x82c1},
222 {0x00, 0xa0, 0x82c2},
223 {0x00, 0x00, 0x82ca},
224 {0x00, 0x00, 0x8117},
225 {0x00, 0x00, 0x8118},
226 {0x00, 0x65, 0x8119},
227 {0x00, 0x00, 0x811a},
228 {0x00, 0x00, 0x811b},
229 {0x00, 0x55, 0x811c},
230 {0x00, 0x65, 0x811d},
231 {0x00, 0x55, 0x811e},
232 {0x00, 0x16, 0x811f},
233 {0x00, 0x19, 0x8120},
234 {0x00, 0x80, 0x8103},
235 {0x00, 0x83, 0x816b},
236 {0x00, 0x25, 0x8168},
237 {0x00, 0x01, 0x820f},
238 {0x00, 0xff, 0x8115},
239 {0x00, 0x48, 0x8116},
240 {0x00, 0x50, 0x8151},
241 {0x00, 0x40, 0x8152},
242 {0x00, 0x78, 0x8153},
243 {0x00, 0x40, 0x8154},
244 {0x00, 0x00, 0x8167},
245 {0x00, 0x20, 0x8168},
246 {0x00, 0x00, 0x816a},
247 {0x00, 0x03, 0x816b},
248 {0x00, 0x20, 0x8169},
249 {0x00, 0x60, 0x8157},
250 {0x00, 0x00, 0x8190},
251 {0x00, 0x00, 0x81a1},
252 {0x00, 0x00, 0x81b2},
253 {0x00, 0x27, 0x8191},
254 {0x00, 0x27, 0x81a2},
255 {0x00, 0x27, 0x81b3},
256 {0x00, 0x4b, 0x8192},
257 {0x00, 0x4b, 0x81a3},
258 {0x00, 0x4b, 0x81b4},
259 {0x00, 0x66, 0x8193},
260 {0x00, 0x66, 0x81a4},
261 {0x00, 0x66, 0x81b5},
262 {0x00, 0x79, 0x8194},
263 {0x00, 0x79, 0x81a5},
264 {0x00, 0x79, 0x81b6},
265 {0x00, 0x8a, 0x8195},
266 {0x00, 0x8a, 0x81a6},
267 {0x00, 0x8a, 0x81b7},
268 {0x00, 0x9b, 0x8196},
269 {0x00, 0x9b, 0x81a7},
270 {0x00, 0x9b, 0x81b8},
271 {0x00, 0xa6, 0x8197},
272 {0x00, 0xa6, 0x81a8},
273 {0x00, 0xa6, 0x81b9},
274 {0x00, 0xb2, 0x8198},
275 {0x00, 0xb2, 0x81a9},
276 {0x00, 0xb2, 0x81ba},
277 {0x00, 0xbe, 0x8199},
278 {0x00, 0xbe, 0x81aa},
279 {0x00, 0xbe, 0x81bb},
280 {0x00, 0xc8, 0x819a},
281 {0x00, 0xc8, 0x81ab},
282 {0x00, 0xc8, 0x81bc},
283 {0x00, 0xd2, 0x819b},
284 {0x00, 0xd2, 0x81ac},
285 {0x00, 0xd2, 0x81bd},
286 {0x00, 0xdb, 0x819c},
287 {0x00, 0xdb, 0x81ad},
288 {0x00, 0xdb, 0x81be},
289 {0x00, 0xe4, 0x819d},
290 {0x00, 0xe4, 0x81ae},
291 {0x00, 0xe4, 0x81bf},
292 {0x00, 0xed, 0x819e},
293 {0x00, 0xed, 0x81af},
294 {0x00, 0xed, 0x81c0},
295 {0x00, 0xf7, 0x819f},
296 {0x00, 0xf7, 0x81b0},
297 {0x00, 0xf7, 0x81c1},
298 {0x00, 0xff, 0x81a0},
299 {0x00, 0xff, 0x81b1},
300 {0x00, 0xff, 0x81c2},
301 {0x00, 0x03, 0x8156},
302 {0x00, 0x00, 0x8211},
303 {0x00, 0x20, 0x8168},
304 {0x00, 0x01, 0x8202},
305 {0x00, 0x30, 0x8101},
306 {0x00, 0x00, 0x8111},
307 {0x00, 0x00, 0x8112},
308 {0x00, 0x00, 0x8113},
309 {0x00, 0x00, 0x8114},
310 {}
311};
312
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300313static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300314 { /* Q-table Y-components */
315 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
316 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
317 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
318 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
319 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
320 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
321 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
322 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
323 { /* Q-table C-components */
324 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x0e, 0x14, 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 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
331 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
332};
333
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300334static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300335 { /* Q-table Y-components */
336 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
337 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
338 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
339 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
340 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
341 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
342 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
343 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
344 { /* Q-table C-components */
345 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x05, 0x07, 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 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
352 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
353};
354
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300355static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300356 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
358 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
359 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
360 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
361 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
362 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
363 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
364 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
365 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300366 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
368 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
369 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x13, 0x1a, 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 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
374 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
375};
376
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300377/* read 'len' bytes to gspca_dev->usb_buf */
378static void reg_r(struct gspca_dev *gspca_dev,
379 __u16 index,
380 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300382 usb_control_msg(gspca_dev->dev,
383 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384 0,
385 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
386 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300387 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388}
389
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300390static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300391 __u16 req, __u16 index, __u16 value)
392{
393 int ret;
394
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300395 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300396 ret = usb_control_msg(gspca_dev->dev,
397 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300398 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300399 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300400 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300401 if (ret < 0)
402 PDEBUG(D_ERR, "reg write: error %d", ret);
403 return ret;
404}
405
406/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300407static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300408 __u16 req, /* bRequest */
409 __u16 index, /* wIndex */
410 __u16 length) /* wLength (1 or 2 only) */
411{
412 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300413
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300414 gspca_dev->usb_buf[1] = 0;
415 ret = usb_control_msg(gspca_dev->dev,
416 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 req,
418 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
419 0, /* value */
420 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300421 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300422 500); /* timeout */
423 if (ret < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300424 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425 return -1;
426 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300427 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300428}
429
430/*
431 * Simple function to wait for a given 8-bit value to be returned from
432 * a reg_read call.
433 * Returns: negative is error or timeout, zero is success.
434 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300435static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300436 __u16 reg, __u16 index, __u16 value)
437{
438 int ret, cnt = 20;
439
440 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300441 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300442 if (ret == value)
443 return 0;
444 msleep(50);
445 }
446 return -EIO;
447}
448
449static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300450 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452 int ret, i = 0;
453
454 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300455 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456 if (ret < 0)
457 return ret;
458 i++;
459 }
460 return 0;
461}
462
463static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
464 unsigned int request,
465 unsigned int ybase,
466 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300467 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469 int i, err;
470
471 /* loop over y components */
472 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300473 err = reg_w(gspca_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 Moine739570b2008-07-14 09:38:29 -0300480 err = reg_w(gspca_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{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300489 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300490 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300491 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492}
493
494static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
495{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300496 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300497 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300498 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
499 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 spca500_ping310(gspca_dev);
501
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300502 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
503 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
504 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
505 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
506 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
507 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
508 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
509 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
510 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
511 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300513 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
514 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
515 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516}
517
518static void spca500_setmode(struct gspca_dev *gspca_dev,
519 __u8 xmult, __u8 ymult)
520{
521 int mode;
522
523 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300524 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525
526 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528
529 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300530 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532}
533
534static int spca500_full_reset(struct gspca_dev *gspca_dev)
535{
536 int err;
537
538 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300539 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540 if (err < 0)
541 return err;
542
543 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300544 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545 if (err < 0)
546 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 if (err < 0)
549 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300552 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300553 return err;
554 }
555 /* all ok */
556 return 0;
557}
558
559/* Synchro the Bridge with sensor */
560/* Maybe that will work on all spca500 chip */
561/* because i only own a clicksmart310 try for that chip */
562/* using spca50x_set_packet_size() cause an Ooops here */
563/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
564/* up-port the same feature as in 2.4.x kernel */
565static int spca500_synch310(struct gspca_dev *gspca_dev)
566{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300567 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
568 PDEBUG(D_ERR, "Set packet size: set interface error");
569 goto error;
570 }
571 spca500_ping310(gspca_dev);
572
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300573 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574
575 /* need alt setting here */
576 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
577
578 /* Windoze use pipe with altsetting 6 why 7 here */
579 if (usb_set_interface(gspca_dev->dev,
580 gspca_dev->iface,
581 gspca_dev->alt) < 0) {
582 PDEBUG(D_ERR, "Set packet size: set interface error");
583 goto error;
584 }
585 return 0;
586error:
587 return -EBUSY;
588}
589
590static void spca500_reinit(struct gspca_dev *gspca_dev)
591{
592 int err;
593 __u8 Data;
594
595 /* some unknow command from Aiptek pocket dv and family300 */
596
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
598 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
599 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600
601 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300602 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603
604 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
605 qtable_pocketdv);
606 if (err < 0)
607 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
608
609 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300610 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300611 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300612 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300613 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300614 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300618 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300620 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
623 reg_r(gspca_dev, 0x816b, 1);
624 Data = gspca_dev->usb_buf[0];
625 reg_w(gspca_dev, 0x00, 0x816b, Data);
626 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627}
628
629/* this function is called at probe time */
630static int sd_config(struct gspca_dev *gspca_dev,
631 const struct usb_device_id *id)
632{
633 struct sd *sd = (struct sd *) gspca_dev;
634 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300637 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 if (sd->subtype != LogitechClickSmart310) {
639 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300640 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 } else {
642 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300643 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300645 sd->brightness = BRIGHTNESS_DEF;
646 sd->contrast = CONTRAST_DEF;
647 sd->colors = COLOR_DEF;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300648 sd->quality = QUALITY_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649 return 0;
650}
651
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300652/* this function is called at probe and resume time */
653static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654{
655 struct sd *sd = (struct sd *) gspca_dev;
656
657 /* initialisation of spca500 based cameras is deferred */
658 PDEBUG(D_STREAM, "SPCA500 init");
659 if (sd->subtype == LogitechClickSmart310)
660 spca500_clksmart310_init(gspca_dev);
661/* else
662 spca500_initialise(gspca_dev); */
663 PDEBUG(D_STREAM, "SPCA500 init done");
664 return 0;
665}
666
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300667static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668{
669 struct sd *sd = (struct sd *) gspca_dev;
670 int err;
671 __u8 Data;
672 __u8 xmult, ymult;
673
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300674 /* create the JPEG header */
675 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
676 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
677 0x22); /* JPEG 411 */
678 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
679
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 if (sd->subtype == LogitechClickSmart310) {
681 xmult = 0x16;
682 ymult = 0x12;
683 } else {
684 xmult = 0x28;
685 ymult = 0x1e;
686 }
687
688 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 reg_r(gspca_dev, 0x8a04, 1);
690 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
691 gspca_dev->usb_buf[0]);
692 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 gspca_dev->curr_mode, xmult, ymult);
694
695 /* setup qtable */
696 switch (sd->subtype) {
697 case LogitechClickSmart310:
698 spca500_setmode(gspca_dev, xmult, ymult);
699
700 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300701 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
702 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 err = spca50x_setup_qtable(gspca_dev,
704 0x00, 0x8800, 0x8840,
705 qtable_creative_pccam);
706 if (err < 0)
707 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
708 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
711 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300712 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300715 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300717 reg_r(gspca_dev, 0x816b, 1);
718 Data = gspca_dev->usb_buf[0];
719 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720
721 spca500_synch310(gspca_dev);
722
723 write_vector(gspca_dev, spca500_visual_defaults);
724 spca500_setmode(gspca_dev, xmult, ymult);
725 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300726 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
727 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300729 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730 err = spca50x_setup_qtable(gspca_dev,
731 0x00, 0x8800, 0x8840,
732 qtable_creative_pccam);
733 if (err < 0)
734 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
735
736 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300737 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738
739 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300740 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300742 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300743 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300745 reg_r(gspca_dev, 0x816b, 1);
746 Data = gspca_dev->usb_buf[0];
747 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748 break;
749 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
750 case IntelPocketPCCamera: /* FIXME: Temporary fix for
751 * Intel Pocket PC Camera
752 * - NWG (Sat 29th March 2003) */
753
754 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300755 err = spca500_full_reset(gspca_dev);
756 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757 PDEBUG(D_ERR, "spca500_full_reset failed");
758
759 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761 if (err < 0)
762 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764 err = spca50x_setup_qtable(gspca_dev,
765 0x00, 0x8800, 0x8840,
766 qtable_creative_pccam);
767 if (err < 0)
768 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
769
770 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300771 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772
773 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300776 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300777 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300779 reg_r(gspca_dev, 0x816b, 1);
780 Data = gspca_dev->usb_buf[0];
781 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300783/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 break;
785 case KodakEZ200: /* Kodak EZ200 */
786
787 /* do a full reset */
788 err = spca500_full_reset(gspca_dev);
789 if (err < 0)
790 PDEBUG(D_ERR, "spca500_full_reset failed");
791 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300792 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
793 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794 err = spca50x_setup_qtable(gspca_dev,
795 0x00, 0x8800, 0x8840,
796 qtable_kodak_ez200);
797 if (err < 0)
798 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
799 spca500_setmode(gspca_dev, xmult, ymult);
800
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300801 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300802
803 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300806 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300807 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300809 reg_r(gspca_dev, 0x816b, 1);
810 Data = gspca_dev->usb_buf[0];
811 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300813/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814 break;
815
816 case BenqDC1016:
817 case DLinkDSC350: /* FamilyCam 300 */
818 case AiptekPocketDV: /* Aiptek PocketDV */
819 case Gsmartmini: /*Mustek Gsmart Mini */
820 case MustekGsmart300: /* Mustek Gsmart 300 */
821 case PalmPixDC85:
822 case Optimedia:
823 case ToptroIndus:
824 case AgfaCl20:
825 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300826 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300828 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829
830 err = spca50x_setup_qtable(gspca_dev,
831 0x00, 0x8800, 0x8840, qtable_pocketdv);
832 if (err < 0)
833 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
836 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300837 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300839 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300841 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300843 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300845 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300847 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300849 reg_r(gspca_dev, 0x816b, 1);
850 Data = gspca_dev->usb_buf[0];
851 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 break;
853 case LogitechTraveler:
854 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300855 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300857 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858
859 err = spca50x_setup_qtable(gspca_dev,
860 0x00, 0x8800,
861 0x8840, qtable_creative_pccam);
862 if (err < 0)
863 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300864 reg_w(gspca_dev, 0x00, 0x8880, 3);
865 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300867 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868
869 spca500_setmode(gspca_dev, xmult, ymult);
870
871 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300872 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
873 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300875 reg_r(gspca_dev, 0x816b, 1);
876 Data = gspca_dev->usb_buf[0];
877 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878 write_vector(gspca_dev, Clicksmart510_defaults);
879 break;
880 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300881 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882}
883
884static void sd_stopN(struct gspca_dev *gspca_dev)
885{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300886 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887
888 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300889 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
890 reg_r(gspca_dev, 0x8000, 1);
891 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
892 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893}
894
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300895static void sd_stop0(struct gspca_dev *gspca_dev)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 kfree(sd->jpeg_hdr);
900}
901
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902static void sd_pkt_scan(struct gspca_dev *gspca_dev,
903 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300904 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 int len) /* iso packet length */
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300909 __u8 *s, *d;
910 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911
912/* frames are jpeg 4.1.1 without 0xff escape */
913 if (data[0] == 0xff) {
914 if (data[1] != 0x01) { /* drop packet */
915/* gspca_dev->last_packet_type = DISCARD_PACKET; */
916 return;
917 }
918 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
919 ffd9, 2);
920
921 /* put the JPEG header in the new frame */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300922 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
923 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924
925 data += SPCA500_OFFSET_DATA;
926 len -= SPCA500_OFFSET_DATA;
927 } else {
928 data += 1;
929 len -= 1;
930 }
931
932 /* add 0x00 after 0xff */
933 for (i = len; --i >= 0; )
934 if (data[i] == 0xff)
935 break;
936 if (i < 0) { /* no 0xff */
937 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
938 return;
939 }
940 s = data;
941 d = sd->packet;
942 for (i = 0; i < len; i++) {
943 *d++ = *s++;
944 if (s[-1] == 0xff)
945 *d++ = 0x00;
946 }
947 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
948 sd->packet, d - sd->packet);
949}
950
951static void setbrightness(struct gspca_dev *gspca_dev)
952{
953 struct sd *sd = (struct sd *) gspca_dev;
954
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300955 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 (__u8) (sd->brightness - 128));
957}
958
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959static void setcontrast(struct gspca_dev *gspca_dev)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300963 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964}
965
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966static void setcolors(struct gspca_dev *gspca_dev)
967{
968 struct sd *sd = (struct sd *) gspca_dev;
969
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300970 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300971}
972
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
974{
975 struct sd *sd = (struct sd *) gspca_dev;
976
977 sd->brightness = val;
978 if (gspca_dev->streaming)
979 setbrightness(gspca_dev);
980 return 0;
981}
982
983static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
984{
985 struct sd *sd = (struct sd *) gspca_dev;
986
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 *val = sd->brightness;
988 return 0;
989}
990
991static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 sd->contrast = val;
996 if (gspca_dev->streaming)
997 setcontrast(gspca_dev);
998 return 0;
999}
1000
1001static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1002{
1003 struct sd *sd = (struct sd *) gspca_dev;
1004
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001005 *val = sd->contrast;
1006 return 0;
1007}
1008
1009static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1010{
1011 struct sd *sd = (struct sd *) gspca_dev;
1012
1013 sd->colors = val;
1014 if (gspca_dev->streaming)
1015 setcolors(gspca_dev);
1016 return 0;
1017}
1018
1019static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1020{
1021 struct sd *sd = (struct sd *) gspca_dev;
1022
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 *val = sd->colors;
1024 return 0;
1025}
1026
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -03001027static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1028 struct v4l2_jpegcompression *jcomp)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031
1032 if (jcomp->quality < QUALITY_MIN)
1033 sd->quality = QUALITY_MIN;
1034 else if (jcomp->quality > QUALITY_MAX)
1035 sd->quality = QUALITY_MAX;
1036 else
1037 sd->quality = jcomp->quality;
1038 if (gspca_dev->streaming)
1039 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1040 return 0;
1041}
1042
1043static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1044 struct v4l2_jpegcompression *jcomp)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
1048 memset(jcomp, 0, sizeof *jcomp);
1049 jcomp->quality = sd->quality;
1050 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1051 | V4L2_JPEG_MARKER_DQT;
1052 return 0;
1053}
1054
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055/* sub-driver description */
1056static struct sd_desc sd_desc = {
1057 .name = MODULE_NAME,
1058 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001059 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001060 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001061 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001062 .start = sd_start,
1063 .stopN = sd_stopN,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -03001064 .stop0 = sd_stop0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001065 .pkt_scan = sd_pkt_scan,
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -03001066 .get_jcomp = sd_get_jcomp,
1067 .set_jcomp = sd_set_jcomp,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068};
1069
1070/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001071static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -03001072 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1073 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1074 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1075 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1076 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1077 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1078 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1079 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1080 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1081 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1082 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1083 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1084 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1085 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1086 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001087 {}
1088};
1089MODULE_DEVICE_TABLE(usb, device_table);
1090
1091/* -- device connect -- */
1092static int sd_probe(struct usb_interface *intf,
1093 const struct usb_device_id *id)
1094{
1095 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1096 THIS_MODULE);
1097}
1098
1099static struct usb_driver sd_driver = {
1100 .name = MODULE_NAME,
1101 .id_table = device_table,
1102 .probe = sd_probe,
1103 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001104#ifdef CONFIG_PM
1105 .suspend = gspca_suspend,
1106 .resume = gspca_resume,
1107#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001108};
1109
1110/* -- module insert / remove -- */
1111static int __init sd_mod_init(void)
1112{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001113 int ret;
1114 ret = usb_register(&sd_driver);
1115 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001116 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001117 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001118 return 0;
1119}
1120static void __exit sd_mod_exit(void)
1121{
1122 usb_deregister(&sd_driver);
1123 PDEBUG(D_PROBE, "deregistered");
1124}
1125
1126module_init(sd_mod_init);
1127module_exit(sd_mod_exit);