blob: 530652dcbfb28dac68e3ca0bbd1593ee9047ab63 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
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
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 "sunplus"
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/SPCA5xx USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
Hans Verkuiled5cd6b2012-05-16 08:49:10 -030037 struct v4l2_ctrl *jpegqual;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -030038#define QUALITY_MIN 70
39#define QUALITY_MAX 95
40#define QUALITY_DEF 85
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030041
Hans Verkuiled5cd6b2012-05-16 08:49:10 -030042 bool autogain;
43
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -030044 u8 bridge;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045#define BRIDGE_SPCA504 0
46#define BRIDGE_SPCA504B 1
47#define BRIDGE_SPCA504C 2
48#define BRIDGE_SPCA533 3
49#define BRIDGE_SPCA536 4
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -030050 u8 subtype;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030051#define AiptekMiniPenCam13 1
52#define LogitechClickSmart420 2
53#define LogitechClickSmart820 3
54#define MegapixV4 4
Johannes Goerneraf5f88c2009-07-09 03:28:46 -030055#define MegaImageVI 5
Jean-Francois Moine71cb2762009-03-03 05:33:41 -030056
Jean-François Moine9a731a32010-06-04 05:26:42 -030057 u8 jpeg_hdr[JPEG_HDR_SZ];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030058};
59
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030060static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030061 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
62 .bytesperline = 320,
63 .sizeimage = 320 * 240 * 3 / 8 + 590,
64 .colorspace = V4L2_COLORSPACE_JPEG,
65 .priv = 2},
66 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
67 .bytesperline = 640,
68 .sizeimage = 640 * 480 * 3 / 8 + 590,
69 .colorspace = V4L2_COLORSPACE_JPEG,
70 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030071};
72
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030073static const struct v4l2_pix_format custom_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030074 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
75 .bytesperline = 320,
76 .sizeimage = 320 * 240 * 3 / 8 + 590,
77 .colorspace = V4L2_COLORSPACE_JPEG,
78 .priv = 2},
79 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
80 .bytesperline = 464,
81 .sizeimage = 464 * 480 * 3 / 8 + 590,
82 .colorspace = V4L2_COLORSPACE_JPEG,
83 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030084};
85
Jean-Francois Moinecc611b82008-12-29 07:49:41 -030086static const struct v4l2_pix_format vga_mode2[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030087 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
88 .bytesperline = 176,
89 .sizeimage = 176 * 144 * 3 / 8 + 590,
90 .colorspace = V4L2_COLORSPACE_JPEG,
91 .priv = 4},
92 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
93 .bytesperline = 320,
94 .sizeimage = 320 * 240 * 3 / 8 + 590,
95 .colorspace = V4L2_COLORSPACE_JPEG,
96 .priv = 3},
97 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
98 .bytesperline = 352,
99 .sizeimage = 352 * 288 * 3 / 8 + 590,
100 .colorspace = V4L2_COLORSPACE_JPEG,
101 .priv = 2},
102 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
103 .bytesperline = 640,
104 .sizeimage = 640 * 480 * 3 / 8 + 590,
105 .colorspace = V4L2_COLORSPACE_JPEG,
106 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300107};
108
109#define SPCA50X_OFFSET_DATA 10
110#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
111#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
112#define SPCA504_PCCAM600_OFFSET_MODE 5
113#define SPCA504_PCCAM600_OFFSET_DATA 14
114 /* Frame packet header offsets for the spca533 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300115#define SPCA533_OFFSET_DATA 16
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300116#define SPCA533_OFFSET_FRAMSEQ 15
117/* Frame packet header offsets for the spca536 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300118#define SPCA536_OFFSET_DATA 4
119#define SPCA536_OFFSET_FRAMSEQ 1
120
121struct cmd {
122 u8 req;
123 u16 val;
124 u16 idx;
125};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126
127/* Initialisation data for the Creative PC-CAM 600 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300128static const struct cmd spca504_pccam600_init_data[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300129/* {0xa0, 0x0000, 0x0503}, * capture mode */
130 {0x00, 0x0000, 0x2000},
131 {0x00, 0x0013, 0x2301},
132 {0x00, 0x0003, 0x2000},
133 {0x00, 0x0001, 0x21ac},
134 {0x00, 0x0001, 0x21a6},
135 {0x00, 0x0000, 0x21a7}, /* brightness */
136 {0x00, 0x0020, 0x21a8}, /* contrast */
137 {0x00, 0x0001, 0x21ac}, /* sat/hue */
138 {0x00, 0x0000, 0x21ad}, /* hue */
139 {0x00, 0x001a, 0x21ae}, /* saturation */
140 {0x00, 0x0002, 0x21a3}, /* gamma */
141 {0x30, 0x0154, 0x0008},
142 {0x30, 0x0004, 0x0006},
143 {0x30, 0x0258, 0x0009},
144 {0x30, 0x0004, 0x0000},
145 {0x30, 0x0093, 0x0004},
146 {0x30, 0x0066, 0x0005},
147 {0x00, 0x0000, 0x2000},
148 {0x00, 0x0013, 0x2301},
149 {0x00, 0x0003, 0x2000},
150 {0x00, 0x0013, 0x2301},
151 {0x00, 0x0003, 0x2000},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152};
153
154/* Creative PC-CAM 600 specific open data, sent before using the
155 * generic initialisation data from spca504_open_data.
156 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300157static const struct cmd spca504_pccam600_open_data[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158 {0x00, 0x0001, 0x2501},
159 {0x20, 0x0500, 0x0001}, /* snapshot mode */
160 {0x00, 0x0003, 0x2880},
161 {0x00, 0x0001, 0x2881},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162};
163
164/* Initialisation data for the logitech clicksmart 420 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300165static const struct cmd spca504A_clicksmart420_init_data[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166/* {0xa0, 0x0000, 0x0503}, * capture mode */
167 {0x00, 0x0000, 0x2000},
168 {0x00, 0x0013, 0x2301},
169 {0x00, 0x0003, 0x2000},
170 {0x00, 0x0001, 0x21ac},
171 {0x00, 0x0001, 0x21a6},
172 {0x00, 0x0000, 0x21a7}, /* brightness */
173 {0x00, 0x0020, 0x21a8}, /* contrast */
174 {0x00, 0x0001, 0x21ac}, /* sat/hue */
175 {0x00, 0x0000, 0x21ad}, /* hue */
176 {0x00, 0x001a, 0x21ae}, /* saturation */
177 {0x00, 0x0002, 0x21a3}, /* gamma */
178 {0x30, 0x0004, 0x000a},
179 {0xb0, 0x0001, 0x0000},
180
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300181 {0xa1, 0x0080, 0x0001},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182 {0x30, 0x0049, 0x0000},
183 {0x30, 0x0060, 0x0005},
184 {0x0c, 0x0004, 0x0000},
185 {0x00, 0x0000, 0x0000},
186 {0x00, 0x0000, 0x2000},
187 {0x00, 0x0013, 0x2301},
188 {0x00, 0x0003, 0x2000},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300189};
190
191/* clicksmart 420 open data ? */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300192static const struct cmd spca504A_clicksmart420_open_data[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300193 {0x00, 0x0001, 0x2501},
194 {0x20, 0x0502, 0x0000},
195 {0x06, 0x0000, 0x0000},
196 {0x00, 0x0004, 0x2880},
197 {0x00, 0x0001, 0x2881},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300198
199 {0xa0, 0x0000, 0x0503},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300200};
201
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300202static const u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203 { /* Q-table Y-components */
204 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
205 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
206 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
207 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
208 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
209 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
210 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
211 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
212 { /* Q-table C-components */
213 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
214 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
215 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
216 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
217 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
218 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
219 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
220 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
221};
222
223/* FIXME: This Q-table is identical to the Creative PC-CAM one,
224 * except for one byte. Possibly a typo?
225 * NWG: 18/05/2003.
226 */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300227static const u8 qtable_spca504_default[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228 { /* Q-table Y-components */
229 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
230 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
231 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
232 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
233 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
234 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
235 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
236 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
237 },
238 { /* Q-table C-components */
239 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
240 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
241 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
242 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
243 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
244 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
245 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
246 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
247};
248
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300249/* read <len> bytes to gspca_dev->usb_buf */
250static void reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300251 u8 req,
252 u16 index,
253 u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300255 int ret;
256
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300257#ifdef GSPCA_DEBUG
258 if (len > USB_BUF_SZ) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300259 pr_err("reg_r: buffer overflow\n");
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300260 return;
261 }
262#endif
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300263 if (gspca_dev->usb_err < 0)
264 return;
265 ret = usb_control_msg(gspca_dev->dev,
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300266 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300267 req,
268 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
269 0, /* value */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300270 index,
271 len ? gspca_dev->usb_buf : NULL, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300272 500);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300273 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300274 pr_err("reg_r err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300275 gspca_dev->usb_err = ret;
276 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300277}
278
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300279/* write one byte */
280static void reg_w_1(struct gspca_dev *gspca_dev,
281 u8 req,
282 u16 value,
283 u16 index,
284 u16 byte)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300285{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300286 int ret;
287
288 if (gspca_dev->usb_err < 0)
289 return;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300290 gspca_dev->usb_buf[0] = byte;
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300291 ret = usb_control_msg(gspca_dev->dev,
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300292 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300293 req,
294 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300295 value, index,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300296 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297 500);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300298 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300299 pr_err("reg_w_1 err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300300 gspca_dev->usb_err = ret;
301 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300302}
303
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300304/* write req / index / value */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300305static void reg_w_riv(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300306 u8 req, u16 index, u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300307{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300308 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 int ret;
310
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300311 if (gspca_dev->usb_err < 0)
312 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300313 ret = usb_control_msg(dev,
314 usb_sndctrlpipe(dev, 0),
315 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300316 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317 value, index, NULL, 0, 500);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300318 if (ret < 0) {
Joe Perches133a9fe2011-08-21 19:56:57 -0300319 pr_err("reg_w_riv err %d\n", ret);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300320 gspca_dev->usb_err = ret;
321 return;
322 }
323 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
324 req, index, value);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300325}
326
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300327static void write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300328 const struct cmd *data, int ncmds)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300329{
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300330 while (--ncmds >= 0) {
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300331 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300332 data++;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300333 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334}
335
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300336static void setup_qtable(struct gspca_dev *gspca_dev,
337 const u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300339 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340
341 /* loop over y components */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300342 for (i = 0; i < 64; i++)
Jean-François Moine780e3122010-10-19 04:29:10 -0300343 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344
345 /* loop over c components */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300346 for (i = 0; i < 64; i++)
347 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348}
349
350static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300351 u8 req, u16 idx, u16 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300352{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300353 reg_w_riv(gspca_dev, req, idx, val);
Jean-François Moinecf252202011-05-17 05:32:39 -0300354 reg_r(gspca_dev, 0x01, 0x0001, 1);
355 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300356 reg_w_riv(gspca_dev, req, idx, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358 msleep(200);
Jean-François Moinecf252202011-05-17 05:32:39 -0300359 reg_r(gspca_dev, 0x01, 0x0001, 1);
360 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361}
362
Jean-François Moinecf252202011-05-17 05:32:39 -0300363#ifdef GSPCA_DEBUG
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300364static void spca504_read_info(struct gspca_dev *gspca_dev)
365{
366 int i;
367 u8 info[6];
368
Jean-François Moinecf252202011-05-17 05:32:39 -0300369 for (i = 0; i < 6; i++) {
370 reg_r(gspca_dev, 0, i, 1);
371 info[i] = gspca_dev->usb_buf[0];
372 }
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300373 PDEBUG(D_STREAM,
374 "Read info: %d %d %d %d %d %d."
375 " Should be 1,0,2,2,0,0",
376 info[0], info[1], info[2],
377 info[3], info[4], info[5]);
378}
Jean-François Moinecf252202011-05-17 05:32:39 -0300379#endif
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300380
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300382 u8 req,
Jean-François Moinecf252202011-05-17 05:32:39 -0300383 u16 idx, u16 val, u8 endcode, u8 count)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384{
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300385 u16 status;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300387 reg_w_riv(gspca_dev, req, idx, val);
Jean-François Moinecf252202011-05-17 05:32:39 -0300388 reg_r(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300389 if (gspca_dev->usb_err < 0)
390 return;
Jean-François Moinecf252202011-05-17 05:32:39 -0300391 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
392 gspca_dev->usb_buf[0], endcode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393 if (!count)
394 return;
395 count = 200;
396 while (--count > 0) {
397 msleep(10);
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200398 /* gsmart mini2 write a each wait setting 1 ms is enough */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300399/* reg_w_riv(gspca_dev, req, idx, val); */
Jean-François Moinecf252202011-05-17 05:32:39 -0300400 reg_r(gspca_dev, 0x01, 0x0001, 1);
401 status = gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300402 if (status == endcode) {
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300403 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300404 status, 200 - count);
405 break;
406 }
407 }
408}
409
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300410static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300412 int count = 10;
413
414 while (--count > 0) {
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300415 reg_r(gspca_dev, 0x21, 0, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300416 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417 break;
418 msleep(10);
419 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300420}
421
422static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
423{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300424 int count = 50;
425
426 while (--count > 0) {
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300427 reg_r(gspca_dev, 0x21, 1, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300428 if (gspca_dev->usb_buf[0] != 0) {
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300429 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300430 reg_r(gspca_dev, 0x21, 1, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300431 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432 break;
433 }
434 msleep(10);
435 }
436}
437
Jean-François Moinecf252202011-05-17 05:32:39 -0300438#ifdef GSPCA_DEBUG
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
440{
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300441 u8 *data;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300442
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300443 data = gspca_dev->usb_buf;
444 reg_r(gspca_dev, 0x20, 0, 5);
Jean-François Moinecf252202011-05-17 05:32:39 -0300445 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300446 data[0], data[1], data[2], data[3], data[4]);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300447 reg_r(gspca_dev, 0x23, 0, 64);
448 reg_r(gspca_dev, 0x23, 1, 64);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300449}
Jean-François Moinecf252202011-05-17 05:32:39 -0300450#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451
452static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
453{
454 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300455 u8 Size;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300457 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300458 switch (sd->bridge) {
459 case BRIDGE_SPCA533:
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300460 reg_w_riv(gspca_dev, 0x31, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300462 spca504B_PollingDataReady(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300463#ifdef GSPCA_DEBUG
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464 spca50x_GetFirmware(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300465#endif
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300466 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300467 reg_r(gspca_dev, 0x24, 8, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300469 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300470 reg_r(gspca_dev, 0x25, 4, 1); /* size */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300471 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472
473 /* Init the cam width height with some values get on init ? */
Jean-Francois Moine07d1c692010-01-10 04:32:11 -0300474 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300476 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300477 break;
478 default:
479/* case BRIDGE_SPCA504B: */
480/* case BRIDGE_SPCA536: */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300481 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300482 reg_r(gspca_dev, 0x25, 4, 1); /* size */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300483 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300484 reg_r(gspca_dev, 0x27, 0, 1); /* type */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300485 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300486 break;
487 case BRIDGE_SPCA504:
488 Size += 3;
489 if (sd->subtype == AiptekMiniPenCam13) {
490 /* spca504a aiptek */
491 spca504A_acknowledged_command(gspca_dev,
492 0x08, Size, 0,
493 0x80 | (Size & 0x0f), 1);
494 spca504A_acknowledged_command(gspca_dev,
495 1, 3, 0, 0x9f, 0);
496 } else {
497 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
498 }
499 break;
500 case BRIDGE_SPCA504C:
501 /* capture mode */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300502 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
503 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 break;
505 }
506}
507
508static void spca504_wait_status(struct gspca_dev *gspca_dev)
509{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510 int cnt;
511
512 cnt = 256;
513 while (--cnt > 0) {
514 /* With this we get the status, when return 0 it's all ok */
Jean-François Moinecf252202011-05-17 05:32:39 -0300515 reg_r(gspca_dev, 0x06, 0x00, 1);
516 if (gspca_dev->usb_buf[0] == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 return;
518 msleep(10);
519 }
520}
521
522static void spca504B_setQtable(struct gspca_dev *gspca_dev)
523{
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300524 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300525 reg_r(gspca_dev, 0x26, 0, 1);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300526 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300527}
528
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300529static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530{
531 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300532 u16 reg;
533
534 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300535 reg_w_riv(gspca_dev, 0x00, reg, val);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300536}
537
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300538static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300539{
540 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300541 u16 reg;
542
543 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300544 reg_w_riv(gspca_dev, 0x00, reg, val);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300545}
546
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300547static void setcolors(struct gspca_dev *gspca_dev, s32 val)
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300548{
549 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300550 u16 reg;
551
552 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300553 reg_w_riv(gspca_dev, 0x00, reg, val);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300554}
555
556static void init_ctl_reg(struct gspca_dev *gspca_dev)
557{
558 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 int pollreg = 1;
560
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300561 v4l2_ctrl_handler_setup(&gspca_dev->ctrl_handler);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300562
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300563 switch (sd->bridge) {
564 case BRIDGE_SPCA504:
565 case BRIDGE_SPCA504C:
566 pollreg = 0;
567 /* fall thru */
568 default:
569/* case BRIDGE_SPCA533: */
570/* case BRIDGE_SPCA504B: */
Jean-Francois Moine07d1c692010-01-10 04:32:11 -0300571 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
572 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
573 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574 break;
575 case BRIDGE_SPCA536:
Jean-Francois Moine07d1c692010-01-10 04:32:11 -0300576 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
577 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
578 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 break;
580 }
581 if (pollreg)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300582 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300583}
584
585/* this function is called at probe time */
586static int sd_config(struct gspca_dev *gspca_dev,
587 const struct usb_device_id *id)
588{
589 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591
592 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300594 sd->bridge = id->driver_info >> 8;
595 sd->subtype = id->driver_info;
596
597 if (sd->subtype == AiptekMiniPenCam13) {
Jean-François Moine780e3122010-10-19 04:29:10 -0300598
599 /* try to get the firmware as some cam answer 2.0.1.2.2
600 * and should be a spca504b then overwrite that setting */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300601 reg_r(gspca_dev, 0x20, 0, 1);
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300602 switch (gspca_dev->usb_buf[0]) {
603 case 1:
604 break; /* (right bridge/subtype) */
605 case 2:
606 sd->bridge = BRIDGE_SPCA504B;
607 sd->subtype = 0;
608 break;
609 default:
610 return -ENODEV;
611 }
612 }
613
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 switch (sd->bridge) {
615 default:
616/* case BRIDGE_SPCA504B: */
617/* case BRIDGE_SPCA504: */
618/* case BRIDGE_SPCA536: */
619 cam->cam_mode = vga_mode;
Jean-François Moine780e3122010-10-19 04:29:10 -0300620 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 break;
622 case BRIDGE_SPCA533:
623 cam->cam_mode = custom_mode;
Johannes Goerneraf5f88c2009-07-09 03:28:46 -0300624 if (sd->subtype == MegaImageVI) /* 320x240 only */
625 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
626 else
627 cam->nmodes = ARRAY_SIZE(custom_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 break;
629 case BRIDGE_SPCA504C:
630 cam->cam_mode = vga_mode2;
Mauro Carvalho Chehabd6f76b92009-07-22 00:02:29 -0300631 cam->nmodes = ARRAY_SIZE(vga_mode2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 break;
633 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 return 0;
635}
636
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300637/* this function is called at probe and resume time */
638static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639{
640 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641
642 switch (sd->bridge) {
643 case BRIDGE_SPCA504B:
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300644 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
Jean-Francois Moine07d1c692010-01-10 04:32:11 -0300645 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
646 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
647 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
648 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
649 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650 /* fall thru */
651 case BRIDGE_SPCA533:
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300652 spca504B_PollingDataReady(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300653#ifdef GSPCA_DEBUG
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 spca50x_GetFirmware(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300655#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656 break;
657 case BRIDGE_SPCA536:
Jean-François Moinecf252202011-05-17 05:32:39 -0300658#ifdef GSPCA_DEBUG
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300659 spca50x_GetFirmware(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300660#endif
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300661 reg_r(gspca_dev, 0x00, 0x5002, 1);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300662 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300663 reg_r(gspca_dev, 0x24, 0, 1);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300664 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300665 reg_w_riv(gspca_dev, 0x34, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300666 spca504B_WaitCmdStatus(gspca_dev);
667 break;
668 case BRIDGE_SPCA504C: /* pccam600 */
669 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300670 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
671 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672 spca504_wait_status(gspca_dev);
673 if (sd->subtype == LogitechClickSmart420)
674 write_vector(gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300675 spca504A_clicksmart420_open_data,
676 ARRAY_SIZE(spca504A_clicksmart420_open_data));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 else
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300678 write_vector(gspca_dev, spca504_pccam600_open_data,
679 ARRAY_SIZE(spca504_pccam600_open_data));
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300680 setup_qtable(gspca_dev, qtable_creative_pccam);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681 break;
682 default:
683/* case BRIDGE_SPCA504: */
684 PDEBUG(D_STREAM, "Opening SPCA504");
685 if (sd->subtype == AiptekMiniPenCam13) {
Jean-François Moinecf252202011-05-17 05:32:39 -0300686#ifdef GSPCA_DEBUG
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300687 spca504_read_info(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300688#endif
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300689
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
691 spca504A_acknowledged_command(gspca_dev, 0x24,
692 8, 3, 0x9e, 1);
Uwe Kleine-Königb27d63d2010-07-01 20:48:44 +0200693 /* Twice sequential need status 0xff->0x9e->0x9d */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 spca504A_acknowledged_command(gspca_dev, 0x24,
695 8, 3, 0x9e, 0);
696
697 spca504A_acknowledged_command(gspca_dev, 0x24,
698 0, 0, 0x9d, 1);
699 /******************************/
700 /* spca504a aiptek */
701 spca504A_acknowledged_command(gspca_dev, 0x08,
702 6, 0, 0x86, 1);
703/* reg_write (dev, 0, 0x2000, 0); */
704/* reg_write (dev, 0, 0x2883, 1); */
705/* spca504A_acknowledged_command (gspca_dev, 0x08,
706 6, 0, 0x86, 1); */
707/* spca504A_acknowledged_command (gspca_dev, 0x24,
708 0, 0, 0x9D, 1); */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300709 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
710 /* L92 sno1t.txt */
711 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712 spca504A_acknowledged_command(gspca_dev, 0x01,
713 0x0f, 0, 0xff, 0);
714 }
715 /* setup qtable */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300716 reg_w_riv(gspca_dev, 0, 0x2000, 0);
717 reg_w_riv(gspca_dev, 0, 0x2883, 1);
718 setup_qtable(gspca_dev, qtable_spca504_default);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 break;
720 }
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300721 return gspca_dev->usb_err;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722}
723
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300724static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725{
726 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727 int enable;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300729 /* create the JPEG header */
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300730 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
731 0x22); /* JPEG 411 */
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300732 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300733
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734 if (sd->bridge == BRIDGE_SPCA504B)
735 spca504B_setQtable(gspca_dev);
736 spca504B_SetSizeType(gspca_dev);
737 switch (sd->bridge) {
738 default:
739/* case BRIDGE_SPCA504B: */
740/* case BRIDGE_SPCA533: */
741/* case BRIDGE_SPCA536: */
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300742 switch (sd->subtype) {
743 case MegapixV4:
744 case LogitechClickSmart820:
745 case MegaImageVI:
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300746 reg_w_riv(gspca_dev, 0xf0, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300748 reg_r(gspca_dev, 0xf0, 4, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300750 break;
751 default:
Jean-Francois Moine07d1c692010-01-10 04:32:11 -0300752 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300754 spca504B_PollingDataReady(gspca_dev);
755 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300756 }
757 break;
758 case BRIDGE_SPCA504:
759 if (sd->subtype == AiptekMiniPenCam13) {
Jean-François Moinecf252202011-05-17 05:32:39 -0300760#ifdef GSPCA_DEBUG
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300761 spca504_read_info(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300762#endif
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300763
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
765 spca504A_acknowledged_command(gspca_dev, 0x24,
766 8, 3, 0x9e, 1);
Uwe Kleine-Königb27d63d2010-07-01 20:48:44 +0200767 /* Twice sequential need status 0xff->0x9e->0x9d */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300768 spca504A_acknowledged_command(gspca_dev, 0x24,
769 8, 3, 0x9e, 0);
770 spca504A_acknowledged_command(gspca_dev, 0x24,
771 0, 0, 0x9d, 1);
772 } else {
773 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
Jean-François Moinecf252202011-05-17 05:32:39 -0300774#ifdef GSPCA_DEBUG
Jean-Francois Moine6f081262010-01-10 14:39:24 -0300775 spca504_read_info(gspca_dev);
Jean-François Moinecf252202011-05-17 05:32:39 -0300776#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300777 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
778 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
779 }
780 spca504B_SetSizeType(gspca_dev);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300781 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
782 /* L92 sno1t.txt */
783 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 break;
785 case BRIDGE_SPCA504C:
786 if (sd->subtype == LogitechClickSmart420) {
787 write_vector(gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300788 spca504A_clicksmart420_init_data,
789 ARRAY_SIZE(spca504A_clicksmart420_init_data));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300790 } else {
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300791 write_vector(gspca_dev, spca504_pccam600_init_data,
792 ARRAY_SIZE(spca504_pccam600_init_data));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300793 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300794 enable = (sd->autogain ? 0x04 : 0x01);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300795 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
796 /* auto exposure */
797 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
798 /* auto whiteness */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799
800 /* set default exposure compensation and whiteness balance */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300801 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
802 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 spca504B_SetSizeType(gspca_dev);
804 break;
805 }
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300806 init_ctl_reg(gspca_dev);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300807 return gspca_dev->usb_err;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808}
809
810static void sd_stopN(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813
814 switch (sd->bridge) {
815 default:
816/* case BRIDGE_SPCA533: */
817/* case BRIDGE_SPCA536: */
818/* case BRIDGE_SPCA504B: */
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300819 reg_w_riv(gspca_dev, 0x31, 0, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300821 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822 break;
823 case BRIDGE_SPCA504:
824 case BRIDGE_SPCA504C:
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300825 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826
827 if (sd->subtype == AiptekMiniPenCam13) {
828 /* spca504a aiptek */
829/* spca504A_acknowledged_command(gspca_dev, 0x08,
830 6, 0, 0x86, 1); */
831 spca504A_acknowledged_command(gspca_dev, 0x24,
832 0x00, 0x00, 0x9d, 1);
833 spca504A_acknowledged_command(gspca_dev, 0x01,
834 0x0f, 0x00, 0xff, 1);
835 } else {
836 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
Jean-Francois Moineecb77682009-12-02 14:39:53 -0300837 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 }
839 break;
840 }
841}
842
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300844 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 int len) /* iso packet length */
846{
847 struct sd *sd = (struct sd *) gspca_dev;
848 int i, sof = 0;
Jean-Francois Moine2e1794b2009-08-31 06:15:22 -0300849 static u8 ffd9[] = {0xff, 0xd9};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850
851/* frames are jpeg 4.1.1 without 0xff escape */
852 switch (sd->bridge) {
853 case BRIDGE_SPCA533:
854 if (data[0] == 0xff) {
855 if (data[1] != 0x01) { /* drop packet */
856/* gspca_dev->last_packet_type = DISCARD_PACKET; */
857 return;
858 }
859 sof = 1;
860 data += SPCA533_OFFSET_DATA;
861 len -= SPCA533_OFFSET_DATA;
862 } else {
863 data += 1;
864 len -= 1;
865 }
866 break;
867 case BRIDGE_SPCA536:
868 if (data[0] == 0xff) {
869 sof = 1;
870 data += SPCA536_OFFSET_DATA;
871 len -= SPCA536_OFFSET_DATA;
872 } else {
873 data += 2;
874 len -= 2;
875 }
876 break;
877 default:
878/* case BRIDGE_SPCA504: */
879/* case BRIDGE_SPCA504B: */
880 switch (data[0]) {
881 case 0xfe: /* start of frame */
882 sof = 1;
883 data += SPCA50X_OFFSET_DATA;
884 len -= SPCA50X_OFFSET_DATA;
885 break;
886 case 0xff: /* drop packet */
887/* gspca_dev->last_packet_type = DISCARD_PACKET; */
888 return;
889 default:
890 data += 1;
891 len -= 1;
892 break;
893 }
894 break;
895 case BRIDGE_SPCA504C:
896 switch (data[0]) {
897 case 0xfe: /* start of frame */
898 sof = 1;
899 data += SPCA504_PCCAM600_OFFSET_DATA;
900 len -= SPCA504_PCCAM600_OFFSET_DATA;
901 break;
902 case 0xff: /* drop packet */
903/* gspca_dev->last_packet_type = DISCARD_PACKET; */
904 return;
905 default:
906 data += 1;
907 len -= 1;
908 break;
909 }
910 break;
911 }
912 if (sof) { /* start of frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300913 gspca_frame_add(gspca_dev, LAST_PACKET,
914 ffd9, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915
916 /* put the JPEG header in the new frame */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300917 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine71cb2762009-03-03 05:33:41 -0300918 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919 }
920
921 /* add 0x00 after 0xff */
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300922 i = 0;
923 do {
924 if (data[i] == 0xff) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300925 gspca_frame_add(gspca_dev, INTER_PACKET,
Jean-Francois Moine59746e12009-04-23 14:33:00 -0300926 data, i + 1);
927 len -= i;
928 data += i;
929 *data = 0x00;
930 i = 0;
931 }
932 i++;
933 } while (i < len);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300934 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935}
936
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300937static int sd_set_jcomp(struct gspca_dev *gspca_dev,
938 struct v4l2_jpegcompression *jcomp)
939{
940 struct sd *sd = (struct sd *) gspca_dev;
941
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300942 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
943 return 0;
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300944}
945
946static int sd_get_jcomp(struct gspca_dev *gspca_dev,
947 struct v4l2_jpegcompression *jcomp)
948{
949 struct sd *sd = (struct sd *) gspca_dev;
950
951 memset(jcomp, 0, sizeof *jcomp);
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300952 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -0300953 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
954 | V4L2_JPEG_MARKER_DQT;
955 return 0;
956}
957
Hans Verkuiled5cd6b2012-05-16 08:49:10 -0300958static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
959{
960 struct gspca_dev *gspca_dev =
961 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
962 struct sd *sd = (struct sd *)gspca_dev;
963
964 gspca_dev->usb_err = 0;
965
966 if (!gspca_dev->streaming)
967 return 0;
968
969 switch (ctrl->id) {
970 case V4L2_CID_BRIGHTNESS:
971 setbrightness(gspca_dev, ctrl->val);
972 break;
973 case V4L2_CID_CONTRAST:
974 setcontrast(gspca_dev, ctrl->val);
975 break;
976 case V4L2_CID_SATURATION:
977 setcolors(gspca_dev, ctrl->val);
978 break;
979 case V4L2_CID_AUTOGAIN:
980 sd->autogain = ctrl->val;
981 break;
982 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
983 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
984 break;
985 }
986 return gspca_dev->usb_err;
987}
988
989static const struct v4l2_ctrl_ops sd_ctrl_ops = {
990 .s_ctrl = sd_s_ctrl,
991};
992
993static int sd_init_controls(struct gspca_dev *gspca_dev)
994{
995 struct sd *sd = (struct sd *)gspca_dev;
996 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
997
998 gspca_dev->vdev.ctrl_handler = hdl;
999 v4l2_ctrl_handler_init(hdl, 5);
1000 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1001 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
1002 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1003 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
1004 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1005 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
1006 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1007 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1008 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1009 V4L2_CID_JPEG_COMPRESSION_QUALITY,
1010 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
1011
1012 if (hdl->error) {
1013 pr_err("Could not initialize controls\n");
1014 return hdl->error;
1015 }
1016 return 0;
1017}
1018
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001020static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 .name = MODULE_NAME,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001023 .init = sd_init,
Hans Verkuiled5cd6b2012-05-16 08:49:10 -03001024 .init_controls = sd_init_controls,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 .start = sd_start,
1026 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 .pkt_scan = sd_pkt_scan,
Jean-Francois Moine77ac0ba2009-03-02 06:40:52 -03001028 .get_jcomp = sd_get_jcomp,
1029 .set_jcomp = sd_set_jcomp,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001030};
1031
1032/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001033#define BS(bridge, subtype) \
1034 .driver_info = (BRIDGE_ ## bridge << 8) \
1035 | (subtype)
Jean-François Moine95c967c2011-01-13 05:20:29 -03001036static const struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001037 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1038 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1039 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1040 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1041 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1042 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1043 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1044 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1045 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1046 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1047 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1048 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1049 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1050 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1051 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1052 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1053 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1054 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
Jean-Francois Moined41592a2009-12-13 14:11:07 -03001055 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001056 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
Johannes Goerneraf5f88c2009-07-09 03:28:46 -03001057 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001058 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1059 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1060 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1061 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1062 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1063 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1064 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1065 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1066 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1067 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1068 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1069 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1070 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1071 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1072 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1073 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1074 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1075 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1076 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1077 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1078 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1079 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1080 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1081 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1082 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1083 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1084 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1085 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1086 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1087 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1088 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1089 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1090 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1091 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1092 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1093 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1094 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1095 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001096 {}
1097};
1098MODULE_DEVICE_TABLE(usb, device_table);
1099
1100/* -- device connect -- */
1101static int sd_probe(struct usb_interface *intf,
1102 const struct usb_device_id *id)
1103{
1104 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1105 THIS_MODULE);
1106}
1107
1108static struct usb_driver sd_driver = {
1109 .name = MODULE_NAME,
1110 .id_table = device_table,
1111 .probe = sd_probe,
1112 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001113#ifdef CONFIG_PM
1114 .suspend = gspca_suspend,
1115 .resume = gspca_resume,
1116#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117};
1118
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001119module_usb_driver(sd_driver);