blob: 2176ac6850e35cdd21d1a0a71588201bc073ca6c [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 Moine6a7eba22008-06-30 15:50:11 -030042
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043 char subtype;
44#define AgfaCl20 0
45#define AiptekPocketDV 1
46#define BenqDC1016 2
47#define CreativePCCam300 3
48#define DLinkDSC350 4
49#define Gsmartmini 5
50#define IntelPocketPCCamera 6
51#define KodakEZ200 7
52#define LogitechClickSmart310 8
53#define LogitechClickSmart510 9
54#define LogitechTraveler 10
55#define MustekGsmart300 11
56#define Optimedia 12
57#define PalmPixDC85 13
58#define ToptroIndus 14
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030059
60 u8 *jpeg_hdr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030061};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70
71static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030072 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030078 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030079 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030080#define BRIGHTNESS_DEF 127
81 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030082 },
83 .set = sd_setbrightness,
84 .get = sd_getbrightness,
85 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030092 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030094#define CONTRAST_DEF 31
95 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030096 },
97 .set = sd_setcontrast,
98 .get = sd_getcontrast,
99 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300106 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300107 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300108#define COLOR_DEF 31
109 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 },
111 .set = sd_setcolors,
112 .get = sd_getcolors,
113 },
114};
115
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300116static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300117 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
118 .bytesperline = 320,
119 .sizeimage = 320 * 240 * 3 / 8 + 590,
120 .colorspace = V4L2_COLORSPACE_JPEG,
121 .priv = 1},
122 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
123 .bytesperline = 640,
124 .sizeimage = 640 * 480 * 3 / 8 + 590,
125 .colorspace = V4L2_COLORSPACE_JPEG,
126 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127};
128
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300129static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300130 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 176,
132 .sizeimage = 176 * 144 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 352,
137 .sizeimage = 352 * 288 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140};
141
142/* Frame packet header offsets for the spca500 */
143#define SPCA500_OFFSET_PADDINGLB 2
144#define SPCA500_OFFSET_PADDINGHB 3
145#define SPCA500_OFFSET_MODE 4
146#define SPCA500_OFFSET_IMGWIDTH 5
147#define SPCA500_OFFSET_IMGHEIGHT 6
148#define SPCA500_OFFSET_IMGMODE 7
149#define SPCA500_OFFSET_QTBLINDEX 8
150#define SPCA500_OFFSET_FRAMSEQ 9
151#define SPCA500_OFFSET_CDSPINFO 10
152#define SPCA500_OFFSET_GPIO 11
153#define SPCA500_OFFSET_AUGPIO 12
154#define SPCA500_OFFSET_DATA 16
155
156
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300157static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
159 * hue (H byte) = 0,
160 * saturation/hue enable,
161 * brightness/contrast enable.
162 */
163 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
164 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
165 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
166 * hue (H byte) = 0, saturation/hue enable,
167 * brightness/contrast enable.
168 * was 0x0003, now 0x0000.
169 */
170 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
171 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
172 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
173 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
174 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
175 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
176 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
177 {0x0c, 0x0004, 0x0000},
178 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300179 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300181static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182 {0x00, 0x00, 0x8211},
183 {0x00, 0x01, 0x82c0},
184 {0x00, 0x10, 0x82cb},
185 {0x00, 0x0f, 0x800d},
186 {0x00, 0x82, 0x8225},
187 {0x00, 0x21, 0x8228},
188 {0x00, 0x00, 0x8203},
189 {0x00, 0x00, 0x8204},
190 {0x00, 0x08, 0x8205},
191 {0x00, 0xf8, 0x8206},
192 {0x00, 0x28, 0x8207},
193 {0x00, 0xa0, 0x8208},
194 {0x00, 0x08, 0x824a},
195 {0x00, 0x08, 0x8214},
196 {0x00, 0x80, 0x82c1},
197 {0x00, 0x00, 0x82c2},
198 {0x00, 0x00, 0x82ca},
199 {0x00, 0x80, 0x82c1},
200 {0x00, 0x04, 0x82c2},
201 {0x00, 0x00, 0x82ca},
202 {0x00, 0xfc, 0x8100},
203 {0x00, 0xfc, 0x8105},
204 {0x00, 0x30, 0x8101},
205 {0x00, 0x00, 0x8102},
206 {0x00, 0x00, 0x8103},
207 {0x00, 0x66, 0x8107},
208 {0x00, 0x00, 0x816b},
209 {0x00, 0x00, 0x8155},
210 {0x00, 0x01, 0x8156},
211 {0x00, 0x60, 0x8157},
212 {0x00, 0x40, 0x8158},
213 {0x00, 0x0a, 0x8159},
214 {0x00, 0x06, 0x815a},
215 {0x00, 0x00, 0x813f},
216 {0x00, 0x00, 0x8200},
217 {0x00, 0x19, 0x8201},
218 {0x00, 0x00, 0x82c1},
219 {0x00, 0xa0, 0x82c2},
220 {0x00, 0x00, 0x82ca},
221 {0x00, 0x00, 0x8117},
222 {0x00, 0x00, 0x8118},
223 {0x00, 0x65, 0x8119},
224 {0x00, 0x00, 0x811a},
225 {0x00, 0x00, 0x811b},
226 {0x00, 0x55, 0x811c},
227 {0x00, 0x65, 0x811d},
228 {0x00, 0x55, 0x811e},
229 {0x00, 0x16, 0x811f},
230 {0x00, 0x19, 0x8120},
231 {0x00, 0x80, 0x8103},
232 {0x00, 0x83, 0x816b},
233 {0x00, 0x25, 0x8168},
234 {0x00, 0x01, 0x820f},
235 {0x00, 0xff, 0x8115},
236 {0x00, 0x48, 0x8116},
237 {0x00, 0x50, 0x8151},
238 {0x00, 0x40, 0x8152},
239 {0x00, 0x78, 0x8153},
240 {0x00, 0x40, 0x8154},
241 {0x00, 0x00, 0x8167},
242 {0x00, 0x20, 0x8168},
243 {0x00, 0x00, 0x816a},
244 {0x00, 0x03, 0x816b},
245 {0x00, 0x20, 0x8169},
246 {0x00, 0x60, 0x8157},
247 {0x00, 0x00, 0x8190},
248 {0x00, 0x00, 0x81a1},
249 {0x00, 0x00, 0x81b2},
250 {0x00, 0x27, 0x8191},
251 {0x00, 0x27, 0x81a2},
252 {0x00, 0x27, 0x81b3},
253 {0x00, 0x4b, 0x8192},
254 {0x00, 0x4b, 0x81a3},
255 {0x00, 0x4b, 0x81b4},
256 {0x00, 0x66, 0x8193},
257 {0x00, 0x66, 0x81a4},
258 {0x00, 0x66, 0x81b5},
259 {0x00, 0x79, 0x8194},
260 {0x00, 0x79, 0x81a5},
261 {0x00, 0x79, 0x81b6},
262 {0x00, 0x8a, 0x8195},
263 {0x00, 0x8a, 0x81a6},
264 {0x00, 0x8a, 0x81b7},
265 {0x00, 0x9b, 0x8196},
266 {0x00, 0x9b, 0x81a7},
267 {0x00, 0x9b, 0x81b8},
268 {0x00, 0xa6, 0x8197},
269 {0x00, 0xa6, 0x81a8},
270 {0x00, 0xa6, 0x81b9},
271 {0x00, 0xb2, 0x8198},
272 {0x00, 0xb2, 0x81a9},
273 {0x00, 0xb2, 0x81ba},
274 {0x00, 0xbe, 0x8199},
275 {0x00, 0xbe, 0x81aa},
276 {0x00, 0xbe, 0x81bb},
277 {0x00, 0xc8, 0x819a},
278 {0x00, 0xc8, 0x81ab},
279 {0x00, 0xc8, 0x81bc},
280 {0x00, 0xd2, 0x819b},
281 {0x00, 0xd2, 0x81ac},
282 {0x00, 0xd2, 0x81bd},
283 {0x00, 0xdb, 0x819c},
284 {0x00, 0xdb, 0x81ad},
285 {0x00, 0xdb, 0x81be},
286 {0x00, 0xe4, 0x819d},
287 {0x00, 0xe4, 0x81ae},
288 {0x00, 0xe4, 0x81bf},
289 {0x00, 0xed, 0x819e},
290 {0x00, 0xed, 0x81af},
291 {0x00, 0xed, 0x81c0},
292 {0x00, 0xf7, 0x819f},
293 {0x00, 0xf7, 0x81b0},
294 {0x00, 0xf7, 0x81c1},
295 {0x00, 0xff, 0x81a0},
296 {0x00, 0xff, 0x81b1},
297 {0x00, 0xff, 0x81c2},
298 {0x00, 0x03, 0x8156},
299 {0x00, 0x00, 0x8211},
300 {0x00, 0x20, 0x8168},
301 {0x00, 0x01, 0x8202},
302 {0x00, 0x30, 0x8101},
303 {0x00, 0x00, 0x8111},
304 {0x00, 0x00, 0x8112},
305 {0x00, 0x00, 0x8113},
306 {0x00, 0x00, 0x8114},
307 {}
308};
309
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300310static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300311 { /* Q-table Y-components */
312 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
313 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
314 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
315 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
316 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
317 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
318 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
319 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
320 { /* Q-table C-components */
321 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
322 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x0e, 0x14, 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 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
329};
330
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300331static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300332 { /* Q-table Y-components */
333 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
334 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
335 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
336 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
337 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
338 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
339 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
340 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
341 { /* Q-table C-components */
342 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
343 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x05, 0x07, 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 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
350};
351
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300352static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300353 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300354 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
355 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
356 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
357 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
358 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
359 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
360 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
361 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
362 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300363 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300364 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
365 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
366 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
367 0x13, 0x1a, 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 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
372};
373
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300374/* read 'len' bytes to gspca_dev->usb_buf */
375static void reg_r(struct gspca_dev *gspca_dev,
376 __u16 index,
377 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300378{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300379 usb_control_msg(gspca_dev->dev,
380 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381 0,
382 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
383 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300384 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385}
386
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300387static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388 __u16 req, __u16 index, __u16 value)
389{
390 int ret;
391
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300392 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300393 ret = usb_control_msg(gspca_dev->dev,
394 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300396 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300397 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300398 if (ret < 0)
399 PDEBUG(D_ERR, "reg write: error %d", ret);
400 return ret;
401}
402
403/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300404static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300405 __u16 req, /* bRequest */
406 __u16 index, /* wIndex */
407 __u16 length) /* wLength (1 or 2 only) */
408{
409 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300410
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300411 gspca_dev->usb_buf[1] = 0;
412 ret = usb_control_msg(gspca_dev->dev,
413 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300414 req,
415 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
416 0, /* value */
417 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300418 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300419 500); /* timeout */
420 if (ret < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300421 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300422 return -1;
423 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300424 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425}
426
427/*
428 * Simple function to wait for a given 8-bit value to be returned from
429 * a reg_read call.
430 * Returns: negative is error or timeout, zero is success.
431 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300432static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433 __u16 reg, __u16 index, __u16 value)
434{
435 int ret, cnt = 20;
436
437 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300438 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439 if (ret == value)
440 return 0;
441 msleep(50);
442 }
443 return -EIO;
444}
445
446static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300447 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300448{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300449 int ret, i = 0;
450
451 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300452 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453 if (ret < 0)
454 return ret;
455 i++;
456 }
457 return 0;
458}
459
460static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
461 unsigned int request,
462 unsigned int ybase,
463 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300464 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300465{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 int i, err;
467
468 /* loop over y components */
469 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300470 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300471 if (err < 0)
472 return err;
473 }
474
475 /* loop over c components */
476 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300477 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300478 if (err < 0)
479 return err;
480 }
481 return 0;
482}
483
484static void spca500_ping310(struct gspca_dev *gspca_dev)
485{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300486 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300487 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300488 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489}
490
491static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
492{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300493 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300494 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300495 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
496 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300497 spca500_ping310(gspca_dev);
498
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300499 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
500 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
501 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
502 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
503 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
504 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
506 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
507 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
508 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300509 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300510 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
511 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
512 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513}
514
515static void spca500_setmode(struct gspca_dev *gspca_dev,
516 __u8 xmult, __u8 ymult)
517{
518 int mode;
519
520 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300521 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300522
523 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300524 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525
526 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300527 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300528 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529}
530
531static int spca500_full_reset(struct gspca_dev *gspca_dev)
532{
533 int err;
534
535 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300536 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537 if (err < 0)
538 return err;
539
540 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300541 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 if (err < 0)
543 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300544 err = reg_w(gspca_dev, 0xe0, 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_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300549 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550 return err;
551 }
552 /* all ok */
553 return 0;
554}
555
556/* Synchro the Bridge with sensor */
557/* Maybe that will work on all spca500 chip */
558/* because i only own a clicksmart310 try for that chip */
559/* using spca50x_set_packet_size() cause an Ooops here */
560/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
561/* up-port the same feature as in 2.4.x kernel */
562static int spca500_synch310(struct gspca_dev *gspca_dev)
563{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300564 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
565 PDEBUG(D_ERR, "Set packet size: set interface error");
566 goto error;
567 }
568 spca500_ping310(gspca_dev);
569
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300570 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571
572 /* need alt setting here */
573 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
574
575 /* Windoze use pipe with altsetting 6 why 7 here */
576 if (usb_set_interface(gspca_dev->dev,
577 gspca_dev->iface,
578 gspca_dev->alt) < 0) {
579 PDEBUG(D_ERR, "Set packet size: set interface error");
580 goto error;
581 }
582 return 0;
583error:
584 return -EBUSY;
585}
586
587static void spca500_reinit(struct gspca_dev *gspca_dev)
588{
589 int err;
590 __u8 Data;
591
592 /* some unknow command from Aiptek pocket dv and family300 */
593
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300594 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
595 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
596 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597
598 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300599 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600
601 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
602 qtable_pocketdv);
603 if (err < 0)
604 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
605
606 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300607 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300609 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300611 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300613 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
620 reg_r(gspca_dev, 0x816b, 1);
621 Data = gspca_dev->usb_buf[0];
622 reg_w(gspca_dev, 0x00, 0x816b, Data);
623 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624}
625
626/* this function is called at probe time */
627static int sd_config(struct gspca_dev *gspca_dev,
628 const struct usb_device_id *id)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
631 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300634 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 if (sd->subtype != LogitechClickSmart310) {
636 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300637 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 } else {
639 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300640 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300642 sd->brightness = BRIGHTNESS_DEF;
643 sd->contrast = CONTRAST_DEF;
644 sd->colors = COLOR_DEF;
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300645 sd->quality = 85;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646 return 0;
647}
648
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300649/* this function is called at probe and resume time */
650static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651{
652 struct sd *sd = (struct sd *) gspca_dev;
653
654 /* initialisation of spca500 based cameras is deferred */
655 PDEBUG(D_STREAM, "SPCA500 init");
656 if (sd->subtype == LogitechClickSmart310)
657 spca500_clksmart310_init(gspca_dev);
658/* else
659 spca500_initialise(gspca_dev); */
660 PDEBUG(D_STREAM, "SPCA500 init done");
661 return 0;
662}
663
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300664static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665{
666 struct sd *sd = (struct sd *) gspca_dev;
667 int err;
668 __u8 Data;
669 __u8 xmult, ymult;
670
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300671 /* create the JPEG header */
672 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
673 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
674 0x22); /* JPEG 411 */
675 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
676
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 if (sd->subtype == LogitechClickSmart310) {
678 xmult = 0x16;
679 ymult = 0x12;
680 } else {
681 xmult = 0x28;
682 ymult = 0x1e;
683 }
684
685 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300686 reg_r(gspca_dev, 0x8a04, 1);
687 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
688 gspca_dev->usb_buf[0]);
689 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 gspca_dev->curr_mode, xmult, ymult);
691
692 /* setup qtable */
693 switch (sd->subtype) {
694 case LogitechClickSmart310:
695 spca500_setmode(gspca_dev, xmult, ymult);
696
697 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
699 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700 err = spca50x_setup_qtable(gspca_dev,
701 0x00, 0x8800, 0x8840,
702 qtable_creative_pccam);
703 if (err < 0)
704 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
705 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
708 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300711 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300712 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 reg_r(gspca_dev, 0x816b, 1);
715 Data = gspca_dev->usb_buf[0];
716 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717
718 spca500_synch310(gspca_dev);
719
720 write_vector(gspca_dev, spca500_visual_defaults);
721 spca500_setmode(gspca_dev, xmult, ymult);
722 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300723 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
724 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300726 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727 err = spca50x_setup_qtable(gspca_dev,
728 0x00, 0x8800, 0x8840,
729 qtable_creative_pccam);
730 if (err < 0)
731 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
732
733 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300734 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735
736 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300737 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300740 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300742 reg_r(gspca_dev, 0x816b, 1);
743 Data = gspca_dev->usb_buf[0];
744 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745 break;
746 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
747 case IntelPocketPCCamera: /* FIXME: Temporary fix for
748 * Intel Pocket PC Camera
749 * - NWG (Sat 29th March 2003) */
750
751 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300752 err = spca500_full_reset(gspca_dev);
753 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300754 PDEBUG(D_ERR, "spca500_full_reset failed");
755
756 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300757 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 if (err < 0)
759 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761 err = spca50x_setup_qtable(gspca_dev,
762 0x00, 0x8800, 0x8840,
763 qtable_creative_pccam);
764 if (err < 0)
765 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
766
767 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300768 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769
770 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300771 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300773 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300774 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300776 reg_r(gspca_dev, 0x816b, 1);
777 Data = gspca_dev->usb_buf[0];
778 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300780/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 break;
782 case KodakEZ200: /* Kodak EZ200 */
783
784 /* do a full reset */
785 err = spca500_full_reset(gspca_dev);
786 if (err < 0)
787 PDEBUG(D_ERR, "spca500_full_reset failed");
788 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300789 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
790 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 err = spca50x_setup_qtable(gspca_dev,
792 0x00, 0x8800, 0x8840,
793 qtable_kodak_ez200);
794 if (err < 0)
795 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
796 spca500_setmode(gspca_dev, xmult, ymult);
797
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300798 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799
800 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300801 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300802
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300803 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300804 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300806 reg_r(gspca_dev, 0x816b, 1);
807 Data = gspca_dev->usb_buf[0];
808 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300810/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 break;
812
813 case BenqDC1016:
814 case DLinkDSC350: /* FamilyCam 300 */
815 case AiptekPocketDV: /* Aiptek PocketDV */
816 case Gsmartmini: /*Mustek Gsmart Mini */
817 case MustekGsmart300: /* Mustek Gsmart 300 */
818 case PalmPixDC85:
819 case Optimedia:
820 case ToptroIndus:
821 case AgfaCl20:
822 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300823 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300825 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826
827 err = spca50x_setup_qtable(gspca_dev,
828 0x00, 0x8800, 0x8840, qtable_pocketdv);
829 if (err < 0)
830 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300831 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832
833 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300836 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300838 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300840 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300841 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300842 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300846 reg_r(gspca_dev, 0x816b, 1);
847 Data = gspca_dev->usb_buf[0];
848 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 break;
850 case LogitechTraveler:
851 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300852 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300854 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855
856 err = spca50x_setup_qtable(gspca_dev,
857 0x00, 0x8800,
858 0x8840, qtable_creative_pccam);
859 if (err < 0)
860 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300861 reg_w(gspca_dev, 0x00, 0x8880, 3);
862 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300864 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865
866 spca500_setmode(gspca_dev, xmult, ymult);
867
868 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300869 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
870 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300871
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300872 reg_r(gspca_dev, 0x816b, 1);
873 Data = gspca_dev->usb_buf[0];
874 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875 write_vector(gspca_dev, Clicksmart510_defaults);
876 break;
877 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300878 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879}
880
881static void sd_stopN(struct gspca_dev *gspca_dev)
882{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300883 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884
885 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300886 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
887 reg_r(gspca_dev, 0x8000, 1);
888 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
889 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890}
891
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300892static void sd_stop0(struct gspca_dev *gspca_dev)
893{
894 struct sd *sd = (struct sd *) gspca_dev;
895
896 kfree(sd->jpeg_hdr);
897}
898
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899static void sd_pkt_scan(struct gspca_dev *gspca_dev,
900 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300901 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902 int len) /* iso packet length */
903{
904 struct sd *sd = (struct sd *) gspca_dev;
905 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300906 __u8 *s, *d;
907 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908
909/* frames are jpeg 4.1.1 without 0xff escape */
910 if (data[0] == 0xff) {
911 if (data[1] != 0x01) { /* drop packet */
912/* gspca_dev->last_packet_type = DISCARD_PACKET; */
913 return;
914 }
915 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
916 ffd9, 2);
917
918 /* put the JPEG header in the new frame */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300919 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
920 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921
922 data += SPCA500_OFFSET_DATA;
923 len -= SPCA500_OFFSET_DATA;
924 } else {
925 data += 1;
926 len -= 1;
927 }
928
929 /* add 0x00 after 0xff */
930 for (i = len; --i >= 0; )
931 if (data[i] == 0xff)
932 break;
933 if (i < 0) { /* no 0xff */
934 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
935 return;
936 }
937 s = data;
938 d = sd->packet;
939 for (i = 0; i < len; i++) {
940 *d++ = *s++;
941 if (s[-1] == 0xff)
942 *d++ = 0x00;
943 }
944 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
945 sd->packet, d - sd->packet);
946}
947
948static void setbrightness(struct gspca_dev *gspca_dev)
949{
950 struct sd *sd = (struct sd *) gspca_dev;
951
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 (__u8) (sd->brightness - 128));
954}
955
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956static void setcontrast(struct gspca_dev *gspca_dev)
957{
958 struct sd *sd = (struct sd *) gspca_dev;
959
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300960 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961}
962
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963static void setcolors(struct gspca_dev *gspca_dev)
964{
965 struct sd *sd = (struct sd *) gspca_dev;
966
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300967 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968}
969
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
971{
972 struct sd *sd = (struct sd *) gspca_dev;
973
974 sd->brightness = val;
975 if (gspca_dev->streaming)
976 setbrightness(gspca_dev);
977 return 0;
978}
979
980static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
981{
982 struct sd *sd = (struct sd *) gspca_dev;
983
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 *val = sd->brightness;
985 return 0;
986}
987
988static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
989{
990 struct sd *sd = (struct sd *) gspca_dev;
991
992 sd->contrast = val;
993 if (gspca_dev->streaming)
994 setcontrast(gspca_dev);
995 return 0;
996}
997
998static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
999{
1000 struct sd *sd = (struct sd *) gspca_dev;
1001
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001002 *val = sd->contrast;
1003 return 0;
1004}
1005
1006static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1007{
1008 struct sd *sd = (struct sd *) gspca_dev;
1009
1010 sd->colors = val;
1011 if (gspca_dev->streaming)
1012 setcolors(gspca_dev);
1013 return 0;
1014}
1015
1016static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1017{
1018 struct sd *sd = (struct sd *) gspca_dev;
1019
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001020 *val = sd->colors;
1021 return 0;
1022}
1023
1024/* sub-driver description */
1025static struct sd_desc sd_desc = {
1026 .name = MODULE_NAME,
1027 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001028 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001029 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001030 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031 .start = sd_start,
1032 .stopN = sd_stopN,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -03001033 .stop0 = sd_stop0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001034 .pkt_scan = sd_pkt_scan,
1035};
1036
1037/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001038static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -03001039 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1040 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1041 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1042 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1043 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1044 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1045 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1046 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1047 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1048 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1049 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1050 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1051 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1052 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1053 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054 {}
1055};
1056MODULE_DEVICE_TABLE(usb, device_table);
1057
1058/* -- device connect -- */
1059static int sd_probe(struct usb_interface *intf,
1060 const struct usb_device_id *id)
1061{
1062 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1063 THIS_MODULE);
1064}
1065
1066static struct usb_driver sd_driver = {
1067 .name = MODULE_NAME,
1068 .id_table = device_table,
1069 .probe = sd_probe,
1070 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001071#ifdef CONFIG_PM
1072 .suspend = gspca_suspend,
1073 .resume = gspca_resume,
1074#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075};
1076
1077/* -- module insert / remove -- */
1078static int __init sd_mod_init(void)
1079{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001080 int ret;
1081 ret = usb_register(&sd_driver);
1082 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001083 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001084 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001085 return 0;
1086}
1087static void __exit sd_mod_exit(void)
1088{
1089 usb_deregister(&sd_driver);
1090 PDEBUG(D_PROBE, "deregistered");
1091}
1092
1093module_init(sd_mod_init);
1094module_exit(sd_mod_exit);