blob: 3a42506830f80971c098860f8ba8a96139a94e2b [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 Moinea5ae2062008-07-04 11:16:16 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4)
28static const char version[] = "2.1.4";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030038 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030039 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44
45 char qindex;
46 char subtype;
47#define AgfaCl20 0
48#define AiptekPocketDV 1
49#define BenqDC1016 2
50#define CreativePCCam300 3
51#define DLinkDSC350 4
52#define Gsmartmini 5
53#define IntelPocketPCCamera 6
54#define KodakEZ200 7
55#define LogitechClickSmart310 8
56#define LogitechClickSmart510 9
57#define LogitechTraveler 10
58#define MustekGsmart300 11
59#define Optimedia 12
60#define PalmPixDC85 13
61#define ToptroIndus 14
62};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030079 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030080 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081#define BRIGHTNESS_DEF 127
82 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030093 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030094 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095#define CONTRAST_DEF 31
96 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300107 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109#define COLOR_DEF 31
110 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115};
116
117static struct cam_mode vga_mode[] = {
118 {V4L2_PIX_FMT_JPEG, 320, 240, 1},
119 {V4L2_PIX_FMT_JPEG, 640, 480, 0},
120};
121
122static struct cam_mode sif_mode[] = {
123 {V4L2_PIX_FMT_JPEG, 176, 144, 1},
124 {V4L2_PIX_FMT_JPEG, 352, 288, 0},
125};
126
127/* Frame packet header offsets for the spca500 */
128#define SPCA500_OFFSET_PADDINGLB 2
129#define SPCA500_OFFSET_PADDINGHB 3
130#define SPCA500_OFFSET_MODE 4
131#define SPCA500_OFFSET_IMGWIDTH 5
132#define SPCA500_OFFSET_IMGHEIGHT 6
133#define SPCA500_OFFSET_IMGMODE 7
134#define SPCA500_OFFSET_QTBLINDEX 8
135#define SPCA500_OFFSET_FRAMSEQ 9
136#define SPCA500_OFFSET_CDSPINFO 10
137#define SPCA500_OFFSET_GPIO 11
138#define SPCA500_OFFSET_AUGPIO 12
139#define SPCA500_OFFSET_DATA 16
140
141
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300142static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
144 * hue (H byte) = 0,
145 * saturation/hue enable,
146 * brightness/contrast enable.
147 */
148 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
149 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
150 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
151 * hue (H byte) = 0, saturation/hue enable,
152 * brightness/contrast enable.
153 * was 0x0003, now 0x0000.
154 */
155 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
156 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
157 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
158 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
159 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
160 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
161 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
162 {0x0c, 0x0004, 0x0000},
163 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300164 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300166static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167 {0x00, 0x00, 0x8211},
168 {0x00, 0x01, 0x82c0},
169 {0x00, 0x10, 0x82cb},
170 {0x00, 0x0f, 0x800d},
171 {0x00, 0x82, 0x8225},
172 {0x00, 0x21, 0x8228},
173 {0x00, 0x00, 0x8203},
174 {0x00, 0x00, 0x8204},
175 {0x00, 0x08, 0x8205},
176 {0x00, 0xf8, 0x8206},
177 {0x00, 0x28, 0x8207},
178 {0x00, 0xa0, 0x8208},
179 {0x00, 0x08, 0x824a},
180 {0x00, 0x08, 0x8214},
181 {0x00, 0x80, 0x82c1},
182 {0x00, 0x00, 0x82c2},
183 {0x00, 0x00, 0x82ca},
184 {0x00, 0x80, 0x82c1},
185 {0x00, 0x04, 0x82c2},
186 {0x00, 0x00, 0x82ca},
187 {0x00, 0xfc, 0x8100},
188 {0x00, 0xfc, 0x8105},
189 {0x00, 0x30, 0x8101},
190 {0x00, 0x00, 0x8102},
191 {0x00, 0x00, 0x8103},
192 {0x00, 0x66, 0x8107},
193 {0x00, 0x00, 0x816b},
194 {0x00, 0x00, 0x8155},
195 {0x00, 0x01, 0x8156},
196 {0x00, 0x60, 0x8157},
197 {0x00, 0x40, 0x8158},
198 {0x00, 0x0a, 0x8159},
199 {0x00, 0x06, 0x815a},
200 {0x00, 0x00, 0x813f},
201 {0x00, 0x00, 0x8200},
202 {0x00, 0x19, 0x8201},
203 {0x00, 0x00, 0x82c1},
204 {0x00, 0xa0, 0x82c2},
205 {0x00, 0x00, 0x82ca},
206 {0x00, 0x00, 0x8117},
207 {0x00, 0x00, 0x8118},
208 {0x00, 0x65, 0x8119},
209 {0x00, 0x00, 0x811a},
210 {0x00, 0x00, 0x811b},
211 {0x00, 0x55, 0x811c},
212 {0x00, 0x65, 0x811d},
213 {0x00, 0x55, 0x811e},
214 {0x00, 0x16, 0x811f},
215 {0x00, 0x19, 0x8120},
216 {0x00, 0x80, 0x8103},
217 {0x00, 0x83, 0x816b},
218 {0x00, 0x25, 0x8168},
219 {0x00, 0x01, 0x820f},
220 {0x00, 0xff, 0x8115},
221 {0x00, 0x48, 0x8116},
222 {0x00, 0x50, 0x8151},
223 {0x00, 0x40, 0x8152},
224 {0x00, 0x78, 0x8153},
225 {0x00, 0x40, 0x8154},
226 {0x00, 0x00, 0x8167},
227 {0x00, 0x20, 0x8168},
228 {0x00, 0x00, 0x816a},
229 {0x00, 0x03, 0x816b},
230 {0x00, 0x20, 0x8169},
231 {0x00, 0x60, 0x8157},
232 {0x00, 0x00, 0x8190},
233 {0x00, 0x00, 0x81a1},
234 {0x00, 0x00, 0x81b2},
235 {0x00, 0x27, 0x8191},
236 {0x00, 0x27, 0x81a2},
237 {0x00, 0x27, 0x81b3},
238 {0x00, 0x4b, 0x8192},
239 {0x00, 0x4b, 0x81a3},
240 {0x00, 0x4b, 0x81b4},
241 {0x00, 0x66, 0x8193},
242 {0x00, 0x66, 0x81a4},
243 {0x00, 0x66, 0x81b5},
244 {0x00, 0x79, 0x8194},
245 {0x00, 0x79, 0x81a5},
246 {0x00, 0x79, 0x81b6},
247 {0x00, 0x8a, 0x8195},
248 {0x00, 0x8a, 0x81a6},
249 {0x00, 0x8a, 0x81b7},
250 {0x00, 0x9b, 0x8196},
251 {0x00, 0x9b, 0x81a7},
252 {0x00, 0x9b, 0x81b8},
253 {0x00, 0xa6, 0x8197},
254 {0x00, 0xa6, 0x81a8},
255 {0x00, 0xa6, 0x81b9},
256 {0x00, 0xb2, 0x8198},
257 {0x00, 0xb2, 0x81a9},
258 {0x00, 0xb2, 0x81ba},
259 {0x00, 0xbe, 0x8199},
260 {0x00, 0xbe, 0x81aa},
261 {0x00, 0xbe, 0x81bb},
262 {0x00, 0xc8, 0x819a},
263 {0x00, 0xc8, 0x81ab},
264 {0x00, 0xc8, 0x81bc},
265 {0x00, 0xd2, 0x819b},
266 {0x00, 0xd2, 0x81ac},
267 {0x00, 0xd2, 0x81bd},
268 {0x00, 0xdb, 0x819c},
269 {0x00, 0xdb, 0x81ad},
270 {0x00, 0xdb, 0x81be},
271 {0x00, 0xe4, 0x819d},
272 {0x00, 0xe4, 0x81ae},
273 {0x00, 0xe4, 0x81bf},
274 {0x00, 0xed, 0x819e},
275 {0x00, 0xed, 0x81af},
276 {0x00, 0xed, 0x81c0},
277 {0x00, 0xf7, 0x819f},
278 {0x00, 0xf7, 0x81b0},
279 {0x00, 0xf7, 0x81c1},
280 {0x00, 0xff, 0x81a0},
281 {0x00, 0xff, 0x81b1},
282 {0x00, 0xff, 0x81c2},
283 {0x00, 0x03, 0x8156},
284 {0x00, 0x00, 0x8211},
285 {0x00, 0x20, 0x8168},
286 {0x00, 0x01, 0x8202},
287 {0x00, 0x30, 0x8101},
288 {0x00, 0x00, 0x8111},
289 {0x00, 0x00, 0x8112},
290 {0x00, 0x00, 0x8113},
291 {0x00, 0x00, 0x8114},
292 {}
293};
294
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300295static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300296 { /* Q-table Y-components */
297 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
298 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
299 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
300 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
301 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
302 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
303 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
304 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
305 { /* Q-table C-components */
306 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
307 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
308 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
309 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
310 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
314};
315
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300316static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317 { /* Q-table Y-components */
318 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
319 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
320 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
321 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
322 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
323 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
324 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
325 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
326 { /* Q-table C-components */
327 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
328 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
329 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
330 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
331 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
332 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
333 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
334 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
335};
336
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300337static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300338 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300339 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
340 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
341 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
342 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
343 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
344 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
345 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
346 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
347 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300348 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300349 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
350 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
351 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
352 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
353 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
354 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
355 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
356 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
357};
358
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300359static void reg_r(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360 __u16 index,
361 __u8 *buffer, __u16 length)
362{
363 usb_control_msg(dev,
364 usb_rcvctrlpipe(dev, 0),
365 0,
366 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
367 0, /* value */
368 index, buffer, length, 500);
369}
370
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300371static int reg_w(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 __u16 req, __u16 index, __u16 value)
373{
374 int ret;
375
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300376 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377 ret = usb_control_msg(dev,
378 usb_sndctrlpipe(dev, 0),
379 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300380 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 if (ret < 0)
383 PDEBUG(D_ERR, "reg write: error %d", ret);
384 return ret;
385}
386
387/* returns: negative is error, pos or zero is data */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300388static int reg_r_12(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300389 __u16 req, /* bRequest */
390 __u16 index, /* wIndex */
391 __u16 length) /* wLength (1 or 2 only) */
392{
393 int ret;
394 __u8 buf[2];
395
396 buf[1] = 0;
397 ret = usb_control_msg(dev,
398 usb_rcvctrlpipe(dev, 0),
399 req,
400 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
401 0, /* value */
402 index,
403 buf, length,
404 500); /* timeout */
405 if (ret < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300406 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300407 return -1;
408 }
409 return (buf[1] << 8) + buf[0];
410}
411
412/*
413 * Simple function to wait for a given 8-bit value to be returned from
414 * a reg_read call.
415 * Returns: negative is error or timeout, zero is success.
416 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300417static int reg_r_wait(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300418 __u16 reg, __u16 index, __u16 value)
419{
420 int ret, cnt = 20;
421
422 while (--cnt > 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300423 ret = reg_r_12(dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300424 if (ret == value)
425 return 0;
426 msleep(50);
427 }
428 return -EIO;
429}
430
431static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300432 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433{
434 struct usb_device *dev = gspca_dev->dev;
435 int ret, i = 0;
436
437 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300438 ret = reg_w(dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439 if (ret < 0)
440 return ret;
441 i++;
442 }
443 return 0;
444}
445
446static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
447 unsigned int request,
448 unsigned int ybase,
449 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300450 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451{
452 struct usb_device *dev = gspca_dev->dev;
453 int i, err;
454
455 /* loop over y components */
456 for (i = 0; i < 64; i++) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300457 err = reg_w(dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300458 if (err < 0)
459 return err;
460 }
461
462 /* loop over c components */
463 for (i = 0; i < 64; i++) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300464 err = reg_w(dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300465 if (err < 0)
466 return err;
467 }
468 return 0;
469}
470
471static void spca500_ping310(struct gspca_dev *gspca_dev)
472{
473 __u8 Data[2];
474
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300475 reg_r(gspca_dev->dev, 0x0d04, Data, 2);
476 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300477 Data[0], Data[1]);
478}
479
480static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
481{
482 __u8 Data[2];
483
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300484 reg_r(gspca_dev->dev, 0x0d05, Data, 2);
485 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
486 Data[0], Data[1]);
487 reg_w(gspca_dev->dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 spca500_ping310(gspca_dev);
489
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300490 reg_w(gspca_dev->dev, 0x00, 0x8168, 0x22);
491 reg_w(gspca_dev->dev, 0x00, 0x816a, 0xc0);
492 reg_w(gspca_dev->dev, 0x00, 0x816b, 0x0b);
493 reg_w(gspca_dev->dev, 0x00, 0x8169, 0x25);
494 reg_w(gspca_dev->dev, 0x00, 0x8157, 0x5b);
495 reg_w(gspca_dev->dev, 0x00, 0x8158, 0x5b);
496 reg_w(gspca_dev->dev, 0x00, 0x813f, 0x03);
497 reg_w(gspca_dev->dev, 0x00, 0x8151, 0x4a);
498 reg_w(gspca_dev->dev, 0x00, 0x8153, 0x78);
499 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 /* 00 for adjust shutter */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300501 reg_w(gspca_dev->dev, 0x00, 0x0d02, 0x01);
502 reg_w(gspca_dev->dev, 0x00, 0x8169, 0x25);
503 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504}
505
506static void spca500_setmode(struct gspca_dev *gspca_dev,
507 __u8 xmult, __u8 ymult)
508{
509 int mode;
510
511 /* set x multiplier */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300512 reg_w(gspca_dev->dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513
514 /* set y multiplier */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300515 reg_w(gspca_dev->dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516
517 /* use compressed mode, VGA, with mode specific subsample */
518 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300519 reg_w(gspca_dev->dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520}
521
522static int spca500_full_reset(struct gspca_dev *gspca_dev)
523{
524 int err;
525
526 /* send the reset command */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300527 err = reg_w(gspca_dev->dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 if (err < 0)
529 return err;
530
531 /* wait for the reset to complete */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300532 err = reg_r_wait(gspca_dev->dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533 if (err < 0)
534 return err;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300535 err = reg_w(gspca_dev->dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536 if (err < 0)
537 return err;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300538 err = reg_r_wait(gspca_dev->dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300540 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 return err;
542 }
543 /* all ok */
544 return 0;
545}
546
547/* Synchro the Bridge with sensor */
548/* Maybe that will work on all spca500 chip */
549/* because i only own a clicksmart310 try for that chip */
550/* using spca50x_set_packet_size() cause an Ooops here */
551/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
552/* up-port the same feature as in 2.4.x kernel */
553static int spca500_synch310(struct gspca_dev *gspca_dev)
554{
555 __u8 Data;
556
557 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
558 PDEBUG(D_ERR, "Set packet size: set interface error");
559 goto error;
560 }
561 spca500_ping310(gspca_dev);
562
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300563 reg_r(gspca_dev->dev, 0x0d00, &Data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300564
565 /* need alt setting here */
566 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
567
568 /* Windoze use pipe with altsetting 6 why 7 here */
569 if (usb_set_interface(gspca_dev->dev,
570 gspca_dev->iface,
571 gspca_dev->alt) < 0) {
572 PDEBUG(D_ERR, "Set packet size: set interface error");
573 goto error;
574 }
575 return 0;
576error:
577 return -EBUSY;
578}
579
580static void spca500_reinit(struct gspca_dev *gspca_dev)
581{
582 int err;
583 __u8 Data;
584
585 /* some unknow command from Aiptek pocket dv and family300 */
586
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300587 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x01);
588 reg_w(gspca_dev->dev, 0x00, 0x0d03, 0x00);
589 reg_w(gspca_dev->dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590
591 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300592 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593
594 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
595 qtable_pocketdv);
596 if (err < 0)
597 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
598
599 /* set qtable index */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300600 reg_w(gspca_dev->dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 /* family cam Quicksmart stuff */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300602 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300604 reg_w(gspca_dev->dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300605 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300606 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607 /*Start init sequence or stream */
608
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300609 reg_w(gspca_dev->dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300611 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 msleep(2000);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300613 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
614 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
615 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616}
617
618/* this function is called at probe time */
619static int sd_config(struct gspca_dev *gspca_dev,
620 const struct usb_device_id *id)
621{
622 struct sd *sd = (struct sd *) gspca_dev;
623 struct cam *cam;
624 __u16 vendor;
625 __u16 product;
626
627 vendor = id->idVendor;
628 product = id->idProduct;
629 switch (vendor) {
630 case 0x040a: /* Kodak cameras */
631/* switch (product) { */
632/* case 0x0300: */
633 sd->subtype = KodakEZ200;
634/* break; */
635/* } */
636 break;
637 case 0x041e: /* Creative cameras */
638/* switch (product) { */
639/* case 0x400a: */
640 sd->subtype = CreativePCCam300;
641/* break; */
642/* } */
643 break;
644 case 0x046d: /* Logitech Labtec */
645 switch (product) {
646 case 0x0890:
647 sd->subtype = LogitechTraveler;
648 break;
649 case 0x0900:
650 sd->subtype = LogitechClickSmart310;
651 break;
652 case 0x0901:
653 sd->subtype = LogitechClickSmart510;
654 break;
655 }
656 break;
657 case 0x04a5: /* Benq */
658/* switch (product) { */
659/* case 0x300c: */
660 sd->subtype = BenqDC1016;
661/* break; */
662/* } */
663 break;
664 case 0x04fc: /* SunPlus */
665/* switch (product) { */
666/* case 0x7333: */
667 sd->subtype = PalmPixDC85;
668/* break; */
669/* } */
670 break;
671 case 0x055f: /* Mustek cameras */
672 switch (product) {
673 case 0xc200:
674 sd->subtype = MustekGsmart300;
675 break;
676 case 0xc220:
677 sd->subtype = Gsmartmini;
678 break;
679 }
680 break;
681 case 0x06bd: /* Agfa Cl20 */
682/* switch (product) { */
683/* case 0x0404: */
684 sd->subtype = AgfaCl20;
685/* break; */
686/* } */
687 break;
688 case 0x06be: /* Optimedia */
689/* switch (product) { */
690/* case 0x0800: */
691 sd->subtype = Optimedia;
692/* break; */
693/* } */
694 break;
695 case 0x084d: /* D-Link / Minton */
696/* switch (product) { */
697/* case 0x0003: * DSC-350 / S-Cam F5 */
698 sd->subtype = DLinkDSC350;
699/* break; */
700/* } */
701 break;
702 case 0x08ca: /* Aiptek */
703/* switch (product) { */
704/* case 0x0103: */
705 sd->subtype = AiptekPocketDV;
706/* break; */
707/* } */
708 break;
709 case 0x2899: /* ToptroIndustrial */
710/* switch (product) { */
711/* case 0x012c: */
712 sd->subtype = ToptroIndus;
713/* break; */
714/* } */
715 break;
716 case 0x8086: /* Intel */
717/* switch (product) { */
718/* case 0x0630: * Pocket PC Camera */
719 sd->subtype = IntelPocketPCCamera;
720/* break; */
721/* } */
722 break;
723 }
724 cam = &gspca_dev->cam;
725 cam->dev_name = (char *) id->driver_info;
726 cam->epaddr = 0x01;
727 if (sd->subtype != LogitechClickSmart310) {
728 cam->cam_mode = vga_mode;
729 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
730 } else {
731 cam->cam_mode = sif_mode;
732 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
733 }
734 sd->qindex = 5;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300735 sd->brightness = BRIGHTNESS_DEF;
736 sd->contrast = CONTRAST_DEF;
737 sd->colors = COLOR_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738 return 0;
739}
740
741/* this function is called at open time */
742static int sd_open(struct gspca_dev *gspca_dev)
743{
744 struct sd *sd = (struct sd *) gspca_dev;
745
746 /* initialisation of spca500 based cameras is deferred */
747 PDEBUG(D_STREAM, "SPCA500 init");
748 if (sd->subtype == LogitechClickSmart310)
749 spca500_clksmart310_init(gspca_dev);
750/* else
751 spca500_initialise(gspca_dev); */
752 PDEBUG(D_STREAM, "SPCA500 init done");
753 return 0;
754}
755
756static void sd_start(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759 int err;
760 __u8 Data;
761 __u8 xmult, ymult;
762
763 if (sd->subtype == LogitechClickSmart310) {
764 xmult = 0x16;
765 ymult = 0x12;
766 } else {
767 xmult = 0x28;
768 ymult = 0x1e;
769 }
770
771 /* is there a sensor here ? */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300772 reg_r(gspca_dev->dev, 0x8a04, &Data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02X", Data);
774 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02X, Ymult: 0x%02X",
775 gspca_dev->curr_mode, xmult, ymult);
776
777 /* setup qtable */
778 switch (sd->subtype) {
779 case LogitechClickSmart310:
780 spca500_setmode(gspca_dev, xmult, ymult);
781
782 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300783 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
784 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300785 err = spca50x_setup_qtable(gspca_dev,
786 0x00, 0x8800, 0x8840,
787 qtable_creative_pccam);
788 if (err < 0)
789 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
790 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300791 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792
793 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300794 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300795 msleep(500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300796 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
797 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300799 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
800 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801
802 spca500_synch310(gspca_dev);
803
804 write_vector(gspca_dev, spca500_visual_defaults);
805 spca500_setmode(gspca_dev, xmult, ymult);
806 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300807 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300809 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810 err = spca50x_setup_qtable(gspca_dev,
811 0x00, 0x8800, 0x8840,
812 qtable_creative_pccam);
813 if (err < 0)
814 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
815
816 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300817 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818
819 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300820 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300821
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300822 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
823 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300825 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
826 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 break;
828 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
829 case IntelPocketPCCamera: /* FIXME: Temporary fix for
830 * Intel Pocket PC Camera
831 * - NWG (Sat 29th March 2003) */
832
833 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300834 err = spca500_full_reset(gspca_dev);
835 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300836 PDEBUG(D_ERR, "spca500_full_reset failed");
837
838 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300839 err = reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 if (err < 0)
841 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300842 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 err = spca50x_setup_qtable(gspca_dev,
844 0x00, 0x8800, 0x8840,
845 qtable_creative_pccam);
846 if (err < 0)
847 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
848
849 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300850 reg_w(gspca_dev->dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300851
852 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300853 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300855 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
856 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300858 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
859 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300861/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862 break;
863 case KodakEZ200: /* Kodak EZ200 */
864
865 /* do a full reset */
866 err = spca500_full_reset(gspca_dev);
867 if (err < 0)
868 PDEBUG(D_ERR, "spca500_full_reset failed");
869 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300870 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
871 reg_w(gspca_dev->dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872 err = spca50x_setup_qtable(gspca_dev,
873 0x00, 0x8800, 0x8840,
874 qtable_kodak_ez200);
875 if (err < 0)
876 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
877 spca500_setmode(gspca_dev, xmult, ymult);
878
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300879 reg_w(gspca_dev->dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880
881 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300882 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300884 if (reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44) != 0)
885 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300887 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
888 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300890/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300891 break;
892
893 case BenqDC1016:
894 case DLinkDSC350: /* FamilyCam 300 */
895 case AiptekPocketDV: /* Aiptek PocketDV */
896 case Gsmartmini: /*Mustek Gsmart Mini */
897 case MustekGsmart300: /* Mustek Gsmart 300 */
898 case PalmPixDC85:
899 case Optimedia:
900 case ToptroIndus:
901 case AgfaCl20:
902 spca500_reinit(gspca_dev);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300903 reg_w(gspca_dev->dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300905 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906
907 err = spca50x_setup_qtable(gspca_dev,
908 0x00, 0x8800, 0x8840, qtable_pocketdv);
909 if (err < 0)
910 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300911 reg_w(gspca_dev->dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912
913 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300914 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 /* Set agc transfer: synced inbetween frames */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300916 reg_w(gspca_dev->dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300918 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300920 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300922 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300924 reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300925
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300926 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
927 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 break;
929 case LogitechTraveler:
930 case LogitechClickSmart510:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300931 reg_w(gspca_dev->dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 /* enable drop packet */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300933 reg_w(gspca_dev->dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934
935 err = spca50x_setup_qtable(gspca_dev,
936 0x00, 0x8800,
937 0x8840, qtable_creative_pccam);
938 if (err < 0)
939 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300940 reg_w(gspca_dev->dev, 0x00, 0x8880, 3);
941 reg_w(gspca_dev->dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300943 reg_w(gspca_dev->dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944
945 spca500_setmode(gspca_dev, xmult, ymult);
946
947 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300948 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
949 reg_r_wait(gspca_dev->dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300951 reg_r(gspca_dev->dev, 0x816b, &Data, 1);
952 reg_w(gspca_dev->dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 write_vector(gspca_dev, Clicksmart510_defaults);
954 break;
955 }
956}
957
958static void sd_stopN(struct gspca_dev *gspca_dev)
959{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300960 __u8 data;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300962 reg_w(gspca_dev->dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963
964 /* switch to video camera mode */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300965 reg_w(gspca_dev->dev, 0x00, 0x8000, 0x0004);
966 reg_r(gspca_dev->dev, 0x8000, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300967 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x", data);
968}
969
970static void sd_stop0(struct gspca_dev *gspca_dev)
971{
972}
973
974static void sd_close(struct gspca_dev *gspca_dev)
975{
976}
977
978static void sd_pkt_scan(struct gspca_dev *gspca_dev,
979 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300980 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300981 int len) /* iso packet length */
982{
983 struct sd *sd = (struct sd *) gspca_dev;
984 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985 __u8 *s, *d;
986 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987
988/* frames are jpeg 4.1.1 without 0xff escape */
989 if (data[0] == 0xff) {
990 if (data[1] != 0x01) { /* drop packet */
991/* gspca_dev->last_packet_type = DISCARD_PACKET; */
992 return;
993 }
994 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
995 ffd9, 2);
996
997 /* put the JPEG header in the new frame */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300998 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999
1000 data += SPCA500_OFFSET_DATA;
1001 len -= SPCA500_OFFSET_DATA;
1002 } else {
1003 data += 1;
1004 len -= 1;
1005 }
1006
1007 /* add 0x00 after 0xff */
1008 for (i = len; --i >= 0; )
1009 if (data[i] == 0xff)
1010 break;
1011 if (i < 0) { /* no 0xff */
1012 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1013 return;
1014 }
1015 s = data;
1016 d = sd->packet;
1017 for (i = 0; i < len; i++) {
1018 *d++ = *s++;
1019 if (s[-1] == 0xff)
1020 *d++ = 0x00;
1021 }
1022 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1023 sd->packet, d - sd->packet);
1024}
1025
1026static void setbrightness(struct gspca_dev *gspca_dev)
1027{
1028 struct sd *sd = (struct sd *) gspca_dev;
1029
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001030 reg_w(gspca_dev->dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031 (__u8) (sd->brightness - 128));
1032}
1033
1034static void getbrightness(struct gspca_dev *gspca_dev)
1035{
1036 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001037 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001039 ret = reg_r_12(gspca_dev->dev, 0x00, 0x8167, 1);
1040 if (ret >= 0)
1041 sd->brightness = ret + 128;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001042}
1043
1044static void setcontrast(struct gspca_dev *gspca_dev)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001048 reg_w(gspca_dev->dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049}
1050
1051static void getcontrast(struct gspca_dev *gspca_dev)
1052{
1053 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001054 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001056 ret = reg_r_12(gspca_dev->dev, 0x0, 0x8168, 1);
1057 if (ret >= 0)
1058 sd->contrast = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059}
1060
1061static void setcolors(struct gspca_dev *gspca_dev)
1062{
1063 struct sd *sd = (struct sd *) gspca_dev;
1064
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001065 reg_w(gspca_dev->dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001066}
1067
1068static void getcolors(struct gspca_dev *gspca_dev)
1069{
1070 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001071 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001073 ret = reg_r_12(gspca_dev->dev, 0x0, 0x8169, 1);
1074 if (ret >= 0)
1075 sd->colors = ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001076}
1077
1078static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1079{
1080 struct sd *sd = (struct sd *) gspca_dev;
1081
1082 sd->brightness = val;
1083 if (gspca_dev->streaming)
1084 setbrightness(gspca_dev);
1085 return 0;
1086}
1087
1088static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1089{
1090 struct sd *sd = (struct sd *) gspca_dev;
1091
1092 getbrightness(gspca_dev);
1093 *val = sd->brightness;
1094 return 0;
1095}
1096
1097static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1098{
1099 struct sd *sd = (struct sd *) gspca_dev;
1100
1101 sd->contrast = val;
1102 if (gspca_dev->streaming)
1103 setcontrast(gspca_dev);
1104 return 0;
1105}
1106
1107static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110
1111 getcontrast(gspca_dev);
1112 *val = sd->contrast;
1113 return 0;
1114}
1115
1116static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1117{
1118 struct sd *sd = (struct sd *) gspca_dev;
1119
1120 sd->colors = val;
1121 if (gspca_dev->streaming)
1122 setcolors(gspca_dev);
1123 return 0;
1124}
1125
1126static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1127{
1128 struct sd *sd = (struct sd *) gspca_dev;
1129
1130 getcolors(gspca_dev);
1131 *val = sd->colors;
1132 return 0;
1133}
1134
1135/* sub-driver description */
1136static struct sd_desc sd_desc = {
1137 .name = MODULE_NAME,
1138 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001139 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140 .config = sd_config,
1141 .open = sd_open,
1142 .start = sd_start,
1143 .stopN = sd_stopN,
1144 .stop0 = sd_stop0,
1145 .close = sd_close,
1146 .pkt_scan = sd_pkt_scan,
1147};
1148
1149/* -- module initialisation -- */
1150#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001151static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001152 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1153 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1154 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1155 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1156 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1157 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1158 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1159 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1160 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1161 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1162 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1163 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1164 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1165 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1166 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1167 {}
1168};
1169MODULE_DEVICE_TABLE(usb, device_table);
1170
1171/* -- device connect -- */
1172static int sd_probe(struct usb_interface *intf,
1173 const struct usb_device_id *id)
1174{
1175 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1176 THIS_MODULE);
1177}
1178
1179static struct usb_driver sd_driver = {
1180 .name = MODULE_NAME,
1181 .id_table = device_table,
1182 .probe = sd_probe,
1183 .disconnect = gspca_disconnect,
1184};
1185
1186/* -- module insert / remove -- */
1187static int __init sd_mod_init(void)
1188{
1189 if (usb_register(&sd_driver) < 0)
1190 return -1;
1191 PDEBUG(D_PROBE, "v%s registered", version);
1192 return 0;
1193}
1194static void __exit sd_mod_exit(void)
1195{
1196 usb_deregister(&sd_driver);
1197 PDEBUG(D_PROBE, "deregistered");
1198}
1199
1200module_init(sd_mod_init);
1201module_exit(sd_mod_exit);