blob: cfefdfefaf623f48a02f886ba8f1fdaab6fbc44c [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
45#include "gspca.h"
46
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030047MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
48MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
49MODULE_LICENSE("GPL");
50
51/* specific webcam descriptor */
52struct sd {
53 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030054 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030055 int prev_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -030056
Hans de Goedead5ef80d2008-07-14 10:11:42 -030057 unsigned char gain;
58 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030060 unsigned char autogain;
61 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030062 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030063 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064
Hans de Goedef45f06b2008-09-03 17:12:21 -030065 __u8 bridge; /* Type of bridge */
66#define BRIDGE_101 0
67#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
68#define BRIDGE_103 1
69
70 __u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030071#define SENSOR_HV7131R 0
72#define SENSOR_OV6650 1
73#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030074#define SENSOR_PAS106 3
75#define SENSOR_PAS202 4
Hans de Goedeb10af3f2010-01-10 19:31:34 -030076#define SENSOR_TAS5110C 5
77#define SENSOR_TAS5110D 6
78#define SENSOR_TAS5130CXX 7
Hans de Goede6af492e2008-07-22 07:09:33 -030079 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030080};
81
Hans de Goedef45f06b2008-09-03 17:12:21 -030082typedef const __u8 sensor_init_t[8];
83
84struct sensor_data {
85 const __u8 *bridge_init[2];
86 int bridge_init_size[2];
87 sensor_init_t *sensor_init;
88 int sensor_init_size;
89 sensor_init_t *sensor_bridge_init[2];
90 int sensor_bridge_init_size[2];
91 int flags;
92 unsigned ctrl_dis;
93 __u8 sensor_addr;
94};
95
96/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030097#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030098#define F_SIF 0x02 /* sif or vga */
Hans de Goedec437d652008-09-03 17:12:22 -030099
100/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
101#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300102#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300103
104/* ctrl_dis helper macros */
105#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
106#define NO_FREQ (1 << FREQ_IDX)
107#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300108
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300109#define COMP2 0x8f
110#define COMP 0xc7 /* 0x87 //0x07 */
111#define COMP1 0xc9 /* 0x89 //0x09 */
112
113#define MCK_INIT 0x63
114#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
115
116#define SYS_CLK 0x04
117
Hans de Goedef45f06b2008-09-03 17:12:21 -0300118#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
119 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
120{ \
121 .bridge_init = { bridge_1, bridge_3 }, \
122 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
123 .sensor_init = sensor, \
124 .sensor_init_size = sizeof(sensor), \
125 .sensor_bridge_init = { sensor_1, sensor_3,}, \
126 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
127 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
128}
129
Hans de Goededcef3232008-07-10 10:40:53 -0300130/* We calculate the autogain at the end of the transfer of a frame, at this
131 moment a frame with the old settings is being transmitted, and a frame is
132 being captured with the old settings. So if we adjust the autogain we must
133 ignore atleast the 2 next frames for the new settings to come into effect
134 before doing any other adjustments */
135#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goededcef3232008-07-10 10:40:53 -0300136
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300137/* V4L2 controls supported by the driver */
138static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
139static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300140static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
141static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
142static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
143static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
144static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
145static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300146static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
147static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300148
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300149static const struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300150#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151 {
152 {
153 .id = V4L2_CID_BRIGHTNESS,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Brightness",
156 .minimum = 0,
157 .maximum = 255,
158 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300159#define BRIGHTNESS_DEF 127
160 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300161 },
162 .set = sd_setbrightness,
163 .get = sd_getbrightness,
164 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300165#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166 {
167 {
Hans de Goededcef3232008-07-10 10:40:53 -0300168 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300170 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300172 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300174#define GAIN_DEF 127
175#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300176 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177 },
Hans de Goededcef3232008-07-10 10:40:53 -0300178 .set = sd_setgain,
179 .get = sd_getgain,
180 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300181#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300182 {
183 {
184 .id = V4L2_CID_EXPOSURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300187#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
188#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300189 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300190 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300191 .step = 1,
192 .default_value = EXPOSURE_DEF,
193 .flags = 0,
194 },
195 .set = sd_setexposure,
196 .get = sd_getexposure,
197 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300198#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300199 {
200 {
201 .id = V4L2_CID_AUTOGAIN,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
203 .name = "Automatic Gain (and Exposure)",
204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300207#define AUTOGAIN_DEF 1
208 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300209 .flags = 0,
210 },
211 .set = sd_setautogain,
212 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300213 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300214#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300215 {
216 {
217 .id = V4L2_CID_POWER_LINE_FREQUENCY,
218 .type = V4L2_CTRL_TYPE_MENU,
219 .name = "Light frequency filter",
220 .minimum = 0,
221 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
222 .step = 1,
223#define FREQ_DEF 1
224 .default_value = FREQ_DEF,
225 },
226 .set = sd_setfreq,
227 .get = sd_getfreq,
228 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300229};
230
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300231static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300232 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
233 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300234 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300237 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
238 .bytesperline = 160,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300239 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300240 .colorspace = V4L2_COLORSPACE_SRGB,
241 .priv = 2},
242 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
243 .bytesperline = 320,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300244 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300245 .colorspace = V4L2_COLORSPACE_SRGB,
246 .priv = 1},
247 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
248 .bytesperline = 640,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300249 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300250 .colorspace = V4L2_COLORSPACE_SRGB,
251 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300253static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300254 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
255 .bytesperline = 160,
256 .sizeimage = 160 * 120,
257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
259 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
260 .bytesperline = 160,
261 .sizeimage = 160 * 120 * 5 / 4,
262 .colorspace = V4L2_COLORSPACE_SRGB,
263 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300264 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
265 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300266 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300269 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
270 .bytesperline = 176,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300271 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300272 .colorspace = V4L2_COLORSPACE_SRGB,
273 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300274 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
275 .bytesperline = 320,
276 .sizeimage = 320 * 240 * 5 / 4,
277 .colorspace = V4L2_COLORSPACE_SRGB,
278 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300279 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
280 .bytesperline = 352,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300281 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300282 .colorspace = V4L2_COLORSPACE_SRGB,
283 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300284};
285
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286static const __u8 initHv7131[] = {
287 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
288 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300289 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300290 0x28, 0x1e, 0x60, 0x8a, 0x20,
291 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
292};
293static const __u8 hv7131_sensor_init[][8] = {
294 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
295 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
296 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
297 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
298 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
299};
300static const __u8 initOv6650[] = {
301 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
302 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300303 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300304 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300305};
306static const __u8 ov6650_sensor_init[][8] =
307{
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200308 /* Bright, contrast, etc are set through SCBB interface.
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 * AVCAP on win2 do not send any data on this controls. */
310 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300311
312 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300313 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300314 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300315 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300316 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
318/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
319 * THIS SET GREEN SCREEN
320 * (pixels could be innverted in decode kind of "brg",
321 * but blue wont be there. Avoid this data ... */
322 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
323 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
324 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300325 /* Enable rgb brightness control */
326 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
327 /* HDG: Note windows uses the line below, which sets both register 0x60
328 and 0x61 I believe these registers of the ov6650 are identical as
329 those of the ov7630, because if this is true the windows settings
330 add a bit additional red gain and a lot additional blue gain, which
331 matches my findings that the windows settings make blue much too
332 blue and red a little too red.
333 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300334 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300335 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
336 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337};
Hans de Goededcef3232008-07-10 10:40:53 -0300338
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300339static const __u8 initOv7630[] = {
340 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
341 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300342 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300343 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300344 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300345 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
346};
347static const __u8 initOv7630_3[] = {
348 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
349 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300350 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300351 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300352 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
353 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
354 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
355 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356};
Hans de Goede6af492e2008-07-22 07:09:33 -0300357static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
359 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
360/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300361 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
363 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
365 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
366 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
368 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300369 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
370/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
372 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
373 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
374 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
375 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
376 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
377};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300378
Hans de Goedef45f06b2008-09-03 17:12:21 -0300379static const __u8 ov7630_sensor_init_3[][8] = {
380 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
381};
382
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383static const __u8 initPas106[] = {
384 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
385 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300386 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300387 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300388 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300389};
390/* compression 0x86 mckinit1 0x2b */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300391static const __u8 pas106_sensor_init[][8] = {
392 /* Pixel Clock Divider 6 */
393 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
394 /* Frame Time MSB (also seen as 0x12) */
395 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
396 /* Frame Time LSB (also seen as 0x05) */
397 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
398 /* Shutter Time Line Offset (also seen as 0x6d) */
399 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
400 /* Shutter Time Pixel Offset (also seen as 0xb1) */
401 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
402 /* Black Level Subtract Sign (also seen 0x00) */
403 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
404 /* Black Level Subtract Level (also seen 0x01) */
405 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
406 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
407 /* Color Gain B Pixel 5 a */
408 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
409 /* Color Gain G1 Pixel 1 5 */
410 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
411 /* Color Gain G2 Pixel 1 0 5 */
412 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
413 /* Color Gain R Pixel 3 1 */
414 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
415 /* Color GainH Pixel */
416 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
417 /* Global Gain */
418 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
419 /* Contrast */
420 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
421 /* H&V synchro polarity */
422 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
423 /* ?default */
424 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
425 /* DAC scale */
426 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
427 /* ?default */
428 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
429 /* Validate Settings */
430 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300431};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300432
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433static const __u8 initPas202[] = {
434 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
435 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300436 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300437 0x28, 0x1e, 0x28, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300438 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
439};
440static const __u8 pas202_sensor_init[][8] = {
441 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
442 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
443 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
444 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
445 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
446 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
450 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
451 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
452 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
453
454 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
455 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
456 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
457 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
458 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
459 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
460 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
461 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
462};
463
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300464static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300465 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
466 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300467 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 0x16, 0x12, 0x60, 0x86, 0x2b,
469 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
470};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300471/* Same as above, except a different hstart */
472static const __u8 initTas5110d[] = {
473 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
474 0x00, 0x00,
475 0x00, 0x01, 0x00, 0x41, 0x09, 0x0a,
476 0x16, 0x12, 0x60, 0x86, 0x2b,
477 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
478};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300479static const __u8 tas5110_sensor_init[][8] = {
480 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
481 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
482 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
483};
484
485static const __u8 initTas5130[] = {
486 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
487 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300488 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489 0x28, 0x1e, 0x60, COMP, MCK_INIT,
490 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
491};
492static const __u8 tas5130_sensor_init[][8] = {
493/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
494 * shutter 0x47 short exposure? */
495 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
496 /* shutter 0x01 long exposure */
497 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
498};
499
Hans Verkuild45b9b82008-09-04 03:33:43 -0300500static struct sensor_data sensor_data[] = {
Hans de Goedef45f06b2008-09-03 17:12:21 -0300501SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300502SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300503SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
504 F_GAIN, 0, 0x21),
505SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
506 0),
Hans de Goede93627732008-09-04 16:20:12 -0300507SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300508 NO_EXPO|NO_FREQ, 0),
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300509SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
510 NO_BRIGHTNESS|NO_FREQ, 0),
511SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300512 NO_BRIGHTNESS|NO_FREQ, 0),
513SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
514 0),
515};
516
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300517/* get one byte in gspca_dev->usb_buf */
518static void reg_r(struct gspca_dev *gspca_dev,
519 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300521 usb_control_msg(gspca_dev->dev,
522 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300523 0, /* request */
524 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
525 value,
526 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 500);
529}
530
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531static void reg_w(struct gspca_dev *gspca_dev,
532 __u16 value,
533 const __u8 *buffer,
534 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300536#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300537 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300538 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
539 return;
540 }
541#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542 memcpy(gspca_dev->usb_buf, buffer, len);
543 usb_control_msg(gspca_dev->dev,
544 usb_sndctrlpipe(gspca_dev->dev, 0),
545 0x08, /* request */
546 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
547 value,
548 0, /* index */
549 gspca_dev->usb_buf, len,
550 500);
551}
552
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300553static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554{
555 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300556
557 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 while (retry--) {
560 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300561 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300562 if (gspca_dev->usb_buf[0] & 0x04) {
563 if (gspca_dev->usb_buf[0] & 0x08)
564 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300566 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300567 }
568 return -1;
569}
570
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300571static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300572 const __u8 buffer[][8], int len)
573{
574 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300575 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300576 len -= 8;
577 if (len <= 0)
578 break;
579 buffer++;
580 }
581}
582
583static void setbrightness(struct gspca_dev *gspca_dev)
584{
585 struct sd *sd = (struct sd *) gspca_dev;
586 __u8 value;
587
588 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300589 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590 case SENSOR_OV7630: {
591 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300592 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593
594 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300595 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300596 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 goto err;
599 break;
600 }
601 case SENSOR_PAS106: {
602 __u8 i2c1[] =
603 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
604
605 i2c1[3] = sd->brightness >> 3;
606 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300607 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 goto err;
609 i2c1[3] = 0x01;
610 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300611 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 goto err;
613 break;
614 }
615 case SENSOR_PAS202: {
616 /* __u8 i2cpexpo1[] =
617 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
618 __u8 i2cpexpo[] =
619 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
620 __u8 i2cp202[] =
621 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
622 static __u8 i2cpdoit[] =
623 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
624
625 /* change reg 0x10 */
626 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300627/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300629/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300631 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300633 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 goto err;
635 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300636 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300638 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 goto err;
640 break;
641 }
Hans de Goededcef3232008-07-10 10:40:53 -0300642 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 __u8 i2c[] =
644 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
645
646 value = 0xff - sd->brightness;
647 i2c[4] = value;
648 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300649 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650 goto err;
651 break;
652 }
653 }
654 return;
655err:
656 PDEBUG(D_ERR, "i2c error brightness");
657}
Hans de Goededcef3232008-07-10 10:40:53 -0300658
659static void setsensorgain(struct gspca_dev *gspca_dev)
660{
661 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300662 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300663
664 switch (sd->sensor) {
665
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300666 case SENSOR_TAS5110C:
667 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300668 __u8 i2c[] =
669 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
670
Hans de Goedea975a522008-07-16 15:29:11 -0300671 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300673 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300674 break;
675 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300676
Hans de Goedea975a522008-07-16 15:29:11 -0300677 case SENSOR_OV6650:
678 gain >>= 1;
679 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300680 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300681 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300682
Hans de Goedef45f06b2008-09-03 17:12:21 -0300683 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300684 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300685 if (i2c_w(gspca_dev, i2c) < 0)
686 goto err;
687 break;
688 }
Hans de Goededcef3232008-07-10 10:40:53 -0300689 }
690 return;
691err:
692 PDEBUG(D_ERR, "i2c error gain");
693}
694
695static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696{
697 struct sd *sd = (struct sd *) gspca_dev;
698 __u8 gain;
699 __u8 rgb_value;
700
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300701 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300702
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 /* red and blue gain */
704 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300705 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706 /* green gain */
707 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300708 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300709
Hans de Goedef45f06b2008-09-03 17:12:21 -0300710 if (sensor_data[sd->sensor].flags & F_GAIN)
Hans de Goededcef3232008-07-10 10:40:53 -0300711 setsensorgain(gspca_dev);
712}
713
714static void setexposure(struct gspca_dev *gspca_dev)
715{
716 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300717
718 switch (sd->sensor) {
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300719 case SENSOR_TAS5110C:
720 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300721 __u8 reg;
722
723 /* register 19's high nibble contains the sn9c10x clock divider
724 The high nibble configures the no fps according to the
725 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300726 reg = 120 * sd->exposure / 1000;
727 if (reg < 2)
728 reg = 2;
729 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300730 reg = 15;
731 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300732 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300733 break;
734 }
Hans de Goedea975a522008-07-16 15:29:11 -0300735 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300736 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300737 /* The ov6650 / ov7630 have 2 registers which both influence
738 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300739 according to: fps = 30 / (low_nibble + 1)
740
741 The fps configures the maximum exposure setting, but it is
742 possible to use less exposure then what the fps maximum
743 allows by setting register 10. register 10 configures the
744 actual exposure as quotient of the full exposure, with 0
745 being no exposure at all (not very usefull) and reg10_max
746 being max exposure possible at that framerate.
747
748 The code maps our 0 - 510 ms exposure ctrl to these 2
749 registers, trying to keep fps as high as possible.
750 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300751 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
752 int reg10, reg11, reg10_max;
753
Hans de Goede66f35822008-07-16 10:16:28 -0300754 /* ov6645 datasheet says reg10_max is 9a, but that uses
755 tline * 2 * reg10 as formula for calculating texpo, the
756 ov6650 probably uses the same formula as the 7730 which uses
757 tline * 4 * reg10, which explains why the reg10max we've
758 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300759 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300760 if (sd->sensor == SENSOR_OV6650) {
761 reg10_max = 0x4d;
762 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
763 } else
764 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300765
766 reg11 = (60 * sd->exposure + 999) / 1000;
767 if (reg11 < 1)
768 reg11 = 1;
769 else if (reg11 > 16)
770 reg11 = 16;
771
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300772 /* In 640x480, if the reg11 has less than 3, the image is
773 unstable (not enough bandwidth). */
774 if (gspca_dev->width == 640 && reg11 < 3)
775 reg11 = 3;
776
Hans de Goedef4d52022008-07-15 09:36:42 -0300777 /* frame exposure time in ms = 1000 * reg11 / 30 ->
778 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
779 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300780
781 /* Don't allow this to get below 10 when using autogain, the
782 steps become very large (relatively) when below 10 causing
783 the image to oscilate from much too dark, to much too bright
784 and back again. */
785 if (sd->autogain && reg10 < 10)
786 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300787 else if (reg10 > reg10_max)
788 reg10 = reg10_max;
789
790 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300791 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300792 i2c[3] = reg10;
793 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300794
795 /* If register 11 didn't change, don't change it */
796 if (sd->reg11 == reg11 )
797 i2c[0] = 0xa0;
798
799 if (i2c_w(gspca_dev, i2c) == 0)
800 sd->reg11 = reg11;
801 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300802 PDEBUG(D_ERR, "i2c error exposure");
803 break;
804 }
Hans de Goededcef3232008-07-10 10:40:53 -0300805 }
806}
807
Hans de Goede66f35822008-07-16 10:16:28 -0300808static void setfreq(struct gspca_dev *gspca_dev)
809{
810 struct sd *sd = (struct sd *) gspca_dev;
811
812 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300813 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300814 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300815 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300816 compensation, for the ov6650 this is identical to ov6630
817 0x2b register, see ov6630 datasheet.
818 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300819 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300820 switch (sd->freq) {
821 default:
822/* case 0: * no filter*/
823/* case 2: * 60 hz */
824 i2c[3] = 0;
825 break;
826 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300827 i2c[3] = (sd->sensor == SENSOR_OV6650)
828 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300829 break;
830 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300831 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300832 if (i2c_w(gspca_dev, i2c) < 0)
833 PDEBUG(D_ERR, "i2c error setfreq");
834 break;
835 }
836 }
837}
838
Hans de Goededcef3232008-07-10 10:40:53 -0300839static void do_autogain(struct gspca_dev *gspca_dev)
840{
Hans de Goede5017c7b2008-10-22 04:59:29 -0300841 int deadzone, desired_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -0300842 struct sd *sd = (struct sd *) gspca_dev;
843 int avg_lum = atomic_read(&sd->avg_lum);
844
845 if (avg_lum == -1)
846 return;
847
Hans de Goede5017c7b2008-10-22 04:59:29 -0300848 /* SIF / VGA sensors have a different autoexposure area and thus
849 different avg_lum values for the same picture brightness */
850 if (sensor_data[sd->sensor].flags & F_SIF) {
851 deadzone = 1000;
852 desired_avg_lum = 7000;
853 } else {
854 deadzone = 3000;
855 desired_avg_lum = 23000;
856 }
857
Hans de Goededcef3232008-07-10 10:40:53 -0300858 if (sd->autogain_ignore_frames > 0)
859 sd->autogain_ignore_frames--;
860 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
Hans de Goede5017c7b2008-10-22 04:59:29 -0300861 sd->brightness * desired_avg_lum / 127,
862 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -0300863 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -0300864 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300865 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300866 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867}
868
869/* this function is called at probe time */
870static int sd_config(struct gspca_dev *gspca_dev,
871 const struct usb_device_id *id)
872{
873 struct sd *sd = (struct sd *) gspca_dev;
874 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -0300875
876 reg_r(gspca_dev, 0x00);
877 if (gspca_dev->usb_buf[0] != 0x10)
878 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300880 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300881 sd->sensor = id->driver_info >> 8;
882 sd->bridge = id->driver_info & 0xff;
883 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884
885 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300886 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300888 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 } else {
890 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300891 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300892 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -0300893 cam->npkt = 36; /* 36 packets per ISOC message */
894
Hans de Goededcef3232008-07-10 10:40:53 -0300895 sd->brightness = BRIGHTNESS_DEF;
896 sd->gain = GAIN_DEF;
897 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300898 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
899 sd->autogain = 0; /* Disable do_autogain callback */
900 else
901 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300902 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300903
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 return 0;
905}
906
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300907/* this function is called at probe and resume time */
908static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909{
Hans de Goede271315a2008-09-03 17:12:19 -0300910 const __u8 stop = 0x09; /* Disable stream turn of LED */
911
912 reg_w(gspca_dev, 0x01, &stop, 1);
913
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300914 return 0;
915}
916
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300918static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919{
920 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -0300921 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300922 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -0300924 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300925
Hans de Goede93627732008-09-04 16:20:12 -0300926 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300927 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
928 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -0300929 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
930 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300931 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 switch (sd->sensor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 case SENSOR_PAS202:
Hans de Goede93627732008-09-04 16:20:12 -0300934 reg12_19[5] = mode ? 0x24 : 0x20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 break;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300936 case SENSOR_TAS5130CXX:
937 /* probably not mode specific at all most likely the upper
938 nibble of 0x19 is exposure (clock divider) just as with
939 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -0300940 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 break;
942 }
Hans de Goedec437d652008-09-03 17:12:22 -0300943 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -0300944 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
945 reg12_19[6] &= ~0x80;
946
947 /* Vga mode emulation on SIF sensor? */
948 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
949 reg12_19[0] += 16; /* 0x12: hstart adjust */
950 reg12_19[1] += 24; /* 0x13: vstart adjust */
951 reg12_19[3] = 320 / 16; /* 0x15: hsize */
952 reg12_19[4] = 240 / 16; /* 0x16: vsize */
953 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300954
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300956 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300958 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300960 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300961
962 /* Init the sensor */
963 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
964 sensor_data[sd->sensor].sensor_init_size);
965 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
966 i2c_w_vector(gspca_dev,
967 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
968 sensor_data[sd->sensor].sensor_bridge_init_size[
969 sd->bridge]);
970
Hans de Goede3647fea2008-07-15 05:36:30 -0300971 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -0300972 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -0300974 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300975 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -0300976 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300977 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -0300978 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979 /* reset 0x17 SensorClk enable inv Clk 0x60 */
980 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -0300981 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -0300983 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300985 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300987 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -0300989 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990 msleep(20);
991
Hans de Goede6af492e2008-07-22 07:09:33 -0300992 sd->reg11 = -1;
993
Hans de Goededcef3232008-07-10 10:40:53 -0300994 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300996 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300997 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300998
Hans de Goede6af492e2008-07-22 07:09:33 -0300999 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001000 sd->autogain_ignore_frames = 0;
1001 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001002 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001003}
1004
1005static void sd_stopN(struct gspca_dev *gspca_dev)
1006{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001007 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001008}
1009
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001010static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001011 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001012 int len) /* iso packet length */
1013{
Hans de Goede0d2a7222008-07-03 08:15:22 -03001014 int i;
Hans de Goededcef3232008-07-10 10:40:53 -03001015 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedec437d652008-09-03 17:12:22 -03001016 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001017
Hans de Goedec36260ee2008-07-16 09:56:07 -03001018 /* frames start with:
1019 * ff ff 00 c4 c4 96 synchro
1020 * 00 (unknown)
1021 * xx (frame sequence / size / compression)
1022 * (xx) (idem - extra byte for sn9c103)
1023 * ll mm brightness sum inside auto exposure
1024 * ll mm brightness sum outside auto exposure
1025 * (xx xx xx xx xx) audio values for snc103
1026 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -03001028 for (i = 0; i < len - 6; i++) {
1029 if (data[0 + i] == 0xff
1030 && data[1 + i] == 0xff
1031 && data[2 + i] == 0x00
1032 && data[3 + i] == 0xc4
1033 && data[4 + i] == 0xc4
1034 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -03001035 int lum = -1;
1036 int pkt_type = LAST_PACKET;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001037 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1038 18 : 12;
Hans de Goede6af492e2008-07-22 07:09:33 -03001039
Hans de Goedef45f06b2008-09-03 17:12:21 -03001040 if (len - i < fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -03001041 PDEBUG(D_STREAM, "packet too short to"
1042 " get avg brightness");
Hans de Goedef45f06b2008-09-03 17:12:21 -03001043 } else if (sd->bridge == BRIDGE_103) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001044 lum = data[i + 9] +
1045 (data[i + 10] << 8);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001046 } else {
1047 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001048 }
Hans de Goedebf2a2202008-09-04 16:22:56 -03001049 /* When exposure changes midway a frame we
1050 get a lum of 0 in this case drop 2 frames
1051 as the frames directly after an exposure
1052 change have an unstable image. Sometimes lum
1053 *really* is 0 (cam used in low light with
1054 low exposure setting), so do not drop frames
1055 if the previous lum was 0 too. */
1056 if (lum == 0 && sd->prev_avg_lum != 0) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001057 lum = -1;
1058 sd->frames_to_drop = 2;
Hans de Goedebf2a2202008-09-04 16:22:56 -03001059 sd->prev_avg_lum = 0;
1060 } else
1061 sd->prev_avg_lum = lum;
Hans de Goede6af492e2008-07-22 07:09:33 -03001062 atomic_set(&sd->avg_lum, lum);
1063
1064 if (sd->frames_to_drop) {
1065 sd->frames_to_drop--;
1066 pkt_type = DISCARD_PACKET;
1067 }
1068
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001069 gspca_frame_add(gspca_dev, pkt_type,
1070 NULL, 0);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001071 data += i + fr_h_sz;
1072 len -= i + fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001073 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001074 data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 return;
1076 }
1077 }
1078 }
Hans de Goedec437d652008-09-03 17:12:22 -03001079
1080 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1081 /* In raw mode we sometimes get some garbage after the frame
1082 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001083 struct gspca_frame *frame;
1084 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001085 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1086
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001087 frame = gspca_get_i_frame(gspca_dev);
1088 if (frame == NULL) {
1089 gspca_dev->last_packet_type = DISCARD_PACKET;
1090 return;
1091 }
1092 used = frame->data_end - frame->data;
Hans de Goedec437d652008-09-03 17:12:22 -03001093 if (used + len > size)
1094 len = size - used;
1095 }
1096
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001097 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001098}
1099
1100static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 sd->brightness = val;
1105 if (gspca_dev->streaming)
1106 setbrightness(gspca_dev);
1107 return 0;
1108}
1109
1110static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1111{
1112 struct sd *sd = (struct sd *) gspca_dev;
1113
1114 *val = sd->brightness;
1115 return 0;
1116}
1117
Hans de Goededcef3232008-07-10 10:40:53 -03001118static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119{
1120 struct sd *sd = (struct sd *) gspca_dev;
1121
Hans de Goededcef3232008-07-10 10:40:53 -03001122 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001123 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001124 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001125 return 0;
1126}
1127
Hans de Goededcef3232008-07-10 10:40:53 -03001128static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001129{
1130 struct sd *sd = (struct sd *) gspca_dev;
1131
Hans de Goededcef3232008-07-10 10:40:53 -03001132 *val = sd->gain;
1133 return 0;
1134}
1135
1136static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1137{
1138 struct sd *sd = (struct sd *) gspca_dev;
1139
1140 sd->exposure = val;
1141 if (gspca_dev->streaming)
1142 setexposure(gspca_dev);
1143 return 0;
1144}
1145
1146static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1147{
1148 struct sd *sd = (struct sd *) gspca_dev;
1149
1150 *val = sd->exposure;
1151 return 0;
1152}
1153
1154static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1155{
1156 struct sd *sd = (struct sd *) gspca_dev;
1157
1158 sd->autogain = val;
1159 /* when switching to autogain set defaults to make sure
1160 we are on a valid point of the autogain gain /
1161 exposure knee graph, and give this change time to
1162 take effect before doing autogain. */
1163 if (sd->autogain) {
1164 sd->exposure = EXPOSURE_DEF;
1165 sd->gain = GAIN_DEF;
1166 if (gspca_dev->streaming) {
1167 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1168 setexposure(gspca_dev);
1169 setgain(gspca_dev);
1170 }
1171 }
1172
1173 return 0;
1174}
1175
1176static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1177{
1178 struct sd *sd = (struct sd *) gspca_dev;
1179
1180 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 return 0;
1182}
1183
Hans de Goede66f35822008-07-16 10:16:28 -03001184static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1185{
1186 struct sd *sd = (struct sd *) gspca_dev;
1187
1188 sd->freq = val;
1189 if (gspca_dev->streaming)
1190 setfreq(gspca_dev);
1191 return 0;
1192}
1193
1194static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197
1198 *val = sd->freq;
1199 return 0;
1200}
1201
1202static int sd_querymenu(struct gspca_dev *gspca_dev,
1203 struct v4l2_querymenu *menu)
1204{
1205 switch (menu->id) {
1206 case V4L2_CID_POWER_LINE_FREQUENCY:
1207 switch (menu->index) {
1208 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1209 strcpy((char *) menu->name, "NoFliker");
1210 return 0;
1211 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1212 strcpy((char *) menu->name, "50 Hz");
1213 return 0;
1214 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1215 strcpy((char *) menu->name, "60 Hz");
1216 return 0;
1217 }
1218 break;
1219 }
1220 return -EINVAL;
1221}
1222
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001223/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001224static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225 .name = MODULE_NAME,
1226 .ctrls = sd_ctrls,
1227 .nctrls = ARRAY_SIZE(sd_ctrls),
1228 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001229 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001230 .start = sd_start,
1231 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001232 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001233 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001234 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001235};
1236
1237/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001238#define SB(sensor, bridge) \
1239 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1240
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001241
Márton Németh37b372e2009-12-10 11:31:09 -03001242static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001243 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1244 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goede222a07f2008-09-03 17:12:20 -03001245#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001246 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001247 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1248 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001249#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001250 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001251#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001252 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1253 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1254 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1255 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1256 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001257#endif
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001258 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001259 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001260#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001261 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001262#endif
Hans de Goede4cce1652008-09-04 16:22:57 -03001263 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1264#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1265 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1266#endif
1267 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001268 {}
1269};
1270MODULE_DEVICE_TABLE(usb, device_table);
1271
1272/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001273static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001274 const struct usb_device_id *id)
1275{
1276 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1277 THIS_MODULE);
1278}
1279
1280static struct usb_driver sd_driver = {
1281 .name = MODULE_NAME,
1282 .id_table = device_table,
1283 .probe = sd_probe,
1284 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001285#ifdef CONFIG_PM
1286 .suspend = gspca_suspend,
1287 .resume = gspca_resume,
1288#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289};
1290
1291/* -- module insert / remove -- */
1292static int __init sd_mod_init(void)
1293{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001294 int ret;
1295 ret = usb_register(&sd_driver);
1296 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001297 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001298 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001299 return 0;
1300}
1301static void __exit sd_mod_exit(void)
1302{
1303 usb_deregister(&sd_driver);
1304 PDEBUG(D_PROBE, "deregistered");
1305}
1306
1307module_init(sd_mod_init);
1308module_exit(sd_mod_exit);