blob: da2d9027914c61a9d33c8cd97f20277cdc9f3a35 [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 *
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030016 */
17
Joe Perches133a9fe2011-08-21 19:56:57 -030018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030020#define MODULE_NAME "spca500"
21
22#include "gspca.h"
23#include "jpeg.h"
24
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030025MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
27MODULE_LICENSE("GPL");
28
Hans de Goedeb56ab4c2012-06-27 16:48:33 -030029#define QUALITY 85
30
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030031/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030035 char subtype;
36#define AgfaCl20 0
37#define AiptekPocketDV 1
38#define BenqDC1016 2
39#define CreativePCCam300 3
40#define DLinkDSC350 4
41#define Gsmartmini 5
42#define IntelPocketPCCamera 6
43#define KodakEZ200 7
44#define LogitechClickSmart310 8
45#define LogitechClickSmart510 9
46#define LogitechTraveler 10
47#define MustekGsmart300 11
48#define Optimedia 12
49#define PalmPixDC85 13
50#define ToptroIndus 14
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030051
Jean-François Moine9a731a32010-06-04 05:26:42 -030052 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053};
54
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030055static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030056 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
57 .bytesperline = 320,
58 .sizeimage = 320 * 240 * 3 / 8 + 590,
59 .colorspace = V4L2_COLORSPACE_JPEG,
60 .priv = 1},
61 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
62 .bytesperline = 640,
63 .sizeimage = 640 * 480 * 3 / 8 + 590,
64 .colorspace = V4L2_COLORSPACE_JPEG,
65 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030066};
67
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030068static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030069 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
70 .bytesperline = 176,
71 .sizeimage = 176 * 144 * 3 / 8 + 590,
72 .colorspace = V4L2_COLORSPACE_JPEG,
73 .priv = 1},
74 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
75 .bytesperline = 352,
76 .sizeimage = 352 * 288 * 3 / 8 + 590,
77 .colorspace = V4L2_COLORSPACE_JPEG,
78 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030079};
80
81/* Frame packet header offsets for the spca500 */
82#define SPCA500_OFFSET_PADDINGLB 2
83#define SPCA500_OFFSET_PADDINGHB 3
84#define SPCA500_OFFSET_MODE 4
85#define SPCA500_OFFSET_IMGWIDTH 5
86#define SPCA500_OFFSET_IMGHEIGHT 6
87#define SPCA500_OFFSET_IMGMODE 7
88#define SPCA500_OFFSET_QTBLINDEX 8
89#define SPCA500_OFFSET_FRAMSEQ 9
90#define SPCA500_OFFSET_CDSPINFO 10
91#define SPCA500_OFFSET_GPIO 11
92#define SPCA500_OFFSET_AUGPIO 12
93#define SPCA500_OFFSET_DATA 16
94
95
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030096static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
98 * hue (H byte) = 0,
99 * saturation/hue enable,
100 * brightness/contrast enable.
101 */
102 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
103 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
104 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
105 * hue (H byte) = 0, saturation/hue enable,
106 * brightness/contrast enable.
107 * was 0x0003, now 0x0000.
108 */
109 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
110 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
111 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
112 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
113 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
114 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
115 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
116 {0x0c, 0x0004, 0x0000},
117 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300118 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300120static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121 {0x00, 0x00, 0x8211},
122 {0x00, 0x01, 0x82c0},
123 {0x00, 0x10, 0x82cb},
124 {0x00, 0x0f, 0x800d},
125 {0x00, 0x82, 0x8225},
126 {0x00, 0x21, 0x8228},
127 {0x00, 0x00, 0x8203},
128 {0x00, 0x00, 0x8204},
129 {0x00, 0x08, 0x8205},
130 {0x00, 0xf8, 0x8206},
131 {0x00, 0x28, 0x8207},
132 {0x00, 0xa0, 0x8208},
133 {0x00, 0x08, 0x824a},
134 {0x00, 0x08, 0x8214},
135 {0x00, 0x80, 0x82c1},
136 {0x00, 0x00, 0x82c2},
137 {0x00, 0x00, 0x82ca},
138 {0x00, 0x80, 0x82c1},
139 {0x00, 0x04, 0x82c2},
140 {0x00, 0x00, 0x82ca},
141 {0x00, 0xfc, 0x8100},
142 {0x00, 0xfc, 0x8105},
143 {0x00, 0x30, 0x8101},
144 {0x00, 0x00, 0x8102},
145 {0x00, 0x00, 0x8103},
146 {0x00, 0x66, 0x8107},
147 {0x00, 0x00, 0x816b},
148 {0x00, 0x00, 0x8155},
149 {0x00, 0x01, 0x8156},
150 {0x00, 0x60, 0x8157},
151 {0x00, 0x40, 0x8158},
152 {0x00, 0x0a, 0x8159},
153 {0x00, 0x06, 0x815a},
154 {0x00, 0x00, 0x813f},
155 {0x00, 0x00, 0x8200},
156 {0x00, 0x19, 0x8201},
157 {0x00, 0x00, 0x82c1},
158 {0x00, 0xa0, 0x82c2},
159 {0x00, 0x00, 0x82ca},
160 {0x00, 0x00, 0x8117},
161 {0x00, 0x00, 0x8118},
162 {0x00, 0x65, 0x8119},
163 {0x00, 0x00, 0x811a},
164 {0x00, 0x00, 0x811b},
165 {0x00, 0x55, 0x811c},
166 {0x00, 0x65, 0x811d},
167 {0x00, 0x55, 0x811e},
168 {0x00, 0x16, 0x811f},
169 {0x00, 0x19, 0x8120},
170 {0x00, 0x80, 0x8103},
171 {0x00, 0x83, 0x816b},
172 {0x00, 0x25, 0x8168},
173 {0x00, 0x01, 0x820f},
174 {0x00, 0xff, 0x8115},
175 {0x00, 0x48, 0x8116},
176 {0x00, 0x50, 0x8151},
177 {0x00, 0x40, 0x8152},
178 {0x00, 0x78, 0x8153},
179 {0x00, 0x40, 0x8154},
180 {0x00, 0x00, 0x8167},
181 {0x00, 0x20, 0x8168},
182 {0x00, 0x00, 0x816a},
183 {0x00, 0x03, 0x816b},
184 {0x00, 0x20, 0x8169},
185 {0x00, 0x60, 0x8157},
186 {0x00, 0x00, 0x8190},
187 {0x00, 0x00, 0x81a1},
188 {0x00, 0x00, 0x81b2},
189 {0x00, 0x27, 0x8191},
190 {0x00, 0x27, 0x81a2},
191 {0x00, 0x27, 0x81b3},
192 {0x00, 0x4b, 0x8192},
193 {0x00, 0x4b, 0x81a3},
194 {0x00, 0x4b, 0x81b4},
195 {0x00, 0x66, 0x8193},
196 {0x00, 0x66, 0x81a4},
197 {0x00, 0x66, 0x81b5},
198 {0x00, 0x79, 0x8194},
199 {0x00, 0x79, 0x81a5},
200 {0x00, 0x79, 0x81b6},
201 {0x00, 0x8a, 0x8195},
202 {0x00, 0x8a, 0x81a6},
203 {0x00, 0x8a, 0x81b7},
204 {0x00, 0x9b, 0x8196},
205 {0x00, 0x9b, 0x81a7},
206 {0x00, 0x9b, 0x81b8},
207 {0x00, 0xa6, 0x8197},
208 {0x00, 0xa6, 0x81a8},
209 {0x00, 0xa6, 0x81b9},
210 {0x00, 0xb2, 0x8198},
211 {0x00, 0xb2, 0x81a9},
212 {0x00, 0xb2, 0x81ba},
213 {0x00, 0xbe, 0x8199},
214 {0x00, 0xbe, 0x81aa},
215 {0x00, 0xbe, 0x81bb},
216 {0x00, 0xc8, 0x819a},
217 {0x00, 0xc8, 0x81ab},
218 {0x00, 0xc8, 0x81bc},
219 {0x00, 0xd2, 0x819b},
220 {0x00, 0xd2, 0x81ac},
221 {0x00, 0xd2, 0x81bd},
222 {0x00, 0xdb, 0x819c},
223 {0x00, 0xdb, 0x81ad},
224 {0x00, 0xdb, 0x81be},
225 {0x00, 0xe4, 0x819d},
226 {0x00, 0xe4, 0x81ae},
227 {0x00, 0xe4, 0x81bf},
228 {0x00, 0xed, 0x819e},
229 {0x00, 0xed, 0x81af},
230 {0x00, 0xed, 0x81c0},
231 {0x00, 0xf7, 0x819f},
232 {0x00, 0xf7, 0x81b0},
233 {0x00, 0xf7, 0x81c1},
234 {0x00, 0xff, 0x81a0},
235 {0x00, 0xff, 0x81b1},
236 {0x00, 0xff, 0x81c2},
237 {0x00, 0x03, 0x8156},
238 {0x00, 0x00, 0x8211},
239 {0x00, 0x20, 0x8168},
240 {0x00, 0x01, 0x8202},
241 {0x00, 0x30, 0x8101},
242 {0x00, 0x00, 0x8111},
243 {0x00, 0x00, 0x8112},
244 {0x00, 0x00, 0x8113},
245 {0x00, 0x00, 0x8114},
246 {}
247};
248
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300249static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300250 { /* Q-table Y-components */
251 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
252 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
253 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
254 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
255 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
256 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
257 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
258 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
259 { /* Q-table C-components */
260 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
261 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
262 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
263 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
264 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
265 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
266 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
267 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
268};
269
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300270static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300271 { /* Q-table Y-components */
272 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
273 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
274 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
275 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
276 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
277 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
278 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
279 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
280 { /* Q-table C-components */
281 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
282 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
283 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
284 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
285 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
286 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
287 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
288 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
289};
290
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300291static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300292 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300293 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
294 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
295 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
296 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
297 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
298 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
299 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
300 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
301 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300302 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300303 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
304 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
305 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
306 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
307 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
308 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
309 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
310 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
311};
312
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300313/* read 'len' bytes to gspca_dev->usb_buf */
314static void reg_r(struct gspca_dev *gspca_dev,
315 __u16 index,
316 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300318 usb_control_msg(gspca_dev->dev,
319 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300320 0,
321 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
322 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300323 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300324}
325
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300326static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327 __u16 req, __u16 index, __u16 value)
328{
329 int ret;
330
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300331 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300332 ret = usb_control_msg(gspca_dev->dev,
333 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300335 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337 if (ret < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300338 pr_err("reg write: error %d\n", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300339 return ret;
340}
341
342/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300343static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 __u16 req, /* bRequest */
345 __u16 index, /* wIndex */
346 __u16 length) /* wLength (1 or 2 only) */
347{
348 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300349
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300350 gspca_dev->usb_buf[1] = 0;
351 ret = usb_control_msg(gspca_dev->dev,
352 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300353 req,
354 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
355 0, /* value */
356 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300357 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358 500); /* timeout */
359 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300360 pr_err("reg_r_12 err %d\n", ret);
Jean-François Moine0b656322010-09-13 05:19:58 -0300361 return ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300363 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300364}
365
366/*
367 * Simple function to wait for a given 8-bit value to be returned from
368 * a reg_read call.
369 * Returns: negative is error or timeout, zero is success.
370 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300371static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 __u16 reg, __u16 index, __u16 value)
373{
374 int ret, cnt = 20;
375
376 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300377 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300378 if (ret == value)
379 return 0;
380 msleep(50);
381 }
382 return -EIO;
383}
384
385static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300386 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300387{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388 int ret, i = 0;
389
390 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300391 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300392 if (ret < 0)
393 return ret;
394 i++;
395 }
396 return 0;
397}
398
399static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
400 unsigned int request,
401 unsigned int ybase,
402 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300403 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300404{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300405 int i, err;
406
407 /* loop over y components */
408 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300409 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300410 if (err < 0)
411 return err;
412 }
413
414 /* loop over c components */
415 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300416 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 if (err < 0)
418 return err;
419 }
420 return 0;
421}
422
423static void spca500_ping310(struct gspca_dev *gspca_dev)
424{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300425 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300426 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300427 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300428}
429
430static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
431{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300432 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300433 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300434 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
435 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300436 spca500_ping310(gspca_dev);
437
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300438 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
439 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
440 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
441 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
442 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
443 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
444 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
445 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
446 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
447 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300448 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300449 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
450 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
451 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452}
453
454static void spca500_setmode(struct gspca_dev *gspca_dev,
455 __u8 xmult, __u8 ymult)
456{
457 int mode;
458
459 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300460 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461
462 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300463 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464
465 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300466 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300467 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468}
469
470static int spca500_full_reset(struct gspca_dev *gspca_dev)
471{
472 int err;
473
474 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300475 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300476 if (err < 0)
477 return err;
478
479 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300480 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300481 if (err < 0)
482 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300483 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300484 if (err < 0)
485 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300486 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300487 if (err < 0) {
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300488 PERR("reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489 return err;
490 }
491 /* all ok */
492 return 0;
493}
494
495/* Synchro the Bridge with sensor */
496/* Maybe that will work on all spca500 chip */
497/* because i only own a clicksmart310 try for that chip */
498/* using spca50x_set_packet_size() cause an Ooops here */
499/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
500/* up-port the same feature as in 2.4.x kernel */
501static int spca500_synch310(struct gspca_dev *gspca_dev)
502{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300504 PERR("Set packet size: set interface error");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300505 goto error;
506 }
507 spca500_ping310(gspca_dev);
508
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300509 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510
511 /* need alt setting here */
512 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
513
514 /* Windoze use pipe with altsetting 6 why 7 here */
515 if (usb_set_interface(gspca_dev->dev,
516 gspca_dev->iface,
517 gspca_dev->alt) < 0) {
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300518 PERR("Set packet size: set interface error");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 goto error;
520 }
521 return 0;
522error:
523 return -EBUSY;
524}
525
526static void spca500_reinit(struct gspca_dev *gspca_dev)
527{
528 int err;
529 __u8 Data;
530
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200531 /* some unknown command from Aiptek pocket dv and family300 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300533 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
534 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
535 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536
537 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539
540 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
541 qtable_pocketdv);
542 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300543 PERR("spca50x_setup_qtable failed on init");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544
545 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300546 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300548 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300549 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300552 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300553 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300554 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300556 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
559 reg_r(gspca_dev, 0x816b, 1);
560 Data = gspca_dev->usb_buf[0];
561 reg_w(gspca_dev, 0x00, 0x816b, Data);
562 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300563}
564
565/* this function is called at probe time */
566static int sd_config(struct gspca_dev *gspca_dev,
567 const struct usb_device_id *id)
568{
569 struct sd *sd = (struct sd *) gspca_dev;
570 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300572 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300573 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574 if (sd->subtype != LogitechClickSmart310) {
575 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300576 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577 } else {
578 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300579 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 return 0;
582}
583
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300584/* this function is called at probe and resume time */
585static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586{
587 struct sd *sd = (struct sd *) gspca_dev;
588
589 /* initialisation of spca500 based cameras is deferred */
590 PDEBUG(D_STREAM, "SPCA500 init");
591 if (sd->subtype == LogitechClickSmart310)
592 spca500_clksmart310_init(gspca_dev);
593/* else
594 spca500_initialise(gspca_dev); */
595 PDEBUG(D_STREAM, "SPCA500 init done");
596 return 0;
597}
598
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300599static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600{
601 struct sd *sd = (struct sd *) gspca_dev;
602 int err;
603 __u8 Data;
604 __u8 xmult, ymult;
605
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300606 /* create the JPEG header */
Ondrej Zary1966bc22013-08-30 17:54:23 -0300607 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
608 gspca_dev->pixfmt.width,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300609 0x22); /* JPEG 411 */
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300610 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300611
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 if (sd->subtype == LogitechClickSmart310) {
613 xmult = 0x16;
614 ymult = 0x12;
615 } else {
616 xmult = 0x28;
617 ymult = 0x1e;
618 }
619
620 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300621 reg_r(gspca_dev, 0x8a04, 1);
622 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
623 gspca_dev->usb_buf[0]);
624 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 gspca_dev->curr_mode, xmult, ymult);
626
627 /* setup qtable */
628 switch (sd->subtype) {
629 case LogitechClickSmart310:
630 spca500_setmode(gspca_dev, xmult, ymult);
631
632 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300633 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
634 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 err = spca50x_setup_qtable(gspca_dev,
636 0x00, 0x8800, 0x8840,
637 qtable_creative_pccam);
638 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300639 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300641 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300642
643 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300646 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300647 PERR("reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300649 reg_r(gspca_dev, 0x816b, 1);
650 Data = gspca_dev->usb_buf[0];
651 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652
653 spca500_synch310(gspca_dev);
654
655 write_vector(gspca_dev, spca500_visual_defaults);
656 spca500_setmode(gspca_dev, xmult, ymult);
657 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300658 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
659 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300660 PERR("failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300661 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 err = spca50x_setup_qtable(gspca_dev,
663 0x00, 0x8800, 0x8840,
664 qtable_creative_pccam);
665 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300666 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667
668 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300669 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670
671 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300674 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300675 PERR("reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300677 reg_r(gspca_dev, 0x816b, 1);
678 Data = gspca_dev->usb_buf[0];
679 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 break;
681 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
682 case IntelPocketPCCamera: /* FIXME: Temporary fix for
683 * Intel Pocket PC Camera
684 * - NWG (Sat 29th March 2003) */
685
686 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300687 err = spca500_full_reset(gspca_dev);
688 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300689 PERR("spca500_full_reset failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690
691 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300692 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300694 PERR("failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300695 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696 err = spca50x_setup_qtable(gspca_dev,
697 0x00, 0x8800, 0x8840,
698 qtable_creative_pccam);
699 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300700 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701
702 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300703 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704
705 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300708 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300709 PERR("reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300711 reg_r(gspca_dev, 0x816b, 1);
712 Data = gspca_dev->usb_buf[0];
713 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300715/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716 break;
717 case KodakEZ200: /* Kodak EZ200 */
718
719 /* do a full reset */
720 err = spca500_full_reset(gspca_dev);
721 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300722 PERR("spca500_full_reset failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300724 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
725 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726 err = spca50x_setup_qtable(gspca_dev,
727 0x00, 0x8800, 0x8840,
728 qtable_kodak_ez200);
729 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300730 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731 spca500_setmode(gspca_dev, xmult, ymult);
732
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300733 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734
735 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300736 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300738 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300739 PERR("reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300741 reg_r(gspca_dev, 0x816b, 1);
742 Data = gspca_dev->usb_buf[0];
743 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300745/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 break;
747
748 case BenqDC1016:
749 case DLinkDSC350: /* FamilyCam 300 */
750 case AiptekPocketDV: /* Aiptek PocketDV */
751 case Gsmartmini: /*Mustek Gsmart Mini */
752 case MustekGsmart300: /* Mustek Gsmart 300 */
753 case PalmPixDC85:
754 case Optimedia:
755 case ToptroIndus:
756 case AgfaCl20:
757 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300758 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761
762 err = spca50x_setup_qtable(gspca_dev,
763 0x00, 0x8800, 0x8840, qtable_pocketdv);
764 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300765 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300766 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767
768 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300769 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300770 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300771 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300773 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300775 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300776 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300779 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300781 reg_r(gspca_dev, 0x816b, 1);
782 Data = gspca_dev->usb_buf[0];
783 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 break;
785 case LogitechTraveler:
786 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300787 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300788 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300789 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300790
791 err = spca50x_setup_qtable(gspca_dev,
792 0x00, 0x8800,
793 0x8840, qtable_creative_pccam);
794 if (err < 0)
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300795 PERR("spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300796 reg_w(gspca_dev, 0x00, 0x8880, 3);
797 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300799 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800
801 spca500_setmode(gspca_dev, xmult, ymult);
802
803 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
805 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
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 write_vector(gspca_dev, Clicksmart510_defaults);
811 break;
812 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300813 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814}
815
816static void sd_stopN(struct gspca_dev *gspca_dev)
817{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300818 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300819
820 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300821 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
822 reg_r(gspca_dev, 0x8000, 1);
823 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
824 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825}
826
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300828 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 int len) /* iso packet length */
830{
831 struct sd *sd = (struct sd *) gspca_dev;
832 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300833 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834
835/* frames are jpeg 4.1.1 without 0xff escape */
836 if (data[0] == 0xff) {
837 if (data[1] != 0x01) { /* drop packet */
838/* gspca_dev->last_packet_type = DISCARD_PACKET; */
839 return;
840 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300841 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 ffd9, 2);
843
844 /* put the JPEG header in the new frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300845 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300846 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847
848 data += SPCA500_OFFSET_DATA;
849 len -= SPCA500_OFFSET_DATA;
850 } else {
851 data += 1;
852 len -= 1;
853 }
854
855 /* add 0x00 after 0xff */
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300856 i = 0;
857 do {
858 if (data[i] == 0xff) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300859 gspca_frame_add(gspca_dev, INTER_PACKET,
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300860 data, i + 1);
861 len -= i;
862 data += i;
863 *data = 0x00;
864 i = 0;
865 }
866 i++;
867 } while (i < len);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300868 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869}
870
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300871static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300873 reg_w(gspca_dev, 0x00, 0x8167,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300874 (__u8) (val - 128));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875}
876
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300877static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300879 reg_w(gspca_dev, 0x00, 0x8168, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880}
881
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300882static void setcolors(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300884 reg_w(gspca_dev, 0x00, 0x8169, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885}
886
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300887static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
888{
889 struct gspca_dev *gspca_dev =
890 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300891
892 gspca_dev->usb_err = 0;
893
894 if (!gspca_dev->streaming)
895 return 0;
896
897 switch (ctrl->id) {
898 case V4L2_CID_BRIGHTNESS:
899 setbrightness(gspca_dev, ctrl->val);
900 break;
901 case V4L2_CID_CONTRAST:
902 setcontrast(gspca_dev, ctrl->val);
903 break;
904 case V4L2_CID_SATURATION:
905 setcolors(gspca_dev, ctrl->val);
906 break;
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300907 }
908 return gspca_dev->usb_err;
909}
910
911static const struct v4l2_ctrl_ops sd_ctrl_ops = {
912 .s_ctrl = sd_s_ctrl,
913};
914
915static int sd_init_controls(struct gspca_dev *gspca_dev)
916{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300917 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
918
919 gspca_dev->vdev.ctrl_handler = hdl;
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300920 v4l2_ctrl_handler_init(hdl, 3);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300921 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
922 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
923 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
924 V4L2_CID_CONTRAST, 0, 63, 1, 31);
925 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
926 V4L2_CID_SATURATION, 0, 63, 1, 31);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300927
928 if (hdl->error) {
929 pr_err("Could not initialize controls\n");
930 return hdl->error;
931 }
932 return 0;
933}
934
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935/* sub-driver description */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300936static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 .name = MODULE_NAME,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300939 .init = sd_init,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300940 .init_controls = sd_init_controls,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 .start = sd_start,
942 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300943 .pkt_scan = sd_pkt_scan,
944};
945
946/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300947static const struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -0300948 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
949 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
950 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
951 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
952 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
953 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
954 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
955 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
956 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
957 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
958 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
959 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
960 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
961 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
962 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963 {}
964};
965MODULE_DEVICE_TABLE(usb, device_table);
966
967/* -- device connect -- */
968static int sd_probe(struct usb_interface *intf,
969 const struct usb_device_id *id)
970{
971 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
972 THIS_MODULE);
973}
974
975static struct usb_driver sd_driver = {
976 .name = MODULE_NAME,
977 .id_table = device_table,
978 .probe = sd_probe,
979 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300980#ifdef CONFIG_PM
981 .suspend = gspca_suspend,
982 .resume = gspca_resume,
Hans de Goede8bb58962012-06-30 06:44:47 -0300983 .reset_resume = gspca_resume,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300984#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985};
986
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800987module_usb_driver(sd_driver);