blob: 25cb68d0556d0e1440cbeab06dc21c4730a1bdc9 [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
Hans de Goedeb56ab4c2012-06-27 16:48:33 -030033#define QUALITY 85
34
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030035/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030039 char subtype;
40#define AgfaCl20 0
41#define AiptekPocketDV 1
42#define BenqDC1016 2
43#define CreativePCCam300 3
44#define DLinkDSC350 4
45#define Gsmartmini 5
46#define IntelPocketPCCamera 6
47#define KodakEZ200 7
48#define LogitechClickSmart310 8
49#define LogitechClickSmart510 9
50#define LogitechTraveler 10
51#define MustekGsmart300 11
52#define Optimedia 12
53#define PalmPixDC85 13
54#define ToptroIndus 14
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030055
Jean-François Moine9a731a32010-06-04 05:26:42 -030056 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030057};
58
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030059static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030060 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
61 .bytesperline = 320,
62 .sizeimage = 320 * 240 * 3 / 8 + 590,
63 .colorspace = V4L2_COLORSPACE_JPEG,
64 .priv = 1},
65 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
66 .bytesperline = 640,
67 .sizeimage = 640 * 480 * 3 / 8 + 590,
68 .colorspace = V4L2_COLORSPACE_JPEG,
69 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030070};
71
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030072static const struct v4l2_pix_format sif_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030073 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
74 .bytesperline = 176,
75 .sizeimage = 176 * 144 * 3 / 8 + 590,
76 .colorspace = V4L2_COLORSPACE_JPEG,
77 .priv = 1},
78 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
79 .bytesperline = 352,
80 .sizeimage = 352 * 288 * 3 / 8 + 590,
81 .colorspace = V4L2_COLORSPACE_JPEG,
82 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083};
84
85/* Frame packet header offsets for the spca500 */
86#define SPCA500_OFFSET_PADDINGLB 2
87#define SPCA500_OFFSET_PADDINGHB 3
88#define SPCA500_OFFSET_MODE 4
89#define SPCA500_OFFSET_IMGWIDTH 5
90#define SPCA500_OFFSET_IMGHEIGHT 6
91#define SPCA500_OFFSET_IMGMODE 7
92#define SPCA500_OFFSET_QTBLINDEX 8
93#define SPCA500_OFFSET_FRAMSEQ 9
94#define SPCA500_OFFSET_CDSPINFO 10
95#define SPCA500_OFFSET_GPIO 11
96#define SPCA500_OFFSET_AUGPIO 12
97#define SPCA500_OFFSET_DATA 16
98
99
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300100static const __u16 spca500_visual_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
102 * hue (H byte) = 0,
103 * saturation/hue enable,
104 * brightness/contrast enable.
105 */
106 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
107 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
108 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
109 * hue (H byte) = 0, saturation/hue enable,
110 * brightness/contrast enable.
111 * was 0x0003, now 0x0000.
112 */
113 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
114 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
115 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
116 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
117 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
118 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
119 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
120 {0x0c, 0x0004, 0x0000},
121 /* set interface */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300122 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300123};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300124static const __u16 Clicksmart510_defaults[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 {0x00, 0x00, 0x8211},
126 {0x00, 0x01, 0x82c0},
127 {0x00, 0x10, 0x82cb},
128 {0x00, 0x0f, 0x800d},
129 {0x00, 0x82, 0x8225},
130 {0x00, 0x21, 0x8228},
131 {0x00, 0x00, 0x8203},
132 {0x00, 0x00, 0x8204},
133 {0x00, 0x08, 0x8205},
134 {0x00, 0xf8, 0x8206},
135 {0x00, 0x28, 0x8207},
136 {0x00, 0xa0, 0x8208},
137 {0x00, 0x08, 0x824a},
138 {0x00, 0x08, 0x8214},
139 {0x00, 0x80, 0x82c1},
140 {0x00, 0x00, 0x82c2},
141 {0x00, 0x00, 0x82ca},
142 {0x00, 0x80, 0x82c1},
143 {0x00, 0x04, 0x82c2},
144 {0x00, 0x00, 0x82ca},
145 {0x00, 0xfc, 0x8100},
146 {0x00, 0xfc, 0x8105},
147 {0x00, 0x30, 0x8101},
148 {0x00, 0x00, 0x8102},
149 {0x00, 0x00, 0x8103},
150 {0x00, 0x66, 0x8107},
151 {0x00, 0x00, 0x816b},
152 {0x00, 0x00, 0x8155},
153 {0x00, 0x01, 0x8156},
154 {0x00, 0x60, 0x8157},
155 {0x00, 0x40, 0x8158},
156 {0x00, 0x0a, 0x8159},
157 {0x00, 0x06, 0x815a},
158 {0x00, 0x00, 0x813f},
159 {0x00, 0x00, 0x8200},
160 {0x00, 0x19, 0x8201},
161 {0x00, 0x00, 0x82c1},
162 {0x00, 0xa0, 0x82c2},
163 {0x00, 0x00, 0x82ca},
164 {0x00, 0x00, 0x8117},
165 {0x00, 0x00, 0x8118},
166 {0x00, 0x65, 0x8119},
167 {0x00, 0x00, 0x811a},
168 {0x00, 0x00, 0x811b},
169 {0x00, 0x55, 0x811c},
170 {0x00, 0x65, 0x811d},
171 {0x00, 0x55, 0x811e},
172 {0x00, 0x16, 0x811f},
173 {0x00, 0x19, 0x8120},
174 {0x00, 0x80, 0x8103},
175 {0x00, 0x83, 0x816b},
176 {0x00, 0x25, 0x8168},
177 {0x00, 0x01, 0x820f},
178 {0x00, 0xff, 0x8115},
179 {0x00, 0x48, 0x8116},
180 {0x00, 0x50, 0x8151},
181 {0x00, 0x40, 0x8152},
182 {0x00, 0x78, 0x8153},
183 {0x00, 0x40, 0x8154},
184 {0x00, 0x00, 0x8167},
185 {0x00, 0x20, 0x8168},
186 {0x00, 0x00, 0x816a},
187 {0x00, 0x03, 0x816b},
188 {0x00, 0x20, 0x8169},
189 {0x00, 0x60, 0x8157},
190 {0x00, 0x00, 0x8190},
191 {0x00, 0x00, 0x81a1},
192 {0x00, 0x00, 0x81b2},
193 {0x00, 0x27, 0x8191},
194 {0x00, 0x27, 0x81a2},
195 {0x00, 0x27, 0x81b3},
196 {0x00, 0x4b, 0x8192},
197 {0x00, 0x4b, 0x81a3},
198 {0x00, 0x4b, 0x81b4},
199 {0x00, 0x66, 0x8193},
200 {0x00, 0x66, 0x81a4},
201 {0x00, 0x66, 0x81b5},
202 {0x00, 0x79, 0x8194},
203 {0x00, 0x79, 0x81a5},
204 {0x00, 0x79, 0x81b6},
205 {0x00, 0x8a, 0x8195},
206 {0x00, 0x8a, 0x81a6},
207 {0x00, 0x8a, 0x81b7},
208 {0x00, 0x9b, 0x8196},
209 {0x00, 0x9b, 0x81a7},
210 {0x00, 0x9b, 0x81b8},
211 {0x00, 0xa6, 0x8197},
212 {0x00, 0xa6, 0x81a8},
213 {0x00, 0xa6, 0x81b9},
214 {0x00, 0xb2, 0x8198},
215 {0x00, 0xb2, 0x81a9},
216 {0x00, 0xb2, 0x81ba},
217 {0x00, 0xbe, 0x8199},
218 {0x00, 0xbe, 0x81aa},
219 {0x00, 0xbe, 0x81bb},
220 {0x00, 0xc8, 0x819a},
221 {0x00, 0xc8, 0x81ab},
222 {0x00, 0xc8, 0x81bc},
223 {0x00, 0xd2, 0x819b},
224 {0x00, 0xd2, 0x81ac},
225 {0x00, 0xd2, 0x81bd},
226 {0x00, 0xdb, 0x819c},
227 {0x00, 0xdb, 0x81ad},
228 {0x00, 0xdb, 0x81be},
229 {0x00, 0xe4, 0x819d},
230 {0x00, 0xe4, 0x81ae},
231 {0x00, 0xe4, 0x81bf},
232 {0x00, 0xed, 0x819e},
233 {0x00, 0xed, 0x81af},
234 {0x00, 0xed, 0x81c0},
235 {0x00, 0xf7, 0x819f},
236 {0x00, 0xf7, 0x81b0},
237 {0x00, 0xf7, 0x81c1},
238 {0x00, 0xff, 0x81a0},
239 {0x00, 0xff, 0x81b1},
240 {0x00, 0xff, 0x81c2},
241 {0x00, 0x03, 0x8156},
242 {0x00, 0x00, 0x8211},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x01, 0x8202},
245 {0x00, 0x30, 0x8101},
246 {0x00, 0x00, 0x8111},
247 {0x00, 0x00, 0x8112},
248 {0x00, 0x00, 0x8113},
249 {0x00, 0x00, 0x8114},
250 {}
251};
252
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300253static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254 { /* Q-table Y-components */
255 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
256 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
257 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
258 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
259 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
260 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
261 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
262 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
263 { /* Q-table C-components */
264 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
265 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
266 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
267 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
268 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
269 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
270 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
271 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
272};
273
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300274static const __u8 qtable_kodak_ez200[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300275 { /* Q-table Y-components */
276 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
277 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
278 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
279 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
280 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
281 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
282 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
283 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
284 { /* Q-table C-components */
285 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
286 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
287 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
288 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
289 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
290 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
291 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
292 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
293};
294
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300295static const __u8 qtable_pocketdv[2][64] = {
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300296 { /* Q-table Y-components start registers 0x8800 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
298 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
299 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
300 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
301 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
302 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
303 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
304 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
305 },
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300306 { /* Q-table C-components start registers 0x8840 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300307 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
308 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
309 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
310 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
311 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
312 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
313 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
314 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
315};
316
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300317/* read 'len' bytes to gspca_dev->usb_buf */
318static void reg_r(struct gspca_dev *gspca_dev,
319 __u16 index,
320 __u16 length)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300321{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300322 usb_control_msg(gspca_dev->dev,
323 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300324 0,
325 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300327 index, gspca_dev->usb_buf, length, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300328}
329
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300330static int reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300331 __u16 req, __u16 index, __u16 value)
332{
333 int ret;
334
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300335 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300336 ret = usb_control_msg(gspca_dev->dev,
337 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300339 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340 value, index, NULL, 0, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300341 if (ret < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300342 pr_err("reg write: error %d\n", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300343 return ret;
344}
345
346/* returns: negative is error, pos or zero is data */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300347static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348 __u16 req, /* bRequest */
349 __u16 index, /* wIndex */
350 __u16 length) /* wLength (1 or 2 only) */
351{
352 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300353
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300354 gspca_dev->usb_buf[1] = 0;
355 ret = usb_control_msg(gspca_dev->dev,
356 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 req,
358 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
359 0, /* value */
360 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300361 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 500); /* timeout */
363 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300364 pr_err("reg_r_12 err %d\n", ret);
Jean-François Moine0b656322010-09-13 05:19:58 -0300365 return ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300367 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300368}
369
370/*
371 * Simple function to wait for a given 8-bit value to be returned from
372 * a reg_read call.
373 * Returns: negative is error or timeout, zero is success.
374 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300375static int reg_r_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376 __u16 reg, __u16 index, __u16 value)
377{
378 int ret, cnt = 20;
379
380 while (--cnt > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300381 ret = reg_r_12(gspca_dev, reg, index, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 if (ret == value)
383 return 0;
384 msleep(50);
385 }
386 return -EIO;
387}
388
389static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300390 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300391{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300392 int ret, i = 0;
393
394 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300395 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396 if (ret < 0)
397 return ret;
398 i++;
399 }
400 return 0;
401}
402
403static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
404 unsigned int request,
405 unsigned int ybase,
406 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300407 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300408{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300409 int i, err;
410
411 /* loop over y components */
412 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300413 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300414 if (err < 0)
415 return err;
416 }
417
418 /* loop over c components */
419 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300420 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300421 if (err < 0)
422 return err;
423 }
424 return 0;
425}
426
427static void spca500_ping310(struct gspca_dev *gspca_dev)
428{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300429 reg_r(gspca_dev, 0x0d04, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300430 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300431 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432}
433
434static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
435{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300436 reg_r(gspca_dev, 0x0d05, 2);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300437 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300438 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
439 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300440 spca500_ping310(gspca_dev);
441
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300442 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
443 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
444 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
445 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
446 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
447 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
448 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
449 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
450 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
451 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452 /* 00 for adjust shutter */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300453 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
454 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
455 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456}
457
458static void spca500_setmode(struct gspca_dev *gspca_dev,
459 __u8 xmult, __u8 ymult)
460{
461 int mode;
462
463 /* set x multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300464 reg_w(gspca_dev, 0, 0x8001, xmult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300465
466 /* set y multiplier */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300467 reg_w(gspca_dev, 0, 0x8002, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468
469 /* use compressed mode, VGA, with mode specific subsample */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300470 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300471 reg_w(gspca_dev, 0, 0x8003, mode << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472}
473
474static int spca500_full_reset(struct gspca_dev *gspca_dev)
475{
476 int err;
477
478 /* send the reset command */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300479 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 if (err < 0)
481 return err;
482
483 /* wait for the reset to complete */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300484 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300485 if (err < 0)
486 return err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300487 err = reg_w(gspca_dev, 0xe0, 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_r_wait(gspca_dev, 0x06, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300491 if (err < 0) {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300492 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493 return err;
494 }
495 /* all ok */
496 return 0;
497}
498
499/* Synchro the Bridge with sensor */
500/* Maybe that will work on all spca500 chip */
501/* because i only own a clicksmart310 try for that chip */
502/* using spca50x_set_packet_size() cause an Ooops here */
503/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
504/* up-port the same feature as in 2.4.x kernel */
505static int spca500_synch310(struct gspca_dev *gspca_dev)
506{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
508 PDEBUG(D_ERR, "Set packet size: set interface error");
509 goto error;
510 }
511 spca500_ping310(gspca_dev);
512
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300513 reg_r(gspca_dev, 0x0d00, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514
515 /* need alt setting here */
516 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
517
518 /* Windoze use pipe with altsetting 6 why 7 here */
519 if (usb_set_interface(gspca_dev->dev,
520 gspca_dev->iface,
521 gspca_dev->alt) < 0) {
522 PDEBUG(D_ERR, "Set packet size: set interface error");
523 goto error;
524 }
525 return 0;
526error:
527 return -EBUSY;
528}
529
530static void spca500_reinit(struct gspca_dev *gspca_dev)
531{
532 int err;
533 __u8 Data;
534
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200535 /* some unknown command from Aiptek pocket dv and family300 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300537 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
538 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
539 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540
541 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543
544 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
545 qtable_pocketdv);
546 if (err < 0)
547 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
548
549 /* set qtable index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551 /* family cam Quicksmart stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300552 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300553 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300554 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300556 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 /*Start init sequence or stream */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300560 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 msleep(2000);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300562 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
563 reg_r(gspca_dev, 0x816b, 1);
564 Data = gspca_dev->usb_buf[0];
565 reg_w(gspca_dev, 0x00, 0x816b, Data);
566 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300567}
568
569/* this function is called at probe time */
570static int sd_config(struct gspca_dev *gspca_dev,
571 const struct usb_device_id *id)
572{
573 struct sd *sd = (struct sd *) gspca_dev;
574 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300575
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300576 cam = &gspca_dev->cam;
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300577 sd->subtype = id->driver_info;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 if (sd->subtype != LogitechClickSmart310) {
579 cam->cam_mode = vga_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300580 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 } else {
582 cam->cam_mode = sif_mode;
Julia Lawall80297122008-11-12 23:18:21 -0300583 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300585 return 0;
586}
587
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300588/* this function is called at probe and resume time */
589static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590{
591 struct sd *sd = (struct sd *) gspca_dev;
592
593 /* initialisation of spca500 based cameras is deferred */
594 PDEBUG(D_STREAM, "SPCA500 init");
595 if (sd->subtype == LogitechClickSmart310)
596 spca500_clksmart310_init(gspca_dev);
597/* else
598 spca500_initialise(gspca_dev); */
599 PDEBUG(D_STREAM, "SPCA500 init done");
600 return 0;
601}
602
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300603static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604{
605 struct sd *sd = (struct sd *) gspca_dev;
606 int err;
607 __u8 Data;
608 __u8 xmult, ymult;
609
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300610 /* create the JPEG header */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300611 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
612 0x22); /* JPEG 411 */
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300613 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300614
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615 if (sd->subtype == LogitechClickSmart310) {
616 xmult = 0x16;
617 ymult = 0x12;
618 } else {
619 xmult = 0x28;
620 ymult = 0x1e;
621 }
622
623 /* is there a sensor here ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300624 reg_r(gspca_dev, 0x8a04, 1);
625 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
626 gspca_dev->usb_buf[0]);
627 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 gspca_dev->curr_mode, xmult, ymult);
629
630 /* setup qtable */
631 switch (sd->subtype) {
632 case LogitechClickSmart310:
633 spca500_setmode(gspca_dev, xmult, ymult);
634
635 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300636 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
637 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 err = spca50x_setup_qtable(gspca_dev,
639 0x00, 0x8800, 0x8840,
640 qtable_creative_pccam);
641 if (err < 0)
642 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
643 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645
646 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300647 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 msleep(500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300649 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300650 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300652 reg_r(gspca_dev, 0x816b, 1);
653 Data = gspca_dev->usb_buf[0];
654 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655
656 spca500_synch310(gspca_dev);
657
658 write_vector(gspca_dev, spca500_visual_defaults);
659 spca500_setmode(gspca_dev, xmult, ymult);
660 /* enable drop packet */
Jean-Francois Moine48d7a892009-01-15 09:34:55 -0300661 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
662 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300663 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300664 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665 err = spca50x_setup_qtable(gspca_dev,
666 0x00, 0x8800, 0x8840,
667 qtable_creative_pccam);
668 if (err < 0)
669 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
670
671 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673
674 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300675 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300677 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300678 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300680 reg_r(gspca_dev, 0x816b, 1);
681 Data = gspca_dev->usb_buf[0];
682 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300683 break;
684 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
685 case IntelPocketPCCamera: /* FIXME: Temporary fix for
686 * Intel Pocket PC Camera
687 * - NWG (Sat 29th March 2003) */
688
689 /* do a full reset */
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300690 err = spca500_full_reset(gspca_dev);
691 if (err < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692 PDEBUG(D_ERR, "spca500_full_reset failed");
693
694 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300695 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696 if (err < 0)
697 PDEBUG(D_ERR, "failed to enable drop packet");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698 reg_w(gspca_dev, 0x00, 0x8880, 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699 err = spca50x_setup_qtable(gspca_dev,
700 0x00, 0x8800, 0x8840,
701 qtable_creative_pccam);
702 if (err < 0)
703 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
704
705 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
708 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300711 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300712 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 reg_r(gspca_dev, 0x816b, 1);
715 Data = gspca_dev->usb_buf[0];
716 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300718/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 break;
720 case KodakEZ200: /* Kodak EZ200 */
721
722 /* do a full reset */
723 err = spca500_full_reset(gspca_dev);
724 if (err < 0)
725 PDEBUG(D_ERR, "spca500_full_reset failed");
726 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300727 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
728 reg_w(gspca_dev, 0x00, 0x8880, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300729 err = spca50x_setup_qtable(gspca_dev,
730 0x00, 0x8800, 0x8840,
731 qtable_kodak_ez200);
732 if (err < 0)
733 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
734 spca500_setmode(gspca_dev, xmult, ymult);
735
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300736 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737
738 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300741 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300742 PDEBUG(D_ERR, "reg_r_wait() failed");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300744 reg_r(gspca_dev, 0x816b, 1);
745 Data = gspca_dev->usb_buf[0];
746 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300748/* write_vector(gspca_dev, spca500_visual_defaults); */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 break;
750
751 case BenqDC1016:
752 case DLinkDSC350: /* FamilyCam 300 */
753 case AiptekPocketDV: /* Aiptek PocketDV */
754 case Gsmartmini: /*Mustek Gsmart Mini */
755 case MustekGsmart300: /* Mustek Gsmart 300 */
756 case PalmPixDC85:
757 case Optimedia:
758 case ToptroIndus:
759 case AgfaCl20:
760 spca500_reinit(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300761 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764
765 err = spca50x_setup_qtable(gspca_dev,
766 0x00, 0x8800, 0x8840, qtable_pocketdv);
767 if (err < 0)
768 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300769 reg_w(gspca_dev, 0x00, 0x8880, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300770
771 /* familycam Quicksmart pocketDV stuff */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300772 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300773 /* Set agc transfer: synced between frames */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300776 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300777
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300778 spca500_setmode(gspca_dev, xmult, ymult);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300780 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300782 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300784 reg_r(gspca_dev, 0x816b, 1);
785 Data = gspca_dev->usb_buf[0];
786 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300787 break;
788 case LogitechTraveler:
789 case LogitechClickSmart510:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 reg_w(gspca_dev, 0x02, 0x00, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 /* enable drop packet */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300792 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300793
794 err = spca50x_setup_qtable(gspca_dev,
795 0x00, 0x8800,
796 0x8840, qtable_creative_pccam);
797 if (err < 0)
798 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300799 reg_w(gspca_dev, 0x00, 0x8880, 3);
800 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801 /* Init SDRAM - needed for SDRAM access */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300802 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803
804 spca500_setmode(gspca_dev, xmult, ymult);
805
806 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300807 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
808 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300810 reg_r(gspca_dev, 0x816b, 1);
811 Data = gspca_dev->usb_buf[0];
812 reg_w(gspca_dev, 0x00, 0x816b, Data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813 write_vector(gspca_dev, Clicksmart510_defaults);
814 break;
815 }
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300816 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817}
818
819static void sd_stopN(struct gspca_dev *gspca_dev)
820{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300821 reg_w(gspca_dev, 0, 0x8003, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822
823 /* switch to video camera mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
825 reg_r(gspca_dev, 0x8000, 1);
826 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
827 gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828}
829
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300831 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832 int len) /* iso packet length */
833{
834 struct sd *sd = (struct sd *) gspca_dev;
835 int i;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300836 static __u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837
838/* frames are jpeg 4.1.1 without 0xff escape */
839 if (data[0] == 0xff) {
840 if (data[1] != 0x01) { /* drop packet */
841/* gspca_dev->last_packet_type = DISCARD_PACKET; */
842 return;
843 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300844 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 ffd9, 2);
846
847 /* put the JPEG header in the new frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300848 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300849 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850
851 data += SPCA500_OFFSET_DATA;
852 len -= SPCA500_OFFSET_DATA;
853 } else {
854 data += 1;
855 len -= 1;
856 }
857
858 /* add 0x00 after 0xff */
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300859 i = 0;
860 do {
861 if (data[i] == 0xff) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300862 gspca_frame_add(gspca_dev, INTER_PACKET,
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300863 data, i + 1);
864 len -= i;
865 data += i;
866 *data = 0x00;
867 i = 0;
868 }
869 i++;
870 } while (i < len);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300871 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872}
873
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300874static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300876 reg_w(gspca_dev, 0x00, 0x8167,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300877 (__u8) (val - 128));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878}
879
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300880static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300882 reg_w(gspca_dev, 0x00, 0x8168, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883}
884
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300885static void setcolors(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300887 reg_w(gspca_dev, 0x00, 0x8169, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888}
889
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300890static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
891{
892 struct gspca_dev *gspca_dev =
893 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300894
895 gspca_dev->usb_err = 0;
896
897 if (!gspca_dev->streaming)
898 return 0;
899
900 switch (ctrl->id) {
901 case V4L2_CID_BRIGHTNESS:
902 setbrightness(gspca_dev, ctrl->val);
903 break;
904 case V4L2_CID_CONTRAST:
905 setcontrast(gspca_dev, ctrl->val);
906 break;
907 case V4L2_CID_SATURATION:
908 setcolors(gspca_dev, ctrl->val);
909 break;
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300910 }
911 return gspca_dev->usb_err;
912}
913
914static const struct v4l2_ctrl_ops sd_ctrl_ops = {
915 .s_ctrl = sd_s_ctrl,
916};
917
918static int sd_init_controls(struct gspca_dev *gspca_dev)
919{
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300920 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
921
922 gspca_dev->vdev.ctrl_handler = hdl;
Hans de Goedeb56ab4c2012-06-27 16:48:33 -0300923 v4l2_ctrl_handler_init(hdl, 3);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300924 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
925 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
926 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
927 V4L2_CID_CONTRAST, 0, 63, 1, 31);
928 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
929 V4L2_CID_SATURATION, 0, 63, 1, 31);
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300930
931 if (hdl->error) {
932 pr_err("Could not initialize controls\n");
933 return hdl->error;
934 }
935 return 0;
936}
937
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938/* sub-driver description */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300939static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 .name = MODULE_NAME,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300942 .init = sd_init,
Hans Verkuil9bf0c432012-05-16 07:29:00 -0300943 .init_controls = sd_init_controls,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 .start = sd_start,
945 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 .pkt_scan = sd_pkt_scan,
947};
948
949/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300950static const struct usb_device_id device_table[] = {
Jean-Francois Moine87581aa2008-07-26 14:30:01 -0300951 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
952 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
953 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
954 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
955 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
956 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
957 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
958 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
959 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
960 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
961 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
962 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
963 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
964 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
965 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 {}
967};
968MODULE_DEVICE_TABLE(usb, device_table);
969
970/* -- device connect -- */
971static int sd_probe(struct usb_interface *intf,
972 const struct usb_device_id *id)
973{
974 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
975 THIS_MODULE);
976}
977
978static struct usb_driver sd_driver = {
979 .name = MODULE_NAME,
980 .id_table = device_table,
981 .probe = sd_probe,
982 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300983#ifdef CONFIG_PM
984 .suspend = gspca_suspend,
985 .resume = gspca_resume,
Hans de Goede8bb58962012-06-30 06:44:47 -0300986 .reset_resume = gspca_resume,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300987#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988};
989
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800990module_usb_driver(sd_driver);