blob: 621b8095b0eb9d45f60a121857ba1498fef02f8b [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
Hans Verkuil9bf0c432012-05-16 07:29:00 -030037 struct v4l2_ctrl *jpegqual;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -030038#define QUALITY_MIN 70
39#define QUALITY_MAX 95
40#define QUALITY_DEF 85
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030041
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030042 char subtype;
43#define AgfaCl20 0
44#define AiptekPocketDV 1
45#define BenqDC1016 2
46#define CreativePCCam300 3
47#define DLinkDSC350 4
48#define Gsmartmini 5
49#define IntelPocketPCCamera 6
50#define KodakEZ200 7
51#define LogitechClickSmart310 8
52#define LogitechClickSmart510 9
53#define LogitechTraveler 10
54#define MustekGsmart300 11
55#define Optimedia 12
56#define PalmPixDC85 13
57#define ToptroIndus 14
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030058
Jean-François Moine9a731a32010-06-04 05:26:42 -030059 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060};
61
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030062static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030063 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
64 .bytesperline = 320,
65 .sizeimage = 320 * 240 * 3 / 8 + 590,
66 .colorspace = V4L2_COLORSPACE_JPEG,
67 .priv = 1},
68 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
69 .bytesperline = 640,
70 .sizeimage = 640 * 480 * 3 / 8 + 590,
71 .colorspace = V4L2_COLORSPACE_JPEG,
72 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073};
74
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030075static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030076 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
77 .bytesperline = 176,
78 .sizeimage = 176 * 144 * 3 / 8 + 590,
79 .colorspace = V4L2_COLORSPACE_JPEG,
80 .priv = 1},
81 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
82 .bytesperline = 352,
83 .sizeimage = 352 * 288 * 3 / 8 + 590,
84 .colorspace = V4L2_COLORSPACE_JPEG,
85 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086};
87
88/* Frame packet header offsets for the spca500 */
89#define SPCA500_OFFSET_PADDINGLB 2
90#define SPCA500_OFFSET_PADDINGHB 3
91#define SPCA500_OFFSET_MODE 4
92#define SPCA500_OFFSET_IMGWIDTH 5
93#define SPCA500_OFFSET_IMGHEIGHT 6
94#define SPCA500_OFFSET_IMGMODE 7
95#define SPCA500_OFFSET_QTBLINDEX 8
96#define SPCA500_OFFSET_FRAMSEQ 9
97#define SPCA500_OFFSET_CDSPINFO 10
98#define SPCA500_OFFSET_GPIO 11
99#define SPCA500_OFFSET_AUGPIO 12
100#define SPCA500_OFFSET_DATA 16
101
102
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300103static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300104 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
105 * hue (H byte) = 0,
106 * saturation/hue enable,
107 * brightness/contrast enable.
108 */
109 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
110 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
111 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
112 * hue (H byte) = 0, saturation/hue enable,
113 * brightness/contrast enable.
114 * was 0x0003, now 0x0000.
115 */
116 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
117 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
118 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
119 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
120 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
121 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
122 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
123 {0x0c, 0x0004, 0x0000},
124 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300125 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300127static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300128 {0x00, 0x00, 0x8211},
129 {0x00, 0x01, 0x82c0},
130 {0x00, 0x10, 0x82cb},
131 {0x00, 0x0f, 0x800d},
132 {0x00, 0x82, 0x8225},
133 {0x00, 0x21, 0x8228},
134 {0x00, 0x00, 0x8203},
135 {0x00, 0x00, 0x8204},
136 {0x00, 0x08, 0x8205},
137 {0x00, 0xf8, 0x8206},
138 {0x00, 0x28, 0x8207},
139 {0x00, 0xa0, 0x8208},
140 {0x00, 0x08, 0x824a},
141 {0x00, 0x08, 0x8214},
142 {0x00, 0x80, 0x82c1},
143 {0x00, 0x00, 0x82c2},
144 {0x00, 0x00, 0x82ca},
145 {0x00, 0x80, 0x82c1},
146 {0x00, 0x04, 0x82c2},
147 {0x00, 0x00, 0x82ca},
148 {0x00, 0xfc, 0x8100},
149 {0x00, 0xfc, 0x8105},
150 {0x00, 0x30, 0x8101},
151 {0x00, 0x00, 0x8102},
152 {0x00, 0x00, 0x8103},
153 {0x00, 0x66, 0x8107},
154 {0x00, 0x00, 0x816b},
155 {0x00, 0x00, 0x8155},
156 {0x00, 0x01, 0x8156},
157 {0x00, 0x60, 0x8157},
158 {0x00, 0x40, 0x8158},
159 {0x00, 0x0a, 0x8159},
160 {0x00, 0x06, 0x815a},
161 {0x00, 0x00, 0x813f},
162 {0x00, 0x00, 0x8200},
163 {0x00, 0x19, 0x8201},
164 {0x00, 0x00, 0x82c1},
165 {0x00, 0xa0, 0x82c2},
166 {0x00, 0x00, 0x82ca},
167 {0x00, 0x00, 0x8117},
168 {0x00, 0x00, 0x8118},
169 {0x00, 0x65, 0x8119},
170 {0x00, 0x00, 0x811a},
171 {0x00, 0x00, 0x811b},
172 {0x00, 0x55, 0x811c},
173 {0x00, 0x65, 0x811d},
174 {0x00, 0x55, 0x811e},
175 {0x00, 0x16, 0x811f},
176 {0x00, 0x19, 0x8120},
177 {0x00, 0x80, 0x8103},
178 {0x00, 0x83, 0x816b},
179 {0x00, 0x25, 0x8168},
180 {0x00, 0x01, 0x820f},
181 {0x00, 0xff, 0x8115},
182 {0x00, 0x48, 0x8116},
183 {0x00, 0x50, 0x8151},
184 {0x00, 0x40, 0x8152},
185 {0x00, 0x78, 0x8153},
186 {0x00, 0x40, 0x8154},
187 {0x00, 0x00, 0x8167},
188 {0x00, 0x20, 0x8168},
189 {0x00, 0x00, 0x816a},
190 {0x00, 0x03, 0x816b},
191 {0x00, 0x20, 0x8169},
192 {0x00, 0x60, 0x8157},
193 {0x00, 0x00, 0x8190},
194 {0x00, 0x00, 0x81a1},
195 {0x00, 0x00, 0x81b2},
196 {0x00, 0x27, 0x8191},
197 {0x00, 0x27, 0x81a2},
198 {0x00, 0x27, 0x81b3},
199 {0x00, 0x4b, 0x8192},
200 {0x00, 0x4b, 0x81a3},
201 {0x00, 0x4b, 0x81b4},
202 {0x00, 0x66, 0x8193},
203 {0x00, 0x66, 0x81a4},
204 {0x00, 0x66, 0x81b5},
205 {0x00, 0x79, 0x8194},
206 {0x00, 0x79, 0x81a5},
207 {0x00, 0x79, 0x81b6},
208 {0x00, 0x8a, 0x8195},
209 {0x00, 0x8a, 0x81a6},
210 {0x00, 0x8a, 0x81b7},
211 {0x00, 0x9b, 0x8196},
212 {0x00, 0x9b, 0x81a7},
213 {0x00, 0x9b, 0x81b8},
214 {0x00, 0xa6, 0x8197},
215 {0x00, 0xa6, 0x81a8},
216 {0x00, 0xa6, 0x81b9},
217 {0x00, 0xb2, 0x8198},
218 {0x00, 0xb2, 0x81a9},
219 {0x00, 0xb2, 0x81ba},
220 {0x00, 0xbe, 0x8199},
221 {0x00, 0xbe, 0x81aa},
222 {0x00, 0xbe, 0x81bb},
223 {0x00, 0xc8, 0x819a},
224 {0x00, 0xc8, 0x81ab},
225 {0x00, 0xc8, 0x81bc},
226 {0x00, 0xd2, 0x819b},
227 {0x00, 0xd2, 0x81ac},
228 {0x00, 0xd2, 0x81bd},
229 {0x00, 0xdb, 0x819c},
230 {0x00, 0xdb, 0x81ad},
231 {0x00, 0xdb, 0x81be},
232 {0x00, 0xe4, 0x819d},
233 {0x00, 0xe4, 0x81ae},
234 {0x00, 0xe4, 0x81bf},
235 {0x00, 0xed, 0x819e},
236 {0x00, 0xed, 0x81af},
237 {0x00, 0xed, 0x81c0},
238 {0x00, 0xf7, 0x819f},
239 {0x00, 0xf7, 0x81b0},
240 {0x00, 0xf7, 0x81c1},
241 {0x00, 0xff, 0x81a0},
242 {0x00, 0xff, 0x81b1},
243 {0x00, 0xff, 0x81c2},
244 {0x00, 0x03, 0x8156},
245 {0x00, 0x00, 0x8211},
246 {0x00, 0x20, 0x8168},
247 {0x00, 0x01, 0x8202},
248 {0x00, 0x30, 0x8101},
249 {0x00, 0x00, 0x8111},
250 {0x00, 0x00, 0x8112},
251 {0x00, 0x00, 0x8113},
252 {0x00, 0x00, 0x8114},
253 {}
254};
255
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300256static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300257 { /* Q-table Y-components */
258 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
259 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
260 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
261 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
262 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
263 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
264 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
265 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
266 { /* Q-table C-components */
267 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
268 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
269 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
270 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
271 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
272 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
273 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
274 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
275};
276
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300277static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300278 { /* Q-table Y-components */
279 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
280 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
281 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
282 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
283 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
284 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
285 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
286 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
287 { /* Q-table C-components */
288 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
289 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
290 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
291 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
292 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
293 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
294 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
295 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
296};
297
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300298static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300299 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300300 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
301 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
302 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
303 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
304 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
305 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
306 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
307 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
308 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300309 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300310 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
311 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
312 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
313 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
314 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
315 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
316 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
317 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
318};
319
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300320/* read 'len' bytes to gspca_dev->usb_buf */
321static void reg_r(struct gspca_dev *gspca_dev,
322 __u16 index,
323 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300324{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300325 usb_control_msg(gspca_dev->dev,
326 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327 0,
328 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
329 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300330 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300331}
332
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300333static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 __u16 req, __u16 index, __u16 value)
335{
336 int ret;
337
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300338 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300339 ret = usb_control_msg(gspca_dev->dev,
340 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300341 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300342 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300343 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 if (ret < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300345 pr_err("reg write: error %d\n", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300346 return ret;
347}
348
349/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300350static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300351 __u16 req, /* bRequest */
352 __u16 index, /* wIndex */
353 __u16 length) /* wLength (1 or 2 only) */
354{
355 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300357 gspca_dev->usb_buf[1] = 0;
358 ret = usb_control_msg(gspca_dev->dev,
359 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360 req,
361 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
362 0, /* value */
363 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300364 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300365 500); /* timeout */
366 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300367 pr_err("reg_r_12 err %d\n", ret);
Jean-François Moine0b656322010-09-13 05:19:58 -0300368 return ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300369 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300370 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371}
372
373/*
374 * Simple function to wait for a given 8-bit value to be returned from
375 * a reg_read call.
376 * Returns: negative is error or timeout, zero is success.
377 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300378static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379 __u16 reg, __u16 index, __u16 value)
380{
381 int ret, cnt = 20;
382
383 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300384 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385 if (ret == value)
386 return 0;
387 msleep(50);
388 }
389 return -EIO;
390}
391
392static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300393 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300394{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 int ret, i = 0;
396
397 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300398 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399 if (ret < 0)
400 return ret;
401 i++;
402 }
403 return 0;
404}
405
406static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
407 unsigned int request,
408 unsigned int ybase,
409 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300410 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300412 int i, err;
413
414 /* loop over y components */
415 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300416 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 if (err < 0)
418 return err;
419 }
420
421 /* loop over c components */
422 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300423 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300424 if (err < 0)
425 return err;
426 }
427 return 0;
428}
429
430static void spca500_ping310(struct gspca_dev *gspca_dev)
431{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300432 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300433 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300434 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435}
436
437static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
438{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300439 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300440 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300441 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
442 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300443 spca500_ping310(gspca_dev);
444
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300445 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
446 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
447 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
448 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
449 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
450 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
451 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
452 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
453 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
454 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300456 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
457 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
458 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300459}
460
461static void spca500_setmode(struct gspca_dev *gspca_dev,
462 __u8 xmult, __u8 ymult)
463{
464 int mode;
465
466 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300467 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468
469 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300470 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300471
472 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300473 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300474 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475}
476
477static int spca500_full_reset(struct gspca_dev *gspca_dev)
478{
479 int err;
480
481 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300482 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300483 if (err < 0)
484 return err;
485
486 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300487 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 if (err < 0)
489 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300490 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300491 if (err < 0)
492 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300493 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300495 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300496 return err;
497 }
498 /* all ok */
499 return 0;
500}
501
502/* Synchro the Bridge with sensor */
503/* Maybe that will work on all spca500 chip */
504/* because i only own a clicksmart310 try for that chip */
505/* using spca50x_set_packet_size() cause an Ooops here */
506/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
507/* up-port the same feature as in 2.4.x kernel */
508static int spca500_synch310(struct gspca_dev *gspca_dev)
509{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
511 PDEBUG(D_ERR, "Set packet size: set interface error");
512 goto error;
513 }
514 spca500_ping310(gspca_dev);
515
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300516 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517
518 /* need alt setting here */
519 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
520
521 /* Windoze use pipe with altsetting 6 why 7 here */
522 if (usb_set_interface(gspca_dev->dev,
523 gspca_dev->iface,
524 gspca_dev->alt) < 0) {
525 PDEBUG(D_ERR, "Set packet size: set interface error");
526 goto error;
527 }
528 return 0;
529error:
530 return -EBUSY;
531}
532
533static void spca500_reinit(struct gspca_dev *gspca_dev)
534{
535 int err;
536 __u8 Data;
537
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200538 /* some unknown command from Aiptek pocket dv and family300 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300540 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
541 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
542 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543
544 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546
547 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
548 qtable_pocketdv);
549 if (err < 0)
550 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
551
552 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300553 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300555 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300556 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300557 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300558 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300559 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300560 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300561 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300563 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300564 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300565 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
566 reg_r(gspca_dev, 0x816b, 1);
567 Data = gspca_dev->usb_buf[0];
568 reg_w(gspca_dev, 0x00, 0x816b, Data);
569 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570}
571
572/* this function is called at probe time */
573static int sd_config(struct gspca_dev *gspca_dev,
574 const struct usb_device_id *id)
575{
576 struct sd *sd = (struct sd *) gspca_dev;
577 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300580 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 if (sd->subtype != LogitechClickSmart310) {
582 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300583 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584 } else {
585 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300586 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588 return 0;
589}
590
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300591/* this function is called at probe and resume time */
592static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593{
594 struct sd *sd = (struct sd *) gspca_dev;
595
596 /* initialisation of spca500 based cameras is deferred */
597 PDEBUG(D_STREAM, "SPCA500 init");
598 if (sd->subtype == LogitechClickSmart310)
599 spca500_clksmart310_init(gspca_dev);
600/* else
601 spca500_initialise(gspca_dev); */
602 PDEBUG(D_STREAM, "SPCA500 init done");
603 return 0;
604}
605
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300606static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607{
608 struct sd *sd = (struct sd *) gspca_dev;
609 int err;
610 __u8 Data;
611 __u8 xmult, ymult;
612
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300613 /* create the JPEG header */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300614 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
615 0x22); /* JPEG 411 */
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300616 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300617
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 if (sd->subtype == LogitechClickSmart310) {
619 xmult = 0x16;
620 ymult = 0x12;
621 } else {
622 xmult = 0x28;
623 ymult = 0x1e;
624 }
625
626 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300627 reg_r(gspca_dev, 0x8a04, 1);
628 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
629 gspca_dev->usb_buf[0]);
630 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 gspca_dev->curr_mode, xmult, ymult);
632
633 /* setup qtable */
634 switch (sd->subtype) {
635 case LogitechClickSmart310:
636 spca500_setmode(gspca_dev, xmult, ymult);
637
638 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300639 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
640 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 err = spca50x_setup_qtable(gspca_dev,
642 0x00, 0x8800, 0x8840,
643 qtable_creative_pccam);
644 if (err < 0)
645 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
646 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300647 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648
649 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300650 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300652 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300653 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300655 reg_r(gspca_dev, 0x816b, 1);
656 Data = gspca_dev->usb_buf[0];
657 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658
659 spca500_synch310(gspca_dev);
660
661 write_vector(gspca_dev, spca500_visual_defaults);
662 spca500_setmode(gspca_dev, xmult, ymult);
663 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300664 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
665 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300666 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300667 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668 err = spca50x_setup_qtable(gspca_dev,
669 0x00, 0x8800, 0x8840,
670 qtable_creative_pccam);
671 if (err < 0)
672 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
673
674 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300675 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
677 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300678 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300680 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300681 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300683 reg_r(gspca_dev, 0x816b, 1);
684 Data = gspca_dev->usb_buf[0];
685 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 break;
687 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
688 case IntelPocketPCCamera: /* FIXME: Temporary fix for
689 * Intel Pocket PC Camera
690 * - NWG (Sat 29th March 2003) */
691
692 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300693 err = spca500_full_reset(gspca_dev);
694 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 PDEBUG(D_ERR, "spca500_full_reset failed");
696
697 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699 if (err < 0)
700 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300701 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702 err = spca50x_setup_qtable(gspca_dev,
703 0x00, 0x8800, 0x8840,
704 qtable_creative_pccam);
705 if (err < 0)
706 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
707
708 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
711 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300712 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300715 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300717 reg_r(gspca_dev, 0x816b, 1);
718 Data = gspca_dev->usb_buf[0];
719 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300721/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722 break;
723 case KodakEZ200: /* Kodak EZ200 */
724
725 /* do a full reset */
726 err = spca500_full_reset(gspca_dev);
727 if (err < 0)
728 PDEBUG(D_ERR, "spca500_full_reset failed");
729 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300730 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
731 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732 err = spca50x_setup_qtable(gspca_dev,
733 0x00, 0x8800, 0x8840,
734 qtable_kodak_ez200);
735 if (err < 0)
736 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
737 spca500_setmode(gspca_dev, xmult, ymult);
738
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740
741 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300742 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300744 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300745 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300747 reg_r(gspca_dev, 0x816b, 1);
748 Data = gspca_dev->usb_buf[0];
749 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300751/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752 break;
753
754 case BenqDC1016:
755 case DLinkDSC350: /* FamilyCam 300 */
756 case AiptekPocketDV: /* Aiptek PocketDV */
757 case Gsmartmini: /*Mustek Gsmart Mini */
758 case MustekGsmart300: /* Mustek Gsmart 300 */
759 case PalmPixDC85:
760 case Optimedia:
761 case ToptroIndus:
762 case AgfaCl20:
763 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300764 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300766 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767
768 err = spca50x_setup_qtable(gspca_dev,
769 0x00, 0x8800, 0x8840, qtable_pocketdv);
770 if (err < 0)
771 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300772 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773
774 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300775 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300776 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300779 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300781 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300783 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300785 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300787 reg_r(gspca_dev, 0x816b, 1);
788 Data = gspca_dev->usb_buf[0];
789 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300790 break;
791 case LogitechTraveler:
792 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300793 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300795 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300796
797 err = spca50x_setup_qtable(gspca_dev,
798 0x00, 0x8800,
799 0x8840, qtable_creative_pccam);
800 if (err < 0)
801 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300802 reg_w(gspca_dev, 0x00, 0x8880, 3);
803 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300805 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806
807 spca500_setmode(gspca_dev, xmult, ymult);
808
809 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300810 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
811 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300813 reg_r(gspca_dev, 0x816b, 1);
814 Data = gspca_dev->usb_buf[0];
815 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300816 write_vector(gspca_dev, Clicksmart510_defaults);
817 break;
818 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300819 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820}
821
822static void sd_stopN(struct gspca_dev *gspca_dev)
823{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825
826 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300827 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
828 reg_r(gspca_dev, 0x8000, 1);
829 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
830 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831}
832
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300834 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 int len) /* iso packet length */
836{
837 struct sd *sd = (struct sd *) gspca_dev;
838 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300839 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840
841/* frames are jpeg 4.1.1 without 0xff escape */
842 if (data[0] == 0xff) {
843 if (data[1] != 0x01) { /* drop packet */
844/* gspca_dev->last_packet_type = DISCARD_PACKET; */
845 return;
846 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300847 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 ffd9, 2);
849
850 /* put the JPEG header in the new frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300851 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300852 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853
854 data += SPCA500_OFFSET_DATA;
855 len -= SPCA500_OFFSET_DATA;
856 } else {
857 data += 1;
858 len -= 1;
859 }
860
861 /* add 0x00 after 0xff */
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300862 i = 0;
863 do {
864 if (data[i] == 0xff) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300865 gspca_frame_add(gspca_dev, INTER_PACKET,
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300866 data, i + 1);
867 len -= i;
868 data += i;
869 *data = 0x00;
870 i = 0;
871 }
872 i++;
873 } while (i < len);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875}
876
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300877static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300879 reg_w(gspca_dev, 0x00, 0x8167,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300880 (__u8) (val - 128));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881}
882
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300883static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300885 reg_w(gspca_dev, 0x00, 0x8168, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886}
887
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300888static void setcolors(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300890 reg_w(gspca_dev, 0x00, 0x8169, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300891}
892
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300893static int sd_set_jcomp(struct gspca_dev *gspca_dev,
894 struct v4l2_jpegcompression *jcomp)
895{
896 struct sd *sd = (struct sd *) gspca_dev;
897
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300898 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300899 return 0;
900}
901
902static int sd_get_jcomp(struct gspca_dev *gspca_dev,
903 struct v4l2_jpegcompression *jcomp)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906
907 memset(jcomp, 0, sizeof *jcomp);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300908 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300909 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
910 | V4L2_JPEG_MARKER_DQT;
911 return 0;
912}
913
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300914static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
915{
916 struct gspca_dev *gspca_dev =
917 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
918 struct sd *sd = (struct sd *)gspca_dev;
919
920 gspca_dev->usb_err = 0;
921
922 if (!gspca_dev->streaming)
923 return 0;
924
925 switch (ctrl->id) {
926 case V4L2_CID_BRIGHTNESS:
927 setbrightness(gspca_dev, ctrl->val);
928 break;
929 case V4L2_CID_CONTRAST:
930 setcontrast(gspca_dev, ctrl->val);
931 break;
932 case V4L2_CID_SATURATION:
933 setcolors(gspca_dev, ctrl->val);
934 break;
935 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
936 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
937 break;
938 }
939 return gspca_dev->usb_err;
940}
941
942static const struct v4l2_ctrl_ops sd_ctrl_ops = {
943 .s_ctrl = sd_s_ctrl,
944};
945
946static int sd_init_controls(struct gspca_dev *gspca_dev)
947{
948 struct sd *sd = (struct sd *)gspca_dev;
949 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
950
951 gspca_dev->vdev.ctrl_handler = hdl;
952 v4l2_ctrl_handler_init(hdl, 4);
953 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
954 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
955 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
956 V4L2_CID_CONTRAST, 0, 63, 1, 31);
957 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
958 V4L2_CID_SATURATION, 0, 63, 1, 31);
959 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
960 V4L2_CID_JPEG_COMPRESSION_QUALITY,
961 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
962
963 if (hdl->error) {
964 pr_err("Could not initialize controls\n");
965 return hdl->error;
966 }
967 return 0;
968}
969
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970/* sub-driver description */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300971static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300972 .name = MODULE_NAME,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300974 .init = sd_init,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300975 .init_controls = sd_init_controls,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976 .start = sd_start,
977 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 .pkt_scan = sd_pkt_scan,
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300979 .get_jcomp = sd_get_jcomp,
980 .set_jcomp = sd_set_jcomp,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300981};
982
983/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300984static const struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -0300985 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
986 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
987 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
988 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
989 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
990 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
991 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
992 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
993 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
994 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
995 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
996 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
997 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
998 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
999 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001000 {}
1001};
1002MODULE_DEVICE_TABLE(usb, device_table);
1003
1004/* -- device connect -- */
1005static int sd_probe(struct usb_interface *intf,
1006 const struct usb_device_id *id)
1007{
1008 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1009 THIS_MODULE);
1010}
1011
1012static struct usb_driver sd_driver = {
1013 .name = MODULE_NAME,
1014 .id_table = device_table,
1015 .probe = sd_probe,
1016 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001017#ifdef CONFIG_PM
1018 .suspend = gspca_suspend,
1019 .resume = gspca_resume,
1020#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021};
1022
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001023module_usb_driver(sd_driver);