blob: 044a9ec58db57345262edb5dd25c47e1afd37302 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define MODULE_NAME "sonixb"
24
25#include "gspca.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030034 atomic_t avg_lum;
35
Hans de Goedead5ef80d2008-07-14 10:11:42 -030036 unsigned char gain;
37 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030038 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030039 unsigned char autogain;
40 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030041 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030042 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -030044 unsigned char fr_h_sz; /* size of frame header */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045 char sensor; /* Type of image sensor chip */
46#define SENSOR_HV7131R 0
47#define SENSOR_OV6650 1
48#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030049#define SENSOR_PAS106 3
50#define SENSOR_PAS202 4
51#define SENSOR_TAS5110 5
52#define SENSOR_TAS5130CXX 6
Hans de Goedea975a522008-07-16 15:29:11 -030053 char sensor_has_gain;
54 __u8 sensor_addr;
Hans de Goede6af492e2008-07-22 07:09:33 -030055 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056};
57
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030058/* flags used in the device id table */
59#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030060#define F_SIF 0x02 /* sif or vga */
61#define F_H18 0x04 /* long (18 b) or short (12 b) frame header */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030062
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063#define COMP2 0x8f
64#define COMP 0xc7 /* 0x87 //0x07 */
65#define COMP1 0xc9 /* 0x89 //0x09 */
66
67#define MCK_INIT 0x63
68#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
69
70#define SYS_CLK 0x04
71
Hans de Goededcef3232008-07-10 10:40:53 -030072/* We calculate the autogain at the end of the transfer of a frame, at this
73 moment a frame with the old settings is being transmitted, and a frame is
74 being captured with the old settings. So if we adjust the autogain we must
75 ignore atleast the 2 next frames for the new settings to come into effect
76 before doing any other adjustments */
77#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goedead5ef80d2008-07-14 10:11:42 -030078#define AUTOGAIN_DEADZONE 1000
Hans de Goededcef3232008-07-10 10:40:53 -030079#define DESIRED_AVG_LUM 7000
80
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -030084static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -030090static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030092
93static struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -030094#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030095 {
96 {
97 .id = V4L2_CID_BRIGHTNESS,
98 .type = V4L2_CTRL_TYPE_INTEGER,
99 .name = "Brightness",
100 .minimum = 0,
101 .maximum = 255,
102 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300103#define BRIGHTNESS_DEF 127
104 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 },
106 .set = sd_setbrightness,
107 .get = sd_getbrightness,
108 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300109#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 {
111 {
Hans de Goededcef3232008-07-10 10:40:53 -0300112 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300113 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300114 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300116 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300118#define GAIN_DEF 127
119#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300120 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121 },
Hans de Goededcef3232008-07-10 10:40:53 -0300122 .set = sd_setgain,
123 .get = sd_getgain,
124 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300125#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300126 {
127 {
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300131#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
132#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300133 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300134 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300135 .step = 1,
136 .default_value = EXPOSURE_DEF,
137 .flags = 0,
138 },
139 .set = sd_setexposure,
140 .get = sd_getexposure,
141 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300142#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300143 {
144 {
145 .id = V4L2_CID_AUTOGAIN,
146 .type = V4L2_CTRL_TYPE_BOOLEAN,
147 .name = "Automatic Gain (and Exposure)",
148 .minimum = 0,
149 .maximum = 1,
150 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300151#define AUTOGAIN_DEF 1
152 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300153 .flags = 0,
154 },
155 .set = sd_setautogain,
156 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300158#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300159 {
160 {
161 .id = V4L2_CID_POWER_LINE_FREQUENCY,
162 .type = V4L2_CTRL_TYPE_MENU,
163 .name = "Light frequency filter",
164 .minimum = 0,
165 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
166 .step = 1,
167#define FREQ_DEF 1
168 .default_value = FREQ_DEF,
169 },
170 .set = sd_setfreq,
171 .get = sd_getfreq,
172 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173};
174
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300175static struct v4l2_pix_format vga_mode[] = {
176 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .bytesperline = 160,
178 .sizeimage = 160 * 120,
179 .colorspace = V4L2_COLORSPACE_SRGB,
180 .priv = 2},
181 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
182 .bytesperline = 320,
183 .sizeimage = 320 * 240,
184 .colorspace = V4L2_COLORSPACE_SRGB,
185 .priv = 1},
186 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
187 .bytesperline = 640,
188 .sizeimage = 640 * 480,
189 .colorspace = V4L2_COLORSPACE_SRGB,
190 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300191};
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300192static struct v4l2_pix_format sif_mode[] = {
193 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
194 .bytesperline = 176,
195 .sizeimage = 176 * 144,
196 .colorspace = V4L2_COLORSPACE_SRGB,
197 .priv = 1},
198 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
199 .bytesperline = 352,
200 .sizeimage = 352 * 288,
201 .colorspace = V4L2_COLORSPACE_SRGB,
202 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203};
204
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300205static const __u8 initHv7131[] = {
206 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
207 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
209 0x28, 0x1e, 0x60, 0x8a, 0x20,
210 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
211};
212static const __u8 hv7131_sensor_init[][8] = {
213 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
214 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
215 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
216 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
217 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
218};
219static const __u8 initOv6650[] = {
220 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
221 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
223 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
224};
225static const __u8 ov6650_sensor_init[][8] =
226{
227 /* Bright, contrast, etc are set througth SCBB interface.
228 * AVCAP on win2 do not send any data on this controls. */
229 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300230
231 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300232 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300233 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300234 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300235 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
237/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
238 * THIS SET GREEN SCREEN
239 * (pixels could be innverted in decode kind of "brg",
240 * but blue wont be there. Avoid this data ... */
241 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
242 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
243 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300244 /* Enable rgb brightness control */
245 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
246 /* HDG: Note windows uses the line below, which sets both register 0x60
247 and 0x61 I believe these registers of the ov6650 are identical as
248 those of the ov7630, because if this is true the windows settings
249 add a bit additional red gain and a lot additional blue gain, which
250 matches my findings that the windows settings make blue much too
251 blue and red a little too red.
252 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300253 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
255 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300256};
Hans de Goededcef3232008-07-10 10:40:53 -0300257
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300258static const __u8 initOv7630[] = {
259 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
260 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
261 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
262 0x28, 0x1e, /* H & V sizes r15 .. r16 */
263 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
264 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
265};
266static const __u8 initOv7630_3[] = {
267 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
268 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300269 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300270 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300271 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
272 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
273 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
274 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300275};
Hans de Goede6af492e2008-07-22 07:09:33 -0300276static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300277 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
278 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
279/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300280 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
282 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
283 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
284 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
285 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
286 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
287 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300288 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
289/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300290 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
291 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
292 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
293 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
294 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
295 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
296};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297
298static const __u8 initPas106[] = {
299 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
300 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
302 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
303 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
304};
305/* compression 0x86 mckinit1 0x2b */
306static const __u8 pas106_data[][2] = {
307 {0x02, 0x04}, /* Pixel Clock Divider 6 */
308 {0x03, 0x13}, /* Frame Time MSB */
309/* {0x03, 0x12}, * Frame Time MSB */
310 {0x04, 0x06}, /* Frame Time LSB */
311/* {0x04, 0x05}, * Frame Time LSB */
312 {0x05, 0x65}, /* Shutter Time Line Offset */
313/* {0x05, 0x6d}, * Shutter Time Line Offset */
314/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
315 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
316 {0x07, 0xc1}, /* Black Level Subtract Sign */
317/* {0x07, 0x00}, * Black Level Subtract Sign */
318 {0x08, 0x06}, /* Black Level Subtract Level */
319 {0x08, 0x06}, /* Black Level Subtract Level */
320/* {0x08, 0x01}, * Black Level Subtract Level */
321 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
322 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
323 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
324 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
325 {0x0d, 0x00}, /* Color GainH Pixel */
326 {0x0e, 0x0e}, /* Global Gain */
327 {0x0f, 0x00}, /* Contrast */
328 {0x10, 0x06}, /* H&V synchro polarity */
329 {0x11, 0x06}, /* ?default */
330 {0x12, 0x06}, /* DAC scale */
331 {0x14, 0x02}, /* ?default */
332 {0x13, 0x01}, /* Validate Settings */
333};
334static const __u8 initPas202[] = {
335 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
336 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
338 0x28, 0x1e, 0x28, 0x89, 0x30,
339 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
340};
341static const __u8 pas202_sensor_init[][8] = {
342 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
343 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
344 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
345 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
346 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
347 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
348 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
349 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
350 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
351 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
352 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
353 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
354
355 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
356 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
357 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
358 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
359 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
360 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
361 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
362 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
363};
364
365static const __u8 initTas5110[] = {
366 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
367 0x00, 0x00,
368 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
369 0x16, 0x12, 0x60, 0x86, 0x2b,
370 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
371};
372static const __u8 tas5110_sensor_init[][8] = {
373 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
374 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
375 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
376};
377
378static const __u8 initTas5130[] = {
379 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
380 0x00, 0x00,
381 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
382 0x28, 0x1e, 0x60, COMP, MCK_INIT,
383 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
384};
385static const __u8 tas5130_sensor_init[][8] = {
386/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
387 * shutter 0x47 short exposure? */
388 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
389 /* shutter 0x01 long exposure */
390 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
391};
392
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300393/* get one byte in gspca_dev->usb_buf */
394static void reg_r(struct gspca_dev *gspca_dev,
395 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300397 usb_control_msg(gspca_dev->dev,
398 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399 0, /* request */
400 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
401 value,
402 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300403 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300404 500);
405}
406
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300407static void reg_w(struct gspca_dev *gspca_dev,
408 __u16 value,
409 const __u8 *buffer,
410 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300412#ifdef GSPCA_DEBUG
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300413 if (len > sizeof gspca_dev->usb_buf) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300414 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
415 return;
416 }
417#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300418 memcpy(gspca_dev->usb_buf, buffer, len);
419 usb_control_msg(gspca_dev->dev,
420 usb_sndctrlpipe(gspca_dev->dev, 0),
421 0x08, /* request */
422 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
423 value,
424 0, /* index */
425 gspca_dev->usb_buf, len,
426 500);
427}
428
429static void reg_w_big(struct gspca_dev *gspca_dev,
430 __u16 value,
431 const __u8 *buffer,
432 int len)
433{
434 __u8 *tmpbuf;
435
436 tmpbuf = kmalloc(len, GFP_KERNEL);
Hans de Goede0d2a7222008-07-03 08:15:22 -0300437 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300438 usb_control_msg(gspca_dev->dev,
439 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300440 0x08, /* request */
441 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
442 value,
443 0, /* index */
Hans de Goede0d2a7222008-07-03 08:15:22 -0300444 tmpbuf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300446 kfree(tmpbuf);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447}
448
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300449static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450{
451 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452
453 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300454 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 while (retry--) {
456 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300457 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300458 if (gspca_dev->usb_buf[0] & 0x04) {
459 if (gspca_dev->usb_buf[0] & 0x08)
460 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300462 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 }
464 return -1;
465}
466
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300467static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 const __u8 buffer[][8], int len)
469{
470 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300471 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472 len -= 8;
473 if (len <= 0)
474 break;
475 buffer++;
476 }
477}
478
479static void setbrightness(struct gspca_dev *gspca_dev)
480{
481 struct sd *sd = (struct sd *) gspca_dev;
482 __u8 value;
483
484 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300485 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300486 case SENSOR_OV7630: {
487 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300488 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489
490 /* change reg 0x06 */
Hans de Goedea975a522008-07-16 15:29:11 -0300491 i2cOV[1] = sd->sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300493 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494 goto err;
495 break;
496 }
497 case SENSOR_PAS106: {
498 __u8 i2c1[] =
499 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
500
501 i2c1[3] = sd->brightness >> 3;
502 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300503 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 goto err;
505 i2c1[3] = 0x01;
506 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300507 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 goto err;
509 break;
510 }
511 case SENSOR_PAS202: {
512 /* __u8 i2cpexpo1[] =
513 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
514 __u8 i2cpexpo[] =
515 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
516 __u8 i2cp202[] =
517 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
518 static __u8 i2cpdoit[] =
519 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
520
521 /* change reg 0x10 */
522 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300523/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300525/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300526 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300529 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 goto err;
531 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 goto err;
536 break;
537 }
Hans de Goededcef3232008-07-10 10:40:53 -0300538 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 __u8 i2c[] =
540 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
541
542 value = 0xff - sd->brightness;
543 i2c[4] = value;
544 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546 goto err;
547 break;
548 }
549 }
550 return;
551err:
552 PDEBUG(D_ERR, "i2c error brightness");
553}
Hans de Goededcef3232008-07-10 10:40:53 -0300554
555static void setsensorgain(struct gspca_dev *gspca_dev)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300558 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300559
560 switch (sd->sensor) {
561
562 case SENSOR_TAS5110: {
563 __u8 i2c[] =
564 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
565
Hans de Goedea975a522008-07-16 15:29:11 -0300566 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300567 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300568 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300569 break;
570 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300571
Hans de Goedea975a522008-07-16 15:29:11 -0300572 case SENSOR_OV6650:
573 gain >>= 1;
574 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300575 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300576 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300577
Hans de Goedea975a522008-07-16 15:29:11 -0300578 i2c[1] = sd->sensor_addr;
579 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300580 if (i2c_w(gspca_dev, i2c) < 0)
581 goto err;
582 break;
583 }
Hans de Goededcef3232008-07-10 10:40:53 -0300584 }
585 return;
586err:
587 PDEBUG(D_ERR, "i2c error gain");
588}
589
590static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591{
592 struct sd *sd = (struct sd *) gspca_dev;
593 __u8 gain;
594 __u8 rgb_value;
595
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300596 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300597
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 /* red and blue gain */
599 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 /* green gain */
602 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300603 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300604
605 if (sd->sensor_has_gain)
606 setsensorgain(gspca_dev);
607}
608
609static void setexposure(struct gspca_dev *gspca_dev)
610{
611 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300612
613 switch (sd->sensor) {
614 case SENSOR_TAS5110: {
615 __u8 reg;
616
617 /* register 19's high nibble contains the sn9c10x clock divider
618 The high nibble configures the no fps according to the
619 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300620 reg = 120 * sd->exposure / 1000;
621 if (reg < 2)
622 reg = 2;
623 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300624 reg = 15;
625 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300627 break;
628 }
Hans de Goedea975a522008-07-16 15:29:11 -0300629 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300630 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300631 /* The ov6650 / ov7630 have 2 registers which both influence
632 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300633 according to: fps = 30 / (low_nibble + 1)
634
635 The fps configures the maximum exposure setting, but it is
636 possible to use less exposure then what the fps maximum
637 allows by setting register 10. register 10 configures the
638 actual exposure as quotient of the full exposure, with 0
639 being no exposure at all (not very usefull) and reg10_max
640 being max exposure possible at that framerate.
641
642 The code maps our 0 - 510 ms exposure ctrl to these 2
643 registers, trying to keep fps as high as possible.
644 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300645 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
646 int reg10, reg11, reg10_max;
647
Hans de Goede66f35822008-07-16 10:16:28 -0300648 /* ov6645 datasheet says reg10_max is 9a, but that uses
649 tline * 2 * reg10 as formula for calculating texpo, the
650 ov6650 probably uses the same formula as the 7730 which uses
651 tline * 4 * reg10, which explains why the reg10max we've
652 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300653 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300654 if (sd->sensor == SENSOR_OV6650) {
655 reg10_max = 0x4d;
656 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
657 } else
658 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300659
660 reg11 = (60 * sd->exposure + 999) / 1000;
661 if (reg11 < 1)
662 reg11 = 1;
663 else if (reg11 > 16)
664 reg11 = 16;
665
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300666 /* In 640x480, if the reg11 has less than 3, the image is
667 unstable (not enough bandwidth). */
668 if (gspca_dev->width == 640 && reg11 < 3)
669 reg11 = 3;
670
Hans de Goedef4d52022008-07-15 09:36:42 -0300671 /* frame exposure time in ms = 1000 * reg11 / 30 ->
672 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
673 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300674
675 /* Don't allow this to get below 10 when using autogain, the
676 steps become very large (relatively) when below 10 causing
677 the image to oscilate from much too dark, to much too bright
678 and back again. */
679 if (sd->autogain && reg10 < 10)
680 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300681 else if (reg10 > reg10_max)
682 reg10 = reg10_max;
683
684 /* Write reg 10 and reg11 low nibble */
Hans de Goedea975a522008-07-16 15:29:11 -0300685 i2c[1] = sd->sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300686 i2c[3] = reg10;
687 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300688
689 /* If register 11 didn't change, don't change it */
690 if (sd->reg11 == reg11 )
691 i2c[0] = 0xa0;
692
693 if (i2c_w(gspca_dev, i2c) == 0)
694 sd->reg11 = reg11;
695 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300696 PDEBUG(D_ERR, "i2c error exposure");
697 break;
698 }
Hans de Goededcef3232008-07-10 10:40:53 -0300699 }
700}
701
Hans de Goede66f35822008-07-16 10:16:28 -0300702static void setfreq(struct gspca_dev *gspca_dev)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300707 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300708 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300709 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300710 compensation, for the ov6650 this is identical to ov6630
711 0x2b register, see ov6630 datasheet.
712 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300713 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300714 switch (sd->freq) {
715 default:
716/* case 0: * no filter*/
717/* case 2: * 60 hz */
718 i2c[3] = 0;
719 break;
720 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300721 i2c[3] = (sd->sensor == SENSOR_OV6650)
722 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300723 break;
724 }
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300725 i2c[1] = sd->sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300726 if (i2c_w(gspca_dev, i2c) < 0)
727 PDEBUG(D_ERR, "i2c error setfreq");
728 break;
729 }
730 }
731}
732
Hans de Goededcef3232008-07-10 10:40:53 -0300733static void do_autogain(struct gspca_dev *gspca_dev)
734{
735 struct sd *sd = (struct sd *) gspca_dev;
736 int avg_lum = atomic_read(&sd->avg_lum);
737
738 if (avg_lum == -1)
739 return;
740
741 if (sd->autogain_ignore_frames > 0)
742 sd->autogain_ignore_frames--;
743 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
744 sd->brightness * DESIRED_AVG_LUM / 127,
Hans de Goedea975a522008-07-16 15:29:11 -0300745 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
746 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
747 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300748 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300749 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750}
751
752/* this function is called at probe time */
753static int sd_config(struct gspca_dev *gspca_dev,
754 const struct usb_device_id *id)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 int sif = 0;
Hans de Goede65f33392008-09-03 17:12:15 -0300759 const __u8 stop = 0x09; /* Disable stream turn of LED */
760
761 reg_r(gspca_dev, 0x00);
762 if (gspca_dev->usb_buf[0] != 0x10)
763 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300765 /* copy the webcam info from the device id */
766 sd->sensor = (id->driver_info >> 24) & 0xff;
767 if (id->driver_info & (F_GAIN << 16))
768 sd->sensor_has_gain = 1;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300769 if (id->driver_info & (F_SIF << 16))
770 sif = 1;
771 if (id->driver_info & (F_H18 << 16))
772 sd->fr_h_sz = 18; /* size of frame header */
773 else
774 sd->fr_h_sz = 12;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300775 gspca_dev->ctrl_dis = (id->driver_info >> 8) & 0xff;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300776 sd->sensor_addr = id->driver_info & 0xff;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300777
778 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779 cam->epaddr = 0x01;
780 if (!sif) {
781 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300782 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 } else {
784 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300785 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786 }
Hans de Goededcef3232008-07-10 10:40:53 -0300787 sd->brightness = BRIGHTNESS_DEF;
788 sd->gain = GAIN_DEF;
789 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300790 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
791 sd->autogain = 0; /* Disable do_autogain callback */
792 else
793 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300794 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300795
Hans de Goede65f33392008-09-03 17:12:15 -0300796 /* Disable stream turn of LED */
797 reg_w(gspca_dev, 0x01, &stop, 1);
798
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799 return 0;
800}
801
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300802/* this function is called at probe and resume time */
803static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805 return 0;
806}
807
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300808static void pas106_i2cinit(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809{
810 int i;
811 const __u8 *data;
812 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
813
814 i = ARRAY_SIZE(pas106_data);
815 data = pas106_data[0];
816 while (--i >= 0) {
817 memcpy(&i2c1[2], data, 2);
818 /* copy 2 bytes from the template */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300819 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820 PDEBUG(D_ERR, "i2c error pas106");
821 data += 2;
822 }
823}
824
825/* -- start the camera -- */
826static void sd_start(struct gspca_dev *gspca_dev)
827{
828 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede6af492e2008-07-22 07:09:33 -0300829 int mode, l = 0x1f;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830 const __u8 *sn9c10x;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831 __u8 reg17_19[3];
832
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300833 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834 switch (sd->sensor) {
835 case SENSOR_HV7131R:
836 sn9c10x = initHv7131;
837 reg17_19[0] = 0x60;
838 reg17_19[1] = (mode << 4) | 0x8a;
839 reg17_19[2] = 0x20;
840 break;
841 case SENSOR_OV6650:
842 sn9c10x = initOv6650;
843 reg17_19[0] = 0x68;
844 reg17_19[1] = (mode << 4) | 0x8b;
845 reg17_19[2] = 0x20;
846 break;
847 case SENSOR_OV7630:
Hans de Goede6af492e2008-07-22 07:09:33 -0300848 if (sd->fr_h_sz == 18) { /* SN9C103 */
849 sn9c10x = initOv7630_3;
850 l = sizeof initOv7630_3;
851 } else
852 sn9c10x = initOv7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 reg17_19[0] = 0x68;
854 reg17_19[1] = (mode << 4) | COMP2;
855 reg17_19[2] = MCK_INIT1;
856 break;
857 case SENSOR_PAS106:
858 sn9c10x = initPas106;
859 reg17_19[0] = 0x24; /* 0x28 */
860 reg17_19[1] = (mode << 4) | COMP1;
861 reg17_19[2] = MCK_INIT1;
862 break;
863 case SENSOR_PAS202:
864 sn9c10x = initPas202;
865 reg17_19[0] = mode ? 0x24 : 0x20;
866 reg17_19[1] = (mode << 4) | 0x89;
867 reg17_19[2] = 0x20;
868 break;
869 case SENSOR_TAS5110:
870 sn9c10x = initTas5110;
871 reg17_19[0] = 0x60;
872 reg17_19[1] = (mode << 4) | 0x86;
873 reg17_19[2] = 0x2b; /* 0xf3; */
874 break;
875 default:
876/* case SENSOR_TAS5130CXX: */
877 sn9c10x = initTas5130;
878 reg17_19[0] = 0x60;
879 reg17_19[1] = (mode << 4) | COMP;
880 reg17_19[2] = mode ? 0x23 : 0x43;
881 break;
882 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300883
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300885 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300887 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 /* Set the registers from the template */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300889 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 switch (sd->sensor) {
891 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300892 i2c_w_vector(gspca_dev, hv7131_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 sizeof hv7131_sensor_init);
894 break;
895 case SENSOR_OV6650:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300896 i2c_w_vector(gspca_dev, ov6650_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300897 sizeof ov6650_sensor_init);
898 break;
899 case SENSOR_OV7630:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300900 i2c_w_vector(gspca_dev, ov7630_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901 sizeof ov7630_sensor_init);
Hans de Goede6af492e2008-07-22 07:09:33 -0300902 if (sd->fr_h_sz == 18) { /* SN9C103 */
903 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
904 0x00, 0x00, 0x10 };
905 i2c_w(gspca_dev, i2c);
906 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 break;
908 case SENSOR_PAS106:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300909 pas106_i2cinit(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 break;
911 case SENSOR_PAS202:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300912 i2c_w_vector(gspca_dev, pas202_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913 sizeof pas202_sensor_init);
914 break;
915 case SENSOR_TAS5110:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300916 i2c_w_vector(gspca_dev, tas5110_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 sizeof tas5110_sensor_init);
918 break;
919 default:
920/* case SENSOR_TAS5130CXX: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300921 i2c_w_vector(gspca_dev, tas5130_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 sizeof tas5130_sensor_init);
923 break;
924 }
Hans de Goede3647fea2008-07-15 05:36:30 -0300925 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
926 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927 /* compression register */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300928 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300929 /* H_start */
930 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
931 /* V_START */
932 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 /* reset 0x17 SensorClk enable inv Clk 0x60 */
934 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300935 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Andoni Zubimendi794af522008-07-16 08:33:14 -0300937 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300939 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300941 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 /* Compression */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300943 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 msleep(20);
945
Hans de Goede6af492e2008-07-22 07:09:33 -0300946 sd->reg11 = -1;
947
Hans de Goededcef3232008-07-10 10:40:53 -0300948 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300949 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300950 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300951 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300952
Hans de Goede6af492e2008-07-22 07:09:33 -0300953 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300954 sd->autogain_ignore_frames = 0;
955 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956}
957
958static void sd_stopN(struct gspca_dev *gspca_dev)
959{
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300960 __u8 ByteSend;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961
962 ByteSend = 0x09; /* 0X00 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300963 reg_w(gspca_dev, 0x01, &ByteSend, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964}
965
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966static void sd_pkt_scan(struct gspca_dev *gspca_dev,
967 struct gspca_frame *frame, /* target */
968 unsigned char *data, /* isoc packet */
969 int len) /* iso packet length */
970{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300971 int i;
Hans de Goededcef3232008-07-10 10:40:53 -0300972 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973
Hans de Goedec36260ee2008-07-16 09:56:07 -0300974 /* frames start with:
975 * ff ff 00 c4 c4 96 synchro
976 * 00 (unknown)
977 * xx (frame sequence / size / compression)
978 * (xx) (idem - extra byte for sn9c103)
979 * ll mm brightness sum inside auto exposure
980 * ll mm brightness sum outside auto exposure
981 * (xx xx xx xx xx) audio values for snc103
982 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300984 for (i = 0; i < len - 6; i++) {
985 if (data[0 + i] == 0xff
986 && data[1 + i] == 0xff
987 && data[2 + i] == 0x00
988 && data[3 + i] == 0xc4
989 && data[4 + i] == 0xc4
990 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -0300991 int lum = -1;
992 int pkt_type = LAST_PACKET;
993
Hans de Goedec36260ee2008-07-16 09:56:07 -0300994 if (len - i < sd->fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -0300995 PDEBUG(D_STREAM, "packet too short to"
996 " get avg brightness");
997 } else if (sd->fr_h_sz == 12) {
Hans de Goede6af492e2008-07-22 07:09:33 -0300998 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -0300999 } else {
Hans de Goede6af492e2008-07-22 07:09:33 -03001000 lum = data[i + 9] +
1001 (data[i + 10] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001002 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001003 if (lum == 0) {
1004 lum = -1;
1005 sd->frames_to_drop = 2;
1006 }
1007 atomic_set(&sd->avg_lum, lum);
1008
1009 if (sd->frames_to_drop) {
1010 sd->frames_to_drop--;
1011 pkt_type = DISCARD_PACKET;
1012 }
1013
1014 frame = gspca_frame_add(gspca_dev, pkt_type,
1015 frame, data, 0);
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -03001016 data += i + sd->fr_h_sz;
1017 len -= i + sd->fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001018 gspca_frame_add(gspca_dev, FIRST_PACKET,
1019 frame, data, len);
1020 return;
1021 }
1022 }
1023 }
1024 gspca_frame_add(gspca_dev, INTER_PACKET,
1025 frame, data, len);
1026}
1027
1028static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031
1032 sd->brightness = val;
1033 if (gspca_dev->streaming)
1034 setbrightness(gspca_dev);
1035 return 0;
1036}
1037
1038static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1039{
1040 struct sd *sd = (struct sd *) gspca_dev;
1041
1042 *val = sd->brightness;
1043 return 0;
1044}
1045
Hans de Goededcef3232008-07-10 10:40:53 -03001046static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047{
1048 struct sd *sd = (struct sd *) gspca_dev;
1049
Hans de Goededcef3232008-07-10 10:40:53 -03001050 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001051 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001052 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 return 0;
1054}
1055
Hans de Goededcef3232008-07-10 10:40:53 -03001056static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057{
1058 struct sd *sd = (struct sd *) gspca_dev;
1059
Hans de Goededcef3232008-07-10 10:40:53 -03001060 *val = sd->gain;
1061 return 0;
1062}
1063
1064static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1065{
1066 struct sd *sd = (struct sd *) gspca_dev;
1067
1068 sd->exposure = val;
1069 if (gspca_dev->streaming)
1070 setexposure(gspca_dev);
1071 return 0;
1072}
1073
1074static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1075{
1076 struct sd *sd = (struct sd *) gspca_dev;
1077
1078 *val = sd->exposure;
1079 return 0;
1080}
1081
1082static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1083{
1084 struct sd *sd = (struct sd *) gspca_dev;
1085
1086 sd->autogain = val;
1087 /* when switching to autogain set defaults to make sure
1088 we are on a valid point of the autogain gain /
1089 exposure knee graph, and give this change time to
1090 take effect before doing autogain. */
1091 if (sd->autogain) {
1092 sd->exposure = EXPOSURE_DEF;
1093 sd->gain = GAIN_DEF;
1094 if (gspca_dev->streaming) {
1095 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1096 setexposure(gspca_dev);
1097 setgain(gspca_dev);
1098 }
1099 }
1100
1101 return 0;
1102}
1103
1104static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1105{
1106 struct sd *sd = (struct sd *) gspca_dev;
1107
1108 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001109 return 0;
1110}
1111
Hans de Goede66f35822008-07-16 10:16:28 -03001112static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 sd->freq = val;
1117 if (gspca_dev->streaming)
1118 setfreq(gspca_dev);
1119 return 0;
1120}
1121
1122static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1123{
1124 struct sd *sd = (struct sd *) gspca_dev;
1125
1126 *val = sd->freq;
1127 return 0;
1128}
1129
1130static int sd_querymenu(struct gspca_dev *gspca_dev,
1131 struct v4l2_querymenu *menu)
1132{
1133 switch (menu->id) {
1134 case V4L2_CID_POWER_LINE_FREQUENCY:
1135 switch (menu->index) {
1136 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1137 strcpy((char *) menu->name, "NoFliker");
1138 return 0;
1139 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1140 strcpy((char *) menu->name, "50 Hz");
1141 return 0;
1142 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1143 strcpy((char *) menu->name, "60 Hz");
1144 return 0;
1145 }
1146 break;
1147 }
1148 return -EINVAL;
1149}
1150
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001151/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001152static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001153 .name = MODULE_NAME,
1154 .ctrls = sd_ctrls,
1155 .nctrls = ARRAY_SIZE(sd_ctrls),
1156 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001157 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 .start = sd_start,
1159 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001161 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001162 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001163};
1164
1165/* -- module initialisation -- */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001166#define SFCI(sensor, flags, disable_ctrls, i2c_addr) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001167 .driver_info = (SENSOR_ ## sensor << 24) \
1168 | ((flags) << 16) \
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001169 | ((disable_ctrls) << 8) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001170 | (i2c_addr)
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001171#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
1172#define NO_FREQ (1 << FREQ_IDX)
1173#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
1174
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175static __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001176#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001177 {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001178 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001179 {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001180 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001181 {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001182 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001183 {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001184 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001185 {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001186 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001187#endif
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001188 {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001189 SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001190#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001191 {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001192 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001193 {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001194 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001195 {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001196 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001197 {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001198 SFCI(PAS202, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001199 {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001200 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001201 {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001202 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001203 {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001204 SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001205 {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001206 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001207 {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001208 SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001209 {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001210 SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001211#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212 {}
1213};
1214MODULE_DEVICE_TABLE(usb, device_table);
1215
1216/* -- device connect -- */
1217static int sd_probe(struct usb_interface *intf,
1218 const struct usb_device_id *id)
1219{
1220 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1221 THIS_MODULE);
1222}
1223
1224static struct usb_driver sd_driver = {
1225 .name = MODULE_NAME,
1226 .id_table = device_table,
1227 .probe = sd_probe,
1228 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001229#ifdef CONFIG_PM
1230 .suspend = gspca_suspend,
1231 .resume = gspca_resume,
1232#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233};
1234
1235/* -- module insert / remove -- */
1236static int __init sd_mod_init(void)
1237{
1238 if (usb_register(&sd_driver) < 0)
1239 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001240 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001241 return 0;
1242}
1243static void __exit sd_mod_exit(void)
1244{
1245 usb_deregister(&sd_driver);
1246 PDEBUG(D_PROBE, "deregistered");
1247}
1248
1249module_init(sd_mod_init);
1250module_exit(sd_mod_exit);