blob: f47a82902fa382aa1ee2ea513921b8fd3257d9df [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
Hans de Goede93627732008-09-04 16:20:12 -030023/* Some documentation on known sonixb registers:
24
25Reg Use
260x10 high nibble red gain low nibble blue gain
270x11 low nibble green gain
280x12 hstart
290x13 vstart
300x15 hsize (hsize = register-value * 16)
310x16 vsize (vsize = register-value * 16)
320x17 bit 0 toggle compression quality (according to sn9c102 driver)
330x18 bit 7 enables compression, bit 4-5 set image down scaling:
34 00 scale 1, 01 scale 1/2, 10, scale 1/4
350x19 high-nibble is sensor clock divider, changes exposure on sensors which
36 use a clock generated by the bridge. Some sensors have their own clock.
370x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
380x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
390x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
400x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
41*/
42
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043#define MODULE_NAME "sonixb"
44
Hans de Goedef65e93d2010-01-31 10:35:15 -030045#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030046#include "gspca.h"
47
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030048MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
49MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
50MODULE_LICENSE("GPL");
51
52/* specific webcam descriptor */
53struct sd {
54 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030055 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030056 int prev_avg_lum;
Hans de Goede26984b02010-02-01 13:18:37 -030057 int exp_too_low_cnt;
58 int exp_too_high_cnt;
Hans de Goede2b3e2842010-12-12 08:55:04 -030059 int header_read;
60 u8 header[12]; /* Header without sof marker */
Hans de Goededcef3232008-07-10 10:40:53 -030061
Hans de Goede26984b02010-02-01 13:18:37 -030062 unsigned short exposure;
Hans de Goedead5ef80d2008-07-14 10:11:42 -030063 unsigned char gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030065 unsigned char autogain;
66 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030067 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030068 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030069
Hans de Goedef45f06b2008-09-03 17:12:21 -030070 __u8 bridge; /* Type of bridge */
71#define BRIDGE_101 0
72#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
73#define BRIDGE_103 1
74
75 __u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076#define SENSOR_HV7131R 0
77#define SENSOR_OV6650 1
78#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030079#define SENSOR_PAS106 3
80#define SENSOR_PAS202 4
Hans de Goedeb10af3f2010-01-10 19:31:34 -030081#define SENSOR_TAS5110C 5
82#define SENSOR_TAS5110D 6
83#define SENSOR_TAS5130CXX 7
Hans de Goede6af492e2008-07-22 07:09:33 -030084 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030085};
86
Hans de Goedef45f06b2008-09-03 17:12:21 -030087typedef const __u8 sensor_init_t[8];
88
89struct sensor_data {
90 const __u8 *bridge_init[2];
91 int bridge_init_size[2];
92 sensor_init_t *sensor_init;
93 int sensor_init_size;
94 sensor_init_t *sensor_bridge_init[2];
95 int sensor_bridge_init_size[2];
96 int flags;
97 unsigned ctrl_dis;
98 __u8 sensor_addr;
99};
100
101/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300102#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300103#define F_SIF 0x02 /* sif or vga */
Hans de Goede26984b02010-02-01 13:18:37 -0300104#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
Hans de Goedec437d652008-09-03 17:12:22 -0300105
106/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
107#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300108#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300109
110/* ctrl_dis helper macros */
Hans de Goede26984b02010-02-01 13:18:37 -0300111#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
112 (1 << AUTOGAIN_IDX))
Hans de Goedef45f06b2008-09-03 17:12:21 -0300113#define NO_FREQ (1 << FREQ_IDX)
114#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300115
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300116#define COMP2 0x8f
117#define COMP 0xc7 /* 0x87 //0x07 */
118#define COMP1 0xc9 /* 0x89 //0x09 */
119
120#define MCK_INIT 0x63
121#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
122
123#define SYS_CLK 0x04
124
Hans de Goedef45f06b2008-09-03 17:12:21 -0300125#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
126 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
127{ \
128 .bridge_init = { bridge_1, bridge_3 }, \
129 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
130 .sensor_init = sensor, \
131 .sensor_init_size = sizeof(sensor), \
132 .sensor_bridge_init = { sensor_1, sensor_3,}, \
133 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
134 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
135}
136
Hans de Goededcef3232008-07-10 10:40:53 -0300137/* We calculate the autogain at the end of the transfer of a frame, at this
Hans de Goede26984b02010-02-01 13:18:37 -0300138 moment a frame with the old settings is being captured and transmitted. So
139 if we adjust the gain or exposure we must ignore atleast the next frame for
140 the new settings to come into effect before doing any other adjustments. */
141#define AUTOGAIN_IGNORE_FRAMES 1
Hans de Goededcef3232008-07-10 10:40:53 -0300142
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143/* V4L2 controls supported by the driver */
144static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
145static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300146static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
147static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
148static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
149static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
150static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
151static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300152static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
153static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300155static const struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300156#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157 {
158 {
159 .id = V4L2_CID_BRIGHTNESS,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Brightness",
162 .minimum = 0,
163 .maximum = 255,
164 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300165#define BRIGHTNESS_DEF 127
166 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167 },
168 .set = sd_setbrightness,
169 .get = sd_getbrightness,
170 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300171#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 {
173 {
Hans de Goededcef3232008-07-10 10:40:53 -0300174 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300176 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300178 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300180#define GAIN_DEF 127
Hans de Goede82e839c2010-02-03 14:37:30 -0300181#define GAIN_KNEE 230
Hans de Goededcef3232008-07-10 10:40:53 -0300182 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183 },
Hans de Goededcef3232008-07-10 10:40:53 -0300184 .set = sd_setgain,
185 .get = sd_getgain,
186 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300187#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300188 {
189 {
190 .id = V4L2_CID_EXPOSURE,
191 .type = V4L2_CTRL_TYPE_INTEGER,
192 .name = "Exposure",
Hans de Goede421763e2010-02-10 18:57:40 -0300193#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
194#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
Hans de Goededcef3232008-07-10 10:40:53 -0300195 .minimum = 0,
Hans de Goede82e839c2010-02-03 14:37:30 -0300196 .maximum = 1023,
Hans de Goededcef3232008-07-10 10:40:53 -0300197 .step = 1,
198 .default_value = EXPOSURE_DEF,
199 .flags = 0,
200 },
201 .set = sd_setexposure,
202 .get = sd_getexposure,
203 },
Hans de Goede26984b02010-02-01 13:18:37 -0300204#define COARSE_EXPOSURE_IDX 3
205 {
206 {
207 .id = V4L2_CID_EXPOSURE,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209 .name = "Exposure",
210#define COARSE_EXPOSURE_DEF 2 /* 30 fps */
211 .minimum = 2,
212 .maximum = 15,
213 .step = 1,
214 .default_value = COARSE_EXPOSURE_DEF,
215 .flags = 0,
216 },
217 .set = sd_setexposure,
218 .get = sd_getexposure,
219 },
220#define AUTOGAIN_IDX 4
Hans de Goededcef3232008-07-10 10:40:53 -0300221 {
222 {
223 .id = V4L2_CID_AUTOGAIN,
224 .type = V4L2_CTRL_TYPE_BOOLEAN,
225 .name = "Automatic Gain (and Exposure)",
226 .minimum = 0,
227 .maximum = 1,
228 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300229#define AUTOGAIN_DEF 1
230 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300231 .flags = 0,
232 },
233 .set = sd_setautogain,
234 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235 },
Hans de Goede26984b02010-02-01 13:18:37 -0300236#define FREQ_IDX 5
Hans de Goede66f35822008-07-16 10:16:28 -0300237 {
238 {
239 .id = V4L2_CID_POWER_LINE_FREQUENCY,
240 .type = V4L2_CTRL_TYPE_MENU,
241 .name = "Light frequency filter",
242 .minimum = 0,
243 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
244 .step = 1,
Hans de Goede606f8422010-02-10 06:49:23 -0300245#define FREQ_DEF 0
Hans de Goede66f35822008-07-16 10:16:28 -0300246 .default_value = FREQ_DEF,
247 },
248 .set = sd_setfreq,
249 .get = sd_getfreq,
250 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251};
252
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300253static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300254 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
255 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300256 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300259 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
260 .bytesperline = 160,
Hans de Goede5c515182008-09-03 17:12:22 -0300261 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300262 .colorspace = V4L2_COLORSPACE_SRGB,
263 .priv = 2},
264 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
265 .bytesperline = 320,
Hans de Goede5c515182008-09-03 17:12:22 -0300266 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 1},
269 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
270 .bytesperline = 640,
Hans de Goede5c515182008-09-03 17:12:22 -0300271 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300272 .colorspace = V4L2_COLORSPACE_SRGB,
273 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300274};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300275static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300276 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
277 .bytesperline = 160,
278 .sizeimage = 160 * 120,
279 .colorspace = V4L2_COLORSPACE_SRGB,
280 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
281 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
282 .bytesperline = 160,
283 .sizeimage = 160 * 120 * 5 / 4,
284 .colorspace = V4L2_COLORSPACE_SRGB,
285 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300286 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
287 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300288 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300289 .colorspace = V4L2_COLORSPACE_SRGB,
290 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300291 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
292 .bytesperline = 176,
Hans de Goede5c515182008-09-03 17:12:22 -0300293 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300294 .colorspace = V4L2_COLORSPACE_SRGB,
295 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300296 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
297 .bytesperline = 320,
298 .sizeimage = 320 * 240 * 5 / 4,
299 .colorspace = V4L2_COLORSPACE_SRGB,
300 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300301 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
302 .bytesperline = 352,
Hans de Goede5c515182008-09-03 17:12:22 -0300303 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300304 .colorspace = V4L2_COLORSPACE_SRGB,
305 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300306};
307
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300308static const __u8 initHv7131[] = {
309 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
310 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300311 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312 0x28, 0x1e, 0x60, 0x8a, 0x20,
313 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
314};
315static const __u8 hv7131_sensor_init[][8] = {
316 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
317 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
318 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
319 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
320 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
321};
322static const __u8 initOv6650[] = {
323 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
324 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300325 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300326 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327};
Jean-François Moine780e3122010-10-19 04:29:10 -0300328static const __u8 ov6650_sensor_init[][8] = {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200329 /* Bright, contrast, etc are set through SCBB interface.
Jean-François Moine780e3122010-10-19 04:29:10 -0300330 * AVCAP on win2 do not send any data on this controls. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300331 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300332
333 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300335 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300337 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
339/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
340 * THIS SET GREEN SCREEN
341 * (pixels could be innverted in decode kind of "brg",
342 * but blue wont be there. Avoid this data ... */
343 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
344 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300345 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300346 /* Enable rgb brightness control */
347 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
348 /* HDG: Note windows uses the line below, which sets both register 0x60
349 and 0x61 I believe these registers of the ov6650 are identical as
350 those of the ov7630, because if this is true the windows settings
351 add a bit additional red gain and a lot additional blue gain, which
352 matches my findings that the windows settings make blue much too
353 blue and red a little too red.
354 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300355 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
357 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358};
Hans de Goededcef3232008-07-10 10:40:53 -0300359
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360static const __u8 initOv7630[] = {
361 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
362 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300363 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300364 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300365 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
367};
368static const __u8 initOv7630_3[] = {
369 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300370 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300371 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300372 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300373 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
374 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
375 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
376 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377};
Hans de Goede6af492e2008-07-22 07:09:33 -0300378static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
380 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
381/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300382 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
384 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
385 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
386 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
387 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
388 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
389 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300390 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
391/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300392 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
393 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
394 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
395 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
396 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
397 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
398};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399
Hans de Goedef45f06b2008-09-03 17:12:21 -0300400static const __u8 ov7630_sensor_init_3[][8] = {
401 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
402};
403
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300404static const __u8 initPas106[] = {
405 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
406 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300407 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300408 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300409 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300410};
411/* compression 0x86 mckinit1 0x2b */
Hans de Goede421763e2010-02-10 18:57:40 -0300412
413/* "Known" PAS106B registers:
414 0x02 clock divider
415 0x03 Variable framerate bits 4-11
416 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
417 The variable framerate control must never be set lower then 300,
418 which sets the framerate at 90 / reg02, otherwise vsync is lost.
419 0x05 Shutter Time Line Offset, this can be used as an exposure control:
420 0 = use full frame time, 255 = no exposure at all
421 Note this may never be larger then "var-framerate control" / 2 - 2.
422 When var-framerate control is < 514, no exposure is reached at the max
423 allowed value for the framerate control value, rather then at 255.
424 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
425 only a very little bit, leave at 0xcd
426 0x07 offset sign bit (bit0 1 > negative offset)
427 0x08 offset
428 0x09 Blue Gain
429 0x0a Green1 Gain
430 0x0b Green2 Gain
431 0x0c Red Gain
432 0x0e Global gain
433 0x13 Write 1 to commit settings to sensor
434*/
435
Hans de Goedef45f06b2008-09-03 17:12:21 -0300436static const __u8 pas106_sensor_init[][8] = {
437 /* Pixel Clock Divider 6 */
438 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
439 /* Frame Time MSB (also seen as 0x12) */
440 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
441 /* Frame Time LSB (also seen as 0x05) */
442 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
443 /* Shutter Time Line Offset (also seen as 0x6d) */
444 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
445 /* Shutter Time Pixel Offset (also seen as 0xb1) */
446 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
447 /* Black Level Subtract Sign (also seen 0x00) */
448 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
449 /* Black Level Subtract Level (also seen 0x01) */
450 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
451 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
452 /* Color Gain B Pixel 5 a */
453 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
454 /* Color Gain G1 Pixel 1 5 */
455 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
456 /* Color Gain G2 Pixel 1 0 5 */
457 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
458 /* Color Gain R Pixel 3 1 */
459 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
460 /* Color GainH Pixel */
461 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
462 /* Global Gain */
463 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
464 /* Contrast */
465 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
466 /* H&V synchro polarity */
467 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
468 /* ?default */
469 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
470 /* DAC scale */
471 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
472 /* ?default */
473 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
474 /* Validate Settings */
475 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300476};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300477
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300478static const __u8 initPas202[] = {
479 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
480 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300481 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goede82e839c2010-02-03 14:37:30 -0300482 0x28, 0x1e, 0x20, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300483 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
484};
Hans de Goede82e839c2010-02-03 14:37:30 -0300485
486/* "Known" PAS202BCB registers:
487 0x02 clock divider
488 0x04 Variable framerate bits 6-11 (*)
489 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
490 0x07 Blue Gain
491 0x08 Green Gain
492 0x09 Red Gain
493 0x0b offset sign bit (bit0 1 > negative offset)
494 0x0c offset
495 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
496 leave at 1 otherwise we get a jump in our exposure control
497 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
498 0x10 Master gain 0 - 31
499 0x11 write 1 to apply changes
500 (*) The variable framerate control must never be set lower then 500
501 which sets the framerate at 30 / reg02, otherwise vsync is lost.
502*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503static const __u8 pas202_sensor_init[][8] = {
Hans de Goede82e839c2010-02-03 14:37:30 -0300504 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
505 to set it lower, but for some reason the bridge starts missing
506 vsync's then */
507 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
509 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300510 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
512 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
513 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
514 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
515 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
516 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517};
518
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300519static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
521 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300522 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300523 0x16, 0x12, 0x60, 0x86, 0x2b,
524 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
525};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300526/* Same as above, except a different hstart */
527static const __u8 initTas5110d[] = {
528 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
529 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300530 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300531 0x16, 0x12, 0x60, 0x86, 0x2b,
532 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
533};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300534static const __u8 tas5110_sensor_init[][8] = {
535 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
536 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
537 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
538};
539
540static const __u8 initTas5130[] = {
541 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
542 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300543 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544 0x28, 0x1e, 0x60, COMP, MCK_INIT,
545 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
546};
547static const __u8 tas5130_sensor_init[][8] = {
Jean-François Moine780e3122010-10-19 04:29:10 -0300548/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549 * shutter 0x47 short exposure? */
550 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
551 /* shutter 0x01 long exposure */
552 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
553};
554
Hans Verkuild45b9b82008-09-04 03:33:43 -0300555static struct sensor_data sensor_data[] = {
Hans de Goedef45f06b2008-09-03 17:12:21 -0300556SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300557SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300558SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
559 F_GAIN, 0, 0x21),
Hans de Goede421763e2010-02-10 18:57:40 -0300560SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300561 0),
Hans de Goede82e839c2010-02-03 14:37:30 -0300562SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN,
563 NO_FREQ, 0),
Hans de Goede26984b02010-02-01 13:18:37 -0300564SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL,
565 F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
566SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL,
567 F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300568SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
569 0),
570};
571
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572/* get one byte in gspca_dev->usb_buf */
573static void reg_r(struct gspca_dev *gspca_dev,
574 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300575{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576 usb_control_msg(gspca_dev->dev,
577 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 0, /* request */
579 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
580 value,
581 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300582 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300583 500);
584}
585
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300586static void reg_w(struct gspca_dev *gspca_dev,
587 __u16 value,
588 const __u8 *buffer,
589 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300591#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300592 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300593 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
594 return;
595 }
596#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 memcpy(gspca_dev->usb_buf, buffer, len);
598 usb_control_msg(gspca_dev->dev,
599 usb_sndctrlpipe(gspca_dev->dev, 0),
600 0x08, /* request */
601 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
602 value,
603 0, /* index */
604 gspca_dev->usb_buf, len,
605 500);
606}
607
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300608static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300609{
610 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300611
612 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300613 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 while (retry--) {
615 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300617 if (gspca_dev->usb_buf[0] & 0x04) {
618 if (gspca_dev->usb_buf[0] & 0x08)
619 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300621 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622 }
623 return -1;
624}
625
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627 const __u8 buffer[][8], int len)
628{
629 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300630 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 len -= 8;
632 if (len <= 0)
633 break;
634 buffer++;
635 }
636}
637
638static void setbrightness(struct gspca_dev *gspca_dev)
639{
640 struct sd *sd = (struct sd *) gspca_dev;
641 __u8 value;
642
643 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300644 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 case SENSOR_OV7630: {
646 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300647 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648
649 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300650 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300652 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300653 goto err;
654 break;
655 }
Hans de Goede421763e2010-02-10 18:57:40 -0300656 case SENSOR_PAS106:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300657 case SENSOR_PAS202: {
Hans de Goede82e839c2010-02-03 14:37:30 -0300658 __u8 i2cpbright[] =
659 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
Hans de Goede421763e2010-02-10 18:57:40 -0300660 __u8 i2cpdoit[] =
Hans de Goede82e839c2010-02-03 14:37:30 -0300661 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662
Hans de Goede421763e2010-02-10 18:57:40 -0300663 /* PAS106 uses reg 7 and 8 instead of b and c */
664 if (sd->sensor == SENSOR_PAS106) {
665 i2cpbright[2] = 7;
666 i2cpdoit[2] = 0x13;
667 }
668
Hans de Goede82e839c2010-02-03 14:37:30 -0300669 if (sd->brightness < 127) {
670 /* change reg 0x0b, signreg */
671 i2cpbright[3] = 0x01;
672 /* set reg 0x0c, offset */
673 i2cpbright[4] = 127 - sd->brightness;
674 } else
675 i2cpbright[4] = sd->brightness - 127;
676
677 if (i2c_w(gspca_dev, i2cpbright) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300679 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 goto err;
681 break;
682 }
Hans de Goededcef3232008-07-10 10:40:53 -0300683 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684 __u8 i2c[] =
685 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
686
687 value = 0xff - sd->brightness;
688 i2c[4] = value;
689 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300690 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 goto err;
692 break;
693 }
694 }
695 return;
696err:
697 PDEBUG(D_ERR, "i2c error brightness");
698}
Hans de Goededcef3232008-07-10 10:40:53 -0300699
700static void setsensorgain(struct gspca_dev *gspca_dev)
701{
702 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300703 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300704
705 switch (sd->sensor) {
706
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300707 case SENSOR_TAS5110C:
708 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300709 __u8 i2c[] =
710 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
711
Hans de Goedea975a522008-07-16 15:29:11 -0300712 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300713 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300714 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300715 break;
716 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300717
Hans de Goedea975a522008-07-16 15:29:11 -0300718 case SENSOR_OV6650:
719 gain >>= 1;
720 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300721 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300722 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300723
Hans de Goedef45f06b2008-09-03 17:12:21 -0300724 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300725 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300726 if (i2c_w(gspca_dev, i2c) < 0)
727 goto err;
728 break;
729 }
Hans de Goede421763e2010-02-10 18:57:40 -0300730 case SENSOR_PAS106:
Hans de Goede82e839c2010-02-03 14:37:30 -0300731 case SENSOR_PAS202: {
732 __u8 i2cpgain[] =
Hans de Goede421763e2010-02-10 18:57:40 -0300733 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede82e839c2010-02-03 14:37:30 -0300734 __u8 i2cpcolorgain[] =
735 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede421763e2010-02-10 18:57:40 -0300736 __u8 i2cpdoit[] =
737 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
738
739 /* PAS106 uses different regs (and has split green gains) */
740 if (sd->sensor == SENSOR_PAS106) {
741 i2cpgain[2] = 0x0e;
742 i2cpcolorgain[0] = 0xd0;
743 i2cpcolorgain[2] = 0x09;
744 i2cpdoit[2] = 0x13;
745 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300746
747 i2cpgain[3] = sd->gain >> 3;
748 i2cpcolorgain[3] = sd->gain >> 4;
749 i2cpcolorgain[4] = sd->gain >> 4;
750 i2cpcolorgain[5] = sd->gain >> 4;
Hans de Goede421763e2010-02-10 18:57:40 -0300751 i2cpcolorgain[6] = sd->gain >> 4;
Hans de Goede82e839c2010-02-03 14:37:30 -0300752
753 if (i2c_w(gspca_dev, i2cpgain) < 0)
754 goto err;
755 if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
756 goto err;
757 if (i2c_w(gspca_dev, i2cpdoit) < 0)
758 goto err;
759 break;
760 }
Hans de Goededcef3232008-07-10 10:40:53 -0300761 }
762 return;
763err:
764 PDEBUG(D_ERR, "i2c error gain");
765}
766
767static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300768{
769 struct sd *sd = (struct sd *) gspca_dev;
770 __u8 gain;
Hans de Goede4efcfa02010-02-01 07:48:17 -0300771 __u8 buf[2] = { 0, 0 };
772
773 if (sensor_data[sd->sensor].flags & F_GAIN) {
774 /* Use the sensor gain to do the actual gain */
775 setsensorgain(gspca_dev);
776 return;
777 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300779 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300780
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 /* red and blue gain */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300782 buf[0] = gain << 4 | gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 /* green gain */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300784 buf[1] = gain;
785 reg_w(gspca_dev, 0x10, buf, 2);
Hans de Goededcef3232008-07-10 10:40:53 -0300786}
787
788static void setexposure(struct gspca_dev *gspca_dev)
789{
790 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300791
792 switch (sd->sensor) {
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300793 case SENSOR_TAS5110C:
794 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300795 /* register 19's high nibble contains the sn9c10x clock divider
796 The high nibble configures the no fps according to the
797 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goede26984b02010-02-01 13:18:37 -0300798 __u8 reg = sd->exposure;
Hans de Goededcef3232008-07-10 10:40:53 -0300799 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300800 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300801 break;
802 }
Hans de Goedea975a522008-07-16 15:29:11 -0300803 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300804 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300805 /* The ov6650 / ov7630 have 2 registers which both influence
806 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300807 according to: fps = 30 / (low_nibble + 1)
808
809 The fps configures the maximum exposure setting, but it is
810 possible to use less exposure then what the fps maximum
811 allows by setting register 10. register 10 configures the
812 actual exposure as quotient of the full exposure, with 0
813 being no exposure at all (not very usefull) and reg10_max
814 being max exposure possible at that framerate.
815
816 The code maps our 0 - 510 ms exposure ctrl to these 2
817 registers, trying to keep fps as high as possible.
818 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300819 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
820 int reg10, reg11, reg10_max;
821
Hans de Goede66f35822008-07-16 10:16:28 -0300822 /* ov6645 datasheet says reg10_max is 9a, but that uses
823 tline * 2 * reg10 as formula for calculating texpo, the
824 ov6650 probably uses the same formula as the 7730 which uses
825 tline * 4 * reg10, which explains why the reg10max we've
826 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300827 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300828 if (sd->sensor == SENSOR_OV6650) {
829 reg10_max = 0x4d;
830 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
831 } else
832 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300833
Hans de Goede82e839c2010-02-03 14:37:30 -0300834 reg11 = (15 * sd->exposure + 999) / 1000;
Hans de Goedef4d52022008-07-15 09:36:42 -0300835 if (reg11 < 1)
836 reg11 = 1;
837 else if (reg11 > 16)
838 reg11 = 16;
839
Hans de Goede10bb7532010-02-04 06:10:55 -0300840 /* In 640x480, if the reg11 has less than 4, the image is
841 unstable (the bridge goes into a higher compression mode
842 which we have not reverse engineered yet). */
843 if (gspca_dev->width == 640 && reg11 < 4)
844 reg11 = 4;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300845
Hans de Goedef4d52022008-07-15 09:36:42 -0300846 /* frame exposure time in ms = 1000 * reg11 / 30 ->
Hans de Goede82e839c2010-02-03 14:37:30 -0300847 reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
848 reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300849
850 /* Don't allow this to get below 10 when using autogain, the
851 steps become very large (relatively) when below 10 causing
852 the image to oscilate from much too dark, to much too bright
853 and back again. */
854 if (sd->autogain && reg10 < 10)
855 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300856 else if (reg10 > reg10_max)
857 reg10 = reg10_max;
858
859 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300860 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300861 i2c[3] = reg10;
862 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300863
864 /* If register 11 didn't change, don't change it */
Jean-François Moine780e3122010-10-19 04:29:10 -0300865 if (sd->reg11 == reg11)
Hans de Goede6af492e2008-07-22 07:09:33 -0300866 i2c[0] = 0xa0;
867
868 if (i2c_w(gspca_dev, i2c) == 0)
869 sd->reg11 = reg11;
870 else
Hans de Goede82e839c2010-02-03 14:37:30 -0300871 goto err;
872 break;
873 }
874 case SENSOR_PAS202: {
875 __u8 i2cpframerate[] =
876 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
877 __u8 i2cpexpo[] =
878 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
879 const __u8 i2cpdoit[] =
880 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
881 int framerate_ctrl;
882
883 /* The exposure knee for the autogain algorithm is 200
884 (100 ms / 10 fps on other sensors), for values below this
885 use the control for setting the partial frame expose time,
886 above that use variable framerate. This way we run at max
887 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
888 is reached. Using the variable framerate control above 200
889 is better then playing around with both clockdiv + partial
890 frame exposure times (like we are doing with the ov chips),
891 as that sometimes leads to jumps in the exposure control,
892 which are bad for auto exposure. */
893 if (sd->exposure < 200) {
894 i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
895 framerate_ctrl = 500;
896 } else {
897 /* The PAS202's exposure control goes from 0 - 4095,
898 but anything below 500 causes vsync issues, so scale
899 our 200-1023 to 500-4095 */
900 framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
901 500;
902 }
903
904 i2cpframerate[3] = framerate_ctrl >> 6;
905 i2cpframerate[4] = framerate_ctrl & 0x3f;
906 if (i2c_w(gspca_dev, i2cpframerate) < 0)
907 goto err;
908 if (i2c_w(gspca_dev, i2cpexpo) < 0)
909 goto err;
910 if (i2c_w(gspca_dev, i2cpdoit) < 0)
911 goto err;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300912 break;
913 }
Hans de Goede421763e2010-02-10 18:57:40 -0300914 case SENSOR_PAS106: {
915 __u8 i2cpframerate[] =
916 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
917 __u8 i2cpexpo[] =
918 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
919 const __u8 i2cpdoit[] =
920 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
921 int framerate_ctrl;
922
923 /* For values below 150 use partial frame exposure, above
924 that use framerate ctrl */
925 if (sd->exposure < 150) {
926 i2cpexpo[3] = 150 - sd->exposure;
927 framerate_ctrl = 300;
928 } else {
929 /* The PAS106's exposure control goes from 0 - 4095,
930 but anything below 300 causes vsync issues, so scale
931 our 150-1023 to 300-4095 */
932 framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
933 300;
934 }
935
936 i2cpframerate[3] = framerate_ctrl >> 4;
937 i2cpframerate[4] = framerate_ctrl & 0x0f;
938 if (i2c_w(gspca_dev, i2cpframerate) < 0)
939 goto err;
940 if (i2c_w(gspca_dev, i2cpexpo) < 0)
941 goto err;
942 if (i2c_w(gspca_dev, i2cpdoit) < 0)
943 goto err;
944 break;
945 }
Hans de Goededcef3232008-07-10 10:40:53 -0300946 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300947 return;
948err:
949 PDEBUG(D_ERR, "i2c error exposure");
Hans de Goededcef3232008-07-10 10:40:53 -0300950}
951
Hans de Goede66f35822008-07-16 10:16:28 -0300952static void setfreq(struct gspca_dev *gspca_dev)
953{
954 struct sd *sd = (struct sd *) gspca_dev;
955
956 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300957 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300958 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300959 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300960 compensation, for the ov6650 this is identical to ov6630
961 0x2b register, see ov6630 datasheet.
962 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300963 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300964 switch (sd->freq) {
965 default:
966/* case 0: * no filter*/
967/* case 2: * 60 hz */
968 i2c[3] = 0;
969 break;
970 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300971 i2c[3] = (sd->sensor == SENSOR_OV6650)
972 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300973 break;
974 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300975 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300976 if (i2c_w(gspca_dev, i2c) < 0)
977 PDEBUG(D_ERR, "i2c error setfreq");
978 break;
979 }
980 }
981}
982
Hans de Goede26984b02010-02-01 13:18:37 -0300983#include "coarse_expo_autogain.h"
984
Hans de Goededcef3232008-07-10 10:40:53 -0300985static void do_autogain(struct gspca_dev *gspca_dev)
986{
Hans de Goede26984b02010-02-01 13:18:37 -0300987 int deadzone, desired_avg_lum, result;
Hans de Goededcef3232008-07-10 10:40:53 -0300988 struct sd *sd = (struct sd *) gspca_dev;
989 int avg_lum = atomic_read(&sd->avg_lum);
990
Hans de Goede26984b02010-02-01 13:18:37 -0300991 if (avg_lum == -1 || !sd->autogain)
Hans de Goededcef3232008-07-10 10:40:53 -0300992 return;
993
Hans de Goede26984b02010-02-01 13:18:37 -0300994 if (sd->autogain_ignore_frames > 0) {
995 sd->autogain_ignore_frames--;
996 return;
997 }
998
Hans de Goede5017c7b2008-10-22 04:59:29 -0300999 /* SIF / VGA sensors have a different autoexposure area and thus
1000 different avg_lum values for the same picture brightness */
1001 if (sensor_data[sd->sensor].flags & F_SIF) {
Hans de Goede26984b02010-02-01 13:18:37 -03001002 deadzone = 500;
1003 /* SIF sensors tend to overexpose, so keep this small */
1004 desired_avg_lum = 5000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001005 } else {
Hans de Goede26984b02010-02-01 13:18:37 -03001006 deadzone = 1500;
Hans de Goede606f8422010-02-10 06:49:23 -03001007 desired_avg_lum = 18000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001008 }
1009
Hans de Goede26984b02010-02-01 13:18:37 -03001010 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
1011 result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
1012 sd->brightness * desired_avg_lum / 127,
1013 deadzone);
1014 else
1015 result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
1016 sd->brightness * desired_avg_lum / 127,
1017 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1018
1019 if (result) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -03001020 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -03001021 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -03001022 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -03001023 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001024}
1025
1026/* this function is called at probe time */
1027static int sd_config(struct gspca_dev *gspca_dev,
1028 const struct usb_device_id *id)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -03001032
1033 reg_r(gspca_dev, 0x00);
1034 if (gspca_dev->usb_buf[0] != 0x10)
1035 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001036
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001037 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001038 sd->sensor = id->driver_info >> 8;
1039 sd->bridge = id->driver_info & 0xff;
1040 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001041
1042 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001043 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001045 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 } else {
1047 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001048 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -03001050 cam->npkt = 36; /* 36 packets per ISOC message */
1051
Hans de Goededcef3232008-07-10 10:40:53 -03001052 sd->brightness = BRIGHTNESS_DEF;
1053 sd->gain = GAIN_DEF;
Hans de Goede26984b02010-02-01 13:18:37 -03001054 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
1055 sd->exposure = COARSE_EXPOSURE_DEF;
1056 gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
1057 } else {
1058 sd->exposure = EXPOSURE_DEF;
1059 gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
1060 }
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001061 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1062 sd->autogain = 0; /* Disable do_autogain callback */
1063 else
1064 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -03001065 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -03001066
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001067 return 0;
1068}
1069
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001070/* this function is called at probe and resume time */
1071static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072{
Hans de Goede271315a2008-09-03 17:12:19 -03001073 const __u8 stop = 0x09; /* Disable stream turn of LED */
1074
1075 reg_w(gspca_dev, 0x01, &stop, 1);
1076
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001077 return 0;
1078}
1079
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001080/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001081static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001082{
1083 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -03001084 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001085 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001086 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -03001087 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001088
Hans de Goede93627732008-09-04 16:20:12 -03001089 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001090 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
1091 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -03001092 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
1093 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001094 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001095 switch (sd->sensor) {
Hans de Goedef45f06b2008-09-03 17:12:21 -03001096 case SENSOR_TAS5130CXX:
1097 /* probably not mode specific at all most likely the upper
1098 nibble of 0x19 is exposure (clock divider) just as with
1099 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -03001100 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001101 break;
1102 }
Hans de Goedec437d652008-09-03 17:12:22 -03001103 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -03001104 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
1105 reg12_19[6] &= ~0x80;
1106
1107 /* Vga mode emulation on SIF sensor? */
1108 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
1109 reg12_19[0] += 16; /* 0x12: hstart adjust */
1110 reg12_19[1] += 24; /* 0x13: vstart adjust */
1111 reg12_19[3] = 320 / 16; /* 0x15: hsize */
1112 reg12_19[4] = 240 / 16; /* 0x16: vsize */
1113 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001114
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001115 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -03001116 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -03001118 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -03001120 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001121
1122 /* Init the sensor */
1123 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1124 sensor_data[sd->sensor].sensor_init_size);
1125 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
1126 i2c_w_vector(gspca_dev,
1127 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
1128 sensor_data[sd->sensor].sensor_bridge_init_size[
1129 sd->bridge]);
1130
Hans de Goede82e839c2010-02-03 14:37:30 -03001131 /* Mode specific sensor setup */
1132 switch (sd->sensor) {
1133 case SENSOR_PAS202: {
1134 const __u8 i2cpclockdiv[] =
1135 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1136 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1137 if (mode)
1138 i2c_w(gspca_dev, i2cpclockdiv);
1139 }
1140 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001141 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -03001142 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -03001144 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001145 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -03001146 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001147 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -03001148 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001149 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1150 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -03001151 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001152 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -03001153 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001154 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001155 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001156 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001157 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -03001159 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160 msleep(20);
1161
Hans de Goede6af492e2008-07-22 07:09:33 -03001162 sd->reg11 = -1;
1163
Hans de Goededcef3232008-07-10 10:40:53 -03001164 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001165 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001166 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -03001167 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001168
Hans de Goede6af492e2008-07-22 07:09:33 -03001169 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001170 sd->autogain_ignore_frames = 0;
Hans de Goede26984b02010-02-01 13:18:37 -03001171 sd->exp_too_high_cnt = 0;
1172 sd->exp_too_low_cnt = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001173 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001174 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175}
1176
1177static void sd_stopN(struct gspca_dev *gspca_dev)
1178{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001179 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180}
1181
Hans de Goede2b3e2842010-12-12 08:55:04 -03001182static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001183{
Hans de Goededcef3232008-07-10 10:40:53 -03001184 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede2b3e2842010-12-12 08:55:04 -03001185 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186
Hans de Goedec36260ee2008-07-16 09:56:07 -03001187 /* frames start with:
1188 * ff ff 00 c4 c4 96 synchro
1189 * 00 (unknown)
1190 * xx (frame sequence / size / compression)
1191 * (xx) (idem - extra byte for sn9c103)
1192 * ll mm brightness sum inside auto exposure
1193 * ll mm brightness sum outside auto exposure
1194 * (xx xx xx xx xx) audio values for snc103
1195 */
Hans de Goede2b3e2842010-12-12 08:55:04 -03001196 for (i = 0; i < len; i++) {
1197 switch (sd->header_read) {
1198 case 0:
1199 if (data[i] == 0xff)
1200 sd->header_read++;
1201 break;
1202 case 1:
1203 if (data[i] == 0xff)
1204 sd->header_read++;
1205 else
1206 sd->header_read = 0;
1207 break;
1208 case 2:
1209 if (data[i] == 0x00)
1210 sd->header_read++;
1211 else if (data[i] != 0xff)
1212 sd->header_read = 0;
1213 break;
1214 case 3:
1215 if (data[i] == 0xc4)
1216 sd->header_read++;
1217 else if (data[i] == 0xff)
1218 sd->header_read = 1;
1219 else
1220 sd->header_read = 0;
1221 break;
1222 case 4:
1223 if (data[i] == 0xc4)
1224 sd->header_read++;
1225 else if (data[i] == 0xff)
1226 sd->header_read = 1;
1227 else
1228 sd->header_read = 0;
1229 break;
1230 case 5:
1231 if (data[i] == 0x96)
1232 sd->header_read++;
1233 else if (data[i] == 0xff)
1234 sd->header_read = 1;
1235 else
1236 sd->header_read = 0;
1237 break;
1238 default:
1239 sd->header[sd->header_read - 6] = data[i];
1240 sd->header_read++;
1241 if (sd->header_read == header_size) {
1242 sd->header_read = 0;
1243 return data + i + 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001244 }
1245 }
1246 }
Hans de Goede2b3e2842010-12-12 08:55:04 -03001247 return NULL;
1248}
1249
1250static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1251 u8 *data, /* isoc packet */
1252 int len) /* iso packet length */
1253{
1254 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1255 struct sd *sd = (struct sd *) gspca_dev;
1256 struct cam *cam = &gspca_dev->cam;
1257 u8 *sof;
1258
1259 sof = find_sof(gspca_dev, data, len);
1260 if (sof) {
1261 if (sd->bridge == BRIDGE_103) {
1262 fr_h_sz = 18;
1263 lum_offset = 3;
1264 } else {
1265 fr_h_sz = 12;
1266 lum_offset = 2;
1267 }
1268
1269 len_after_sof = len - (sof - data);
1270 len = (sof - data) - fr_h_sz;
1271 if (len < 0)
1272 len = 0;
1273 }
Hans de Goedec437d652008-09-03 17:12:22 -03001274
1275 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1276 /* In raw mode we sometimes get some garbage after the frame
1277 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001278 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001279 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1280
Jean-François Moineb192ca92010-06-27 03:08:19 -03001281 used = gspca_dev->image_len;
Hans de Goedec437d652008-09-03 17:12:22 -03001282 if (used + len > size)
1283 len = size - used;
1284 }
1285
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001286 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Hans de Goede2b3e2842010-12-12 08:55:04 -03001287
1288 if (sof) {
1289 int lum = sd->header[lum_offset] +
1290 (sd->header[lum_offset + 1] << 8);
1291
1292 /* When exposure changes midway a frame we
1293 get a lum of 0 in this case drop 2 frames
1294 as the frames directly after an exposure
1295 change have an unstable image. Sometimes lum
1296 *really* is 0 (cam used in low light with
1297 low exposure setting), so do not drop frames
1298 if the previous lum was 0 too. */
1299 if (lum == 0 && sd->prev_avg_lum != 0) {
1300 lum = -1;
1301 sd->frames_to_drop = 2;
1302 sd->prev_avg_lum = 0;
1303 } else
1304 sd->prev_avg_lum = lum;
1305 atomic_set(&sd->avg_lum, lum);
1306
1307 if (sd->frames_to_drop)
1308 sd->frames_to_drop--;
1309 else
1310 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1311
1312 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1313 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001314}
1315
1316static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1317{
1318 struct sd *sd = (struct sd *) gspca_dev;
1319
1320 sd->brightness = val;
1321 if (gspca_dev->streaming)
1322 setbrightness(gspca_dev);
1323 return 0;
1324}
1325
1326static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1327{
1328 struct sd *sd = (struct sd *) gspca_dev;
1329
1330 *val = sd->brightness;
1331 return 0;
1332}
1333
Hans de Goededcef3232008-07-10 10:40:53 -03001334static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001335{
1336 struct sd *sd = (struct sd *) gspca_dev;
1337
Hans de Goededcef3232008-07-10 10:40:53 -03001338 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001339 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001340 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001341 return 0;
1342}
1343
Hans de Goededcef3232008-07-10 10:40:53 -03001344static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001345{
1346 struct sd *sd = (struct sd *) gspca_dev;
1347
Hans de Goededcef3232008-07-10 10:40:53 -03001348 *val = sd->gain;
1349 return 0;
1350}
1351
1352static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1353{
1354 struct sd *sd = (struct sd *) gspca_dev;
1355
1356 sd->exposure = val;
1357 if (gspca_dev->streaming)
1358 setexposure(gspca_dev);
1359 return 0;
1360}
1361
1362static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1363{
1364 struct sd *sd = (struct sd *) gspca_dev;
1365
1366 *val = sd->exposure;
1367 return 0;
1368}
1369
1370static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1371{
1372 struct sd *sd = (struct sd *) gspca_dev;
1373
1374 sd->autogain = val;
Hans de Goede26984b02010-02-01 13:18:37 -03001375 sd->exp_too_high_cnt = 0;
1376 sd->exp_too_low_cnt = 0;
1377
Hans de Goededcef3232008-07-10 10:40:53 -03001378 /* when switching to autogain set defaults to make sure
1379 we are on a valid point of the autogain gain /
1380 exposure knee graph, and give this change time to
1381 take effect before doing autogain. */
Hans de Goede26984b02010-02-01 13:18:37 -03001382 if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
Hans de Goededcef3232008-07-10 10:40:53 -03001383 sd->exposure = EXPOSURE_DEF;
1384 sd->gain = GAIN_DEF;
1385 if (gspca_dev->streaming) {
1386 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1387 setexposure(gspca_dev);
1388 setgain(gspca_dev);
1389 }
1390 }
1391
1392 return 0;
1393}
1394
1395static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1396{
1397 struct sd *sd = (struct sd *) gspca_dev;
1398
1399 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001400 return 0;
1401}
1402
Hans de Goede66f35822008-07-16 10:16:28 -03001403static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1404{
1405 struct sd *sd = (struct sd *) gspca_dev;
1406
1407 sd->freq = val;
1408 if (gspca_dev->streaming)
1409 setfreq(gspca_dev);
1410 return 0;
1411}
1412
1413static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1414{
1415 struct sd *sd = (struct sd *) gspca_dev;
1416
1417 *val = sd->freq;
1418 return 0;
1419}
1420
1421static int sd_querymenu(struct gspca_dev *gspca_dev,
1422 struct v4l2_querymenu *menu)
1423{
1424 switch (menu->id) {
1425 case V4L2_CID_POWER_LINE_FREQUENCY:
1426 switch (menu->index) {
1427 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1428 strcpy((char *) menu->name, "NoFliker");
1429 return 0;
1430 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1431 strcpy((char *) menu->name, "50 Hz");
1432 return 0;
1433 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1434 strcpy((char *) menu->name, "60 Hz");
1435 return 0;
1436 }
1437 break;
1438 }
1439 return -EINVAL;
1440}
1441
Jean-François Moine28566432010-10-01 07:33:26 -03001442#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001443static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1444 u8 *data, /* interrupt packet data */
1445 int len) /* interrupt packet length */
1446{
1447 int ret = -EINVAL;
1448
1449 if (len == 1 && data[0] == 1) {
1450 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1451 input_sync(gspca_dev->input_dev);
1452 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1453 input_sync(gspca_dev->input_dev);
1454 ret = 0;
1455 }
1456
1457 return ret;
1458}
1459#endif
1460
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001461/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001462static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001463 .name = MODULE_NAME,
1464 .ctrls = sd_ctrls,
1465 .nctrls = ARRAY_SIZE(sd_ctrls),
1466 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001467 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001468 .start = sd_start,
1469 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001470 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001471 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001472 .dq_callback = do_autogain,
Jean-François Moine28566432010-10-01 07:33:26 -03001473#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001474 .int_pkt_scan = sd_int_pkt_scan,
1475#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001476};
1477
1478/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001479#define SB(sensor, bridge) \
1480 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1481
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001482
Márton Németh37b372e2009-12-10 11:31:09 -03001483static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001484 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1485 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001486 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001487 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1488 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001489 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001490#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001491 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1492 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1493 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
Hans de Goede0e4b91c2010-02-10 20:29:43 -03001494#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001495 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1496 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001497 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001498 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001499 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Hans de Goede4cce1652008-09-04 16:22:57 -03001500 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1501#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1502 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1503#endif
1504 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001505 {}
1506};
1507MODULE_DEVICE_TABLE(usb, device_table);
1508
1509/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001510static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001511 const struct usb_device_id *id)
1512{
1513 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1514 THIS_MODULE);
1515}
1516
1517static struct usb_driver sd_driver = {
1518 .name = MODULE_NAME,
1519 .id_table = device_table,
1520 .probe = sd_probe,
1521 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001522#ifdef CONFIG_PM
1523 .suspend = gspca_suspend,
1524 .resume = gspca_resume,
1525#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001526};
1527
1528/* -- module insert / remove -- */
1529static int __init sd_mod_init(void)
1530{
Jean-François Moine54826432010-09-13 04:53:03 -03001531 return usb_register(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001532}
1533static void __exit sd_mod_exit(void)
1534{
1535 usb_deregister(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001536}
1537
1538module_init(sd_mod_init);
1539module_exit(sd_mod_exit);