blob: dd9417eea16a2fb92b5a4e0b2d26571a0516515f [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
76#define SENSOR_TAS5110 5
77#define SENSOR_TAS5130CXX 6
Hans de Goede6af492e2008-07-22 07:09:33 -030078 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030079};
80
Hans de Goedef45f06b2008-09-03 17:12:21 -030081typedef const __u8 sensor_init_t[8];
82
83struct sensor_data {
84 const __u8 *bridge_init[2];
85 int bridge_init_size[2];
86 sensor_init_t *sensor_init;
87 int sensor_init_size;
88 sensor_init_t *sensor_bridge_init[2];
89 int sensor_bridge_init_size[2];
90 int flags;
91 unsigned ctrl_dis;
92 __u8 sensor_addr;
93};
94
95/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030096#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030097#define F_SIF 0x02 /* sif or vga */
Hans de Goedec437d652008-09-03 17:12:22 -030098
99/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
100#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300101#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300102
103/* ctrl_dis helper macros */
104#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
105#define NO_FREQ (1 << FREQ_IDX)
106#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300107
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108#define COMP2 0x8f
109#define COMP 0xc7 /* 0x87 //0x07 */
110#define COMP1 0xc9 /* 0x89 //0x09 */
111
112#define MCK_INIT 0x63
113#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
114
115#define SYS_CLK 0x04
116
Hans de Goedef45f06b2008-09-03 17:12:21 -0300117#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
118 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
119{ \
120 .bridge_init = { bridge_1, bridge_3 }, \
121 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
122 .sensor_init = sensor, \
123 .sensor_init_size = sizeof(sensor), \
124 .sensor_bridge_init = { sensor_1, sensor_3,}, \
125 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
126 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
127}
128
Hans de Goededcef3232008-07-10 10:40:53 -0300129/* We calculate the autogain at the end of the transfer of a frame, at this
130 moment a frame with the old settings is being transmitted, and a frame is
131 being captured with the old settings. So if we adjust the autogain we must
132 ignore atleast the 2 next frames for the new settings to come into effect
133 before doing any other adjustments */
134#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goededcef3232008-07-10 10:40:53 -0300135
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300136/* V4L2 controls supported by the driver */
137static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
138static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300139static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
140static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
141static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
142static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
143static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
144static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300145static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
146static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147
148static struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300149#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150 {
151 {
152 .id = V4L2_CID_BRIGHTNESS,
153 .type = V4L2_CTRL_TYPE_INTEGER,
154 .name = "Brightness",
155 .minimum = 0,
156 .maximum = 255,
157 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300158#define BRIGHTNESS_DEF 127
159 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160 },
161 .set = sd_setbrightness,
162 .get = sd_getbrightness,
163 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300164#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 {
166 {
Hans de Goededcef3232008-07-10 10:40:53 -0300167 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300169 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300171 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300173#define GAIN_DEF 127
174#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300175 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176 },
Hans de Goededcef3232008-07-10 10:40:53 -0300177 .set = sd_setgain,
178 .get = sd_getgain,
179 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300180#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300181 {
182 {
183 .id = V4L2_CID_EXPOSURE,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300186#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
187#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300188 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300189 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300190 .step = 1,
191 .default_value = EXPOSURE_DEF,
192 .flags = 0,
193 },
194 .set = sd_setexposure,
195 .get = sd_getexposure,
196 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300197#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300198 {
199 {
200 .id = V4L2_CID_AUTOGAIN,
201 .type = V4L2_CTRL_TYPE_BOOLEAN,
202 .name = "Automatic Gain (and Exposure)",
203 .minimum = 0,
204 .maximum = 1,
205 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300206#define AUTOGAIN_DEF 1
207 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300208 .flags = 0,
209 },
210 .set = sd_setautogain,
211 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300213#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300214 {
215 {
216 .id = V4L2_CID_POWER_LINE_FREQUENCY,
217 .type = V4L2_CTRL_TYPE_MENU,
218 .name = "Light frequency filter",
219 .minimum = 0,
220 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
221 .step = 1,
222#define FREQ_DEF 1
223 .default_value = FREQ_DEF,
224 },
225 .set = sd_setfreq,
226 .get = sd_getfreq,
227 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228};
229
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300230static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300231 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
232 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300233 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300234 .colorspace = V4L2_COLORSPACE_SRGB,
235 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300236 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
237 .bytesperline = 160,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300238 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300239 .colorspace = V4L2_COLORSPACE_SRGB,
240 .priv = 2},
241 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
242 .bytesperline = 320,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300243 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300244 .colorspace = V4L2_COLORSPACE_SRGB,
245 .priv = 1},
246 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
247 .bytesperline = 640,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300248 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300249 .colorspace = V4L2_COLORSPACE_SRGB,
250 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300252static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300253 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
254 .bytesperline = 160,
255 .sizeimage = 160 * 120,
256 .colorspace = V4L2_COLORSPACE_SRGB,
257 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
258 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
259 .bytesperline = 160,
260 .sizeimage = 160 * 120 * 5 / 4,
261 .colorspace = V4L2_COLORSPACE_SRGB,
262 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300263 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
264 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300265 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300266 .colorspace = V4L2_COLORSPACE_SRGB,
267 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300268 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
269 .bytesperline = 176,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300270 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300271 .colorspace = V4L2_COLORSPACE_SRGB,
272 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300273 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
274 .bytesperline = 320,
275 .sizeimage = 320 * 240 * 5 / 4,
276 .colorspace = V4L2_COLORSPACE_SRGB,
277 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300278 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
279 .bytesperline = 352,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300280 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300281 .colorspace = V4L2_COLORSPACE_SRGB,
282 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283};
284
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300285static const __u8 initHv7131[] = {
286 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
287 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300288 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300289 0x28, 0x1e, 0x60, 0x8a, 0x20,
290 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
291};
292static const __u8 hv7131_sensor_init[][8] = {
293 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
294 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
295 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
296 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
297 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
298};
299static const __u8 initOv6650[] = {
300 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
301 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300302 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300303 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300304};
305static const __u8 ov6650_sensor_init[][8] =
306{
307 /* Bright, contrast, etc are set througth SCBB interface.
308 * AVCAP on win2 do not send any data on this controls. */
309 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300310
311 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300313 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300314 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300315 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300316 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
317/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
318 * THIS SET GREEN SCREEN
319 * (pixels could be innverted in decode kind of "brg",
320 * but blue wont be there. Avoid this data ... */
321 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
322 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
323 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300324 /* Enable rgb brightness control */
325 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
326 /* HDG: Note windows uses the line below, which sets both register 0x60
327 and 0x61 I believe these registers of the ov6650 are identical as
328 those of the ov7630, because if this is true the windows settings
329 add a bit additional red gain and a lot additional blue gain, which
330 matches my findings that the windows settings make blue much too
331 blue and red a little too red.
332 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300333 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
335 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336};
Hans de Goededcef3232008-07-10 10:40:53 -0300337
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338static const __u8 initOv7630[] = {
339 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
340 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300341 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300343 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
345};
346static const __u8 initOv7630_3[] = {
347 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
348 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300349 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300350 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300351 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
352 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
353 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
354 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300355};
Hans de Goede6af492e2008-07-22 07:09:33 -0300356static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
358 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
359/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300360 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
362 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
363 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
364 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
365 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
366 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
367 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300368 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
369/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
371 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
372 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
373 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
374 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
375 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
376};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377
Hans de Goedef45f06b2008-09-03 17:12:21 -0300378static const __u8 ov7630_sensor_init_3[][8] = {
379 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
380};
381
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382static const __u8 initPas106[] = {
383 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
384 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300385 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300386 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300387 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388};
389/* compression 0x86 mckinit1 0x2b */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300390static const __u8 pas106_sensor_init[][8] = {
391 /* Pixel Clock Divider 6 */
392 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
393 /* Frame Time MSB (also seen as 0x12) */
394 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
395 /* Frame Time LSB (also seen as 0x05) */
396 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
397 /* Shutter Time Line Offset (also seen as 0x6d) */
398 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
399 /* Shutter Time Pixel Offset (also seen as 0xb1) */
400 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
401 /* Black Level Subtract Sign (also seen 0x00) */
402 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
403 /* Black Level Subtract Level (also seen 0x01) */
404 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
405 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
406 /* Color Gain B Pixel 5 a */
407 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
408 /* Color Gain G1 Pixel 1 5 */
409 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
410 /* Color Gain G2 Pixel 1 0 5 */
411 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
412 /* Color Gain R Pixel 3 1 */
413 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
414 /* Color GainH Pixel */
415 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
416 /* Global Gain */
417 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
418 /* Contrast */
419 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
420 /* H&V synchro polarity */
421 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
422 /* ?default */
423 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
424 /* DAC scale */
425 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 /* ?default */
427 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
428 /* Validate Settings */
429 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300430};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300431
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432static const __u8 initPas202[] = {
433 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
434 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300435 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300436 0x28, 0x1e, 0x28, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300437 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
438};
439static const __u8 pas202_sensor_init[][8] = {
440 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
441 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
442 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
443 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
444 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
445 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
446 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
450 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
451 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
452
453 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
454 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
455 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
456 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
457 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
458 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
459 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
460 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
461};
462
463static const __u8 initTas5110[] = {
464 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
465 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300466 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 0x16, 0x12, 0x60, 0x86, 0x2b,
468 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
469};
470static const __u8 tas5110_sensor_init[][8] = {
471 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
472 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
473 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
474};
475
476static const __u8 initTas5130[] = {
477 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
478 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300479 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 0x28, 0x1e, 0x60, COMP, MCK_INIT,
481 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
482};
483static const __u8 tas5130_sensor_init[][8] = {
484/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
485 * shutter 0x47 short exposure? */
486 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
487 /* shutter 0x01 long exposure */
488 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
489};
490
Hans Verkuild45b9b82008-09-04 03:33:43 -0300491static struct sensor_data sensor_data[] = {
Hans de Goedef45f06b2008-09-03 17:12:21 -0300492SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300493SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300494SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
495 F_GAIN, 0, 0x21),
496SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
497 0),
Hans de Goede93627732008-09-04 16:20:12 -0300498SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300499 NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300500SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300501 NO_BRIGHTNESS|NO_FREQ, 0),
502SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
503 0),
504};
505
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300506/* get one byte in gspca_dev->usb_buf */
507static void reg_r(struct gspca_dev *gspca_dev,
508 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300509{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300510 usb_control_msg(gspca_dev->dev,
511 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512 0, /* request */
513 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
514 value,
515 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300516 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 500);
518}
519
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300520static void reg_w(struct gspca_dev *gspca_dev,
521 __u16 value,
522 const __u8 *buffer,
523 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300525#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300526 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300527 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
528 return;
529 }
530#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531 memcpy(gspca_dev->usb_buf, buffer, len);
532 usb_control_msg(gspca_dev->dev,
533 usb_sndctrlpipe(gspca_dev->dev, 0),
534 0x08, /* request */
535 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
536 value,
537 0, /* index */
538 gspca_dev->usb_buf, len,
539 500);
540}
541
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543{
544 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545
546 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 while (retry--) {
549 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300551 if (gspca_dev->usb_buf[0] & 0x04) {
552 if (gspca_dev->usb_buf[0] & 0x08)
553 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300555 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300556 }
557 return -1;
558}
559
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300560static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 const __u8 buffer[][8], int len)
562{
563 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300564 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 len -= 8;
566 if (len <= 0)
567 break;
568 buffer++;
569 }
570}
571
572static void setbrightness(struct gspca_dev *gspca_dev)
573{
574 struct sd *sd = (struct sd *) gspca_dev;
575 __u8 value;
576
577 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300578 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 case SENSOR_OV7630: {
580 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300581 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300582
583 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300584 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300585 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300586 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587 goto err;
588 break;
589 }
590 case SENSOR_PAS106: {
591 __u8 i2c1[] =
592 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
593
594 i2c1[3] = sd->brightness >> 3;
595 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300596 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 goto err;
598 i2c1[3] = 0x01;
599 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 goto err;
602 break;
603 }
604 case SENSOR_PAS202: {
605 /* __u8 i2cpexpo1[] =
606 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
607 __u8 i2cpexpo[] =
608 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
609 __u8 i2cp202[] =
610 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
611 static __u8 i2cpdoit[] =
612 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
613
614 /* change reg 0x10 */
615 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300618/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300620 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623 goto err;
624 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300625 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300627 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 goto err;
629 break;
630 }
Hans de Goededcef3232008-07-10 10:40:53 -0300631 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 __u8 i2c[] =
633 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
634
635 value = 0xff - sd->brightness;
636 i2c[4] = value;
637 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300638 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 goto err;
640 break;
641 }
642 }
643 return;
644err:
645 PDEBUG(D_ERR, "i2c error brightness");
646}
Hans de Goededcef3232008-07-10 10:40:53 -0300647
648static void setsensorgain(struct gspca_dev *gspca_dev)
649{
650 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300651 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300652
653 switch (sd->sensor) {
654
655 case SENSOR_TAS5110: {
656 __u8 i2c[] =
657 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
658
Hans de Goedea975a522008-07-16 15:29:11 -0300659 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300660 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300661 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300662 break;
663 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300664
Hans de Goedea975a522008-07-16 15:29:11 -0300665 case SENSOR_OV6650:
666 gain >>= 1;
667 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300668 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300669 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300670
Hans de Goedef45f06b2008-09-03 17:12:21 -0300671 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300672 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300673 if (i2c_w(gspca_dev, i2c) < 0)
674 goto err;
675 break;
676 }
Hans de Goededcef3232008-07-10 10:40:53 -0300677 }
678 return;
679err:
680 PDEBUG(D_ERR, "i2c error gain");
681}
682
683static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684{
685 struct sd *sd = (struct sd *) gspca_dev;
686 __u8 gain;
687 __u8 rgb_value;
688
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300689 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300690
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 /* red and blue gain */
692 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300693 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 /* green gain */
695 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300696 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300697
Hans de Goedef45f06b2008-09-03 17:12:21 -0300698 if (sensor_data[sd->sensor].flags & F_GAIN)
Hans de Goededcef3232008-07-10 10:40:53 -0300699 setsensorgain(gspca_dev);
700}
701
702static void setexposure(struct gspca_dev *gspca_dev)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300705
706 switch (sd->sensor) {
707 case SENSOR_TAS5110: {
708 __u8 reg;
709
710 /* register 19's high nibble contains the sn9c10x clock divider
711 The high nibble configures the no fps according to the
712 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300713 reg = 120 * sd->exposure / 1000;
714 if (reg < 2)
715 reg = 2;
716 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300717 reg = 15;
718 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300719 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300720 break;
721 }
Hans de Goedea975a522008-07-16 15:29:11 -0300722 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300723 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300724 /* The ov6650 / ov7630 have 2 registers which both influence
725 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300726 according to: fps = 30 / (low_nibble + 1)
727
728 The fps configures the maximum exposure setting, but it is
729 possible to use less exposure then what the fps maximum
730 allows by setting register 10. register 10 configures the
731 actual exposure as quotient of the full exposure, with 0
732 being no exposure at all (not very usefull) and reg10_max
733 being max exposure possible at that framerate.
734
735 The code maps our 0 - 510 ms exposure ctrl to these 2
736 registers, trying to keep fps as high as possible.
737 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300738 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
739 int reg10, reg11, reg10_max;
740
Hans de Goede66f35822008-07-16 10:16:28 -0300741 /* ov6645 datasheet says reg10_max is 9a, but that uses
742 tline * 2 * reg10 as formula for calculating texpo, the
743 ov6650 probably uses the same formula as the 7730 which uses
744 tline * 4 * reg10, which explains why the reg10max we've
745 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300746 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300747 if (sd->sensor == SENSOR_OV6650) {
748 reg10_max = 0x4d;
749 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
750 } else
751 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300752
753 reg11 = (60 * sd->exposure + 999) / 1000;
754 if (reg11 < 1)
755 reg11 = 1;
756 else if (reg11 > 16)
757 reg11 = 16;
758
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300759 /* In 640x480, if the reg11 has less than 3, the image is
760 unstable (not enough bandwidth). */
761 if (gspca_dev->width == 640 && reg11 < 3)
762 reg11 = 3;
763
Hans de Goedef4d52022008-07-15 09:36:42 -0300764 /* frame exposure time in ms = 1000 * reg11 / 30 ->
765 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
766 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300767
768 /* Don't allow this to get below 10 when using autogain, the
769 steps become very large (relatively) when below 10 causing
770 the image to oscilate from much too dark, to much too bright
771 and back again. */
772 if (sd->autogain && reg10 < 10)
773 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300774 else if (reg10 > reg10_max)
775 reg10 = reg10_max;
776
777 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300778 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300779 i2c[3] = reg10;
780 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300781
782 /* If register 11 didn't change, don't change it */
783 if (sd->reg11 == reg11 )
784 i2c[0] = 0xa0;
785
786 if (i2c_w(gspca_dev, i2c) == 0)
787 sd->reg11 = reg11;
788 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300789 PDEBUG(D_ERR, "i2c error exposure");
790 break;
791 }
Hans de Goededcef3232008-07-10 10:40:53 -0300792 }
793}
794
Hans de Goede66f35822008-07-16 10:16:28 -0300795static void setfreq(struct gspca_dev *gspca_dev)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798
799 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300800 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300801 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300802 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300803 compensation, for the ov6650 this is identical to ov6630
804 0x2b register, see ov6630 datasheet.
805 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300806 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300807 switch (sd->freq) {
808 default:
809/* case 0: * no filter*/
810/* case 2: * 60 hz */
811 i2c[3] = 0;
812 break;
813 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300814 i2c[3] = (sd->sensor == SENSOR_OV6650)
815 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300816 break;
817 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300818 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300819 if (i2c_w(gspca_dev, i2c) < 0)
820 PDEBUG(D_ERR, "i2c error setfreq");
821 break;
822 }
823 }
824}
825
Hans de Goededcef3232008-07-10 10:40:53 -0300826static void do_autogain(struct gspca_dev *gspca_dev)
827{
Hans de Goede5017c7b2008-10-22 04:59:29 -0300828 int deadzone, desired_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -0300829 struct sd *sd = (struct sd *) gspca_dev;
830 int avg_lum = atomic_read(&sd->avg_lum);
831
832 if (avg_lum == -1)
833 return;
834
Hans de Goede5017c7b2008-10-22 04:59:29 -0300835 /* SIF / VGA sensors have a different autoexposure area and thus
836 different avg_lum values for the same picture brightness */
837 if (sensor_data[sd->sensor].flags & F_SIF) {
838 deadzone = 1000;
839 desired_avg_lum = 7000;
840 } else {
841 deadzone = 3000;
842 desired_avg_lum = 23000;
843 }
844
Hans de Goededcef3232008-07-10 10:40:53 -0300845 if (sd->autogain_ignore_frames > 0)
846 sd->autogain_ignore_frames--;
847 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
Hans de Goede5017c7b2008-10-22 04:59:29 -0300848 sd->brightness * desired_avg_lum / 127,
849 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -0300850 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -0300851 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300852 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300853 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854}
855
856/* this function is called at probe time */
857static int sd_config(struct gspca_dev *gspca_dev,
858 const struct usb_device_id *id)
859{
860 struct sd *sd = (struct sd *) gspca_dev;
861 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -0300862
863 reg_r(gspca_dev, 0x00);
864 if (gspca_dev->usb_buf[0] != 0x10)
865 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300867 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300868 sd->sensor = id->driver_info >> 8;
869 sd->bridge = id->driver_info & 0xff;
870 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300871
872 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300873 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300875 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876 } else {
877 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300878 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 }
Hans de Goededcef3232008-07-10 10:40:53 -0300880 sd->brightness = BRIGHTNESS_DEF;
881 sd->gain = GAIN_DEF;
882 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300883 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
884 sd->autogain = 0; /* Disable do_autogain callback */
885 else
886 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300887 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300888
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 return 0;
890}
891
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300892/* this function is called at probe and resume time */
893static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894{
Hans de Goede271315a2008-09-03 17:12:19 -0300895 const __u8 stop = 0x09; /* Disable stream turn of LED */
896
897 reg_w(gspca_dev, 0x01, &stop, 1);
898
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 return 0;
900}
901
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300903static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904{
905 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -0300906 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300907 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -0300909 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910
Hans de Goede93627732008-09-04 16:20:12 -0300911 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300912 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
913 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -0300914 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
915 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300916 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 switch (sd->sensor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 case SENSOR_PAS202:
Hans de Goede93627732008-09-04 16:20:12 -0300919 reg12_19[5] = mode ? 0x24 : 0x20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 break;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300921 case SENSOR_TAS5130CXX:
922 /* probably not mode specific at all most likely the upper
923 nibble of 0x19 is exposure (clock divider) just as with
924 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -0300925 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 break;
927 }
Hans de Goedec437d652008-09-03 17:12:22 -0300928 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -0300929 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
930 reg12_19[6] &= ~0x80;
931
932 /* Vga mode emulation on SIF sensor? */
933 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
934 reg12_19[0] += 16; /* 0x12: hstart adjust */
935 reg12_19[1] += 24; /* 0x13: vstart adjust */
936 reg12_19[3] = 320 / 16; /* 0x15: hsize */
937 reg12_19[4] = 240 / 16; /* 0x16: vsize */
938 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300939
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300941 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300943 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300945 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300946
947 /* Init the sensor */
948 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
949 sensor_data[sd->sensor].sensor_init_size);
950 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
951 i2c_w_vector(gspca_dev,
952 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
953 sensor_data[sd->sensor].sensor_bridge_init_size[
954 sd->bridge]);
955
Hans de Goede3647fea2008-07-15 05:36:30 -0300956 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -0300957 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -0300959 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300960 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -0300961 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300962 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -0300963 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964 /* reset 0x17 SensorClk enable inv Clk 0x60 */
965 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -0300966 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300967 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -0300968 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300970 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300971 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300972 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -0300974 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 msleep(20);
976
Hans de Goede6af492e2008-07-22 07:09:33 -0300977 sd->reg11 = -1;
978
Hans de Goededcef3232008-07-10 10:40:53 -0300979 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300981 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300982 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300983
Hans de Goede6af492e2008-07-22 07:09:33 -0300984 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300985 sd->autogain_ignore_frames = 0;
986 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300987 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988}
989
990static void sd_stopN(struct gspca_dev *gspca_dev)
991{
Hans de Goedef45f06b2008-09-03 17:12:21 -0300992 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993}
994
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995static void sd_pkt_scan(struct gspca_dev *gspca_dev,
996 struct gspca_frame *frame, /* target */
997 unsigned char *data, /* isoc packet */
998 int len) /* iso packet length */
999{
Hans de Goede0d2a7222008-07-03 08:15:22 -03001000 int i;
Hans de Goededcef3232008-07-10 10:40:53 -03001001 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedec437d652008-09-03 17:12:22 -03001002 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001003
Hans de Goedec36260ee2008-07-16 09:56:07 -03001004 /* frames start with:
1005 * ff ff 00 c4 c4 96 synchro
1006 * 00 (unknown)
1007 * xx (frame sequence / size / compression)
1008 * (xx) (idem - extra byte for sn9c103)
1009 * ll mm brightness sum inside auto exposure
1010 * ll mm brightness sum outside auto exposure
1011 * (xx xx xx xx xx) audio values for snc103
1012 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -03001014 for (i = 0; i < len - 6; i++) {
1015 if (data[0 + i] == 0xff
1016 && data[1 + i] == 0xff
1017 && data[2 + i] == 0x00
1018 && data[3 + i] == 0xc4
1019 && data[4 + i] == 0xc4
1020 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -03001021 int lum = -1;
1022 int pkt_type = LAST_PACKET;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001023 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1024 18 : 12;
Hans de Goede6af492e2008-07-22 07:09:33 -03001025
Hans de Goedef45f06b2008-09-03 17:12:21 -03001026 if (len - i < fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -03001027 PDEBUG(D_STREAM, "packet too short to"
1028 " get avg brightness");
Hans de Goedef45f06b2008-09-03 17:12:21 -03001029 } else if (sd->bridge == BRIDGE_103) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001030 lum = data[i + 9] +
1031 (data[i + 10] << 8);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001032 } else {
1033 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001034 }
Hans de Goedebf2a2202008-09-04 16:22:56 -03001035 /* When exposure changes midway a frame we
1036 get a lum of 0 in this case drop 2 frames
1037 as the frames directly after an exposure
1038 change have an unstable image. Sometimes lum
1039 *really* is 0 (cam used in low light with
1040 low exposure setting), so do not drop frames
1041 if the previous lum was 0 too. */
1042 if (lum == 0 && sd->prev_avg_lum != 0) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001043 lum = -1;
1044 sd->frames_to_drop = 2;
Hans de Goedebf2a2202008-09-04 16:22:56 -03001045 sd->prev_avg_lum = 0;
1046 } else
1047 sd->prev_avg_lum = lum;
Hans de Goede6af492e2008-07-22 07:09:33 -03001048 atomic_set(&sd->avg_lum, lum);
1049
1050 if (sd->frames_to_drop) {
1051 sd->frames_to_drop--;
1052 pkt_type = DISCARD_PACKET;
1053 }
1054
1055 frame = gspca_frame_add(gspca_dev, pkt_type,
1056 frame, data, 0);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001057 data += i + fr_h_sz;
1058 len -= i + fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059 gspca_frame_add(gspca_dev, FIRST_PACKET,
1060 frame, data, len);
1061 return;
1062 }
1063 }
1064 }
Hans de Goedec437d652008-09-03 17:12:22 -03001065
1066 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1067 /* In raw mode we sometimes get some garbage after the frame
1068 ignore this */
1069 int used = frame->data_end - frame->data;
1070 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1071
1072 if (used + len > size)
1073 len = size - used;
1074 }
1075
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001076 gspca_frame_add(gspca_dev, INTER_PACKET,
1077 frame, data, len);
1078}
1079
1080static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083
1084 sd->brightness = val;
1085 if (gspca_dev->streaming)
1086 setbrightness(gspca_dev);
1087 return 0;
1088}
1089
1090static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1091{
1092 struct sd *sd = (struct sd *) gspca_dev;
1093
1094 *val = sd->brightness;
1095 return 0;
1096}
1097
Hans de Goededcef3232008-07-10 10:40:53 -03001098static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101
Hans de Goededcef3232008-07-10 10:40:53 -03001102 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001103 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001104 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001105 return 0;
1106}
1107
Hans de Goededcef3232008-07-10 10:40:53 -03001108static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001109{
1110 struct sd *sd = (struct sd *) gspca_dev;
1111
Hans de Goededcef3232008-07-10 10:40:53 -03001112 *val = sd->gain;
1113 return 0;
1114}
1115
1116static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1117{
1118 struct sd *sd = (struct sd *) gspca_dev;
1119
1120 sd->exposure = val;
1121 if (gspca_dev->streaming)
1122 setexposure(gspca_dev);
1123 return 0;
1124}
1125
1126static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1127{
1128 struct sd *sd = (struct sd *) gspca_dev;
1129
1130 *val = sd->exposure;
1131 return 0;
1132}
1133
1134static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1135{
1136 struct sd *sd = (struct sd *) gspca_dev;
1137
1138 sd->autogain = val;
1139 /* when switching to autogain set defaults to make sure
1140 we are on a valid point of the autogain gain /
1141 exposure knee graph, and give this change time to
1142 take effect before doing autogain. */
1143 if (sd->autogain) {
1144 sd->exposure = EXPOSURE_DEF;
1145 sd->gain = GAIN_DEF;
1146 if (gspca_dev->streaming) {
1147 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1148 setexposure(gspca_dev);
1149 setgain(gspca_dev);
1150 }
1151 }
1152
1153 return 0;
1154}
1155
1156static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1157{
1158 struct sd *sd = (struct sd *) gspca_dev;
1159
1160 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161 return 0;
1162}
1163
Hans de Goede66f35822008-07-16 10:16:28 -03001164static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1165{
1166 struct sd *sd = (struct sd *) gspca_dev;
1167
1168 sd->freq = val;
1169 if (gspca_dev->streaming)
1170 setfreq(gspca_dev);
1171 return 0;
1172}
1173
1174static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1175{
1176 struct sd *sd = (struct sd *) gspca_dev;
1177
1178 *val = sd->freq;
1179 return 0;
1180}
1181
1182static int sd_querymenu(struct gspca_dev *gspca_dev,
1183 struct v4l2_querymenu *menu)
1184{
1185 switch (menu->id) {
1186 case V4L2_CID_POWER_LINE_FREQUENCY:
1187 switch (menu->index) {
1188 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1189 strcpy((char *) menu->name, "NoFliker");
1190 return 0;
1191 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1192 strcpy((char *) menu->name, "50 Hz");
1193 return 0;
1194 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1195 strcpy((char *) menu->name, "60 Hz");
1196 return 0;
1197 }
1198 break;
1199 }
1200 return -EINVAL;
1201}
1202
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001203/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001204static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 .name = MODULE_NAME,
1206 .ctrls = sd_ctrls,
1207 .nctrls = ARRAY_SIZE(sd_ctrls),
1208 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001209 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 .start = sd_start,
1211 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001213 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001214 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001215};
1216
1217/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001218#define SB(sensor, bridge) \
1219 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1220
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001221
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001222static __devinitdata struct usb_device_id device_table[] = {
Hans de Goedea94a5082008-09-04 16:22:55 -03001223 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
1224 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
Hans de Goede222a07f2008-09-03 17:12:20 -03001225#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedea94a5082008-09-04 16:22:55 -03001226 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001227 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1228 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001229#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001230 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001231#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001232 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1233 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1234 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1235 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1236 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001237#endif
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001238 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001239 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001240#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001241 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001242#endif
Hans de Goede4cce1652008-09-04 16:22:57 -03001243 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1244#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1245 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1246#endif
1247 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001248 {}
1249};
1250MODULE_DEVICE_TABLE(usb, device_table);
1251
1252/* -- device connect -- */
1253static int sd_probe(struct usb_interface *intf,
1254 const struct usb_device_id *id)
1255{
1256 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1257 THIS_MODULE);
1258}
1259
1260static struct usb_driver sd_driver = {
1261 .name = MODULE_NAME,
1262 .id_table = device_table,
1263 .probe = sd_probe,
1264 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001265#ifdef CONFIG_PM
1266 .suspend = gspca_suspend,
1267 .resume = gspca_resume,
1268#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001269};
1270
1271/* -- module insert / remove -- */
1272static int __init sd_mod_init(void)
1273{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001274 int ret;
1275 ret = usb_register(&sd_driver);
1276 if (ret < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001277 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001278 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001279 return 0;
1280}
1281static void __exit sd_mod_exit(void)
1282{
1283 usb_deregister(&sd_driver);
1284 PDEBUG(D_PROBE, "deregistered");
1285}
1286
1287module_init(sd_mod_init);
1288module_exit(sd_mod_exit);