blob: 473e813b680e4dd0c1440bfdcdbc765485d98a7b [file] [log] [blame]
Kyle Guinnd661e622009-01-16 05:36:14 -03001/*
2 * Mars MR97310A library
3 *
Theodore Kilgore930bf782009-10-05 05:11:35 -03004 * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
Kyle Guinnd661e622009-01-16 05:36:14 -03005 * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
6 *
Theodore Kilgore89f08632009-08-14 06:51:52 -03007 * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
8 * and for the routines for detecting and classifying these various cameras,
Theodore Kilgore930bf782009-10-05 05:11:35 -03009 * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
Theodore Kilgore89f08632009-08-14 06:51:52 -030010 *
Theodore Kilgore930bf782009-10-05 05:11:35 -030011 * Support for the control settings for the CIF cameras is
Hans de Goede1fddcf02010-09-05 07:06:04 -030012 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
Theodore Kilgore930bf782009-10-05 05:11:35 -030013 * Thomas Kaiser <thomas@kaiser-linux.li>
14 *
15 * Support for the control settings for the VGA cameras is
Theodore Kilgore89f08632009-08-14 06:51:52 -030016 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
17 *
Theodore Kilgore930bf782009-10-05 05:11:35 -030018 * Several previously unsupported cameras are owned and have been tested by
Hans de Goede1fddcf02010-09-05 07:06:04 -030019 * Hans de Goede <hdegoede@redhat.com> and
Theodore Kilgore930bf782009-10-05 05:11:35 -030020 * Thomas Kaiser <thomas@kaiser-linux.li> and
Theodore Kilgore1160a382009-10-30 04:29:56 -030021 * Theodore Kilgore <kilgota@auburn.edu> and
22 * Edmond Rodriguez <erodrig_97@yahoo.com> and
23 * Aurelien Jacobs <aurel@gnuage.org>
Theodore Kilgore89f08632009-08-14 06:51:52 -030024 *
25 * The MR97311A support in gspca/mars.c has been helpful in understanding some
26 * of the registers in these cameras.
27 *
Kyle Guinnd661e622009-01-16 05:36:14 -030028 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 */
42
Joe Perches133a9fe2011-08-21 19:56:57 -030043#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
44
Kyle Guinnd661e622009-01-16 05:36:14 -030045#define MODULE_NAME "mr97310a"
46
47#include "gspca.h"
48
Theodore Kilgore89f08632009-08-14 06:51:52 -030049#define CAM_TYPE_CIF 0
50#define CAM_TYPE_VGA 1
51
Theodore Kilgore89f08632009-08-14 06:51:52 -030052#define MR97310A_BRIGHTNESS_DEFAULT 0
53
Theodore Kilgore930bf782009-10-05 05:11:35 -030054#define MR97310A_EXPOSURE_MIN 0
Theodore Kilgore89f08632009-08-14 06:51:52 -030055#define MR97310A_EXPOSURE_MAX 4095
56#define MR97310A_EXPOSURE_DEFAULT 1000
57
58#define MR97310A_GAIN_MIN 0
59#define MR97310A_GAIN_MAX 31
60#define MR97310A_GAIN_DEFAULT 25
61
Theodore Kilgore9d3103d2010-02-09 18:05:25 -030062#define MR97310A_CONTRAST_MIN 0
63#define MR97310A_CONTRAST_MAX 31
64#define MR97310A_CONTRAST_DEFAULT 23
65
66#define MR97310A_CS_GAIN_MIN 0
67#define MR97310A_CS_GAIN_MAX 0x7ff
68#define MR97310A_CS_GAIN_DEFAULT 0x110
69
Hans de Goede065b6f72009-10-29 07:42:30 -030070#define MR97310A_MIN_CLOCKDIV_MIN 3
71#define MR97310A_MIN_CLOCKDIV_MAX 8
72#define MR97310A_MIN_CLOCKDIV_DEFAULT 3
73
Theodore Kilgore89f08632009-08-14 06:51:52 -030074MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
75 "Theodore Kilgore <kilgota@auburn.edu>");
Kyle Guinnd661e622009-01-16 05:36:14 -030076MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
77MODULE_LICENSE("GPL");
78
Hans de Goede78028702009-09-02 09:55:16 -030079/* global parameters */
Jean-Francois Moine83955552009-12-12 06:58:01 -030080static int force_sensor_type = -1;
Hans de Goede78028702009-09-02 09:55:16 -030081module_param(force_sensor_type, int, 0644);
82MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
83
Kyle Guinnd661e622009-01-16 05:36:14 -030084/* specific webcam descriptor */
85struct sd {
86 struct gspca_dev gspca_dev; /* !! must be the first item */
Kyle Guinnd661e622009-01-16 05:36:14 -030087 u8 sof_read;
Theodore Kilgore89f08632009-08-14 06:51:52 -030088 u8 cam_type; /* 0 is CIF and 1 is VGA */
89 u8 sensor_type; /* We use 0 and 1 here, too. */
90 u8 do_lcd_stop;
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -030091 u8 adj_colors;
Theodore Kilgore89f08632009-08-14 06:51:52 -030092
93 int brightness;
94 u16 exposure;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -030095 u32 gain;
96 u8 contrast;
Hans de Goede065b6f72009-10-29 07:42:30 -030097 u8 min_clockdiv;
Kyle Guinnd661e622009-01-16 05:36:14 -030098};
99
Theodore Kilgore89f08632009-08-14 06:51:52 -0300100struct sensor_w_data {
101 u8 reg;
102 u8 flags;
103 u8 data[16];
104 int len;
105};
106
Theodore Kilgore930bf782009-10-05 05:11:35 -0300107static void sd_stopN(struct gspca_dev *gspca_dev);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300108static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
111static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300112static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
113static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300114static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede065b6f72009-10-29 07:42:30 -0300116static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
117static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede9ac69782009-08-14 10:15:52 -0300118static void setbrightness(struct gspca_dev *gspca_dev);
119static void setexposure(struct gspca_dev *gspca_dev);
120static void setgain(struct gspca_dev *gspca_dev);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300121static void setcontrast(struct gspca_dev *gspca_dev);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300122
Kyle Guinnd661e622009-01-16 05:36:14 -0300123/* V4L2 controls supported by the driver */
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300124static const struct ctrl sd_ctrls[] = {
Theodore Kilgore1160a382009-10-30 04:29:56 -0300125/* Separate brightness control description for Argus QuickClix as it has
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300126 * different limits from the other mr97310a cameras, and separate gain
127 * control for Sakar CyberPix camera. */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300128 {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300129#define NORM_BRIGHTNESS_IDX 0
Theodore Kilgore89f08632009-08-14 06:51:52 -0300130 {
131 .id = V4L2_CID_BRIGHTNESS,
132 .type = V4L2_CTRL_TYPE_INTEGER,
133 .name = "Brightness",
Theodore Kilgore930bf782009-10-05 05:11:35 -0300134 .minimum = -254,
135 .maximum = 255,
Theodore Kilgore89f08632009-08-14 06:51:52 -0300136 .step = 1,
137 .default_value = MR97310A_BRIGHTNESS_DEFAULT,
138 .flags = 0,
139 },
140 .set = sd_setbrightness,
141 .get = sd_getbrightness,
142 },
143 {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300144#define ARGUS_QC_BRIGHTNESS_IDX 1
145 {
146 .id = V4L2_CID_BRIGHTNESS,
147 .type = V4L2_CTRL_TYPE_INTEGER,
148 .name = "Brightness",
149 .minimum = 0,
150 .maximum = 15,
151 .step = 1,
152 .default_value = MR97310A_BRIGHTNESS_DEFAULT,
153 .flags = 0,
154 },
155 .set = sd_setbrightness,
156 .get = sd_getbrightness,
157 },
158 {
159#define EXPOSURE_IDX 2
Theodore Kilgore89f08632009-08-14 06:51:52 -0300160 {
161 .id = V4L2_CID_EXPOSURE,
162 .type = V4L2_CTRL_TYPE_INTEGER,
163 .name = "Exposure",
164 .minimum = MR97310A_EXPOSURE_MIN,
165 .maximum = MR97310A_EXPOSURE_MAX,
166 .step = 1,
167 .default_value = MR97310A_EXPOSURE_DEFAULT,
168 .flags = 0,
169 },
170 .set = sd_setexposure,
171 .get = sd_getexposure,
172 },
173 {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300174#define GAIN_IDX 3
Theodore Kilgore89f08632009-08-14 06:51:52 -0300175 {
176 .id = V4L2_CID_GAIN,
177 .type = V4L2_CTRL_TYPE_INTEGER,
178 .name = "Gain",
179 .minimum = MR97310A_GAIN_MIN,
180 .maximum = MR97310A_GAIN_MAX,
181 .step = 1,
182 .default_value = MR97310A_GAIN_DEFAULT,
183 .flags = 0,
184 },
185 .set = sd_setgain,
186 .get = sd_getgain,
187 },
Hans de Goede065b6f72009-10-29 07:42:30 -0300188 {
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300189#define SAKAR_CS_GAIN_IDX 4
190 {
191 .id = V4L2_CID_GAIN,
192 .type = V4L2_CTRL_TYPE_INTEGER,
193 .name = "Gain",
194 .minimum = MR97310A_CS_GAIN_MIN,
195 .maximum = MR97310A_CS_GAIN_MAX,
196 .step = 1,
197 .default_value = MR97310A_CS_GAIN_DEFAULT,
198 .flags = 0,
199 },
200 .set = sd_setgain,
201 .get = sd_getgain,
202 },
203 {
204#define CONTRAST_IDX 5
205 {
206 .id = V4L2_CID_CONTRAST,
207 .type = V4L2_CTRL_TYPE_INTEGER,
208 .name = "Contrast",
209 .minimum = MR97310A_CONTRAST_MIN,
210 .maximum = MR97310A_CONTRAST_MAX,
211 .step = 1,
212 .default_value = MR97310A_CONTRAST_DEFAULT,
213 .flags = 0,
214 },
215 .set = sd_setcontrast,
216 .get = sd_getcontrast,
217 },
218 {
219#define MIN_CLOCKDIV_IDX 6
Hans de Goede065b6f72009-10-29 07:42:30 -0300220 {
221 .id = V4L2_CID_PRIVATE_BASE,
222 .type = V4L2_CTRL_TYPE_INTEGER,
223 .name = "Minimum Clock Divider",
224 .minimum = MR97310A_MIN_CLOCKDIV_MIN,
225 .maximum = MR97310A_MIN_CLOCKDIV_MAX,
226 .step = 1,
227 .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT,
228 .flags = 0,
229 },
230 .set = sd_setmin_clockdiv,
231 .get = sd_getmin_clockdiv,
232 },
Kyle Guinnd661e622009-01-16 05:36:14 -0300233};
234
235static const struct v4l2_pix_format vga_mode[] = {
236 {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
237 .bytesperline = 160,
238 .sizeimage = 160 * 120,
239 .colorspace = V4L2_COLORSPACE_SRGB,
240 .priv = 4},
241 {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
242 .bytesperline = 176,
243 .sizeimage = 176 * 144,
244 .colorspace = V4L2_COLORSPACE_SRGB,
245 .priv = 3},
246 {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
247 .bytesperline = 320,
248 .sizeimage = 320 * 240,
249 .colorspace = V4L2_COLORSPACE_SRGB,
250 .priv = 2},
251 {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
252 .bytesperline = 352,
253 .sizeimage = 352 * 288,
254 .colorspace = V4L2_COLORSPACE_SRGB,
255 .priv = 1},
256 {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
257 .bytesperline = 640,
258 .sizeimage = 640 * 480,
259 .colorspace = V4L2_COLORSPACE_SRGB,
260 .priv = 0},
261};
262
263/* the bytes to write are in gspca_dev->usb_buf */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300264static int mr_write(struct gspca_dev *gspca_dev, int len)
Kyle Guinnd661e622009-01-16 05:36:14 -0300265{
266 int rc;
267
268 rc = usb_bulk_msg(gspca_dev->dev,
269 usb_sndbulkpipe(gspca_dev->dev, 4),
Jean-Francois Moine92e8c912009-02-02 16:25:38 -0300270 gspca_dev->usb_buf, len, NULL, 500);
Kyle Guinnd661e622009-01-16 05:36:14 -0300271 if (rc < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300272 pr_err("reg write [%02x] error %d\n",
Kyle Guinnd661e622009-01-16 05:36:14 -0300273 gspca_dev->usb_buf[0], rc);
274 return rc;
275}
276
Theodore Kilgore89f08632009-08-14 06:51:52 -0300277/* the bytes are read into gspca_dev->usb_buf */
278static int mr_read(struct gspca_dev *gspca_dev, int len)
279{
280 int rc;
281
282 rc = usb_bulk_msg(gspca_dev->dev,
283 usb_rcvbulkpipe(gspca_dev->dev, 3),
284 gspca_dev->usb_buf, len, NULL, 500);
285 if (rc < 0)
Joe Perches133a9fe2011-08-21 19:56:57 -0300286 pr_err("reg read [%02x] error %d\n",
Theodore Kilgore89f08632009-08-14 06:51:52 -0300287 gspca_dev->usb_buf[0], rc);
288 return rc;
289}
290
291static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
292 const u8 *data, int len)
293{
294 gspca_dev->usb_buf[0] = 0x1f;
295 gspca_dev->usb_buf[1] = flags;
296 gspca_dev->usb_buf[2] = reg;
297 memcpy(gspca_dev->usb_buf + 3, data, len);
298
299 return mr_write(gspca_dev, len + 3);
300}
301
302static int sensor_write_regs(struct gspca_dev *gspca_dev,
303 const struct sensor_w_data *data, int len)
304{
305 int i, rc;
306
307 for (i = 0; i < len; i++) {
308 rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
309 data[i].data, data[i].len);
310 if (rc < 0)
311 return rc;
312 }
313
314 return 0;
315}
316
317static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
318{
Hans de Goedea2e081b2009-08-14 17:11:36 -0300319 struct sd *sd = (struct sd *) gspca_dev;
320 u8 buf, confirm_reg;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300321 int rc;
322
323 buf = data;
Theodore Kilgore930bf782009-10-05 05:11:35 -0300324 if (sd->cam_type == CAM_TYPE_CIF) {
325 rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
326 confirm_reg = sd->sensor_type ? 0x13 : 0x11;
327 } else {
328 rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
329 confirm_reg = 0x11;
330 }
Theodore Kilgore89f08632009-08-14 06:51:52 -0300331 if (rc < 0)
332 return rc;
333
334 buf = 0x01;
Hans de Goedea2e081b2009-08-14 17:11:36 -0300335 rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300336 if (rc < 0)
337 return rc;
338
339 return 0;
340}
341
Theodore Kilgore930bf782009-10-05 05:11:35 -0300342static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
Theodore Kilgore89f08632009-08-14 06:51:52 -0300343{
Theodore Kilgore89f08632009-08-14 06:51:52 -0300344 int err_code;
345
Theodore Kilgore930bf782009-10-05 05:11:35 -0300346 gspca_dev->usb_buf[0] = reg;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300347 err_code = mr_write(gspca_dev, 1);
348 if (err_code < 0)
349 return err_code;
350
351 err_code = mr_read(gspca_dev, 16);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300352 if (err_code < 0)
353 return err_code;
354
355 if (verbose)
356 PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
357 gspca_dev->usb_buf[0],
358 gspca_dev->usb_buf[1],
359 gspca_dev->usb_buf[2]);
360
361 return 0;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300362}
363
364static int zero_the_pointer(struct gspca_dev *gspca_dev)
365{
366 __u8 *data = gspca_dev->usb_buf;
367 int err_code;
368 u8 status = 0;
369 int tries = 0;
370
Theodore Kilgore930bf782009-10-05 05:11:35 -0300371 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300372 if (err_code < 0)
373 return err_code;
374
Theodore Kilgore89f08632009-08-14 06:51:52 -0300375 data[0] = 0x19;
376 data[1] = 0x51;
377 err_code = mr_write(gspca_dev, 2);
378 if (err_code < 0)
379 return err_code;
380
Theodore Kilgore930bf782009-10-05 05:11:35 -0300381 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300382 if (err_code < 0)
383 return err_code;
384
385 data[0] = 0x19;
386 data[1] = 0xba;
387 err_code = mr_write(gspca_dev, 2);
388 if (err_code < 0)
389 return err_code;
390
Theodore Kilgore930bf782009-10-05 05:11:35 -0300391 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300392 if (err_code < 0)
393 return err_code;
394
395 data[0] = 0x19;
396 data[1] = 0x00;
397 err_code = mr_write(gspca_dev, 2);
398 if (err_code < 0)
399 return err_code;
400
Theodore Kilgore930bf782009-10-05 05:11:35 -0300401 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300402 if (err_code < 0)
403 return err_code;
404
405 data[0] = 0x19;
406 data[1] = 0x00;
407 err_code = mr_write(gspca_dev, 2);
408 if (err_code < 0)
409 return err_code;
410
411 while (status != 0x0a && tries < 256) {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300412 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300413 status = data[0];
414 tries++;
415 if (err_code < 0)
416 return err_code;
417 }
Hans de Goede54943782009-08-14 11:05:38 -0300418 if (status != 0x0a)
419 PDEBUG(D_ERR, "status is %02x", status);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300420
421 tries = 0;
422 while (tries < 4) {
423 data[0] = 0x19;
424 data[1] = 0x00;
425 err_code = mr_write(gspca_dev, 2);
426 if (err_code < 0)
427 return err_code;
428
Theodore Kilgore930bf782009-10-05 05:11:35 -0300429 err_code = cam_get_response16(gspca_dev, 0x21, 0);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300430 status = data[0];
431 tries++;
432 if (err_code < 0)
433 return err_code;
434 }
Theodore Kilgore89f08632009-08-14 06:51:52 -0300435
436 data[0] = 0x19;
437 err_code = mr_write(gspca_dev, 1);
438 if (err_code < 0)
439 return err_code;
440
441 err_code = mr_read(gspca_dev, 16);
442 if (err_code < 0)
443 return err_code;
444
445 return 0;
446}
447
Theodore Kilgore930bf782009-10-05 05:11:35 -0300448static int stream_start(struct gspca_dev *gspca_dev)
Theodore Kilgore89f08632009-08-14 06:51:52 -0300449{
Theodore Kilgore930bf782009-10-05 05:11:35 -0300450 gspca_dev->usb_buf[0] = 0x01;
451 gspca_dev->usb_buf[1] = 0x01;
452 return mr_write(gspca_dev, 2);
453}
Theodore Kilgore89f08632009-08-14 06:51:52 -0300454
Theodore Kilgore930bf782009-10-05 05:11:35 -0300455static void stream_stop(struct gspca_dev *gspca_dev)
456{
457 gspca_dev->usb_buf[0] = 0x01;
458 gspca_dev->usb_buf[1] = 0x00;
459 if (mr_write(gspca_dev, 2) < 0)
460 PDEBUG(D_ERR, "Stream Stop failed");
461}
Theodore Kilgore89f08632009-08-14 06:51:52 -0300462
Theodore Kilgore930bf782009-10-05 05:11:35 -0300463static void lcd_stop(struct gspca_dev *gspca_dev)
464{
465 gspca_dev->usb_buf[0] = 0x19;
466 gspca_dev->usb_buf[1] = 0x54;
467 if (mr_write(gspca_dev, 2) < 0)
468 PDEBUG(D_ERR, "LCD Stop failed");
469}
Theodore Kilgore89f08632009-08-14 06:51:52 -0300470
Theodore Kilgore930bf782009-10-05 05:11:35 -0300471static int isoc_enable(struct gspca_dev *gspca_dev)
472{
473 gspca_dev->usb_buf[0] = 0x00;
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300474 gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */
Theodore Kilgore930bf782009-10-05 05:11:35 -0300475 return mr_write(gspca_dev, 2);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300476}
477
Theodore Kilgore1160a382009-10-30 04:29:56 -0300478/* This function is called at probe time */
Kyle Guinnd661e622009-01-16 05:36:14 -0300479static int sd_config(struct gspca_dev *gspca_dev,
480 const struct usb_device_id *id)
481{
Theodore Kilgore89f08632009-08-14 06:51:52 -0300482 struct sd *sd = (struct sd *) gspca_dev;
Kyle Guinnd661e622009-01-16 05:36:14 -0300483 struct cam *cam;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300484 int gain_default = MR97310A_GAIN_DEFAULT;
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300485 int err_code;
Kyle Guinnd661e622009-01-16 05:36:14 -0300486
487 cam = &gspca_dev->cam;
488 cam->cam_mode = vga_mode;
489 cam->nmodes = ARRAY_SIZE(vga_mode);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300490 sd->do_lcd_stop = 0;
491
Theodore Kilgore1160a382009-10-30 04:29:56 -0300492 /* Several of the supported CIF cameras share the same USB ID but
493 * require different initializations and different control settings.
494 * The same is true of the VGA cameras. Therefore, we are forced
495 * to start the initialization process in order to determine which
496 * camera is present. Some of the supported cameras require the
Theodore Kilgore930bf782009-10-05 05:11:35 -0300497 * memory pointer to be set to 0 as the very first item of business
498 * or else they will not stream. So we do that immediately.
499 */
500 err_code = zero_the_pointer(gspca_dev);
501 if (err_code < 0)
502 return err_code;
Hans de Goede9ac69782009-08-14 10:15:52 -0300503
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300504 err_code = stream_start(gspca_dev);
505 if (err_code < 0)
506 return err_code;
507
Theodore Kilgorec260fe92010-01-15 05:54:36 -0300508 /* Now, the query for sensor type. */
509 err_code = cam_get_response16(gspca_dev, 0x07, 1);
510 if (err_code < 0)
511 return err_code;
512
Aurelien Jacobs8ac246c2009-10-29 07:45:24 -0300513 if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300514 sd->cam_type = CAM_TYPE_CIF;
Hans de Goede9ac69782009-08-14 10:15:52 -0300515 cam->nmodes--;
Theodore Kilgore930bf782009-10-05 05:11:35 -0300516 /*
Theodore Kilgore1160a382009-10-30 04:29:56 -0300517 * All but one of the known CIF cameras share the same USB ID,
518 * but two different init routines are in use, and the control
519 * settings are different, too. We need to detect which camera
520 * of the two known varieties is connected!
Theodore Kilgore930bf782009-10-05 05:11:35 -0300521 *
522 * A list of known CIF cameras follows. They all report either
Theodore Kilgorec260fe92010-01-15 05:54:36 -0300523 * 0200 for type 0 or 0300 for type 1.
Theodore Kilgore930bf782009-10-05 05:11:35 -0300524 * If you have another to report, please do
525 *
526 * Name sd->sensor_type reported by
527 *
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300528 * Sakar 56379 Spy-shot 0 T. Kilgore
Theodore Kilgore930bf782009-10-05 05:11:35 -0300529 * Innovage 0 T. Kilgore
530 * Vivitar Mini 0 H. De Goede
531 * Vivitar Mini 0 E. Rodriguez
532 * Vivitar Mini 1 T. Kilgore
533 * Elta-Media 8212dc 1 T. Kaiser
534 * Philips dig. keych. 1 T. Kilgore
Theodore Kilgore1160a382009-10-30 04:29:56 -0300535 * Trust Spyc@m 100 1 A. Jacobs
Theodore Kilgore930bf782009-10-05 05:11:35 -0300536 */
Theodore Kilgorec260fe92010-01-15 05:54:36 -0300537 switch (gspca_dev->usb_buf[0]) {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300538 case 2:
539 sd->sensor_type = 0;
540 break;
541 case 3:
542 sd->sensor_type = 1;
543 break;
544 default:
Joe Perches133a9fe2011-08-21 19:56:57 -0300545 pr_err("Unknown CIF Sensor id : %02x\n",
Theodore Kilgore930bf782009-10-05 05:11:35 -0300546 gspca_dev->usb_buf[1]);
547 return -ENODEV;
548 }
549 PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
550 sd->sensor_type);
551 } else {
552 sd->cam_type = CAM_TYPE_VGA;
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300553
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300554 /*
Theodore Kilgorec260fe92010-01-15 05:54:36 -0300555 * Here is a table of the responses to the query for sensor
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300556 * type, from the known MR97310A VGA cameras. Six different
557 * cameras of which five share the same USB ID.
Theodore Kilgore930bf782009-10-05 05:11:35 -0300558 *
559 * Name gspca_dev->usb_buf[] sd->sensor_type
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300560 * sd->do_lcd_stop
561 * Aiptek Pencam VGA+ 0300 0 1
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300562 * ION digital 0300 0 1
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300563 * Argus DC-1620 0450 1 0
564 * Argus QuickClix 0420 1 1
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300565 * Sakar 77379 Digital 0350 0 1
566 * Sakar 1638x CyberPix 0120 0 2
Theodore Kilgore930bf782009-10-05 05:11:35 -0300567 *
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300568 * Based upon these results, we assume default settings
569 * and then correct as necessary, as follows.
Theodore Kilgore930bf782009-10-05 05:11:35 -0300570 *
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300571 */
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300572
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300573 sd->sensor_type = 1;
574 sd->do_lcd_stop = 0;
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300575 sd->adj_colors = 0;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300576 if (gspca_dev->usb_buf[0] == 0x01) {
577 sd->sensor_type = 2;
578 } else if ((gspca_dev->usb_buf[0] != 0x03) &&
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300579 (gspca_dev->usb_buf[0] != 0x04)) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300580 pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
581 gspca_dev->usb_buf[0]);
582 pr_err("Defaults assumed, may not work\n");
583 pr_err("Please report this\n");
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300584 }
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300585 /* Sakar Digital color needs to be adjusted. */
586 if ((gspca_dev->usb_buf[0] == 0x03) &&
587 (gspca_dev->usb_buf[1] == 0x50))
588 sd->adj_colors = 1;
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300589 if (gspca_dev->usb_buf[0] == 0x04) {
590 sd->do_lcd_stop = 1;
Theodore Kilgore930bf782009-10-05 05:11:35 -0300591 switch (gspca_dev->usb_buf[1]) {
592 case 0x50:
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300593 sd->sensor_type = 0;
594 PDEBUG(D_PROBE, "sensor_type corrected to 0");
Theodore Kilgore930bf782009-10-05 05:11:35 -0300595 break;
596 case 0x20:
Theodore Kilgoreb3e440e2009-10-09 03:54:49 -0300597 /* Nothing to do here. */
Theodore Kilgore930bf782009-10-05 05:11:35 -0300598 break;
599 default:
Joe Perches133a9fe2011-08-21 19:56:57 -0300600 pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
601 gspca_dev->usb_buf[1]);
602 pr_err("Defaults assumed, may not work\n");
603 pr_err("Please report this\n");
Theodore Kilgore930bf782009-10-05 05:11:35 -0300604 }
Hans de Goede78028702009-09-02 09:55:16 -0300605 }
Theodore Kilgore930bf782009-10-05 05:11:35 -0300606 PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
607 sd->sensor_type);
608 }
Theodore Kilgorec260fe92010-01-15 05:54:36 -0300609 /* Stop streaming as we've started it only to probe the sensor type. */
Theodore Kilgore930bf782009-10-05 05:11:35 -0300610 sd_stopN(gspca_dev);
Hans de Goede78028702009-09-02 09:55:16 -0300611
Theodore Kilgore930bf782009-10-05 05:11:35 -0300612 if (force_sensor_type != -1) {
613 sd->sensor_type = !!force_sensor_type;
614 PDEBUG(D_PROBE, "Forcing sensor type to: %d",
615 sd->sensor_type);
616 }
617
618 /* Setup controls depending on camera type */
619 if (sd->cam_type == CAM_TYPE_CIF) {
620 /* No brightness for sensor_type 0 */
Hans de Goede5f5e26b2009-08-14 10:40:26 -0300621 if (sd->sensor_type == 0)
Theodore Kilgore930bf782009-10-05 05:11:35 -0300622 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300623 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
624 (1 << CONTRAST_IDX) |
625 (1 << SAKAR_CS_GAIN_IDX);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300626 else
Hans de Goede065b6f72009-10-29 07:42:30 -0300627 gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300628 (1 << CONTRAST_IDX) |
629 (1 << SAKAR_CS_GAIN_IDX) |
Hans de Goede065b6f72009-10-29 07:42:30 -0300630 (1 << MIN_CLOCKDIV_IDX);
Hans de Goede9ac69782009-08-14 10:15:52 -0300631 } else {
Theodore Kilgore930bf782009-10-05 05:11:35 -0300632 /* All controls need to be disabled if VGA sensor_type is 0 */
633 if (sd->sensor_type == 0)
634 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
635 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
636 (1 << EXPOSURE_IDX) |
Hans de Goede065b6f72009-10-29 07:42:30 -0300637 (1 << GAIN_IDX) |
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300638 (1 << CONTRAST_IDX) |
639 (1 << SAKAR_CS_GAIN_IDX) |
Hans de Goede065b6f72009-10-29 07:42:30 -0300640 (1 << MIN_CLOCKDIV_IDX);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300641 else if (sd->sensor_type == 2) {
642 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
643 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
644 (1 << GAIN_IDX) |
645 (1 << MIN_CLOCKDIV_IDX);
646 gain_default = MR97310A_CS_GAIN_DEFAULT;
647 } else if (sd->do_lcd_stop)
Theodore Kilgore930bf782009-10-05 05:11:35 -0300648 /* Argus QuickClix has different brightness limits */
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300649 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
650 (1 << CONTRAST_IDX) |
651 (1 << SAKAR_CS_GAIN_IDX);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300652 else
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300653 gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
654 (1 << CONTRAST_IDX) |
655 (1 << SAKAR_CS_GAIN_IDX);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300656 }
Hans de Goede9ac69782009-08-14 10:15:52 -0300657
658 sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
659 sd->exposure = MR97310A_EXPOSURE_DEFAULT;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300660 sd->gain = gain_default;
661 sd->contrast = MR97310A_CONTRAST_DEFAULT;
Hans de Goede065b6f72009-10-29 07:42:30 -0300662 sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT;
Hans de Goede9ac69782009-08-14 10:15:52 -0300663
Kyle Guinnd661e622009-01-16 05:36:14 -0300664 return 0;
665}
666
667/* this function is called at probe and resume time */
668static int sd_init(struct gspca_dev *gspca_dev)
669{
670 return 0;
671}
672
Theodore Kilgore89f08632009-08-14 06:51:52 -0300673static int start_cif_cam(struct gspca_dev *gspca_dev)
Kyle Guinnd661e622009-01-16 05:36:14 -0300674{
675 struct sd *sd = (struct sd *) gspca_dev;
676 __u8 *data = gspca_dev->usb_buf;
677 int err_code;
Jean-François Moine294d8b42010-10-01 07:37:15 -0300678 static const __u8 startup_string[] = {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300679 0x00,
680 0x0d,
681 0x01,
682 0x00, /* Hsize/8 for 352 or 320 */
683 0x00, /* Vsize/4 for 288 or 240 */
684 0x13, /* or 0xbb, depends on sensor */
685 0x00, /* Hstart, depends on res. */
686 0x00, /* reserved ? */
687 0x00, /* Vstart, depends on res. and sensor */
688 0x50, /* 0x54 to get 176 or 160 */
689 0xc0
690 };
Kyle Guinnd661e622009-01-16 05:36:14 -0300691
Theodore Kilgore89f08632009-08-14 06:51:52 -0300692 /* Note: Some of the above descriptions guessed from MR97113A driver */
Kyle Guinnd661e622009-01-16 05:36:14 -0300693
Theodore Kilgore89f08632009-08-14 06:51:52 -0300694 memcpy(data, startup_string, 11);
695 if (sd->sensor_type)
696 data[5] = 0xbb;
697
698 switch (gspca_dev->width) {
699 case 160:
700 data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
701 /* fall thru */
702 case 320:
703 default:
704 data[3] = 0x28; /* reg 2, H size/8 */
705 data[4] = 0x3c; /* reg 3, V size/4 */
706 data[6] = 0x14; /* reg 5, H start */
707 data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */
708 break;
709 case 176:
710 data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
711 /* fall thru */
712 case 352:
713 data[3] = 0x2c; /* reg 2, H size/8 */
714 data[4] = 0x48; /* reg 3, V size/4 */
715 data[6] = 0x06; /* reg 5, H start */
Theodore Kilgore32345b02009-11-01 12:59:42 -0300716 data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300717 break;
718 }
719 err_code = mr_write(gspca_dev, 11);
720 if (err_code < 0)
721 return err_code;
722
723 if (!sd->sensor_type) {
Jean-François Moine294d8b42010-10-01 07:37:15 -0300724 static const struct sensor_w_data cif_sensor0_init_data[] = {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300725 {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
726 0x0f, 0x14, 0x0f, 0x10}, 8},
727 {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
728 {0x12, 0x00, {0x07}, 1},
729 {0x1f, 0x00, {0x06}, 1},
730 {0x27, 0x00, {0x04}, 1},
731 {0x29, 0x00, {0x0c}, 1},
732 {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
733 {0x50, 0x00, {0x60}, 1},
734 {0x60, 0x00, {0x06}, 1},
735 {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
736 {0x72, 0x00, {0x1e, 0x56}, 2},
737 {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
738 0x31, 0x80, 0x00}, 9},
739 {0x11, 0x00, {0x01}, 1},
740 {0, 0, {0}, 0}
741 };
742 err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
743 ARRAY_SIZE(cif_sensor0_init_data));
744 } else { /* sd->sensor_type = 1 */
Jean-François Moine294d8b42010-10-01 07:37:15 -0300745 static const struct sensor_w_data cif_sensor1_init_data[] = {
Hans de Goede9ac69782009-08-14 10:15:52 -0300746 /* Reg 3,4, 7,8 get set by the controls */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300747 {0x02, 0x00, {0x10}, 1},
Hans de Goede9ac69782009-08-14 10:15:52 -0300748 {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
749 {0x06, 0x01, {0x00}, 1},
Theodore Kilgore89f08632009-08-14 06:51:52 -0300750 {0x09, 0x02, {0x0e}, 1},
751 {0x0a, 0x02, {0x05}, 1},
752 {0x0b, 0x02, {0x05}, 1},
753 {0x0c, 0x02, {0x0f}, 1},
Hans de Goede9ac69782009-08-14 10:15:52 -0300754 {0x0d, 0x02, {0x07}, 1},
Theodore Kilgore89f08632009-08-14 06:51:52 -0300755 {0x0e, 0x02, {0x0c}, 1},
756 {0x0f, 0x00, {0x00}, 1},
757 {0x10, 0x00, {0x06}, 1},
758 {0x11, 0x00, {0x07}, 1},
759 {0x12, 0x00, {0x00}, 1},
760 {0x13, 0x00, {0x01}, 1},
761 {0, 0, {0}, 0}
762 };
Theodore Kilgore70136082009-12-25 05:15:10 -0300763 /* Without this command the cam won't work with USB-UHCI */
764 gspca_dev->usb_buf[0] = 0x0a;
765 gspca_dev->usb_buf[1] = 0x00;
766 err_code = mr_write(gspca_dev, 2);
767 if (err_code < 0)
768 return err_code;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300769 err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
770 ARRAY_SIZE(cif_sensor1_init_data));
771 }
Theodore Kilgore930bf782009-10-05 05:11:35 -0300772 return err_code;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300773}
774
775static int start_vga_cam(struct gspca_dev *gspca_dev)
776{
777 struct sd *sd = (struct sd *) gspca_dev;
778 __u8 *data = gspca_dev->usb_buf;
779 int err_code;
Jean-François Moine294d8b42010-10-01 07:37:15 -0300780 static const __u8 startup_string[] =
781 {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
782 0x00, 0x50, 0xc0};
Theodore Kilgore89f08632009-08-14 06:51:52 -0300783 /* What some of these mean is explained in start_cif_cam(), above */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300784
Theodore Kilgore89f08632009-08-14 06:51:52 -0300785 memcpy(data, startup_string, 11);
786 if (!sd->sensor_type) {
787 data[5] = 0x00;
788 data[10] = 0x91;
789 }
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300790 if (sd->sensor_type == 2) {
791 data[5] = 0x00;
792 data[10] = 0x18;
793 }
Kyle Guinnd661e622009-01-16 05:36:14 -0300794
795 switch (gspca_dev->width) {
796 case 160:
797 data[9] |= 0x0c; /* reg 8, 4:1 scale down */
798 /* fall thru */
799 case 320:
800 data[9] |= 0x04; /* reg 8, 2:1 scale down */
801 /* fall thru */
802 case 640:
803 default:
Theodore Kilgore89f08632009-08-14 06:51:52 -0300804 data[3] = 0x50; /* reg 2, H size/8 */
805 data[4] = 0x78; /* reg 3, V size/4 */
Kyle Guinnd661e622009-01-16 05:36:14 -0300806 data[6] = 0x04; /* reg 5, H start */
807 data[8] = 0x03; /* reg 7, V start */
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300808 if (sd->sensor_type == 2) {
809 data[6] = 2;
810 data[8] = 1;
811 }
Theodore Kilgore89f08632009-08-14 06:51:52 -0300812 if (sd->do_lcd_stop)
813 data[8] = 0x04; /* Bayer tile shifted */
Kyle Guinnd661e622009-01-16 05:36:14 -0300814 break;
815
816 case 176:
817 data[9] |= 0x04; /* reg 8, 2:1 scale down */
818 /* fall thru */
819 case 352:
820 data[3] = 0x2c; /* reg 2, H size */
821 data[4] = 0x48; /* reg 3, V size */
822 data[6] = 0x94; /* reg 5, H start */
823 data[8] = 0x63; /* reg 7, V start */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300824 if (sd->do_lcd_stop)
825 data[8] = 0x64; /* Bayer tile shifted */
Kyle Guinnd661e622009-01-16 05:36:14 -0300826 break;
827 }
828
Theodore Kilgore89f08632009-08-14 06:51:52 -0300829 err_code = mr_write(gspca_dev, 11);
Kyle Guinnd661e622009-01-16 05:36:14 -0300830 if (err_code < 0)
831 return err_code;
832
Theodore Kilgore89f08632009-08-14 06:51:52 -0300833 if (!sd->sensor_type) {
Jean-François Moine294d8b42010-10-01 07:37:15 -0300834 static const struct sensor_w_data vga_sensor0_init_data[] = {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300835 {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
836 {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
837 {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
838 {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
839 {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
840 {0, 0, {0}, 0}
841 };
842 err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
843 ARRAY_SIZE(vga_sensor0_init_data));
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300844 } else if (sd->sensor_type == 1) {
Jean-François Moine294d8b42010-10-01 07:37:15 -0300845 static const struct sensor_w_data color_adj[] = {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300846 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300847 /* adjusted blue, green, red gain correct
848 too much blue from the Sakar Digital */
Theodore Kilgoreb31210d2009-11-01 13:02:59 -0300849 0x05, 0x01, 0x04}, 8}
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300850 };
851
Jean-François Moine294d8b42010-10-01 07:37:15 -0300852 static const struct sensor_w_data color_no_adj[] = {
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300853 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
854 /* default blue, green, red gain settings */
855 0x07, 0x00, 0x01}, 8}
856 };
857
Jean-François Moine294d8b42010-10-01 07:37:15 -0300858 static const struct sensor_w_data vga_sensor1_init_data[] = {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300859 {0x11, 0x04, {0x01}, 1},
Theodore Kilgore542821d2009-11-01 13:09:15 -0300860 {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
861 /* These settings may be better for some cameras */
862 /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300863 0x00, 0x0a}, 7},
864 {0x11, 0x04, {0x01}, 1},
865 {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
866 {0x11, 0x04, {0x01}, 1},
867 {0, 0, {0}, 0}
868 };
Theodore Kilgore64f4d9a2009-10-30 04:43:39 -0300869
870 if (sd->adj_colors)
871 err_code = sensor_write_regs(gspca_dev, color_adj,
872 ARRAY_SIZE(color_adj));
873 else
874 err_code = sensor_write_regs(gspca_dev, color_no_adj,
875 ARRAY_SIZE(color_no_adj));
876
877 if (err_code < 0)
878 return err_code;
879
Theodore Kilgore89f08632009-08-14 06:51:52 -0300880 err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
881 ARRAY_SIZE(vga_sensor1_init_data));
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300882 } else { /* sensor type == 2 */
Jean-François Moine294d8b42010-10-01 07:37:15 -0300883 static const struct sensor_w_data vga_sensor2_init_data[] = {
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300884
885 {0x01, 0x00, {0x48}, 1},
886 {0x02, 0x00, {0x22}, 1},
887 /* Reg 3 msb and 4 is lsb of the exposure setting*/
888 {0x05, 0x00, {0x10}, 1},
889 {0x06, 0x00, {0x00}, 1},
890 {0x07, 0x00, {0x00}, 1},
891 {0x08, 0x00, {0x00}, 1},
892 {0x09, 0x00, {0x00}, 1},
893 /* The following are used in the gain control
894 * which is BTW completely borked in the OEM driver
895 * The values for each color go from 0 to 0x7ff
896 *{0x0a, 0x00, {0x01}, 1}, green1 gain msb
897 *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb
898 *{0x0c, 0x00, {0x01}, 1}, red gain msb
899 *{0x0d, 0x00, {0x10}, 1}, red gain lsb
900 *{0x0e, 0x00, {0x01}, 1}, blue gain msb
901 *{0x0f, 0x00, {0x10}, 1}, blue gain lsb
902 *{0x10, 0x00, {0x01}, 1}, green2 gain msb
903 *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
904 */
905 {0x12, 0x00, {0x00}, 1},
906 {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
907 {0x14, 0x00, {0x00}, 1},
908 {0x15, 0x00, {0x06}, 1},
909 {0x16, 0x00, {0x01}, 1},
910 {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
911 {0x18, 0x00, {0x02}, 1},
912 {0x19, 0x00, {0x82}, 1}, /* don't mess with */
913 {0x1a, 0x00, {0x00}, 1},
914 {0x1b, 0x00, {0x20}, 1},
915 /* {0x1c, 0x00, {0x17}, 1}, contrast control */
916 {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
917 {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
918 {0x1f, 0x00, {0x0c}, 1},
919 {0x20, 0x00, {0x00}, 1},
920 {0, 0, {0}, 0}
921 };
922 err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
923 ARRAY_SIZE(vga_sensor2_init_data));
Theodore Kilgore89f08632009-08-14 06:51:52 -0300924 }
Theodore Kilgore89f08632009-08-14 06:51:52 -0300925 return err_code;
926}
927
928static int sd_start(struct gspca_dev *gspca_dev)
929{
930 struct sd *sd = (struct sd *) gspca_dev;
931 int err_code;
Theodore Kilgore89f08632009-08-14 06:51:52 -0300932
Theodore Kilgore89f08632009-08-14 06:51:52 -0300933 sd->sof_read = 0;
Theodore Kilgore930bf782009-10-05 05:11:35 -0300934
935 /* Some of the VGA cameras require the memory pointer
936 * to be set to 0 again. We have been forced to start the
Theodore Kilgoreb4b84de2009-11-01 13:07:08 -0300937 * stream in sd_config() to detect the hardware, and closed it.
938 * Thus, we need here to do a completely fresh and clean start. */
Theodore Kilgore930bf782009-10-05 05:11:35 -0300939 err_code = zero_the_pointer(gspca_dev);
940 if (err_code < 0)
941 return err_code;
942
943 err_code = stream_start(gspca_dev);
944 if (err_code < 0)
945 return err_code;
946
Theodore Kilgore89f08632009-08-14 06:51:52 -0300947 if (sd->cam_type == CAM_TYPE_CIF) {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300948 err_code = start_cif_cam(gspca_dev);
949 } else {
Theodore Kilgore89f08632009-08-14 06:51:52 -0300950 err_code = start_vga_cam(gspca_dev);
951 }
Theodore Kilgore930bf782009-10-05 05:11:35 -0300952 if (err_code < 0)
953 return err_code;
954
955 setbrightness(gspca_dev);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -0300956 setcontrast(gspca_dev);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300957 setexposure(gspca_dev);
958 setgain(gspca_dev);
959
960 return isoc_enable(gspca_dev);
Kyle Guinnd661e622009-01-16 05:36:14 -0300961}
962
963static void sd_stopN(struct gspca_dev *gspca_dev)
964{
Theodore Kilgore89f08632009-08-14 06:51:52 -0300965 struct sd *sd = (struct sd *) gspca_dev;
Kyle Guinnd661e622009-01-16 05:36:14 -0300966
Theodore Kilgore930bf782009-10-05 05:11:35 -0300967 stream_stop(gspca_dev);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300968 /* Not all the cams need this, but even if not, probably a good idea */
969 zero_the_pointer(gspca_dev);
Theodore Kilgore930bf782009-10-05 05:11:35 -0300970 if (sd->do_lcd_stop)
971 lcd_stop(gspca_dev);
Theodore Kilgore89f08632009-08-14 06:51:52 -0300972}
973
974static void setbrightness(struct gspca_dev *gspca_dev)
975{
976 struct sd *sd = (struct sd *) gspca_dev;
977 u8 val;
Theodore Kilgore930bf782009-10-05 05:11:35 -0300978 u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */
979 u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
Jean-François Moine294d8b42010-10-01 07:37:15 -0300980 static const u8 quick_clix_table[] =
Theodore Kilgore930bf782009-10-05 05:11:35 -0300981 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
982 { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15};
983 /*
984 * This control is disabled for CIF type 1 and VGA type 0 cameras.
985 * It does not quite act linearly for the Argus QuickClix camera,
986 * but it does control brightness. The values are 0 - 15 only, and
987 * the table above makes them act consecutively.
988 */
989 if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) &&
990 (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX)))
Hans de Goede9ac69782009-08-14 10:15:52 -0300991 return;
992
Theodore Kilgore930bf782009-10-05 05:11:35 -0300993 if (sd->cam_type == CAM_TYPE_VGA) {
994 sign_reg += 4;
995 value_reg += 4;
996 }
997
Theodore Kilgoreb4b84de2009-11-01 13:07:08 -0300998 /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
Theodore Kilgore89f08632009-08-14 06:51:52 -0300999 if (sd->brightness > 0) {
Theodore Kilgore930bf782009-10-05 05:11:35 -03001000 sensor_write1(gspca_dev, sign_reg, 0x00);
Theodore Kilgore89f08632009-08-14 06:51:52 -03001001 val = sd->brightness;
1002 } else {
Theodore Kilgore930bf782009-10-05 05:11:35 -03001003 sensor_write1(gspca_dev, sign_reg, 0x01);
1004 val = (257 - sd->brightness);
Theodore Kilgore89f08632009-08-14 06:51:52 -03001005 }
Theodore Kilgore930bf782009-10-05 05:11:35 -03001006 /* Use lookup table for funky Argus QuickClix brightness */
1007 if (sd->do_lcd_stop)
1008 val = quick_clix_table[val];
1009
1010 sensor_write1(gspca_dev, value_reg, val);
Theodore Kilgore89f08632009-08-14 06:51:52 -03001011}
1012
1013static void setexposure(struct gspca_dev *gspca_dev)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001016 int exposure = MR97310A_EXPOSURE_DEFAULT;
Hans de Goede065b6f72009-10-29 07:42:30 -03001017 u8 buf[2];
Theodore Kilgore89f08632009-08-14 06:51:52 -03001018
Hans de Goede9ac69782009-08-14 10:15:52 -03001019 if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
1020 return;
1021
Theodore Kilgore930bf782009-10-05 05:11:35 -03001022 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
Theodore Kilgoreb4b84de2009-11-01 13:07:08 -03001023 /* This cam does not like exposure settings < 300,
Hans de Goeded76f9752009-10-11 05:22:29 -03001024 so scale 0 - 4095 to 300 - 4095 */
1025 exposure = (sd->exposure * 9267) / 10000 + 300;
Theodore Kilgore930bf782009-10-05 05:11:35 -03001026 sensor_write1(gspca_dev, 3, exposure >> 4);
1027 sensor_write1(gspca_dev, 4, exposure & 0x0f);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001028 } else if (sd->sensor_type == 2) {
1029 exposure = sd->exposure;
1030 exposure >>= 3;
1031 sensor_write1(gspca_dev, 3, exposure >> 8);
1032 sensor_write1(gspca_dev, 4, exposure & 0xff);
Hans de Goedea2e081b2009-08-14 17:11:36 -03001033 } else {
Hans de Goedea2e081b2009-08-14 17:11:36 -03001034 /* We have both a clock divider and an exposure register.
1035 We first calculate the clock divider, as that determines
Theodore Kilgoreb4b84de2009-11-01 13:07:08 -03001036 the maximum exposure and then we calculate the exposure
Hans de Goedea2e081b2009-08-14 17:11:36 -03001037 register setting (which goes from 0 - 511).
1038
1039 Note our 0 - 4095 exposure is mapped to 0 - 511
1040 milliseconds exposure time */
Theodore Kilgore930bf782009-10-05 05:11:35 -03001041 u8 clockdiv = (60 * sd->exposure + 7999) / 8000;
Hans de Goedea2e081b2009-08-14 17:11:36 -03001042
1043 /* Limit framerate to not exceed usb bandwidth */
Hans de Goede065b6f72009-10-29 07:42:30 -03001044 if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320)
1045 clockdiv = sd->min_clockdiv;
Hans de Goedea2e081b2009-08-14 17:11:36 -03001046 else if (clockdiv < 2)
1047 clockdiv = 2;
1048
Theodore Kilgore930bf782009-10-05 05:11:35 -03001049 if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
1050 clockdiv = 4;
1051
Hans de Goedea2e081b2009-08-14 17:11:36 -03001052 /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
1053 exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
1054 exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv);
1055 if (exposure > 511)
1056 exposure = 511;
1057
1058 /* exposure register value is reversed! */
1059 exposure = 511 - exposure;
1060
Hans de Goede065b6f72009-10-29 07:42:30 -03001061 buf[0] = exposure & 0xff;
1062 buf[1] = exposure >> 8;
1063 sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
Hans de Goedea2e081b2009-08-14 17:11:36 -03001064 sensor_write1(gspca_dev, 0x02, clockdiv);
Hans de Goedea2e081b2009-08-14 17:11:36 -03001065 }
Theodore Kilgore89f08632009-08-14 06:51:52 -03001066}
1067
1068static void setgain(struct gspca_dev *gspca_dev)
1069{
1070 struct sd *sd = (struct sd *) gspca_dev;
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001071 u8 gainreg;
Theodore Kilgore89f08632009-08-14 06:51:52 -03001072
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001073 if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) &&
1074 (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX)))
Hans de Goede9ac69782009-08-14 10:15:52 -03001075 return;
1076
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001077 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
Hans de Goede823902d2009-08-17 12:25:17 -03001078 sensor_write1(gspca_dev, 0x0e, sd->gain);
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001079 else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
1080 for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
1081 sensor_write1(gspca_dev, gainreg, sd->gain >> 8);
1082 sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff);
1083 }
1084 else
Hans de Goedea2e081b2009-08-14 17:11:36 -03001085 sensor_write1(gspca_dev, 0x10, sd->gain);
Theodore Kilgore89f08632009-08-14 06:51:52 -03001086}
1087
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001088static void setcontrast(struct gspca_dev *gspca_dev)
1089{
1090 struct sd *sd = (struct sd *) gspca_dev;
1091
1092 if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
1093 return;
1094
1095 sensor_write1(gspca_dev, 0x1c, sd->contrast);
1096}
1097
1098
Theodore Kilgore89f08632009-08-14 06:51:52 -03001099static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102
1103 sd->brightness = val;
1104 if (gspca_dev->streaming)
1105 setbrightness(gspca_dev);
1106 return 0;
1107}
1108
1109static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1110{
1111 struct sd *sd = (struct sd *) gspca_dev;
1112
1113 *val = sd->brightness;
1114 return 0;
1115}
1116
1117static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1118{
1119 struct sd *sd = (struct sd *) gspca_dev;
1120
1121 sd->exposure = val;
1122 if (gspca_dev->streaming)
1123 setexposure(gspca_dev);
1124 return 0;
1125}
1126
1127static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1128{
1129 struct sd *sd = (struct sd *) gspca_dev;
1130
1131 *val = sd->exposure;
1132 return 0;
1133}
1134
1135static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1136{
1137 struct sd *sd = (struct sd *) gspca_dev;
1138
1139 sd->gain = val;
1140 if (gspca_dev->streaming)
1141 setgain(gspca_dev);
1142 return 0;
1143}
1144
1145static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1146{
1147 struct sd *sd = (struct sd *) gspca_dev;
1148
1149 *val = sd->gain;
1150 return 0;
Kyle Guinnd661e622009-01-16 05:36:14 -03001151}
1152
Theodore Kilgore9d3103d2010-02-09 18:05:25 -03001153static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1154{
1155 struct sd *sd = (struct sd *) gspca_dev;
1156
1157 sd->contrast = val;
1158 if (gspca_dev->streaming)
1159 setcontrast(gspca_dev);
1160 return 0;
1161}
1162
1163
1164static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1165{
1166 struct sd *sd = (struct sd *) gspca_dev;
1167
1168 *val = sd->contrast;
1169 return 0;
1170}
1171
Hans de Goede065b6f72009-10-29 07:42:30 -03001172static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val)
1173{
1174 struct sd *sd = (struct sd *) gspca_dev;
1175
1176 sd->min_clockdiv = val;
1177 if (gspca_dev->streaming)
1178 setexposure(gspca_dev);
1179 return 0;
1180}
1181
1182static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val)
1183{
1184 struct sd *sd = (struct sd *) gspca_dev;
1185
1186 *val = sd->min_clockdiv;
1187 return 0;
1188}
1189
Kyle Guinnd661e622009-01-16 05:36:14 -03001190/* Include pac common sof detection functions */
1191#include "pac_common.h"
1192
1193static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001194 u8 *data, /* isoc packet */
1195 int len) /* iso packet length */
Kyle Guinnd661e622009-01-16 05:36:14 -03001196{
Marton Nemetha6b69e42009-11-02 08:05:51 -03001197 struct sd *sd = (struct sd *) gspca_dev;
Kyle Guinnd661e622009-01-16 05:36:14 -03001198 unsigned char *sof;
1199
Marton Nemetha6b69e42009-11-02 08:05:51 -03001200 sof = pac_find_sof(&sd->sof_read, data, len);
Kyle Guinnd661e622009-01-16 05:36:14 -03001201 if (sof) {
1202 int n;
1203
1204 /* finish decoding current frame */
1205 n = sof - data;
1206 if (n > sizeof pac_sof_marker)
1207 n -= sizeof pac_sof_marker;
1208 else
1209 n = 0;
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001210 gspca_frame_add(gspca_dev, LAST_PACKET,
Kyle Guinnd661e622009-01-16 05:36:14 -03001211 data, n);
Theodore Kilgore9832d762009-03-13 13:04:31 -03001212 /* Start next frame. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001213 gspca_frame_add(gspca_dev, FIRST_PACKET,
Theodore Kilgore9832d762009-03-13 13:04:31 -03001214 pac_sof_marker, sizeof pac_sof_marker);
Kyle Guinnd661e622009-01-16 05:36:14 -03001215 len -= sof - data;
1216 data = sof;
1217 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001218 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Kyle Guinnd661e622009-01-16 05:36:14 -03001219}
1220
1221/* sub-driver description */
1222static const struct sd_desc sd_desc = {
1223 .name = MODULE_NAME,
1224 .ctrls = sd_ctrls,
1225 .nctrls = ARRAY_SIZE(sd_ctrls),
1226 .config = sd_config,
1227 .init = sd_init,
1228 .start = sd_start,
1229 .stopN = sd_stopN,
1230 .pkt_scan = sd_pkt_scan,
1231};
1232
1233/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001234static const struct usb_device_id device_table[] = {
Aurelien Jacobs8ac246c2009-10-29 07:45:24 -03001235 {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */
Theodore Kilgore89f08632009-08-14 06:51:52 -03001236 {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */
1237 {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */
1238 {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */
Kyle Guinnd661e622009-01-16 05:36:14 -03001239 {}
1240};
1241MODULE_DEVICE_TABLE(usb, device_table);
1242
1243/* -- device connect -- */
1244static int sd_probe(struct usb_interface *intf,
1245 const struct usb_device_id *id)
1246{
1247 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1248 THIS_MODULE);
1249}
1250
1251static struct usb_driver sd_driver = {
1252 .name = MODULE_NAME,
1253 .id_table = device_table,
1254 .probe = sd_probe,
1255 .disconnect = gspca_disconnect,
1256#ifdef CONFIG_PM
1257 .suspend = gspca_suspend,
1258 .resume = gspca_resume,
1259#endif
1260};
1261
1262/* -- module insert / remove -- */
1263static int __init sd_mod_init(void)
1264{
Jean-François Moine54826432010-09-13 04:53:03 -03001265 return usb_register(&sd_driver);
Kyle Guinnd661e622009-01-16 05:36:14 -03001266}
1267static void __exit sd_mod_exit(void)
1268{
1269 usb_deregister(&sd_driver);
Kyle Guinnd661e622009-01-16 05:36:14 -03001270}
1271
1272module_init(sd_mod_init);
1273module_exit(sd_mod_exit);