blob: 43784027568feb0f707411633a919351e6c465d3 [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
Hans de Goede0a76cb82011-01-05 13:55:43 -030026sn9c101 / sn9c102:
Hans de Goede93627732008-09-04 16:20:12 -0300270x10 high nibble red gain low nibble blue gain
280x11 low nibble green gain
Hans de Goede0a76cb82011-01-05 13:55:43 -030029sn9c103:
300x05 red gain 0-127
310x06 blue gain 0-127
320x07 green gain 0-127
33all:
340x08-0x0f i2c / 3wire registers
Hans de Goede93627732008-09-04 16:20:12 -0300350x12 hstart
360x13 vstart
370x15 hsize (hsize = register-value * 16)
380x16 vsize (vsize = register-value * 16)
390x17 bit 0 toggle compression quality (according to sn9c102 driver)
400x18 bit 7 enables compression, bit 4-5 set image down scaling:
41 00 scale 1, 01 scale 1/2, 10, scale 1/4
420x19 high-nibble is sensor clock divider, changes exposure on sensors which
43 use a clock generated by the bridge. Some sensors have their own clock.
440x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
450x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
460x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
470x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
48*/
49
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030050#define MODULE_NAME "sonixb"
51
Hans de Goedef65e93d2010-01-31 10:35:15 -030052#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053#include "gspca.h"
54
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
56MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
57MODULE_LICENSE("GPL");
58
59/* specific webcam descriptor */
60struct sd {
61 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030062 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030063 int prev_avg_lum;
Hans de Goede26984b02010-02-01 13:18:37 -030064 int exp_too_low_cnt;
65 int exp_too_high_cnt;
Hans de Goede2b3e2842010-12-12 08:55:04 -030066 int header_read;
67 u8 header[12]; /* Header without sof marker */
Hans de Goededcef3232008-07-10 10:40:53 -030068
Hans de Goede26984b02010-02-01 13:18:37 -030069 unsigned short exposure;
Hans de Goedead5ef80d2008-07-14 10:11:42 -030070 unsigned char gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030071 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030072 unsigned char autogain;
73 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030074 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030075 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076
Hans de Goedef45f06b2008-09-03 17:12:21 -030077 __u8 bridge; /* Type of bridge */
78#define BRIDGE_101 0
79#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
80#define BRIDGE_103 1
81
82 __u8 sensor; /* Type of image sensor chip */
Hans de Goede00765f12010-12-12 15:55:03 -030083#define SENSOR_HV7131D 0
84#define SENSOR_HV7131R 1
85#define SENSOR_OV6650 2
86#define SENSOR_OV7630 3
87#define SENSOR_PAS106 4
88#define SENSOR_PAS202 5
89#define SENSOR_TAS5110C 6
90#define SENSOR_TAS5110D 7
91#define SENSOR_TAS5130CXX 8
Hans de Goede6af492e2008-07-22 07:09:33 -030092 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093};
94
Hans de Goedef45f06b2008-09-03 17:12:21 -030095typedef const __u8 sensor_init_t[8];
96
97struct sensor_data {
Hans de Goede0a76cb82011-01-05 13:55:43 -030098 const __u8 *bridge_init;
Hans de Goedef45f06b2008-09-03 17:12:21 -030099 sensor_init_t *sensor_init;
100 int sensor_init_size;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300101 int flags;
102 unsigned ctrl_dis;
103 __u8 sensor_addr;
104};
105
106/* sensor_data flags */
Jean-Francois Moine5da162e72008-07-26 14:17:23 -0300107#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300108#define F_SIF 0x02 /* sif or vga */
Hans de Goede26984b02010-02-01 13:18:37 -0300109#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
Hans de Goedec437d652008-09-03 17:12:22 -0300110
111/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
112#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300113#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300114
115/* ctrl_dis helper macros */
Hans de Goede26984b02010-02-01 13:18:37 -0300116#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
117 (1 << AUTOGAIN_IDX))
Hans de Goedef45f06b2008-09-03 17:12:21 -0300118#define NO_FREQ (1 << FREQ_IDX)
119#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e72008-07-26 14:17:23 -0300120
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121#define COMP 0xc7 /* 0x87 //0x07 */
122#define COMP1 0xc9 /* 0x89 //0x09 */
123
124#define MCK_INIT 0x63
125#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
126
127#define SYS_CLK 0x04
128
Hans de Goede0a76cb82011-01-05 13:55:43 -0300129#define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300130{ \
Hans de Goede0a76cb82011-01-05 13:55:43 -0300131 .bridge_init = bridge, \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300132 .sensor_init = sensor, \
133 .sensor_init_size = sizeof(sensor), \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300134 .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
Hans de Goede00765f12010-12-12 15:55:03 -0300308static const __u8 initHv7131d[] = {
309 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
310 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
312 0x28, 0x1e, 0x60, 0x8e, 0x42,
Hans de Goede00765f12010-12-12 15:55:03 -0300313};
314static const __u8 hv7131d_sensor_init[][8] = {
315 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
316 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
317 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
318 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
319 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
320};
321
322static const __u8 initHv7131r[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300323 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
324 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300325 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300326 0x28, 0x1e, 0x60, 0x8a, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327};
Hans de Goede00765f12010-12-12 15:55:03 -0300328static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300329 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
330 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
331 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
332 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
333 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
334};
335static const __u8 initOv6650[] = {
336 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
337 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300338 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede0a76cb82011-01-05 13:55:43 -0300339 0x10,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340};
Jean-François Moine780e3122010-10-19 04:29:10 -0300341static const __u8 ov6650_sensor_init[][8] = {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200342 /* Bright, contrast, etc are set through SCBB interface.
Jean-François Moine780e3122010-10-19 04:29:10 -0300343 * AVCAP on win2 do not send any data on this controls. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300345
346 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300347 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300348 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300349 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300350 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300351 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
352/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
353 * THIS SET GREEN SCREEN
354 * (pixels could be innverted in decode kind of "brg",
355 * but blue wont be there. Avoid this data ... */
356 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
357 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300358 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300359 /* Enable rgb brightness control */
360 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
361 /* HDG: Note windows uses the line below, which sets both register 0x60
362 and 0x61 I believe these registers of the ov6650 are identical as
363 those of the ov7630, because if this is true the windows settings
364 add a bit additional red gain and a lot additional blue gain, which
365 matches my findings that the windows settings make blue much too
366 blue and red a little too red.
367 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300368 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300369 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
370 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371};
Hans de Goededcef3232008-07-10 10:40:53 -0300372
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300373static const __u8 initOv7630[] = {
374 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
375 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300376 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300378 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379};
Hans de Goede6af492e2008-07-22 07:09:33 -0300380static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
382 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
383/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300384 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
386 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
387 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
388 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
389 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
390 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
391 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300392 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
393/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300394 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
395 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
396 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
397 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
398 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
399 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
400};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300401
402static const __u8 initPas106[] = {
403 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
404 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300405 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300406 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300407};
408/* compression 0x86 mckinit1 0x2b */
Hans de Goede421763e2010-02-10 18:57:40 -0300409
410/* "Known" PAS106B registers:
411 0x02 clock divider
412 0x03 Variable framerate bits 4-11
413 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
414 The variable framerate control must never be set lower then 300,
415 which sets the framerate at 90 / reg02, otherwise vsync is lost.
416 0x05 Shutter Time Line Offset, this can be used as an exposure control:
417 0 = use full frame time, 255 = no exposure at all
418 Note this may never be larger then "var-framerate control" / 2 - 2.
419 When var-framerate control is < 514, no exposure is reached at the max
420 allowed value for the framerate control value, rather then at 255.
421 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
422 only a very little bit, leave at 0xcd
423 0x07 offset sign bit (bit0 1 > negative offset)
424 0x08 offset
425 0x09 Blue Gain
426 0x0a Green1 Gain
427 0x0b Green2 Gain
428 0x0c Red Gain
429 0x0e Global gain
430 0x13 Write 1 to commit settings to sensor
431*/
432
Hans de Goedef45f06b2008-09-03 17:12:21 -0300433static const __u8 pas106_sensor_init[][8] = {
434 /* Pixel Clock Divider 6 */
435 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
436 /* Frame Time MSB (also seen as 0x12) */
437 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
438 /* Frame Time LSB (also seen as 0x05) */
439 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
440 /* Shutter Time Line Offset (also seen as 0x6d) */
441 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
442 /* Shutter Time Pixel Offset (also seen as 0xb1) */
443 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
444 /* Black Level Subtract Sign (also seen 0x00) */
445 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
446 /* Black Level Subtract Level (also seen 0x01) */
447 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
448 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
449 /* Color Gain B Pixel 5 a */
450 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
451 /* Color Gain G1 Pixel 1 5 */
452 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
453 /* Color Gain G2 Pixel 1 0 5 */
454 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
455 /* Color Gain R Pixel 3 1 */
456 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
457 /* Color GainH Pixel */
458 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
459 /* Global Gain */
460 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
461 /* Contrast */
462 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
463 /* H&V synchro polarity */
464 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
465 /* ?default */
466 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
467 /* DAC scale */
468 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
469 /* ?default */
470 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
471 /* Validate Settings */
472 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300474
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475static const __u8 initPas202[] = {
476 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
477 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300478 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goede82e839c2010-02-03 14:37:30 -0300479 0x28, 0x1e, 0x20, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480};
Hans de Goede82e839c2010-02-03 14:37:30 -0300481
482/* "Known" PAS202BCB registers:
483 0x02 clock divider
484 0x04 Variable framerate bits 6-11 (*)
485 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
486 0x07 Blue Gain
487 0x08 Green Gain
488 0x09 Red Gain
489 0x0b offset sign bit (bit0 1 > negative offset)
490 0x0c offset
491 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
492 leave at 1 otherwise we get a jump in our exposure control
493 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
494 0x10 Master gain 0 - 31
495 0x11 write 1 to apply changes
496 (*) The variable framerate control must never be set lower then 500
497 which sets the framerate at 30 / reg02, otherwise vsync is lost.
498*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499static const __u8 pas202_sensor_init[][8] = {
Hans de Goede82e839c2010-02-03 14:37:30 -0300500 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
501 to set it lower, but for some reason the bridge starts missing
502 vsync's then */
503 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
505 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300506 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
508 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
509 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
510 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
511 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
512 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513};
514
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300515static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
517 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300518 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 0x16, 0x12, 0x60, 0x86, 0x2b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300521/* Same as above, except a different hstart */
522static const __u8 initTas5110d[] = {
523 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
524 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300525 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300526 0x16, 0x12, 0x60, 0x86, 0x2b,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300527};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528static const __u8 tas5110_sensor_init[][8] = {
529 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
530 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
531 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
532};
533
534static const __u8 initTas5130[] = {
535 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
536 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300537 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538 0x28, 0x1e, 0x60, COMP, MCK_INIT,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539};
540static const __u8 tas5130_sensor_init[][8] = {
Jean-François Moine780e3122010-10-19 04:29:10 -0300541/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 * shutter 0x47 short exposure? */
543 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
544 /* shutter 0x01 long exposure */
545 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
546};
547
Hans Verkuild45b9b82008-09-04 03:33:43 -0300548static struct sensor_data sensor_data[] = {
Hans de Goede0a76cb82011-01-05 13:55:43 -0300549SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
550SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
551SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60),
552SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21),
553SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0),
554SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0),
555SENS(initTas5110c, tas5110_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
556 NO_BRIGHTNESS|NO_FREQ, 0),
557SENS(initTas5110d, tas5110_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
558 NO_BRIGHTNESS|NO_FREQ, 0),
559SENS(initTas5130, tas5130_sensor_init, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300560};
561
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300562/* get one byte in gspca_dev->usb_buf */
563static void reg_r(struct gspca_dev *gspca_dev,
564 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300566 usb_control_msg(gspca_dev->dev,
567 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300568 0, /* request */
569 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
570 value,
571 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300573 500);
574}
575
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576static void reg_w(struct gspca_dev *gspca_dev,
577 __u16 value,
578 const __u8 *buffer,
579 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300581#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300582 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300583 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
584 return;
585 }
586#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300587 memcpy(gspca_dev->usb_buf, buffer, len);
588 usb_control_msg(gspca_dev->dev,
589 usb_sndctrlpipe(gspca_dev->dev, 0),
590 0x08, /* request */
591 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
592 value,
593 0, /* index */
594 gspca_dev->usb_buf, len,
595 500);
596}
597
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300598static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300599{
600 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601
602 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300603 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604 while (retry--) {
605 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300606 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300607 if (gspca_dev->usb_buf[0] & 0x04) {
608 if (gspca_dev->usb_buf[0] & 0x08)
609 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300611 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 }
613 return -1;
614}
615
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 const __u8 buffer[][8], int len)
618{
619 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300620 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 len -= 8;
622 if (len <= 0)
623 break;
624 buffer++;
625 }
626}
627
628static void setbrightness(struct gspca_dev *gspca_dev)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
631 __u8 value;
632
633 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300634 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 case SENSOR_OV7630: {
636 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300637 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638
639 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300640 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300642 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 goto err;
644 break;
645 }
Hans de Goede421763e2010-02-10 18:57:40 -0300646 case SENSOR_PAS106:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647 case SENSOR_PAS202: {
Hans de Goede82e839c2010-02-03 14:37:30 -0300648 __u8 i2cpbright[] =
649 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
Hans de Goede421763e2010-02-10 18:57:40 -0300650 __u8 i2cpdoit[] =
Hans de Goede82e839c2010-02-03 14:37:30 -0300651 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652
Hans de Goede421763e2010-02-10 18:57:40 -0300653 /* PAS106 uses reg 7 and 8 instead of b and c */
654 if (sd->sensor == SENSOR_PAS106) {
655 i2cpbright[2] = 7;
656 i2cpdoit[2] = 0x13;
657 }
658
Hans de Goede82e839c2010-02-03 14:37:30 -0300659 if (sd->brightness < 127) {
660 /* change reg 0x0b, signreg */
661 i2cpbright[3] = 0x01;
662 /* set reg 0x0c, offset */
663 i2cpbright[4] = 127 - sd->brightness;
664 } else
665 i2cpbright[4] = sd->brightness - 127;
666
667 if (i2c_w(gspca_dev, i2cpbright) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300669 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670 goto err;
671 break;
672 }
Hans de Goededcef3232008-07-10 10:40:53 -0300673 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300674 __u8 i2c[] =
675 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
676
677 value = 0xff - sd->brightness;
678 i2c[4] = value;
679 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300680 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681 goto err;
682 break;
683 }
684 }
685 return;
686err:
687 PDEBUG(D_ERR, "i2c error brightness");
688}
Hans de Goededcef3232008-07-10 10:40:53 -0300689
690static void setsensorgain(struct gspca_dev *gspca_dev)
691{
692 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300693 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300694
695 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300696 case SENSOR_HV7131D: {
697 __u8 i2c[] =
698 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
Hans de Goededcef3232008-07-10 10:40:53 -0300699
Hans de Goede00765f12010-12-12 15:55:03 -0300700 i2c[3] = 0x3f - (sd->gain / 4);
701 i2c[4] = 0x3f - (sd->gain / 4);
702 i2c[5] = 0x3f - (sd->gain / 4);
703
704 if (i2c_w(gspca_dev, i2c) < 0)
705 goto err;
706 break;
707 }
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300708 case SENSOR_TAS5110C:
709 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300710 __u8 i2c[] =
711 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
712
Hans de Goedea975a522008-07-16 15:29:11 -0300713 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300715 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300716 break;
717 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300718
Hans de Goedea975a522008-07-16 15:29:11 -0300719 case SENSOR_OV6650:
720 gain >>= 1;
721 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300722 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300723 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300724
Hans de Goedef45f06b2008-09-03 17:12:21 -0300725 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300726 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300727 if (i2c_w(gspca_dev, i2c) < 0)
728 goto err;
729 break;
730 }
Hans de Goede421763e2010-02-10 18:57:40 -0300731 case SENSOR_PAS106:
Hans de Goede82e839c2010-02-03 14:37:30 -0300732 case SENSOR_PAS202: {
733 __u8 i2cpgain[] =
Hans de Goede421763e2010-02-10 18:57:40 -0300734 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede82e839c2010-02-03 14:37:30 -0300735 __u8 i2cpcolorgain[] =
736 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede421763e2010-02-10 18:57:40 -0300737 __u8 i2cpdoit[] =
738 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
739
740 /* PAS106 uses different regs (and has split green gains) */
741 if (sd->sensor == SENSOR_PAS106) {
742 i2cpgain[2] = 0x0e;
743 i2cpcolorgain[0] = 0xd0;
744 i2cpcolorgain[2] = 0x09;
745 i2cpdoit[2] = 0x13;
746 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300747
748 i2cpgain[3] = sd->gain >> 3;
749 i2cpcolorgain[3] = sd->gain >> 4;
750 i2cpcolorgain[4] = sd->gain >> 4;
751 i2cpcolorgain[5] = sd->gain >> 4;
Hans de Goede421763e2010-02-10 18:57:40 -0300752 i2cpcolorgain[6] = sd->gain >> 4;
Hans de Goede82e839c2010-02-03 14:37:30 -0300753
754 if (i2c_w(gspca_dev, i2cpgain) < 0)
755 goto err;
756 if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
757 goto err;
758 if (i2c_w(gspca_dev, i2cpdoit) < 0)
759 goto err;
760 break;
761 }
Hans de Goededcef3232008-07-10 10:40:53 -0300762 }
763 return;
764err:
765 PDEBUG(D_ERR, "i2c error gain");
766}
767
768static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769{
770 struct sd *sd = (struct sd *) gspca_dev;
771 __u8 gain;
Hans de Goede0a76cb82011-01-05 13:55:43 -0300772 __u8 buf[3] = { 0, 0, 0 };
Hans de Goede4efcfa02010-02-01 07:48:17 -0300773
774 if (sensor_data[sd->sensor].flags & F_GAIN) {
775 /* Use the sensor gain to do the actual gain */
776 setsensorgain(gspca_dev);
777 return;
778 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
Hans de Goede0a76cb82011-01-05 13:55:43 -0300780 if (sd->bridge == BRIDGE_103) {
781 gain = sd->gain >> 1;
782 buf[0] = gain; /* Red */
783 buf[1] = gain; /* Green */
784 buf[2] = gain; /* Blue */
785 reg_w(gspca_dev, 0x05, buf, 3);
786 } else {
787 gain = sd->gain >> 4;
788 buf[0] = gain << 4 | gain; /* Red and blue */
789 buf[1] = gain; /* Green */
790 reg_w(gspca_dev, 0x10, buf, 2);
791 }
Hans de Goededcef3232008-07-10 10:40:53 -0300792}
793
794static void setexposure(struct gspca_dev *gspca_dev)
795{
796 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300797
798 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300799 case SENSOR_HV7131D: {
800 /* Note the datasheet wrongly says line mode exposure uses reg
801 0x26 and 0x27, testing has shown 0x25 + 0x26 */
802 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
803 /* The HV7131D's exposure goes from 0 - 65535, we scale our
804 exposure of 0-1023 to 0-6138. There are 2 reasons for this:
805 1) This puts our exposure knee of 200 at approx the point
806 where the framerate starts dropping
807 2) At 6138 the framerate has already dropped to 2 fps,
808 going any lower makes little sense */
809 __u16 reg = sd->exposure * 6;
810 i2c[3] = reg >> 8;
811 i2c[4] = reg & 0xff;
812 if (i2c_w(gspca_dev, i2c) != 0)
813 goto err;
814 break;
815 }
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300816 case SENSOR_TAS5110C:
817 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300818 /* register 19's high nibble contains the sn9c10x clock divider
819 The high nibble configures the no fps according to the
820 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goede26984b02010-02-01 13:18:37 -0300821 __u8 reg = sd->exposure;
Hans de Goededcef3232008-07-10 10:40:53 -0300822 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300823 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300824 break;
825 }
Hans de Goedea975a522008-07-16 15:29:11 -0300826 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300827 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300828 /* The ov6650 / ov7630 have 2 registers which both influence
829 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300830 according to: fps = 30 / (low_nibble + 1)
831
832 The fps configures the maximum exposure setting, but it is
833 possible to use less exposure then what the fps maximum
834 allows by setting register 10. register 10 configures the
835 actual exposure as quotient of the full exposure, with 0
836 being no exposure at all (not very usefull) and reg10_max
837 being max exposure possible at that framerate.
838
839 The code maps our 0 - 510 ms exposure ctrl to these 2
840 registers, trying to keep fps as high as possible.
841 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300842 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
843 int reg10, reg11, reg10_max;
844
Hans de Goede66f35822008-07-16 10:16:28 -0300845 /* ov6645 datasheet says reg10_max is 9a, but that uses
846 tline * 2 * reg10 as formula for calculating texpo, the
847 ov6650 probably uses the same formula as the 7730 which uses
848 tline * 4 * reg10, which explains why the reg10max we've
849 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300850 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300851 if (sd->sensor == SENSOR_OV6650) {
852 reg10_max = 0x4d;
853 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
854 } else
855 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300856
Hans de Goede82e839c2010-02-03 14:37:30 -0300857 reg11 = (15 * sd->exposure + 999) / 1000;
Hans de Goedef4d52022008-07-15 09:36:42 -0300858 if (reg11 < 1)
859 reg11 = 1;
860 else if (reg11 > 16)
861 reg11 = 16;
862
Hans de Goede10bb7532010-02-04 06:10:55 -0300863 /* In 640x480, if the reg11 has less than 4, the image is
864 unstable (the bridge goes into a higher compression mode
865 which we have not reverse engineered yet). */
866 if (gspca_dev->width == 640 && reg11 < 4)
867 reg11 = 4;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300868
Hans de Goedef4d52022008-07-15 09:36:42 -0300869 /* frame exposure time in ms = 1000 * reg11 / 30 ->
Hans de Goede82e839c2010-02-03 14:37:30 -0300870 reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
871 reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300872
873 /* Don't allow this to get below 10 when using autogain, the
874 steps become very large (relatively) when below 10 causing
875 the image to oscilate from much too dark, to much too bright
876 and back again. */
877 if (sd->autogain && reg10 < 10)
878 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300879 else if (reg10 > reg10_max)
880 reg10 = reg10_max;
881
882 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300883 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300884 i2c[3] = reg10;
885 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300886
887 /* If register 11 didn't change, don't change it */
Jean-François Moine780e3122010-10-19 04:29:10 -0300888 if (sd->reg11 == reg11)
Hans de Goede6af492e2008-07-22 07:09:33 -0300889 i2c[0] = 0xa0;
890
891 if (i2c_w(gspca_dev, i2c) == 0)
892 sd->reg11 = reg11;
893 else
Hans de Goede82e839c2010-02-03 14:37:30 -0300894 goto err;
895 break;
896 }
897 case SENSOR_PAS202: {
898 __u8 i2cpframerate[] =
899 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
900 __u8 i2cpexpo[] =
901 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
902 const __u8 i2cpdoit[] =
903 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
904 int framerate_ctrl;
905
906 /* The exposure knee for the autogain algorithm is 200
907 (100 ms / 10 fps on other sensors), for values below this
908 use the control for setting the partial frame expose time,
909 above that use variable framerate. This way we run at max
910 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
911 is reached. Using the variable framerate control above 200
912 is better then playing around with both clockdiv + partial
913 frame exposure times (like we are doing with the ov chips),
914 as that sometimes leads to jumps in the exposure control,
915 which are bad for auto exposure. */
916 if (sd->exposure < 200) {
917 i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
918 framerate_ctrl = 500;
919 } else {
920 /* The PAS202's exposure control goes from 0 - 4095,
921 but anything below 500 causes vsync issues, so scale
922 our 200-1023 to 500-4095 */
923 framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
924 500;
925 }
926
927 i2cpframerate[3] = framerate_ctrl >> 6;
928 i2cpframerate[4] = framerate_ctrl & 0x3f;
929 if (i2c_w(gspca_dev, i2cpframerate) < 0)
930 goto err;
931 if (i2c_w(gspca_dev, i2cpexpo) < 0)
932 goto err;
933 if (i2c_w(gspca_dev, i2cpdoit) < 0)
934 goto err;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300935 break;
936 }
Hans de Goede421763e2010-02-10 18:57:40 -0300937 case SENSOR_PAS106: {
938 __u8 i2cpframerate[] =
939 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
940 __u8 i2cpexpo[] =
941 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
942 const __u8 i2cpdoit[] =
943 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
944 int framerate_ctrl;
945
946 /* For values below 150 use partial frame exposure, above
947 that use framerate ctrl */
948 if (sd->exposure < 150) {
949 i2cpexpo[3] = 150 - sd->exposure;
950 framerate_ctrl = 300;
951 } else {
952 /* The PAS106's exposure control goes from 0 - 4095,
953 but anything below 300 causes vsync issues, so scale
954 our 150-1023 to 300-4095 */
955 framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
956 300;
957 }
958
959 i2cpframerate[3] = framerate_ctrl >> 4;
960 i2cpframerate[4] = framerate_ctrl & 0x0f;
961 if (i2c_w(gspca_dev, i2cpframerate) < 0)
962 goto err;
963 if (i2c_w(gspca_dev, i2cpexpo) < 0)
964 goto err;
965 if (i2c_w(gspca_dev, i2cpdoit) < 0)
966 goto err;
967 break;
968 }
Hans de Goededcef3232008-07-10 10:40:53 -0300969 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300970 return;
971err:
972 PDEBUG(D_ERR, "i2c error exposure");
Hans de Goededcef3232008-07-10 10:40:53 -0300973}
974
Hans de Goede66f35822008-07-16 10:16:28 -0300975static void setfreq(struct gspca_dev *gspca_dev)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300980 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300981 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300982 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300983 compensation, for the ov6650 this is identical to ov6630
984 0x2b register, see ov6630 datasheet.
985 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300986 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300987 switch (sd->freq) {
988 default:
989/* case 0: * no filter*/
990/* case 2: * 60 hz */
991 i2c[3] = 0;
992 break;
993 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300994 i2c[3] = (sd->sensor == SENSOR_OV6650)
995 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300996 break;
997 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300998 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300999 if (i2c_w(gspca_dev, i2c) < 0)
1000 PDEBUG(D_ERR, "i2c error setfreq");
1001 break;
1002 }
1003 }
1004}
1005
Hans de Goede26984b02010-02-01 13:18:37 -03001006#include "coarse_expo_autogain.h"
1007
Hans de Goededcef3232008-07-10 10:40:53 -03001008static void do_autogain(struct gspca_dev *gspca_dev)
1009{
Hans de Goede26984b02010-02-01 13:18:37 -03001010 int deadzone, desired_avg_lum, result;
Hans de Goededcef3232008-07-10 10:40:53 -03001011 struct sd *sd = (struct sd *) gspca_dev;
1012 int avg_lum = atomic_read(&sd->avg_lum);
1013
Hans de Goede26984b02010-02-01 13:18:37 -03001014 if (avg_lum == -1 || !sd->autogain)
Hans de Goededcef3232008-07-10 10:40:53 -03001015 return;
1016
Hans de Goede26984b02010-02-01 13:18:37 -03001017 if (sd->autogain_ignore_frames > 0) {
1018 sd->autogain_ignore_frames--;
1019 return;
1020 }
1021
Hans de Goede5017c7b2008-10-22 04:59:29 -03001022 /* SIF / VGA sensors have a different autoexposure area and thus
1023 different avg_lum values for the same picture brightness */
1024 if (sensor_data[sd->sensor].flags & F_SIF) {
Hans de Goede26984b02010-02-01 13:18:37 -03001025 deadzone = 500;
1026 /* SIF sensors tend to overexpose, so keep this small */
1027 desired_avg_lum = 5000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001028 } else {
Hans de Goede26984b02010-02-01 13:18:37 -03001029 deadzone = 1500;
Hans de Goede606f8422010-02-10 06:49:23 -03001030 desired_avg_lum = 18000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001031 }
1032
Hans de Goede26984b02010-02-01 13:18:37 -03001033 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
1034 result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
1035 sd->brightness * desired_avg_lum / 127,
1036 deadzone);
1037 else
1038 result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
1039 sd->brightness * desired_avg_lum / 127,
1040 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1041
1042 if (result) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -03001043 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -03001044 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -03001045 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -03001046 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047}
1048
1049/* this function is called at probe time */
1050static int sd_config(struct gspca_dev *gspca_dev,
1051 const struct usb_device_id *id)
1052{
1053 struct sd *sd = (struct sd *) gspca_dev;
1054 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -03001055
1056 reg_r(gspca_dev, 0x00);
1057 if (gspca_dev->usb_buf[0] != 0x10)
1058 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059
Jean-Francois Moine5da162e72008-07-26 14:17:23 -03001060 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001061 sd->sensor = id->driver_info >> 8;
1062 sd->bridge = id->driver_info & 0xff;
1063 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064
1065 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001066 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001067 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001068 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001069 } else {
1070 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001071 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -03001073 cam->npkt = 36; /* 36 packets per ISOC message */
1074
Hans de Goededcef3232008-07-10 10:40:53 -03001075 sd->brightness = BRIGHTNESS_DEF;
1076 sd->gain = GAIN_DEF;
Hans de Goede26984b02010-02-01 13:18:37 -03001077 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
1078 sd->exposure = COARSE_EXPOSURE_DEF;
1079 gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
1080 } else {
1081 sd->exposure = EXPOSURE_DEF;
1082 gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
1083 }
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001084 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1085 sd->autogain = 0; /* Disable do_autogain callback */
1086 else
1087 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -03001088 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -03001089
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090 return 0;
1091}
1092
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001093/* this function is called at probe and resume time */
1094static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001095{
Hans de Goede271315a2008-09-03 17:12:19 -03001096 const __u8 stop = 0x09; /* Disable stream turn of LED */
1097
1098 reg_w(gspca_dev, 0x01, &stop, 1);
1099
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001100 return 0;
1101}
1102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001103/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001104static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001105{
1106 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -03001107 struct cam *cam = &gspca_dev->cam;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001108 int i, mode;
1109 __u8 regs[0x31];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110
Hans de Goede93627732008-09-04 16:20:12 -03001111 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001112 /* Copy registers 0x01 - 0x19 from the template */
1113 memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
1114 /* Set the mode */
1115 regs[0x18] |= mode << 4;
1116
1117 /* Set bridge gain to 1.0 */
1118 if (sd->bridge == BRIDGE_103) {
1119 regs[0x05] = 0x20; /* Red */
1120 regs[0x06] = 0x20; /* Green */
1121 regs[0x07] = 0x20; /* Blue */
1122 } else {
1123 regs[0x10] = 0x00; /* Red and blue */
1124 regs[0x11] = 0x00; /* Green */
1125 }
1126
1127 /* Setup pixel numbers and auto exposure window */
1128 if (sensor_data[sd->sensor].flags & F_SIF) {
1129 regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
1130 regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
1131 regs[0x1c] = 0x02; /* AE H-start 64 */
1132 regs[0x1d] = 0x02; /* AE V-start 64 */
1133 regs[0x1e] = 0x09; /* AE H-end 288 */
1134 regs[0x1f] = 0x07; /* AE V-end 224 */
1135 } else {
1136 regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
1137 regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
1138 regs[0x1c] = 0x02; /* AE H-start 64 */
1139 regs[0x1d] = 0x03; /* AE V-start 96 */
1140 regs[0x1e] = 0x0f; /* AE H-end 480 */
1141 regs[0x1f] = 0x0c; /* AE V-end 384 */
1142 }
1143
1144 /* Setup the gamma table (only used with the sn9c103 bridge) */
1145 for (i = 0; i < 16; i++)
1146 regs[0x20 + i] = i * 16;
1147 regs[0x20 + i] = 255;
1148
1149 /* Special cases where some regs depend on mode or bridge */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001150 switch (sd->sensor) {
Hans de Goedef45f06b2008-09-03 17:12:21 -03001151 case SENSOR_TAS5130CXX:
Hans de Goede0a76cb82011-01-05 13:55:43 -03001152 /* FIXME / TESTME
1153 probably not mode specific at all most likely the upper
Hans de Goedef45f06b2008-09-03 17:12:21 -03001154 nibble of 0x19 is exposure (clock divider) just as with
1155 the tas5110, we need someone to test this. */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001156 regs[0x19] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001157 break;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001158 case SENSOR_OV7630:
1159 /* FIXME / TESTME for some reason with the 101/102 bridge the
1160 clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
1161 Also the hstart needs to go from 1 to 2 when using a 103,
1162 which is likely related. This does not seem right. */
1163 if (sd->bridge == BRIDGE_103) {
1164 regs[0x01] = 0x44; /* Select 24 Mhz clock */
1165 regs[0x12] = 0x02; /* Set hstart to 2 */
1166 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001167 }
Hans de Goedec437d652008-09-03 17:12:22 -03001168 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -03001169 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
Hans de Goede0a76cb82011-01-05 13:55:43 -03001170 regs[0x18] &= ~0x80;
Hans de Goede93627732008-09-04 16:20:12 -03001171
1172 /* Vga mode emulation on SIF sensor? */
1173 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
Hans de Goede0a76cb82011-01-05 13:55:43 -03001174 regs[0x12] += 16; /* hstart adjust */
1175 regs[0x13] += 24; /* vstart adjust */
1176 regs[0x15] = 320 / 16; /* hsize */
1177 regs[0x16] = 240 / 16; /* vsize */
Hans de Goede93627732008-09-04 16:20:12 -03001178 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001179
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180 /* reg 0x01 bit 2 video transfert on */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001181 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001183 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184 /* Set the registers from the template */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001185 reg_w(gspca_dev, 0x01, &regs[0x01],
1186 (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001187
1188 /* Init the sensor */
1189 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1190 sensor_data[sd->sensor].sensor_init_size);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001191
Hans de Goede0a76cb82011-01-05 13:55:43 -03001192 /* Mode / bridge specific sensor setup */
Hans de Goede82e839c2010-02-03 14:37:30 -03001193 switch (sd->sensor) {
1194 case SENSOR_PAS202: {
1195 const __u8 i2cpclockdiv[] =
1196 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1197 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1198 if (mode)
1199 i2c_w(gspca_dev, i2cpclockdiv);
Hans de Goede0a76cb82011-01-05 13:55:43 -03001200 break;
Hans de Goede82e839c2010-02-03 14:37:30 -03001201 }
Hans de Goede0a76cb82011-01-05 13:55:43 -03001202 case SENSOR_OV7630:
1203 /* FIXME / TESTME We should be able to handle this identical
1204 for the 101/102 and the 103 case */
1205 if (sd->bridge == BRIDGE_103) {
1206 const __u8 i2c[] = { 0xa0, 0x21, 0x13,
1207 0x80, 0x00, 0x00, 0x00, 0x10 };
1208 i2c_w(gspca_dev, i2c);
1209 }
1210 break;
Hans de Goede82e839c2010-02-03 14:37:30 -03001211 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001212 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001213 reg_w(gspca_dev, 0x15, &regs[0x15], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001214 /* compression register */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001215 reg_w(gspca_dev, 0x18, &regs[0x18], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001216 /* H_start */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001217 reg_w(gspca_dev, 0x12, &regs[0x12], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001218 /* V_START */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001219 reg_w(gspca_dev, 0x13, &regs[0x13], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001220 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1221 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede0a76cb82011-01-05 13:55:43 -03001222 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001223 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede0a76cb82011-01-05 13:55:43 -03001224 reg_w(gspca_dev, 0x19, &regs[0x19], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001226 reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227 /* Enable video transfert */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001228 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229 /* Compression */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001230 reg_w(gspca_dev, 0x18, &regs[0x18], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231 msleep(20);
1232
Hans de Goede6af492e2008-07-22 07:09:33 -03001233 sd->reg11 = -1;
1234
Hans de Goededcef3232008-07-10 10:40:53 -03001235 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001236 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001237 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -03001238 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001239
Hans de Goede6af492e2008-07-22 07:09:33 -03001240 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001241 sd->autogain_ignore_frames = 0;
Hans de Goede26984b02010-02-01 13:18:37 -03001242 sd->exp_too_high_cnt = 0;
1243 sd->exp_too_low_cnt = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001244 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001245 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001246}
1247
1248static void sd_stopN(struct gspca_dev *gspca_dev)
1249{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001250 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001251}
1252
Hans de Goede2b3e2842010-12-12 08:55:04 -03001253static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001254{
Hans de Goededcef3232008-07-10 10:40:53 -03001255 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede2b3e2842010-12-12 08:55:04 -03001256 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001257
Hans de Goedec36260ee2008-07-16 09:56:07 -03001258 /* frames start with:
1259 * ff ff 00 c4 c4 96 synchro
1260 * 00 (unknown)
1261 * xx (frame sequence / size / compression)
1262 * (xx) (idem - extra byte for sn9c103)
1263 * ll mm brightness sum inside auto exposure
1264 * ll mm brightness sum outside auto exposure
1265 * (xx xx xx xx xx) audio values for snc103
1266 */
Hans de Goede2b3e2842010-12-12 08:55:04 -03001267 for (i = 0; i < len; i++) {
1268 switch (sd->header_read) {
1269 case 0:
1270 if (data[i] == 0xff)
1271 sd->header_read++;
1272 break;
1273 case 1:
1274 if (data[i] == 0xff)
1275 sd->header_read++;
1276 else
1277 sd->header_read = 0;
1278 break;
1279 case 2:
1280 if (data[i] == 0x00)
1281 sd->header_read++;
1282 else if (data[i] != 0xff)
1283 sd->header_read = 0;
1284 break;
1285 case 3:
1286 if (data[i] == 0xc4)
1287 sd->header_read++;
1288 else if (data[i] == 0xff)
1289 sd->header_read = 1;
1290 else
1291 sd->header_read = 0;
1292 break;
1293 case 4:
1294 if (data[i] == 0xc4)
1295 sd->header_read++;
1296 else if (data[i] == 0xff)
1297 sd->header_read = 1;
1298 else
1299 sd->header_read = 0;
1300 break;
1301 case 5:
1302 if (data[i] == 0x96)
1303 sd->header_read++;
1304 else if (data[i] == 0xff)
1305 sd->header_read = 1;
1306 else
1307 sd->header_read = 0;
1308 break;
1309 default:
1310 sd->header[sd->header_read - 6] = data[i];
1311 sd->header_read++;
1312 if (sd->header_read == header_size) {
1313 sd->header_read = 0;
1314 return data + i + 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001315 }
1316 }
1317 }
Hans de Goede2b3e2842010-12-12 08:55:04 -03001318 return NULL;
1319}
1320
1321static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1322 u8 *data, /* isoc packet */
1323 int len) /* iso packet length */
1324{
1325 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1326 struct sd *sd = (struct sd *) gspca_dev;
1327 struct cam *cam = &gspca_dev->cam;
1328 u8 *sof;
1329
1330 sof = find_sof(gspca_dev, data, len);
1331 if (sof) {
1332 if (sd->bridge == BRIDGE_103) {
1333 fr_h_sz = 18;
1334 lum_offset = 3;
1335 } else {
1336 fr_h_sz = 12;
1337 lum_offset = 2;
1338 }
1339
1340 len_after_sof = len - (sof - data);
1341 len = (sof - data) - fr_h_sz;
1342 if (len < 0)
1343 len = 0;
1344 }
Hans de Goedec437d652008-09-03 17:12:22 -03001345
1346 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1347 /* In raw mode we sometimes get some garbage after the frame
1348 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001349 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001350 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1351
Jean-François Moineb192ca92010-06-27 03:08:19 -03001352 used = gspca_dev->image_len;
Hans de Goedec437d652008-09-03 17:12:22 -03001353 if (used + len > size)
1354 len = size - used;
1355 }
1356
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001357 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Hans de Goede2b3e2842010-12-12 08:55:04 -03001358
1359 if (sof) {
1360 int lum = sd->header[lum_offset] +
1361 (sd->header[lum_offset + 1] << 8);
1362
1363 /* When exposure changes midway a frame we
1364 get a lum of 0 in this case drop 2 frames
1365 as the frames directly after an exposure
1366 change have an unstable image. Sometimes lum
1367 *really* is 0 (cam used in low light with
1368 low exposure setting), so do not drop frames
1369 if the previous lum was 0 too. */
1370 if (lum == 0 && sd->prev_avg_lum != 0) {
1371 lum = -1;
1372 sd->frames_to_drop = 2;
1373 sd->prev_avg_lum = 0;
1374 } else
1375 sd->prev_avg_lum = lum;
1376 atomic_set(&sd->avg_lum, lum);
1377
1378 if (sd->frames_to_drop)
1379 sd->frames_to_drop--;
1380 else
1381 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1382
1383 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1384 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001385}
1386
1387static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1388{
1389 struct sd *sd = (struct sd *) gspca_dev;
1390
1391 sd->brightness = val;
1392 if (gspca_dev->streaming)
1393 setbrightness(gspca_dev);
1394 return 0;
1395}
1396
1397static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400
1401 *val = sd->brightness;
1402 return 0;
1403}
1404
Hans de Goededcef3232008-07-10 10:40:53 -03001405static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001406{
1407 struct sd *sd = (struct sd *) gspca_dev;
1408
Hans de Goededcef3232008-07-10 10:40:53 -03001409 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001410 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001411 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001412 return 0;
1413}
1414
Hans de Goededcef3232008-07-10 10:40:53 -03001415static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001416{
1417 struct sd *sd = (struct sd *) gspca_dev;
1418
Hans de Goededcef3232008-07-10 10:40:53 -03001419 *val = sd->gain;
1420 return 0;
1421}
1422
1423static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1424{
1425 struct sd *sd = (struct sd *) gspca_dev;
1426
1427 sd->exposure = val;
1428 if (gspca_dev->streaming)
1429 setexposure(gspca_dev);
1430 return 0;
1431}
1432
1433static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1434{
1435 struct sd *sd = (struct sd *) gspca_dev;
1436
1437 *val = sd->exposure;
1438 return 0;
1439}
1440
1441static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444
1445 sd->autogain = val;
Hans de Goede26984b02010-02-01 13:18:37 -03001446 sd->exp_too_high_cnt = 0;
1447 sd->exp_too_low_cnt = 0;
1448
Hans de Goededcef3232008-07-10 10:40:53 -03001449 /* when switching to autogain set defaults to make sure
1450 we are on a valid point of the autogain gain /
1451 exposure knee graph, and give this change time to
1452 take effect before doing autogain. */
Hans de Goede26984b02010-02-01 13:18:37 -03001453 if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
Hans de Goededcef3232008-07-10 10:40:53 -03001454 sd->exposure = EXPOSURE_DEF;
1455 sd->gain = GAIN_DEF;
1456 if (gspca_dev->streaming) {
1457 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1458 setexposure(gspca_dev);
1459 setgain(gspca_dev);
1460 }
1461 }
1462
1463 return 0;
1464}
1465
1466static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469
1470 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001471 return 0;
1472}
1473
Hans de Goede66f35822008-07-16 10:16:28 -03001474static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1475{
1476 struct sd *sd = (struct sd *) gspca_dev;
1477
1478 sd->freq = val;
1479 if (gspca_dev->streaming)
1480 setfreq(gspca_dev);
1481 return 0;
1482}
1483
1484static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1485{
1486 struct sd *sd = (struct sd *) gspca_dev;
1487
1488 *val = sd->freq;
1489 return 0;
1490}
1491
1492static int sd_querymenu(struct gspca_dev *gspca_dev,
1493 struct v4l2_querymenu *menu)
1494{
1495 switch (menu->id) {
1496 case V4L2_CID_POWER_LINE_FREQUENCY:
1497 switch (menu->index) {
1498 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1499 strcpy((char *) menu->name, "NoFliker");
1500 return 0;
1501 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1502 strcpy((char *) menu->name, "50 Hz");
1503 return 0;
1504 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1505 strcpy((char *) menu->name, "60 Hz");
1506 return 0;
1507 }
1508 break;
1509 }
1510 return -EINVAL;
1511}
1512
Jean-François Moine28566432010-10-01 07:33:26 -03001513#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001514static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1515 u8 *data, /* interrupt packet data */
1516 int len) /* interrupt packet length */
1517{
1518 int ret = -EINVAL;
1519
1520 if (len == 1 && data[0] == 1) {
1521 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1522 input_sync(gspca_dev->input_dev);
1523 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1524 input_sync(gspca_dev->input_dev);
1525 ret = 0;
1526 }
1527
1528 return ret;
1529}
1530#endif
1531
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001532/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001533static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001534 .name = MODULE_NAME,
1535 .ctrls = sd_ctrls,
1536 .nctrls = ARRAY_SIZE(sd_ctrls),
1537 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001538 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001539 .start = sd_start,
1540 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001541 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001542 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001543 .dq_callback = do_autogain,
Jean-François Moine28566432010-10-01 07:33:26 -03001544#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001545 .int_pkt_scan = sd_int_pkt_scan,
1546#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001547};
1548
1549/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001550#define SB(sensor, bridge) \
1551 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1552
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001553
Márton Németh37b372e2009-12-10 11:31:09 -03001554static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001555 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1556 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001557 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001558 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1559 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001560 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001561#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001562 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1563 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1564 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
Hans de Goede0e4b91c2010-02-10 20:29:43 -03001565#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001566 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1567 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001568 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1569 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001570 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001571 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001572 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001573 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
Hans de Goede4cce1652008-09-04 16:22:57 -03001574 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1575#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1576 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1577#endif
1578 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001579 {}
1580};
1581MODULE_DEVICE_TABLE(usb, device_table);
1582
1583/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001584static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001585 const struct usb_device_id *id)
1586{
1587 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1588 THIS_MODULE);
1589}
1590
1591static struct usb_driver sd_driver = {
1592 .name = MODULE_NAME,
1593 .id_table = device_table,
1594 .probe = sd_probe,
1595 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001596#ifdef CONFIG_PM
1597 .suspend = gspca_suspend,
1598 .resume = gspca_resume,
1599#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001600};
1601
1602/* -- module insert / remove -- */
1603static int __init sd_mod_init(void)
1604{
Jean-François Moine54826432010-09-13 04:53:03 -03001605 return usb_register(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001606}
1607static void __exit sd_mod_exit(void)
1608{
1609 usb_deregister(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001610}
1611
1612module_init(sd_mod_init);
1613module_exit(sd_mod_exit);