blob: 103984708c771a9555ff4661cc13c0e1b5467fa7 [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
Joe Perches133a9fe2011-08-21 19:56:57 -030022#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030024#define MODULE_NAME "spca500"
25
26#include "gspca.h"
27#include "jpeg.h"
28
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030037 unsigned char brightness;
38 unsigned char contrast;
39 unsigned char colors;
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030040 u8 quality;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -030041#define QUALITY_MIN 70
42#define QUALITY_MAX 95
43#define QUALITY_DEF 85
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030044
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045 char subtype;
46#define AgfaCl20 0
47#define AiptekPocketDV 1
48#define BenqDC1016 2
49#define CreativePCCam300 3
50#define DLinkDSC350 4
51#define Gsmartmini 5
52#define IntelPocketPCCamera 6
53#define KodakEZ200 7
54#define LogitechClickSmart310 8
55#define LogitechClickSmart510 9
56#define LogitechTraveler 10
57#define MustekGsmart300 11
58#define Optimedia 12
59#define PalmPixDC85 13
60#define ToptroIndus 14
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030061
Jean-François Moine9a731a32010-06-04 05:26:42 -030062 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72
Marton Nemeth7e64dc42009-12-30 09:12:41 -030073static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030074 {
75 {
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "Brightness",
79 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030080 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030082#define BRIGHTNESS_DEF 127
83 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030084 },
85 .set = sd_setbrightness,
86 .get = sd_getbrightness,
87 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030088 {
89 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030094 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030095 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030096#define CONTRAST_DEF 31
97 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 },
99 .set = sd_setcontrast,
100 .get = sd_getcontrast,
101 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300102 {
103 {
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Color",
107 .minimum = 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300108 .maximum = 63,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300109 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300110#define COLOR_DEF 31
111 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300112 },
113 .set = sd_setcolors,
114 .get = sd_getcolors,
115 },
116};
117
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300118static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300119 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
120 .bytesperline = 320,
121 .sizeimage = 320 * 240 * 3 / 8 + 590,
122 .colorspace = V4L2_COLORSPACE_JPEG,
123 .priv = 1},
124 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
125 .bytesperline = 640,
126 .sizeimage = 640 * 480 * 3 / 8 + 590,
127 .colorspace = V4L2_COLORSPACE_JPEG,
128 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300129};
130
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300131static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300132 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 176,
134 .sizeimage = 176 * 144 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 1},
137 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 352,
139 .sizeimage = 352 * 288 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300142};
143
144/* Frame packet header offsets for the spca500 */
145#define SPCA500_OFFSET_PADDINGLB 2
146#define SPCA500_OFFSET_PADDINGHB 3
147#define SPCA500_OFFSET_MODE 4
148#define SPCA500_OFFSET_IMGWIDTH 5
149#define SPCA500_OFFSET_IMGHEIGHT 6
150#define SPCA500_OFFSET_IMGMODE 7
151#define SPCA500_OFFSET_QTBLINDEX 8
152#define SPCA500_OFFSET_FRAMSEQ 9
153#define SPCA500_OFFSET_CDSPINFO 10
154#define SPCA500_OFFSET_GPIO 11
155#define SPCA500_OFFSET_AUGPIO 12
156#define SPCA500_OFFSET_DATA 16
157
158
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300159static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
161 * hue (H byte) = 0,
162 * saturation/hue enable,
163 * brightness/contrast enable.
164 */
165 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
166 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
167 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
168 * hue (H byte) = 0, saturation/hue enable,
169 * brightness/contrast enable.
170 * was 0x0003, now 0x0000.
171 */
172 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
173 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
174 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
175 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
176 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
177 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
178 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
179 {0x0c, 0x0004, 0x0000},
180 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300181 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300183static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 {0x00, 0x00, 0x8211},
185 {0x00, 0x01, 0x82c0},
186 {0x00, 0x10, 0x82cb},
187 {0x00, 0x0f, 0x800d},
188 {0x00, 0x82, 0x8225},
189 {0x00, 0x21, 0x8228},
190 {0x00, 0x00, 0x8203},
191 {0x00, 0x00, 0x8204},
192 {0x00, 0x08, 0x8205},
193 {0x00, 0xf8, 0x8206},
194 {0x00, 0x28, 0x8207},
195 {0x00, 0xa0, 0x8208},
196 {0x00, 0x08, 0x824a},
197 {0x00, 0x08, 0x8214},
198 {0x00, 0x80, 0x82c1},
199 {0x00, 0x00, 0x82c2},
200 {0x00, 0x00, 0x82ca},
201 {0x00, 0x80, 0x82c1},
202 {0x00, 0x04, 0x82c2},
203 {0x00, 0x00, 0x82ca},
204 {0x00, 0xfc, 0x8100},
205 {0x00, 0xfc, 0x8105},
206 {0x00, 0x30, 0x8101},
207 {0x00, 0x00, 0x8102},
208 {0x00, 0x00, 0x8103},
209 {0x00, 0x66, 0x8107},
210 {0x00, 0x00, 0x816b},
211 {0x00, 0x00, 0x8155},
212 {0x00, 0x01, 0x8156},
213 {0x00, 0x60, 0x8157},
214 {0x00, 0x40, 0x8158},
215 {0x00, 0x0a, 0x8159},
216 {0x00, 0x06, 0x815a},
217 {0x00, 0x00, 0x813f},
218 {0x00, 0x00, 0x8200},
219 {0x00, 0x19, 0x8201},
220 {0x00, 0x00, 0x82c1},
221 {0x00, 0xa0, 0x82c2},
222 {0x00, 0x00, 0x82ca},
223 {0x00, 0x00, 0x8117},
224 {0x00, 0x00, 0x8118},
225 {0x00, 0x65, 0x8119},
226 {0x00, 0x00, 0x811a},
227 {0x00, 0x00, 0x811b},
228 {0x00, 0x55, 0x811c},
229 {0x00, 0x65, 0x811d},
230 {0x00, 0x55, 0x811e},
231 {0x00, 0x16, 0x811f},
232 {0x00, 0x19, 0x8120},
233 {0x00, 0x80, 0x8103},
234 {0x00, 0x83, 0x816b},
235 {0x00, 0x25, 0x8168},
236 {0x00, 0x01, 0x820f},
237 {0x00, 0xff, 0x8115},
238 {0x00, 0x48, 0x8116},
239 {0x00, 0x50, 0x8151},
240 {0x00, 0x40, 0x8152},
241 {0x00, 0x78, 0x8153},
242 {0x00, 0x40, 0x8154},
243 {0x00, 0x00, 0x8167},
244 {0x00, 0x20, 0x8168},
245 {0x00, 0x00, 0x816a},
246 {0x00, 0x03, 0x816b},
247 {0x00, 0x20, 0x8169},
248 {0x00, 0x60, 0x8157},
249 {0x00, 0x00, 0x8190},
250 {0x00, 0x00, 0x81a1},
251 {0x00, 0x00, 0x81b2},
252 {0x00, 0x27, 0x8191},
253 {0x00, 0x27, 0x81a2},
254 {0x00, 0x27, 0x81b3},
255 {0x00, 0x4b, 0x8192},
256 {0x00, 0x4b, 0x81a3},
257 {0x00, 0x4b, 0x81b4},
258 {0x00, 0x66, 0x8193},
259 {0x00, 0x66, 0x81a4},
260 {0x00, 0x66, 0x81b5},
261 {0x00, 0x79, 0x8194},
262 {0x00, 0x79, 0x81a5},
263 {0x00, 0x79, 0x81b6},
264 {0x00, 0x8a, 0x8195},
265 {0x00, 0x8a, 0x81a6},
266 {0x00, 0x8a, 0x81b7},
267 {0x00, 0x9b, 0x8196},
268 {0x00, 0x9b, 0x81a7},
269 {0x00, 0x9b, 0x81b8},
270 {0x00, 0xa6, 0x8197},
271 {0x00, 0xa6, 0x81a8},
272 {0x00, 0xa6, 0x81b9},
273 {0x00, 0xb2, 0x8198},
274 {0x00, 0xb2, 0x81a9},
275 {0x00, 0xb2, 0x81ba},
276 {0x00, 0xbe, 0x8199},
277 {0x00, 0xbe, 0x81aa},
278 {0x00, 0xbe, 0x81bb},
279 {0x00, 0xc8, 0x819a},
280 {0x00, 0xc8, 0x81ab},
281 {0x00, 0xc8, 0x81bc},
282 {0x00, 0xd2, 0x819b},
283 {0x00, 0xd2, 0x81ac},
284 {0x00, 0xd2, 0x81bd},
285 {0x00, 0xdb, 0x819c},
286 {0x00, 0xdb, 0x81ad},
287 {0x00, 0xdb, 0x81be},
288 {0x00, 0xe4, 0x819d},
289 {0x00, 0xe4, 0x81ae},
290 {0x00, 0xe4, 0x81bf},
291 {0x00, 0xed, 0x819e},
292 {0x00, 0xed, 0x81af},
293 {0x00, 0xed, 0x81c0},
294 {0x00, 0xf7, 0x819f},
295 {0x00, 0xf7, 0x81b0},
296 {0x00, 0xf7, 0x81c1},
297 {0x00, 0xff, 0x81a0},
298 {0x00, 0xff, 0x81b1},
299 {0x00, 0xff, 0x81c2},
300 {0x00, 0x03, 0x8156},
301 {0x00, 0x00, 0x8211},
302 {0x00, 0x20, 0x8168},
303 {0x00, 0x01, 0x8202},
304 {0x00, 0x30, 0x8101},
305 {0x00, 0x00, 0x8111},
306 {0x00, 0x00, 0x8112},
307 {0x00, 0x00, 0x8113},
308 {0x00, 0x00, 0x8114},
309 {}
310};
311
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300312static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300313 { /* Q-table Y-components */
314 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
315 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
316 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
317 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
318 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
319 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
320 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
321 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
322 { /* Q-table C-components */
323 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x0e, 0x14, 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 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
330 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
331};
332
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300333static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 { /* Q-table Y-components */
335 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
336 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
337 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
338 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
339 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
340 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
341 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
342 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
343 { /* Q-table C-components */
344 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x05, 0x07, 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 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
351 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
352};
353
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300354static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300355 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
357 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
358 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
359 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
360 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
361 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
362 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
363 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
364 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300365 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
367 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
368 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x13, 0x1a, 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 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
373 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
374};
375
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300376/* read 'len' bytes to gspca_dev->usb_buf */
377static void reg_r(struct gspca_dev *gspca_dev,
378 __u16 index,
379 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300380{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300381 usb_control_msg(gspca_dev->dev,
382 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383 0,
384 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
385 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300386 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300387}
388
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300389static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300390 __u16 req, __u16 index, __u16 value)
391{
392 int ret;
393
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300394 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300395 ret = usb_control_msg(gspca_dev->dev,
396 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300397 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300398 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300400 if (ret < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300401 pr_err("reg write: error %d\n", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300402 return ret;
403}
404
405/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300406static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300407 __u16 req, /* bRequest */
408 __u16 index, /* wIndex */
409 __u16 length) /* wLength (1 or 2 only) */
410{
411 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300412
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300413 gspca_dev->usb_buf[1] = 0;
414 ret = usb_control_msg(gspca_dev->dev,
415 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300416 req,
417 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
418 0, /* value */
419 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300420 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300421 500); /* timeout */
422 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300423 pr_err("reg_r_12 err %d\n", ret);
Jean-François Moine0b656322010-09-13 05:19:58 -0300424 return ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300426 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300427}
428
429/*
430 * Simple function to wait for a given 8-bit value to be returned from
431 * a reg_read call.
432 * Returns: negative is error or timeout, zero is success.
433 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300434static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435 __u16 reg, __u16 index, __u16 value)
436{
437 int ret, cnt = 20;
438
439 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300440 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300441 if (ret == value)
442 return 0;
443 msleep(50);
444 }
445 return -EIO;
446}
447
448static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300449 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451 int ret, i = 0;
452
453 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300454 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 if (ret < 0)
456 return ret;
457 i++;
458 }
459 return 0;
460}
461
462static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
463 unsigned int request,
464 unsigned int ybase,
465 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300466 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 int i, err;
469
470 /* loop over y components */
471 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300472 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473 if (err < 0)
474 return err;
475 }
476
477 /* loop over c components */
478 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300479 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 if (err < 0)
481 return err;
482 }
483 return 0;
484}
485
486static void spca500_ping310(struct gspca_dev *gspca_dev)
487{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300488 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300489 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300490 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300491}
492
493static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
494{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300495 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300496 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300497 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
498 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499 spca500_ping310(gspca_dev);
500
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300501 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
502 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
503 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
504 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
505 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
506 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
507 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
508 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
509 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
510 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300512 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
513 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
514 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515}
516
517static void spca500_setmode(struct gspca_dev *gspca_dev,
518 __u8 xmult, __u8 ymult)
519{
520 int mode;
521
522 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300523 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524
525 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300526 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300527
528 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300529 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300530 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300531}
532
533static int spca500_full_reset(struct gspca_dev *gspca_dev)
534{
535 int err;
536
537 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 if (err < 0)
540 return err;
541
542 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544 if (err < 0)
545 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300546 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547 if (err < 0)
548 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300549 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300551 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300552 return err;
553 }
554 /* all ok */
555 return 0;
556}
557
558/* Synchro the Bridge with sensor */
559/* Maybe that will work on all spca500 chip */
560/* because i only own a clicksmart310 try for that chip */
561/* using spca50x_set_packet_size() cause an Ooops here */
562/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
563/* up-port the same feature as in 2.4.x kernel */
564static int spca500_synch310(struct gspca_dev *gspca_dev)
565{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
567 PDEBUG(D_ERR, "Set packet size: set interface error");
568 goto error;
569 }
570 spca500_ping310(gspca_dev);
571
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300573
574 /* need alt setting here */
575 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
576
577 /* Windoze use pipe with altsetting 6 why 7 here */
578 if (usb_set_interface(gspca_dev->dev,
579 gspca_dev->iface,
580 gspca_dev->alt) < 0) {
581 PDEBUG(D_ERR, "Set packet size: set interface error");
582 goto error;
583 }
584 return 0;
585error:
586 return -EBUSY;
587}
588
589static void spca500_reinit(struct gspca_dev *gspca_dev)
590{
591 int err;
592 __u8 Data;
593
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200594 /* some unknown command from Aiptek pocket dv and family300 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300596 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
597 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
598 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300599
600 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300601 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300602
603 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
604 qtable_pocketdv);
605 if (err < 0)
606 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
607
608 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300609 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300611 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300612 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300613 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300621 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
622 reg_r(gspca_dev, 0x816b, 1);
623 Data = gspca_dev->usb_buf[0];
624 reg_w(gspca_dev, 0x00, 0x816b, Data);
625 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626}
627
628/* this function is called at probe time */
629static int sd_config(struct gspca_dev *gspca_dev,
630 const struct usb_device_id *id)
631{
632 struct sd *sd = (struct sd *) gspca_dev;
633 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300636 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637 if (sd->subtype != LogitechClickSmart310) {
638 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300639 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 } else {
641 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300642 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300644 sd->brightness = BRIGHTNESS_DEF;
645 sd->contrast = CONTRAST_DEF;
646 sd->colors = COLOR_DEF;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300647 sd->quality = QUALITY_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 return 0;
649}
650
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300651/* this function is called at probe and resume time */
652static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300653{
654 struct sd *sd = (struct sd *) gspca_dev;
655
656 /* initialisation of spca500 based cameras is deferred */
657 PDEBUG(D_STREAM, "SPCA500 init");
658 if (sd->subtype == LogitechClickSmart310)
659 spca500_clksmart310_init(gspca_dev);
660/* else
661 spca500_initialise(gspca_dev); */
662 PDEBUG(D_STREAM, "SPCA500 init done");
663 return 0;
664}
665
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300666static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667{
668 struct sd *sd = (struct sd *) gspca_dev;
669 int err;
670 __u8 Data;
671 __u8 xmult, ymult;
672
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300673 /* create the JPEG header */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300674 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
675 0x22); /* JPEG 411 */
676 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
677
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 if (sd->subtype == LogitechClickSmart310) {
679 xmult = 0x16;
680 ymult = 0x12;
681 } else {
682 xmult = 0x28;
683 ymult = 0x1e;
684 }
685
686 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300687 reg_r(gspca_dev, 0x8a04, 1);
688 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
689 gspca_dev->usb_buf[0]);
690 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 gspca_dev->curr_mode, xmult, ymult);
692
693 /* setup qtable */
694 switch (sd->subtype) {
695 case LogitechClickSmart310:
696 spca500_setmode(gspca_dev, xmult, ymult);
697
698 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300699 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
700 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 err = spca50x_setup_qtable(gspca_dev,
702 0x00, 0x8800, 0x8840,
703 qtable_creative_pccam);
704 if (err < 0)
705 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
706 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300707 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708
709 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300710 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300712 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300713 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300715 reg_r(gspca_dev, 0x816b, 1);
716 Data = gspca_dev->usb_buf[0];
717 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718
719 spca500_synch310(gspca_dev);
720
721 write_vector(gspca_dev, spca500_visual_defaults);
722 spca500_setmode(gspca_dev, xmult, ymult);
723 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300724 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
725 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300727 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728 err = spca50x_setup_qtable(gspca_dev,
729 0x00, 0x8800, 0x8840,
730 qtable_creative_pccam);
731 if (err < 0)
732 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
733
734 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300735 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736
737 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300738 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300740 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300741 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300743 reg_r(gspca_dev, 0x816b, 1);
744 Data = gspca_dev->usb_buf[0];
745 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 break;
747 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
748 case IntelPocketPCCamera: /* FIXME: Temporary fix for
749 * Intel Pocket PC Camera
750 * - NWG (Sat 29th March 2003) */
751
752 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300753 err = spca500_full_reset(gspca_dev);
754 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755 PDEBUG(D_ERR, "spca500_full_reset failed");
756
757 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300758 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 if (err < 0)
760 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300761 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762 err = spca50x_setup_qtable(gspca_dev,
763 0x00, 0x8800, 0x8840,
764 qtable_creative_pccam);
765 if (err < 0)
766 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
767
768 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300769 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300770
771 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300772 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300775 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300776
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 reg_r(gspca_dev, 0x816b, 1);
778 Data = gspca_dev->usb_buf[0];
779 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300781/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 break;
783 case KodakEZ200: /* Kodak EZ200 */
784
785 /* do a full reset */
786 err = spca500_full_reset(gspca_dev);
787 if (err < 0)
788 PDEBUG(D_ERR, "spca500_full_reset failed");
789 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
791 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 err = spca50x_setup_qtable(gspca_dev,
793 0x00, 0x8800, 0x8840,
794 qtable_kodak_ez200);
795 if (err < 0)
796 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
797 spca500_setmode(gspca_dev, xmult, ymult);
798
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300799 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800
801 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300802 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300804 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300805 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300807 reg_r(gspca_dev, 0x816b, 1);
808 Data = gspca_dev->usb_buf[0];
809 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300811/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812 break;
813
814 case BenqDC1016:
815 case DLinkDSC350: /* FamilyCam 300 */
816 case AiptekPocketDV: /* Aiptek PocketDV */
817 case Gsmartmini: /*Mustek Gsmart Mini */
818 case MustekGsmart300: /* Mustek Gsmart 300 */
819 case PalmPixDC85:
820 case Optimedia:
821 case ToptroIndus:
822 case AgfaCl20:
823 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300826 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827
828 err = spca50x_setup_qtable(gspca_dev,
829 0x00, 0x8800, 0x8840, qtable_pocketdv);
830 if (err < 0)
831 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300832 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833
834 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300835 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300836 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300837 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300839 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300841 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300843 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300845 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300847 reg_r(gspca_dev, 0x816b, 1);
848 Data = gspca_dev->usb_buf[0];
849 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 break;
851 case LogitechTraveler:
852 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300853 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300855 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856
857 err = spca50x_setup_qtable(gspca_dev,
858 0x00, 0x8800,
859 0x8840, qtable_creative_pccam);
860 if (err < 0)
861 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300862 reg_w(gspca_dev, 0x00, 0x8880, 3);
863 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300865 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866
867 spca500_setmode(gspca_dev, xmult, ymult);
868
869 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300870 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
871 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300873 reg_r(gspca_dev, 0x816b, 1);
874 Data = gspca_dev->usb_buf[0];
875 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876 write_vector(gspca_dev, Clicksmart510_defaults);
877 break;
878 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300879 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880}
881
882static void sd_stopN(struct gspca_dev *gspca_dev)
883{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300884 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885
886 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300887 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
888 reg_r(gspca_dev, 0x8000, 1);
889 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
890 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300891}
892
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300894 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300895 int len) /* iso packet length */
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300899 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900
901/* frames are jpeg 4.1.1 without 0xff escape */
902 if (data[0] == 0xff) {
903 if (data[1] != 0x01) { /* drop packet */
904/* gspca_dev->last_packet_type = DISCARD_PACKET; */
905 return;
906 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300907 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 ffd9, 2);
909
910 /* put the JPEG header in the new frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300911 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300912 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913
914 data += SPCA500_OFFSET_DATA;
915 len -= SPCA500_OFFSET_DATA;
916 } else {
917 data += 1;
918 len -= 1;
919 }
920
921 /* add 0x00 after 0xff */
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300922 i = 0;
923 do {
924 if (data[i] == 0xff) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300925 gspca_frame_add(gspca_dev, INTER_PACKET,
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300926 data, i + 1);
927 len -= i;
928 data += i;
929 *data = 0x00;
930 i = 0;
931 }
932 i++;
933 } while (i < len);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300934 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935}
936
937static void setbrightness(struct gspca_dev *gspca_dev)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300941 reg_w(gspca_dev, 0x00, 0x8167,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 (__u8) (sd->brightness - 128));
943}
944
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300945static void setcontrast(struct gspca_dev *gspca_dev)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300949 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950}
951
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952static void setcolors(struct gspca_dev *gspca_dev)
953{
954 struct sd *sd = (struct sd *) gspca_dev;
955
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300956 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957}
958
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 sd->brightness = val;
964 if (gspca_dev->streaming)
965 setbrightness(gspca_dev);
966 return 0;
967}
968
969static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
970{
971 struct sd *sd = (struct sd *) gspca_dev;
972
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 *val = sd->brightness;
974 return 0;
975}
976
977static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 sd->contrast = val;
982 if (gspca_dev->streaming)
983 setcontrast(gspca_dev);
984 return 0;
985}
986
987static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
988{
989 struct sd *sd = (struct sd *) gspca_dev;
990
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300991 *val = sd->contrast;
992 return 0;
993}
994
995static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 sd->colors = val;
1000 if (gspca_dev->streaming)
1001 setcolors(gspca_dev);
1002 return 0;
1003}
1004
1005static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1006{
1007 struct sd *sd = (struct sd *) gspca_dev;
1008
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 *val = sd->colors;
1010 return 0;
1011}
1012
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -03001013static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1014 struct v4l2_jpegcompression *jcomp)
1015{
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 if (jcomp->quality < QUALITY_MIN)
1019 sd->quality = QUALITY_MIN;
1020 else if (jcomp->quality > QUALITY_MAX)
1021 sd->quality = QUALITY_MAX;
1022 else
1023 sd->quality = jcomp->quality;
1024 if (gspca_dev->streaming)
1025 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1026 return 0;
1027}
1028
1029static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1030 struct v4l2_jpegcompression *jcomp)
1031{
1032 struct sd *sd = (struct sd *) gspca_dev;
1033
1034 memset(jcomp, 0, sizeof *jcomp);
1035 jcomp->quality = sd->quality;
1036 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1037 | V4L2_JPEG_MARKER_DQT;
1038 return 0;
1039}
1040
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001041/* sub-driver description */
Márton Némethaabcdfb2010-01-05 12:39:02 -03001042static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001043 .name = MODULE_NAME,
1044 .ctrls = sd_ctrls,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001045 .nctrls = ARRAY_SIZE(sd_ctrls),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001047 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001048 .start = sd_start,
1049 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050 .pkt_scan = sd_pkt_scan,
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -03001051 .get_jcomp = sd_get_jcomp,
1052 .set_jcomp = sd_set_jcomp,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053};
1054
1055/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001056static const struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -03001057 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1058 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1059 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1060 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1061 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1062 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1063 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1064 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1065 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1066 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1067 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1068 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1069 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1070 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1071 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072 {}
1073};
1074MODULE_DEVICE_TABLE(usb, device_table);
1075
1076/* -- device connect -- */
1077static int sd_probe(struct usb_interface *intf,
1078 const struct usb_device_id *id)
1079{
1080 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1081 THIS_MODULE);
1082}
1083
1084static struct usb_driver sd_driver = {
1085 .name = MODULE_NAME,
1086 .id_table = device_table,
1087 .probe = sd_probe,
1088 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001089#ifdef CONFIG_PM
1090 .suspend = gspca_suspend,
1091 .resume = gspca_resume,
1092#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001093};
1094
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001095module_usb_driver(sd_driver);