blob: d4c6ad2f1156458691a1b36975ab97a7c03d25a3 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
Hans de Goede327c4ab2008-09-03 17:12:14 -030022/* Some documentation about various registers as determined by trial and error.
Hans de Goede327c4ab2008-09-03 17:12:14 -030023
24 Register page 1:
25
26 Address Description
Hans de Goedeb053c1d2012-04-25 12:00:49 -030027 0x08 Unknown compressor related, must always be 8 except when not
Hans de Goede327c4ab2008-09-03 17:12:14 -030028 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
Hans de Goedeb053c1d2012-04-25 12:00:49 -030029 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
Hans de Goede327c4ab2008-09-03 17:12:14 -030030 bits 345 seem to toggle per color gains on/off (inverted)
31 0x78 Global control, bit 6 controls the LED (inverted)
Hans de Goedeb053c1d2012-04-25 12:00:49 -030032 0x80 JPEG compression ratio ? Best not touched
Hans de Goede327c4ab2008-09-03 17:12:14 -030033
Hans de Goedeb053c1d2012-04-25 12:00:49 -030034 Register page 4:
Hans de Goede327c4ab2008-09-03 17:12:14 -030035
36 Address Description
37 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
Hans de Goede038ec7c2008-09-03 17:12:18 -030038 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
Hans de Goedeb053c1d2012-04-25 12:00:49 -030039 0x0f Master gain 1-245, low value = high gain
40 0x10 Another gain 0-15, limited influence (1-2x gain I guess)
Hans de Goede327c4ab2008-09-03 17:12:14 -030041 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
Hans de Goedeb053c1d2012-04-25 12:00:49 -030042 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
Hans de Goede8a5b2e92008-09-03 17:12:17 -030043 completely disable the analog amplification block. Set to 0x68
44 for max gain, 0x14 for minimal gain.
Hans de Goede327c4ab2008-09-03 17:12:14 -030045*/
46
Joe Perches133a9fe2011-08-21 19:56:57 -030047#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
48
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030049#define MODULE_NAME "pac7311"
50
Hans de Goede32ea3e42010-01-29 11:04:19 -030051#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030052#include "gspca.h"
Hans de Goedea5340ce2012-04-27 11:40:28 -030053/* Include pac common sof detection functions */
54#include "pac_common.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
57MODULE_DESCRIPTION("Pixart PAC7311");
58MODULE_LICENSE("GPL");
59
Hans de Goedea5340ce2012-04-27 11:40:28 -030060enum e_ctrl {
61 CONTRAST,
62 GAIN,
63 EXPOSURE,
64 AUTOGAIN,
65 HFLIP,
66 VFLIP,
67 NCTRLS /* number of controls */
68};
69
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030070struct sd {
71 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goedea5340ce2012-04-27 11:40:28 -030072 struct gspca_ctrl ctrls[NCTRLS];
Jean-Francois Moine49b57db2008-09-03 16:47:25 -030073
Hans de Goede327c4ab2008-09-03 17:12:14 -030074 u8 sof_read;
Hans de Goede327c4ab2008-09-03 17:12:14 -030075 u8 autogain_ignore_frames;
76
77 atomic_t avg_lum;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030078};
79
80/* V4L2 controls supported by the driver */
Hans de Goedea5340ce2012-04-27 11:40:28 -030081static void setcontrast(struct gspca_dev *gspca_dev);
82static void setgain(struct gspca_dev *gspca_dev);
83static void setexposure(struct gspca_dev *gspca_dev);
84static void setautogain(struct gspca_dev *gspca_dev);
85static void sethvflip(struct gspca_dev *gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086
Marton Nemeth7e64dc42009-12-30 09:12:41 -030087static const struct ctrl sd_ctrls[] = {
Hans de Goedea5340ce2012-04-27 11:40:28 -030088[CONTRAST] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
Hans de Goedea5340ce2012-04-27 11:40:28 -030094 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030095 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -030096 .default_value = 7,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
Hans de Goedea5340ce2012-04-27 11:40:28 -030098 .set_control = setcontrast
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030099 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300100[GAIN] = {
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300101 {
102 .id = V4L2_CID_GAIN,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Gain",
105 .minimum = 0,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300106 .maximum = 244,
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300107 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300108 .default_value = 122,
109#define GAIN_KNEE 244 /* Gain seems to cause little noise on the 7311 */
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300110 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300111 .set_control = setgain,
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300112 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300113[EXPOSURE] = {
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300114 {
115 .id = V4L2_CID_EXPOSURE,
116 .type = V4L2_CTRL_TYPE_INTEGER,
117 .name = "Exposure",
Hans de Goedec894d262012-04-25 12:17:19 -0300118 .minimum = 2,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300119 .maximum = 63,
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300120 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300121 .default_value = 2, /* 30 fps */
Hans de Goedec894d262012-04-25 12:17:19 -0300122#define EXPOSURE_KNEE 6 /* 10 fps */
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300123 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300124 .set_control = setexposure,
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300125 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300126[AUTOGAIN] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127 {
128 .id = V4L2_CID_AUTOGAIN,
129 .type = V4L2_CTRL_TYPE_BOOLEAN,
130 .name = "Auto Gain",
131 .minimum = 0,
132 .maximum = 1,
133 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300134 .default_value = 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300135 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300136 .set_control = setautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300137 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300138[HFLIP] = {
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300139 {
140 .id = V4L2_CID_HFLIP,
141 .type = V4L2_CTRL_TYPE_BOOLEAN,
142 .name = "Mirror",
143 .minimum = 0,
144 .maximum = 1,
145 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300146 .default_value = 0,
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300147 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300148 .set_control = sethvflip,
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300149 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300150[VFLIP] = {
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300151 {
152 .id = V4L2_CID_VFLIP,
153 .type = V4L2_CTRL_TYPE_BOOLEAN,
154 .name = "Vflip",
155 .minimum = 0,
156 .maximum = 1,
157 .step = 1,
Hans de Goedea5340ce2012-04-27 11:40:28 -0300158 .default_value = 0,
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300159 },
Hans de Goedea5340ce2012-04-27 11:40:28 -0300160 .set_control = sethvflip,
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300161 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162};
163
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300164static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinef75c4952008-09-03 16:47:35 -0300165 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300166 .bytesperline = 160,
167 .sizeimage = 160 * 120 * 3 / 8 + 590,
168 .colorspace = V4L2_COLORSPACE_JPEG,
169 .priv = 2},
Jean-Francois Moinef75c4952008-09-03 16:47:35 -0300170 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300171 .bytesperline = 320,
172 .sizeimage = 320 * 240 * 3 / 8 + 590,
173 .colorspace = V4L2_COLORSPACE_JPEG,
174 .priv = 1},
Jean-Francois Moinef75c4952008-09-03 16:47:35 -0300175 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300176 .bytesperline = 640,
177 .sizeimage = 640 * 480 * 3 / 8 + 590,
178 .colorspace = V4L2_COLORSPACE_JPEG,
179 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180};
181
Marton Nemeth5a2e8d92009-10-04 13:53:22 -0300182#define LOAD_PAGE4 254
183#define END_OF_SEQUENCE 0
184
Hans de Goede271315a2008-09-03 17:12:19 -0300185static const __u8 init_7311[] = {
Hans de Goede327c4ab2008-09-03 17:12:14 -0300186 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
187 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
188 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300189 0xff, 0x04,
190 0x27, 0x80,
191 0x28, 0xca,
192 0x29, 0x53,
193 0x2a, 0x0e,
194 0xff, 0x01,
195 0x3e, 0x20,
196};
197
198static const __u8 start_7311[] = {
199/* index, len, [value]* */
Jean-Francois Moine285a4f62008-09-03 16:47:33 -0300200 0xff, 1, 0x01, /* page 1 */
201 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300202 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
203 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
204 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00,
Jean-Francois Moine285a4f62008-09-03 16:47:33 -0300207 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300208 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
209 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
210 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
211 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
212 0xd0, 0xff,
213 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
214 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
215 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
216 0x18, 0x20,
217 0x96, 3, 0x01, 0x08, 0x04,
218 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
219 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
220 0x3f, 0x00, 0x0a, 0x01, 0x00,
Jean-Francois Moine285a4f62008-09-03 16:47:33 -0300221 0xff, 1, 0x04, /* page 4 */
Marton Nemeth5a2e8d92009-10-04 13:53:22 -0300222 0, LOAD_PAGE4, /* load the page 4 */
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300223 0x11, 1, 0x01,
Marton Nemeth5a2e8d92009-10-04 13:53:22 -0300224 0, END_OF_SEQUENCE /* end of sequence */
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300225};
226
Marton Nemeth1408b842009-11-02 08:13:21 -0300227#define SKIP 0xaa
Marton Nemethff75e992009-10-04 13:51:26 -0300228/* page 4 - the value SKIP says skip the index - see reg_w_page() */
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300229static const __u8 page4_7311[] = {
Marton Nemethff75e992009-10-04 13:51:26 -0300230 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
231 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
232 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
234 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300235 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
236 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
237};
238
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300239static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300240 __u8 index,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300241 const u8 *buffer, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300242{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300243 int ret;
244
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300245 if (gspca_dev->usb_err < 0)
246 return;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300247 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300248 ret = usb_control_msg(gspca_dev->dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300249 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300250 0, /* request */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300252 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300253 index, gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254 500);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300255 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300256 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
257 index, ret);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300258 gspca_dev->usb_err = ret;
259 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300260}
261
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300262
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300263static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300264 __u8 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300265 __u8 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300266{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300267 int ret;
268
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300269 if (gspca_dev->usb_err < 0)
270 return;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300271 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300272 ret = usb_control_msg(gspca_dev->dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300273 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300274 0, /* request */
275 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300276 0, index, gspca_dev->usb_buf, 1,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300277 500);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300278 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300279 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
280 index, value, ret);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300281 gspca_dev->usb_err = ret;
282 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283}
284
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300285static void reg_w_seq(struct gspca_dev *gspca_dev,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300286 const __u8 *seq, int len)
287{
288 while (--len >= 0) {
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300289 reg_w(gspca_dev, seq[0], seq[1]);
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300290 seq += 2;
291 }
292}
293
294/* load the beginning of a page */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300295static void reg_w_page(struct gspca_dev *gspca_dev,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300296 const __u8 *page, int len)
297{
298 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300299 int ret = 0;
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300300
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300301 if (gspca_dev->usb_err < 0)
302 return;
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300303 for (index = 0; index < len; index++) {
Marton Nemethff75e992009-10-04 13:51:26 -0300304 if (page[index] == SKIP) /* skip this index */
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300305 continue;
306 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300307 ret = usb_control_msg(gspca_dev->dev,
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300308 usb_sndctrlpipe(gspca_dev->dev, 0),
309 0, /* request */
310 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
311 0, index, gspca_dev->usb_buf, 1,
312 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300313 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300314 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
315 index, page[index], ret);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300316 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300317 break;
318 }
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300319 }
320}
321
322/* output a variable sequence */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300323static void reg_w_var(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300324 const __u8 *seq,
Marton Nemeth1408b842009-11-02 08:13:21 -0300325 const __u8 *page4, unsigned int page4_len)
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300326{
327 int index, len;
328
329 for (;;) {
330 index = *seq++;
331 len = *seq++;
332 switch (len) {
Marton Nemeth5a2e8d92009-10-04 13:53:22 -0300333 case END_OF_SEQUENCE:
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300334 return;
Marton Nemeth5a2e8d92009-10-04 13:53:22 -0300335 case LOAD_PAGE4:
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300336 reg_w_page(gspca_dev, page4, page4_len);
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300337 break;
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300338 default:
Marton Nemeth24067bb2009-10-04 13:54:48 -0300339 if (len > USB_BUF_SZ) {
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300340 PDEBUG(D_ERR|D_STREAM,
341 "Incorrect variable sequence");
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300342 return;
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300343 }
344 while (len > 0) {
345 if (len < 8) {
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300346 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300347 index, seq, len);
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300348 seq += len;
349 break;
350 }
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300351 reg_w_buf(gspca_dev, index, seq, 8);
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300352 seq += 8;
353 index += 8;
354 len -= 8;
355 }
356 }
357 }
358 /* not reached */
359}
360
Marton Nemeth1408b842009-11-02 08:13:21 -0300361/* this function is called at probe time for pac7311 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362static int sd_config(struct gspca_dev *gspca_dev,
363 const struct usb_device_id *id)
364{
365 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea5340ce2012-04-27 11:40:28 -0300366 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine49b57db2008-09-03 16:47:25 -0300367
Marton Nemeth1408b842009-11-02 08:13:21 -0300368 cam->cam_mode = vga_mode;
369 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370
Hans de Goedea5340ce2012-04-27 11:40:28 -0300371 gspca_dev->cam.ctrls = sd->ctrls;
372
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300373 return 0;
374}
375
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300376static void setcontrast(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377{
378 struct sd *sd = (struct sd *) gspca_dev;
379
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300380 reg_w(gspca_dev, 0xff, 0x04);
Hans de Goedea5340ce2012-04-27 11:40:28 -0300381 reg_w(gspca_dev, 0x10, sd->ctrls[CONTRAST].val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300383 reg_w(gspca_dev, 0x11, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384}
385
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300386static void setgain(struct gspca_dev *gspca_dev)
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300387{
388 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300389
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300390 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
391 reg_w(gspca_dev, 0x0e, 0x00);
Hans de Goedea5340ce2012-04-27 11:40:28 -0300392 reg_w(gspca_dev, 0x0f, sd->ctrls[GAIN].max - sd->ctrls[GAIN].val + 1);
Marton Nemeth1408b842009-11-02 08:13:21 -0300393
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300394 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300395 reg_w(gspca_dev, 0x11, 0x01);
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300396}
397
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300398static void setexposure(struct gspca_dev *gspca_dev)
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300399{
400 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300401
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300402 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
Hans de Goedea5340ce2012-04-27 11:40:28 -0300403 reg_w(gspca_dev, 0x02, sd->ctrls[EXPOSURE].val);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300404
Hans de Goede51ae23d2012-04-18 06:12:57 -0300405 /* load registers to sensor (Bit 0, auto clear) */
406 reg_w(gspca_dev, 0x11, 0x01);
407
Marton Nemeth1408b842009-11-02 08:13:21 -0300408 /* Page 1 register 8 must always be 0x08 except when not in
Hans de Goedeb053c1d2012-04-25 12:00:49 -0300409 640x480 mode and page 4 reg 2 <= 3 then it must be 9 */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300410 reg_w(gspca_dev, 0xff, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300411 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
Hans de Goedea5340ce2012-04-27 11:40:28 -0300412 sd->ctrls[EXPOSURE].val <= 3) {
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300413 reg_w(gspca_dev, 0x08, 0x09);
Márton Némethb1784b32009-11-07 05:52:02 -0300414 } else {
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300415 reg_w(gspca_dev, 0x08, 0x08);
Márton Némethb1784b32009-11-07 05:52:02 -0300416 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300417
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300418 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300419 reg_w(gspca_dev, 0x11, 0x01);
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300420}
421
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300422static void sethvflip(struct gspca_dev *gspca_dev)
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300423{
424 struct sd *sd = (struct sd *) gspca_dev;
425 __u8 data;
426
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300427 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
Hans de Goedea5340ce2012-04-27 11:40:28 -0300428 data = (sd->ctrls[HFLIP].val ? 0x04 : 0x00) |
429 (sd->ctrls[VFLIP].val ? 0x08 : 0x00);
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300430 reg_w(gspca_dev, 0x21, data);
431
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300432 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300433 reg_w(gspca_dev, 0x11, 0x01);
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300434}
435
Marton Nemeth1408b842009-11-02 08:13:21 -0300436/* this function is called at probe and resume time for pac7311 */
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300437static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300438{
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300439 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
440 return gspca_dev->usb_err;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300441}
442
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300443static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300444{
Jean-Francois Moinee52a5572008-09-03 16:47:21 -0300445 struct sd *sd = (struct sd *) gspca_dev;
446
Hans de Goede327c4ab2008-09-03 17:12:14 -0300447 sd->sof_read = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300448
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300449 reg_w_var(gspca_dev, start_7311,
Marton Nemeth1408b842009-11-02 08:13:21 -0300450 page4_7311, sizeof(page4_7311));
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300451 setcontrast(gspca_dev);
452 setgain(gspca_dev);
453 setexposure(gspca_dev);
454 sethvflip(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455
456 /* set correct resolution */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300457 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
Hans de Goedeb053c1d2012-04-25 12:00:49 -0300458 case 2: /* 160x120 */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300459 reg_w(gspca_dev, 0xff, 0x01);
460 reg_w(gspca_dev, 0x17, 0x20);
461 reg_w(gspca_dev, 0x87, 0x10);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300462 break;
Hans de Goedeb053c1d2012-04-25 12:00:49 -0300463 case 1: /* 320x240 */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300464 reg_w(gspca_dev, 0xff, 0x01);
465 reg_w(gspca_dev, 0x17, 0x30);
466 reg_w(gspca_dev, 0x87, 0x11);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 break;
468 case 0: /* 640x480 */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300469 reg_w(gspca_dev, 0xff, 0x01);
470 reg_w(gspca_dev, 0x17, 0x00);
471 reg_w(gspca_dev, 0x87, 0x12);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472 break;
473 }
474
Hans de Goede327c4ab2008-09-03 17:12:14 -0300475 sd->sof_read = 0;
476 sd->autogain_ignore_frames = 0;
477 atomic_set(&sd->avg_lum, -1);
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300478
479 /* start stream */
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300480 reg_w(gspca_dev, 0xff, 0x01);
481 reg_w(gspca_dev, 0x78, 0x05);
Marton Nemeth1408b842009-11-02 08:13:21 -0300482
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300483 return gspca_dev->usb_err;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300484}
485
486static void sd_stopN(struct gspca_dev *gspca_dev)
487{
Jean-Francois Moine14799f62010-01-13 15:28:22 -0300488 reg_w(gspca_dev, 0xff, 0x04);
489 reg_w(gspca_dev, 0x27, 0x80);
490 reg_w(gspca_dev, 0x28, 0xca);
491 reg_w(gspca_dev, 0x29, 0x53);
492 reg_w(gspca_dev, 0x2a, 0x0e);
493 reg_w(gspca_dev, 0xff, 0x01);
494 reg_w(gspca_dev, 0x3e, 0x20);
495 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
496 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
497 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300498}
499
Hans de Goedea5340ce2012-04-27 11:40:28 -0300500#define WANT_REGULAR_AUTOGAIN
501#include "autogain_functions.h"
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300502
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300503static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504{
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300505 struct sd *sd = (struct sd *) gspca_dev;
506 int avg_lum = atomic_read(&sd->avg_lum);
Hans de Goede038ec7c2008-09-03 17:12:18 -0300507 int desired_lum, deadzone;
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300508
Hans de Goedea5340ce2012-04-27 11:40:28 -0300509 if (sd->ctrls[AUTOGAIN].val == 0 || avg_lum == -1)
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300510 return;
511
Marton Nemeth1408b842009-11-02 08:13:21 -0300512 desired_lum = 200;
513 deadzone = 20;
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300514
515 if (sd->autogain_ignore_frames > 0)
516 sd->autogain_ignore_frames--;
Hans de Goedea5340ce2012-04-27 11:40:28 -0300517 else if (auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
Hans de Goede038ec7c2008-09-03 17:12:18 -0300518 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300519 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520}
521
Marton Nemeth56f6f552009-10-04 13:58:19 -0300522/* JPEG header, part 1 */
Marton Nemethcc409c02009-11-02 08:09:34 -0300523static const unsigned char pac_jpeg_header1[] = {
Marton Nemeth56f6f552009-10-04 13:58:19 -0300524 0xff, 0xd8, /* SOI: Start of Image */
525
526 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
527 0x00, 0x11, /* length = 17 bytes (including this length field) */
528 0x08 /* Precision: 8 */
529 /* 2 bytes is placed here: number of image lines */
530 /* 2 bytes is placed here: samples per line */
Hans de Goede327c4ab2008-09-03 17:12:14 -0300531};
532
Marton Nemeth56f6f552009-10-04 13:58:19 -0300533/* JPEG header, continued */
Marton Nemethcc409c02009-11-02 08:09:34 -0300534static const unsigned char pac_jpeg_header2[] = {
Marton Nemeth56f6f552009-10-04 13:58:19 -0300535 0x03, /* Number of image components: 3 */
536 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
537 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
538 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
539
540 0xff, 0xda, /* SOS: Start Of Scan */
541 0x00, 0x0c, /* length = 12 bytes (including this length field) */
542 0x03, /* number of components: 3 */
543 0x01, 0x00, /* selector 1, table 0x00 */
544 0x02, 0x11, /* selector 2, table 0x11 */
545 0x03, 0x11, /* selector 3, table 0x11 */
546 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
547 0x00 /* Successive approximation: 0 */
Hans de Goede327c4ab2008-09-03 17:12:14 -0300548};
549
Marton Nemethcc409c02009-11-02 08:09:34 -0300550static void pac_start_frame(struct gspca_dev *gspca_dev,
Marton Nemethcc409c02009-11-02 08:09:34 -0300551 __u16 lines, __u16 samples_per_line)
552{
553 unsigned char tmpbuf[4];
554
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300555 gspca_frame_add(gspca_dev, FIRST_PACKET,
Marton Nemethcc409c02009-11-02 08:09:34 -0300556 pac_jpeg_header1, sizeof(pac_jpeg_header1));
557
558 tmpbuf[0] = lines >> 8;
559 tmpbuf[1] = lines & 0xff;
560 tmpbuf[2] = samples_per_line >> 8;
561 tmpbuf[3] = samples_per_line & 0xff;
562
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300563 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemethcc409c02009-11-02 08:09:34 -0300564 tmpbuf, sizeof(tmpbuf));
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300565 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemethcc409c02009-11-02 08:09:34 -0300566 pac_jpeg_header2, sizeof(pac_jpeg_header2));
567}
568
Jean-Francois Moinee52a5572008-09-03 16:47:21 -0300569/* this function is run at interrupt level */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300571 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300572 int len) /* iso packet length */
573{
574 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300575 u8 *image;
Hans de Goede327c4ab2008-09-03 17:12:14 -0300576 unsigned char *sof;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577
Marton Nemetha6b69e42009-11-02 08:05:51 -0300578 sof = pac_find_sof(&sd->sof_read, data, len);
Hans de Goede327c4ab2008-09-03 17:12:14 -0300579 if (sof) {
Hans de Goede327c4ab2008-09-03 17:12:14 -0300580 int n, lum_offset, footer_length;
Jean-Francois Moinee52a5572008-09-03 16:47:21 -0300581
Marton Nemeth1408b842009-11-02 08:13:21 -0300582 /* 6 bytes after the FF D9 EOF marker a number of lumination
583 bytes are send corresponding to different parts of the
584 image, the 14th and 15th byte after the EOF seem to
585 correspond to the center of the image */
586 lum_offset = 24 + sizeof pac_sof_marker;
587 footer_length = 26;
Hans de Goede327c4ab2008-09-03 17:12:14 -0300588
589 /* Finish decoding current frame */
590 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
591 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300592 gspca_dev->image_len += n;
Hans de Goede327c4ab2008-09-03 17:12:14 -0300593 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300594 } else {
595 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Hans de Goede327c4ab2008-09-03 17:12:14 -0300596 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300597 image = gspca_dev->image;
598 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300599 && image[gspca_dev->image_len - 2] == 0xff
600 && image[gspca_dev->image_len - 1] == 0xd9)
601 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Hans de Goede327c4ab2008-09-03 17:12:14 -0300602
603 n = sof - data;
604 len -= n;
605 data = sof;
606
607 /* Get average lumination */
608 if (gspca_dev->last_packet_type == LAST_PACKET &&
Hans de Goede038ec7c2008-09-03 17:12:18 -0300609 n >= lum_offset)
610 atomic_set(&sd->avg_lum, data[-lum_offset] +
Hans de Goede327c4ab2008-09-03 17:12:14 -0300611 data[-lum_offset + 1]);
Hans de Goede038ec7c2008-09-03 17:12:18 -0300612 else
Hans de Goede327c4ab2008-09-03 17:12:14 -0300613 atomic_set(&sd->avg_lum, -1);
Hans de Goede327c4ab2008-09-03 17:12:14 -0300614
615 /* Start the new frame with the jpeg header */
Jean-François Moineb192ca92010-06-27 03:08:19 -0300616 pac_start_frame(gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300617 gspca_dev->height, gspca_dev->width);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300619 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620}
621
Hans de Goedea5340ce2012-04-27 11:40:28 -0300622static void setautogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623{
624 struct sd *sd = (struct sd *) gspca_dev;
625
Hans de Goedea5340ce2012-04-27 11:40:28 -0300626 if (sd->ctrls[AUTOGAIN].val) {
627 sd->ctrls[EXPOSURE].val = 2;
628 sd->ctrls[GAIN].val = 122;
Hans de Goede8a5b2e92008-09-03 17:12:17 -0300629 if (gspca_dev->streaming) {
630 sd->autogain_ignore_frames =
631 PAC_AUTOGAIN_IGNORE_FRAMES;
632 setexposure(gspca_dev);
633 setgain(gspca_dev);
634 }
635 }
Jean-Francois Moine41b46972008-09-03 16:47:58 -0300636}
637
Jean-François Moine28566432010-10-01 07:33:26 -0300638#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goede32ea3e42010-01-29 11:04:19 -0300639static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
640 u8 *data, /* interrupt packet data */
641 int len) /* interrupt packet length */
642{
643 int ret = -EINVAL;
644 u8 data0, data1;
645
646 if (len == 2) {
647 data0 = data[0];
648 data1 = data[1];
649 if ((data0 == 0x00 && data1 == 0x11) ||
650 (data0 == 0x22 && data1 == 0x33) ||
651 (data0 == 0x44 && data1 == 0x55) ||
652 (data0 == 0x66 && data1 == 0x77) ||
653 (data0 == 0x88 && data1 == 0x99) ||
654 (data0 == 0xaa && data1 == 0xbb) ||
655 (data0 == 0xcc && data1 == 0xdd) ||
656 (data0 == 0xee && data1 == 0xff)) {
657 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
658 input_sync(gspca_dev->input_dev);
659 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
660 input_sync(gspca_dev->input_dev);
661 ret = 0;
662 }
663 }
664
665 return ret;
666}
667#endif
668
Márton Némethaabcdfb2010-01-05 12:39:02 -0300669static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670 .name = MODULE_NAME,
671 .ctrls = sd_ctrls,
672 .nctrls = ARRAY_SIZE(sd_ctrls),
673 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300674 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675 .start = sd_start,
676 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300678 .dq_callback = do_autogain,
Jean-François Moine28566432010-10-01 07:33:26 -0300679#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goede32ea3e42010-01-29 11:04:19 -0300680 .int_pkt_scan = sd_int_pkt_scan,
681#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682};
683
684/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300685static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300686 {USB_DEVICE(0x093a, 0x2600)},
687 {USB_DEVICE(0x093a, 0x2601)},
688 {USB_DEVICE(0x093a, 0x2603)},
689 {USB_DEVICE(0x093a, 0x2608)},
690 {USB_DEVICE(0x093a, 0x260e)},
691 {USB_DEVICE(0x093a, 0x260f)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692 {}
693};
694MODULE_DEVICE_TABLE(usb, device_table);
695
696/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300697static int sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698 const struct usb_device_id *id)
699{
700 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
701 THIS_MODULE);
702}
703
704static struct usb_driver sd_driver = {
705 .name = MODULE_NAME,
706 .id_table = device_table,
707 .probe = sd_probe,
708 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -0300709#ifdef CONFIG_PM
710 .suspend = gspca_suspend,
711 .resume = gspca_resume,
712#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713};
714
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800715module_usb_driver(sd_driver);