blob: 28843a6a6fea0d7ee78185a2738097059242fbed [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
Hans de Goede93627732008-09-04 16:20:12 -030023/* Some documentation on known sonixb registers:
24
25Reg Use
260x10 high nibble red gain low nibble blue gain
270x11 low nibble green gain
280x12 hstart
290x13 vstart
300x15 hsize (hsize = register-value * 16)
310x16 vsize (vsize = register-value * 16)
320x17 bit 0 toggle compression quality (according to sn9c102 driver)
330x18 bit 7 enables compression, bit 4-5 set image down scaling:
34 00 scale 1, 01 scale 1/2, 10, scale 1/4
350x19 high-nibble is sensor clock divider, changes exposure on sensors which
36 use a clock generated by the bridge. Some sensors have their own clock.
370x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
380x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
390x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
400x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
41*/
42
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043#define MODULE_NAME "sonixb"
44
Hans de Goedef65e93d2010-01-31 10:35:15 -030045#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030046#include "gspca.h"
47
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030048MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
49MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
50MODULE_LICENSE("GPL");
51
52/* specific webcam descriptor */
53struct sd {
54 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030055 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030056 int prev_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -030057
Hans de Goedead5ef80d2008-07-14 10:11:42 -030058 unsigned char gain;
59 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030061 unsigned char autogain;
62 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030063 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030064 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030065
Hans de Goedef45f06b2008-09-03 17:12:21 -030066 __u8 bridge; /* Type of bridge */
67#define BRIDGE_101 0
68#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
69#define BRIDGE_103 1
70
71 __u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030072#define SENSOR_HV7131R 0
73#define SENSOR_OV6650 1
74#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030075#define SENSOR_PAS106 3
76#define SENSOR_PAS202 4
Hans de Goedeb10af3f2010-01-10 19:31:34 -030077#define SENSOR_TAS5110C 5
78#define SENSOR_TAS5110D 6
79#define SENSOR_TAS5130CXX 7
Hans de Goede6af492e2008-07-22 07:09:33 -030080 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081};
82
Hans de Goedef45f06b2008-09-03 17:12:21 -030083typedef const __u8 sensor_init_t[8];
84
85struct sensor_data {
86 const __u8 *bridge_init[2];
87 int bridge_init_size[2];
88 sensor_init_t *sensor_init;
89 int sensor_init_size;
90 sensor_init_t *sensor_bridge_init[2];
91 int sensor_bridge_init_size[2];
92 int flags;
93 unsigned ctrl_dis;
94 __u8 sensor_addr;
95};
96
97/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030098#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030099#define F_SIF 0x02 /* sif or vga */
Hans de Goedec437d652008-09-03 17:12:22 -0300100
101/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
102#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300103#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300104
105/* ctrl_dis helper macros */
106#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
107#define NO_FREQ (1 << FREQ_IDX)
108#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300109
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110#define COMP2 0x8f
111#define COMP 0xc7 /* 0x87 //0x07 */
112#define COMP1 0xc9 /* 0x89 //0x09 */
113
114#define MCK_INIT 0x63
115#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
116
117#define SYS_CLK 0x04
118
Hans de Goedef45f06b2008-09-03 17:12:21 -0300119#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
120 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
121{ \
122 .bridge_init = { bridge_1, bridge_3 }, \
123 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
124 .sensor_init = sensor, \
125 .sensor_init_size = sizeof(sensor), \
126 .sensor_bridge_init = { sensor_1, sensor_3,}, \
127 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
128 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
129}
130
Hans de Goededcef3232008-07-10 10:40:53 -0300131/* We calculate the autogain at the end of the transfer of a frame, at this
132 moment a frame with the old settings is being transmitted, and a frame is
133 being captured with the old settings. So if we adjust the autogain we must
134 ignore atleast the 2 next frames for the new settings to come into effect
135 before doing any other adjustments */
136#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goededcef3232008-07-10 10:40:53 -0300137
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300138/* V4L2 controls supported by the driver */
139static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
140static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300141static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
142static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
143static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
144static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
145static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
146static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300147static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
148static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300149
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300150static const struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300151#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152 {
153 {
154 .id = V4L2_CID_BRIGHTNESS,
155 .type = V4L2_CTRL_TYPE_INTEGER,
156 .name = "Brightness",
157 .minimum = 0,
158 .maximum = 255,
159 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300160#define BRIGHTNESS_DEF 127
161 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162 },
163 .set = sd_setbrightness,
164 .get = sd_getbrightness,
165 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300166#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167 {
168 {
Hans de Goededcef3232008-07-10 10:40:53 -0300169 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300171 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300173 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300174 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300175#define GAIN_DEF 127
176#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300177 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178 },
Hans de Goededcef3232008-07-10 10:40:53 -0300179 .set = sd_setgain,
180 .get = sd_getgain,
181 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300182#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300183 {
184 {
185 .id = V4L2_CID_EXPOSURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300188#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
189#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300190 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300191 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300192 .step = 1,
193 .default_value = EXPOSURE_DEF,
194 .flags = 0,
195 },
196 .set = sd_setexposure,
197 .get = sd_getexposure,
198 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300199#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300200 {
201 {
202 .id = V4L2_CID_AUTOGAIN,
203 .type = V4L2_CTRL_TYPE_BOOLEAN,
204 .name = "Automatic Gain (and Exposure)",
205 .minimum = 0,
206 .maximum = 1,
207 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300208#define AUTOGAIN_DEF 1
209 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300210 .flags = 0,
211 },
212 .set = sd_setautogain,
213 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300214 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300215#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300216 {
217 {
218 .id = V4L2_CID_POWER_LINE_FREQUENCY,
219 .type = V4L2_CTRL_TYPE_MENU,
220 .name = "Light frequency filter",
221 .minimum = 0,
222 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
223 .step = 1,
224#define FREQ_DEF 1
225 .default_value = FREQ_DEF,
226 },
227 .set = sd_setfreq,
228 .get = sd_getfreq,
229 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300230};
231
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300232static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300233 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
234 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300235 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300236 .colorspace = V4L2_COLORSPACE_SRGB,
237 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300238 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
239 .bytesperline = 160,
Hans de Goede5c515182008-09-03 17:12:22 -0300240 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300241 .colorspace = V4L2_COLORSPACE_SRGB,
242 .priv = 2},
243 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
244 .bytesperline = 320,
Hans de Goede5c515182008-09-03 17:12:22 -0300245 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300246 .colorspace = V4L2_COLORSPACE_SRGB,
247 .priv = 1},
248 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
249 .bytesperline = 640,
Hans de Goede5c515182008-09-03 17:12:22 -0300250 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300251 .colorspace = V4L2_COLORSPACE_SRGB,
252 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300253};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300254static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300255 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
256 .bytesperline = 160,
257 .sizeimage = 160 * 120,
258 .colorspace = V4L2_COLORSPACE_SRGB,
259 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
260 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
261 .bytesperline = 160,
262 .sizeimage = 160 * 120 * 5 / 4,
263 .colorspace = V4L2_COLORSPACE_SRGB,
264 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300265 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
266 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300267 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300268 .colorspace = V4L2_COLORSPACE_SRGB,
269 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300270 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
271 .bytesperline = 176,
Hans de Goede5c515182008-09-03 17:12:22 -0300272 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300273 .colorspace = V4L2_COLORSPACE_SRGB,
274 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300275 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
276 .bytesperline = 320,
277 .sizeimage = 320 * 240 * 5 / 4,
278 .colorspace = V4L2_COLORSPACE_SRGB,
279 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300280 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
281 .bytesperline = 352,
Hans de Goede5c515182008-09-03 17:12:22 -0300282 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300283 .colorspace = V4L2_COLORSPACE_SRGB,
284 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300285};
286
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300287static const __u8 initHv7131[] = {
288 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
289 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300290 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300291 0x28, 0x1e, 0x60, 0x8a, 0x20,
292 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
293};
294static const __u8 hv7131_sensor_init[][8] = {
295 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
296 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
297 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
298 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
299 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
300};
301static const __u8 initOv6650[] = {
302 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
303 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300304 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300305 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300306};
307static const __u8 ov6650_sensor_init[][8] =
308{
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200309 /* Bright, contrast, etc are set through SCBB interface.
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300310 * AVCAP on win2 do not send any data on this controls. */
311 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300312
313 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300314 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300315 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300316 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300317 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300318 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
319/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
320 * THIS SET GREEN SCREEN
321 * (pixels could be innverted in decode kind of "brg",
322 * but blue wont be there. Avoid this data ... */
323 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
324 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
325 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300326 /* Enable rgb brightness control */
327 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
328 /* HDG: Note windows uses the line below, which sets both register 0x60
329 and 0x61 I believe these registers of the ov6650 are identical as
330 those of the ov7630, because if this is true the windows settings
331 add a bit additional red gain and a lot additional blue gain, which
332 matches my findings that the windows settings make blue much too
333 blue and red a little too red.
334 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300335 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
337 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338};
Hans de Goededcef3232008-07-10 10:40:53 -0300339
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340static const __u8 initOv7630[] = {
341 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
342 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300343 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300345 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300346 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
347};
348static const __u8 initOv7630_3[] = {
349 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
350 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300351 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300352 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300353 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
354 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
355 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
356 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357};
Hans de Goede6af492e2008-07-22 07:09:33 -0300358static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300359 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
360 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
361/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300362 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
365 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
366 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
368 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
369 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300370 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
371/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
373 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
374 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
375 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
376 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
377 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
378};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379
Hans de Goedef45f06b2008-09-03 17:12:21 -0300380static const __u8 ov7630_sensor_init_3[][8] = {
381 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
382};
383
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384static const __u8 initPas106[] = {
385 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
386 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300387 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300388 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300389 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300390};
391/* compression 0x86 mckinit1 0x2b */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300392static const __u8 pas106_sensor_init[][8] = {
393 /* Pixel Clock Divider 6 */
394 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
395 /* Frame Time MSB (also seen as 0x12) */
396 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
397 /* Frame Time LSB (also seen as 0x05) */
398 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
399 /* Shutter Time Line Offset (also seen as 0x6d) */
400 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
401 /* Shutter Time Pixel Offset (also seen as 0xb1) */
402 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
403 /* Black Level Subtract Sign (also seen 0x00) */
404 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
405 /* Black Level Subtract Level (also seen 0x01) */
406 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
407 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
408 /* Color Gain B Pixel 5 a */
409 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
410 /* Color Gain G1 Pixel 1 5 */
411 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
412 /* Color Gain G2 Pixel 1 0 5 */
413 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
414 /* Color Gain R Pixel 3 1 */
415 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
416 /* Color GainH Pixel */
417 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
418 /* Global Gain */
419 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
420 /* Contrast */
421 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
422 /* H&V synchro polarity */
423 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
424 /* ?default */
425 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 /* DAC scale */
427 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
428 /* ?default */
429 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
430 /* Validate Settings */
431 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300433
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300434static const __u8 initPas202[] = {
435 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
436 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300437 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300438 0x28, 0x1e, 0x28, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
440};
441static const __u8 pas202_sensor_init[][8] = {
442 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
443 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
444 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
445 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
446 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
450 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
451 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
452 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
453 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
454
455 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
456 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
457 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
458 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
459 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
460 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
461 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
462 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
463};
464
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300465static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
467 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300468 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469 0x16, 0x12, 0x60, 0x86, 0x2b,
470 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
471};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300472/* Same as above, except a different hstart */
473static const __u8 initTas5110d[] = {
474 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
475 0x00, 0x00,
476 0x00, 0x01, 0x00, 0x41, 0x09, 0x0a,
477 0x16, 0x12, 0x60, 0x86, 0x2b,
478 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
479};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480static const __u8 tas5110_sensor_init[][8] = {
481 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
482 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
483 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
484};
485
486static const __u8 initTas5130[] = {
487 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
488 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300489 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300490 0x28, 0x1e, 0x60, COMP, MCK_INIT,
491 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
492};
493static const __u8 tas5130_sensor_init[][8] = {
494/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
495 * shutter 0x47 short exposure? */
496 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
497 /* shutter 0x01 long exposure */
498 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
499};
500
Hans Verkuild45b9b82008-09-04 03:33:43 -0300501static struct sensor_data sensor_data[] = {
Hans de Goedef45f06b2008-09-03 17:12:21 -0300502SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300503SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300504SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
505 F_GAIN, 0, 0x21),
506SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
507 0),
Hans de Goede93627732008-09-04 16:20:12 -0300508SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300509 NO_EXPO|NO_FREQ, 0),
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300510SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
511 NO_BRIGHTNESS|NO_FREQ, 0),
512SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300513 NO_BRIGHTNESS|NO_FREQ, 0),
514SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
515 0),
516};
517
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300518/* get one byte in gspca_dev->usb_buf */
519static void reg_r(struct gspca_dev *gspca_dev,
520 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300521{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300522 usb_control_msg(gspca_dev->dev,
523 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 0, /* request */
525 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
526 value,
527 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300528 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529 500);
530}
531
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532static void reg_w(struct gspca_dev *gspca_dev,
533 __u16 value,
534 const __u8 *buffer,
535 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300537#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300538 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300539 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
540 return;
541 }
542#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543 memcpy(gspca_dev->usb_buf, buffer, len);
544 usb_control_msg(gspca_dev->dev,
545 usb_sndctrlpipe(gspca_dev->dev, 0),
546 0x08, /* request */
547 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
548 value,
549 0, /* index */
550 gspca_dev->usb_buf, len,
551 500);
552}
553
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300554static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555{
556 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557
558 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300559 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300560 while (retry--) {
561 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300562 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300563 if (gspca_dev->usb_buf[0] & 0x04) {
564 if (gspca_dev->usb_buf[0] & 0x08)
565 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300567 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300568 }
569 return -1;
570}
571
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300573 const __u8 buffer[][8], int len)
574{
575 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577 len -= 8;
578 if (len <= 0)
579 break;
580 buffer++;
581 }
582}
583
584static void setbrightness(struct gspca_dev *gspca_dev)
585{
586 struct sd *sd = (struct sd *) gspca_dev;
587 __u8 value;
588
589 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300590 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591 case SENSOR_OV7630: {
592 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300593 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594
595 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300596 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300598 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300599 goto err;
600 break;
601 }
602 case SENSOR_PAS106: {
603 __u8 i2c1[] =
604 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
605
606 i2c1[3] = sd->brightness >> 3;
607 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300608 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300609 goto err;
610 i2c1[3] = 0x01;
611 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300612 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300613 goto err;
614 break;
615 }
616 case SENSOR_PAS202: {
617 /* __u8 i2cpexpo1[] =
618 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
619 __u8 i2cpexpo[] =
620 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
621 __u8 i2cp202[] =
622 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
623 static __u8 i2cpdoit[] =
624 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
625
626 /* change reg 0x10 */
627 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300630/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300632 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300634 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 goto err;
636 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300637 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300639 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 goto err;
641 break;
642 }
Hans de Goededcef3232008-07-10 10:40:53 -0300643 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 __u8 i2c[] =
645 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
646
647 value = 0xff - sd->brightness;
648 i2c[4] = value;
649 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300650 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 goto err;
652 break;
653 }
654 }
655 return;
656err:
657 PDEBUG(D_ERR, "i2c error brightness");
658}
Hans de Goededcef3232008-07-10 10:40:53 -0300659
660static void setsensorgain(struct gspca_dev *gspca_dev)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300663 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300664
665 switch (sd->sensor) {
666
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300667 case SENSOR_TAS5110C:
668 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300669 __u8 i2c[] =
670 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
671
Hans de Goedea975a522008-07-16 15:29:11 -0300672 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300673 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300674 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300675 break;
676 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300677
Hans de Goedea975a522008-07-16 15:29:11 -0300678 case SENSOR_OV6650:
679 gain >>= 1;
680 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300681 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300682 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300683
Hans de Goedef45f06b2008-09-03 17:12:21 -0300684 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300685 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300686 if (i2c_w(gspca_dev, i2c) < 0)
687 goto err;
688 break;
689 }
Hans de Goededcef3232008-07-10 10:40:53 -0300690 }
691 return;
692err:
693 PDEBUG(D_ERR, "i2c error gain");
694}
695
696static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697{
698 struct sd *sd = (struct sd *) gspca_dev;
699 __u8 gain;
700 __u8 rgb_value;
701
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300702 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300703
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704 /* red and blue gain */
705 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707 /* green gain */
708 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300710
Hans de Goedef45f06b2008-09-03 17:12:21 -0300711 if (sensor_data[sd->sensor].flags & F_GAIN)
Hans de Goededcef3232008-07-10 10:40:53 -0300712 setsensorgain(gspca_dev);
713}
714
715static void setexposure(struct gspca_dev *gspca_dev)
716{
717 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300718
719 switch (sd->sensor) {
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300720 case SENSOR_TAS5110C:
721 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300722 __u8 reg;
723
724 /* register 19's high nibble contains the sn9c10x clock divider
725 The high nibble configures the no fps according to the
726 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300727 reg = 120 * sd->exposure / 1000;
728 if (reg < 2)
729 reg = 2;
730 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300731 reg = 15;
732 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300733 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300734 break;
735 }
Hans de Goedea975a522008-07-16 15:29:11 -0300736 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300737 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300738 /* The ov6650 / ov7630 have 2 registers which both influence
739 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300740 according to: fps = 30 / (low_nibble + 1)
741
742 The fps configures the maximum exposure setting, but it is
743 possible to use less exposure then what the fps maximum
744 allows by setting register 10. register 10 configures the
745 actual exposure as quotient of the full exposure, with 0
746 being no exposure at all (not very usefull) and reg10_max
747 being max exposure possible at that framerate.
748
749 The code maps our 0 - 510 ms exposure ctrl to these 2
750 registers, trying to keep fps as high as possible.
751 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300752 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
753 int reg10, reg11, reg10_max;
754
Hans de Goede66f35822008-07-16 10:16:28 -0300755 /* ov6645 datasheet says reg10_max is 9a, but that uses
756 tline * 2 * reg10 as formula for calculating texpo, the
757 ov6650 probably uses the same formula as the 7730 which uses
758 tline * 4 * reg10, which explains why the reg10max we've
759 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300760 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300761 if (sd->sensor == SENSOR_OV6650) {
762 reg10_max = 0x4d;
763 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
764 } else
765 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300766
767 reg11 = (60 * sd->exposure + 999) / 1000;
768 if (reg11 < 1)
769 reg11 = 1;
770 else if (reg11 > 16)
771 reg11 = 16;
772
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300773 /* In 640x480, if the reg11 has less than 3, the image is
774 unstable (not enough bandwidth). */
775 if (gspca_dev->width == 640 && reg11 < 3)
776 reg11 = 3;
777
Hans de Goedef4d52022008-07-15 09:36:42 -0300778 /* frame exposure time in ms = 1000 * reg11 / 30 ->
779 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
780 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300781
782 /* Don't allow this to get below 10 when using autogain, the
783 steps become very large (relatively) when below 10 causing
784 the image to oscilate from much too dark, to much too bright
785 and back again. */
786 if (sd->autogain && reg10 < 10)
787 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300788 else if (reg10 > reg10_max)
789 reg10 = reg10_max;
790
791 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300792 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300793 i2c[3] = reg10;
794 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300795
796 /* If register 11 didn't change, don't change it */
797 if (sd->reg11 == reg11 )
798 i2c[0] = 0xa0;
799
800 if (i2c_w(gspca_dev, i2c) == 0)
801 sd->reg11 = reg11;
802 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300803 PDEBUG(D_ERR, "i2c error exposure");
804 break;
805 }
Hans de Goededcef3232008-07-10 10:40:53 -0300806 }
807}
808
Hans de Goede66f35822008-07-16 10:16:28 -0300809static void setfreq(struct gspca_dev *gspca_dev)
810{
811 struct sd *sd = (struct sd *) gspca_dev;
812
813 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300814 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300815 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300816 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300817 compensation, for the ov6650 this is identical to ov6630
818 0x2b register, see ov6630 datasheet.
819 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300820 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300821 switch (sd->freq) {
822 default:
823/* case 0: * no filter*/
824/* case 2: * 60 hz */
825 i2c[3] = 0;
826 break;
827 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300828 i2c[3] = (sd->sensor == SENSOR_OV6650)
829 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300830 break;
831 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300832 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300833 if (i2c_w(gspca_dev, i2c) < 0)
834 PDEBUG(D_ERR, "i2c error setfreq");
835 break;
836 }
837 }
838}
839
Hans de Goededcef3232008-07-10 10:40:53 -0300840static void do_autogain(struct gspca_dev *gspca_dev)
841{
Hans de Goede5017c7b2008-10-22 04:59:29 -0300842 int deadzone, desired_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -0300843 struct sd *sd = (struct sd *) gspca_dev;
844 int avg_lum = atomic_read(&sd->avg_lum);
845
846 if (avg_lum == -1)
847 return;
848
Hans de Goede5017c7b2008-10-22 04:59:29 -0300849 /* SIF / VGA sensors have a different autoexposure area and thus
850 different avg_lum values for the same picture brightness */
851 if (sensor_data[sd->sensor].flags & F_SIF) {
852 deadzone = 1000;
853 desired_avg_lum = 7000;
854 } else {
855 deadzone = 3000;
856 desired_avg_lum = 23000;
857 }
858
Hans de Goededcef3232008-07-10 10:40:53 -0300859 if (sd->autogain_ignore_frames > 0)
860 sd->autogain_ignore_frames--;
861 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
Hans de Goede5017c7b2008-10-22 04:59:29 -0300862 sd->brightness * desired_avg_lum / 127,
863 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -0300864 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -0300865 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300866 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300867 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868}
869
870/* this function is called at probe time */
871static int sd_config(struct gspca_dev *gspca_dev,
872 const struct usb_device_id *id)
873{
874 struct sd *sd = (struct sd *) gspca_dev;
875 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -0300876
877 reg_r(gspca_dev, 0x00);
878 if (gspca_dev->usb_buf[0] != 0x10)
879 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300881 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300882 sd->sensor = id->driver_info >> 8;
883 sd->bridge = id->driver_info & 0xff;
884 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885
886 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300887 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300889 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 } else {
891 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300892 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -0300894 cam->npkt = 36; /* 36 packets per ISOC message */
895
Hans de Goededcef3232008-07-10 10:40:53 -0300896 sd->brightness = BRIGHTNESS_DEF;
897 sd->gain = GAIN_DEF;
898 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300899 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
900 sd->autogain = 0; /* Disable do_autogain callback */
901 else
902 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300903 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300904
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 return 0;
906}
907
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300908/* this function is called at probe and resume time */
909static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910{
Hans de Goede271315a2008-09-03 17:12:19 -0300911 const __u8 stop = 0x09; /* Disable stream turn of LED */
912
913 reg_w(gspca_dev, 0x01, &stop, 1);
914
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 return 0;
916}
917
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300919static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920{
921 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -0300922 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300923 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -0300925 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926
Hans de Goede93627732008-09-04 16:20:12 -0300927 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300928 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
929 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -0300930 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
931 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300932 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 switch (sd->sensor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934 case SENSOR_PAS202:
Hans de Goede93627732008-09-04 16:20:12 -0300935 reg12_19[5] = mode ? 0x24 : 0x20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 break;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300937 case SENSOR_TAS5130CXX:
938 /* probably not mode specific at all most likely the upper
939 nibble of 0x19 is exposure (clock divider) just as with
940 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -0300941 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 break;
943 }
Hans de Goedec437d652008-09-03 17:12:22 -0300944 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -0300945 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
946 reg12_19[6] &= ~0x80;
947
948 /* Vga mode emulation on SIF sensor? */
949 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
950 reg12_19[0] += 16; /* 0x12: hstart adjust */
951 reg12_19[1] += 24; /* 0x13: vstart adjust */
952 reg12_19[3] = 320 / 16; /* 0x15: hsize */
953 reg12_19[4] = 240 / 16; /* 0x16: vsize */
954 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300955
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300957 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300959 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300961 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300962
963 /* Init the sensor */
964 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
965 sensor_data[sd->sensor].sensor_init_size);
966 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
967 i2c_w_vector(gspca_dev,
968 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
969 sensor_data[sd->sensor].sensor_bridge_init_size[
970 sd->bridge]);
971
Hans de Goede3647fea2008-07-15 05:36:30 -0300972 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -0300973 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300974 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -0300975 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300976 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -0300977 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300978 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -0300979 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980 /* reset 0x17 SensorClk enable inv Clk 0x60 */
981 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -0300982 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -0300984 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300986 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300988 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -0300990 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300991 msleep(20);
992
Hans de Goede6af492e2008-07-22 07:09:33 -0300993 sd->reg11 = -1;
994
Hans de Goededcef3232008-07-10 10:40:53 -0300995 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300997 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300998 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300999
Hans de Goede6af492e2008-07-22 07:09:33 -03001000 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001001 sd->autogain_ignore_frames = 0;
1002 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001003 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004}
1005
1006static void sd_stopN(struct gspca_dev *gspca_dev)
1007{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001008 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009}
1010
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001012 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 int len) /* iso packet length */
1014{
Hans de Goede0d2a7222008-07-03 08:15:22 -03001015 int i;
Hans de Goededcef3232008-07-10 10:40:53 -03001016 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedec437d652008-09-03 17:12:22 -03001017 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001018
Hans de Goedec36260ee2008-07-16 09:56:07 -03001019 /* frames start with:
1020 * ff ff 00 c4 c4 96 synchro
1021 * 00 (unknown)
1022 * xx (frame sequence / size / compression)
1023 * (xx) (idem - extra byte for sn9c103)
1024 * ll mm brightness sum inside auto exposure
1025 * ll mm brightness sum outside auto exposure
1026 * (xx xx xx xx xx) audio values for snc103
1027 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001028 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -03001029 for (i = 0; i < len - 6; i++) {
1030 if (data[0 + i] == 0xff
1031 && data[1 + i] == 0xff
1032 && data[2 + i] == 0x00
1033 && data[3 + i] == 0xc4
1034 && data[4 + i] == 0xc4
1035 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -03001036 int lum = -1;
1037 int pkt_type = LAST_PACKET;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001038 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1039 18 : 12;
Hans de Goede6af492e2008-07-22 07:09:33 -03001040
Hans de Goedef45f06b2008-09-03 17:12:21 -03001041 if (len - i < fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -03001042 PDEBUG(D_STREAM, "packet too short to"
1043 " get avg brightness");
Hans de Goedef45f06b2008-09-03 17:12:21 -03001044 } else if (sd->bridge == BRIDGE_103) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001045 lum = data[i + 9] +
1046 (data[i + 10] << 8);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001047 } else {
1048 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001049 }
Hans de Goedebf2a2202008-09-04 16:22:56 -03001050 /* When exposure changes midway a frame we
1051 get a lum of 0 in this case drop 2 frames
1052 as the frames directly after an exposure
1053 change have an unstable image. Sometimes lum
1054 *really* is 0 (cam used in low light with
1055 low exposure setting), so do not drop frames
1056 if the previous lum was 0 too. */
1057 if (lum == 0 && sd->prev_avg_lum != 0) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001058 lum = -1;
1059 sd->frames_to_drop = 2;
Hans de Goedebf2a2202008-09-04 16:22:56 -03001060 sd->prev_avg_lum = 0;
1061 } else
1062 sd->prev_avg_lum = lum;
Hans de Goede6af492e2008-07-22 07:09:33 -03001063 atomic_set(&sd->avg_lum, lum);
1064
1065 if (sd->frames_to_drop) {
1066 sd->frames_to_drop--;
1067 pkt_type = DISCARD_PACKET;
1068 }
1069
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001070 gspca_frame_add(gspca_dev, pkt_type,
1071 NULL, 0);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001072 data += i + fr_h_sz;
1073 len -= i + fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001074 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001075 data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001076 return;
1077 }
1078 }
1079 }
Hans de Goedec437d652008-09-03 17:12:22 -03001080
1081 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1082 /* In raw mode we sometimes get some garbage after the frame
1083 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001084 struct gspca_frame *frame;
1085 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001086 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1087
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001088 frame = gspca_get_i_frame(gspca_dev);
1089 if (frame == NULL) {
1090 gspca_dev->last_packet_type = DISCARD_PACKET;
1091 return;
1092 }
1093 used = frame->data_end - frame->data;
Hans de Goedec437d652008-09-03 17:12:22 -03001094 if (used + len > size)
1095 len = size - used;
1096 }
1097
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001098 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001099}
1100
1101static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1102{
1103 struct sd *sd = (struct sd *) gspca_dev;
1104
1105 sd->brightness = val;
1106 if (gspca_dev->streaming)
1107 setbrightness(gspca_dev);
1108 return 0;
1109}
1110
1111static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1112{
1113 struct sd *sd = (struct sd *) gspca_dev;
1114
1115 *val = sd->brightness;
1116 return 0;
1117}
1118
Hans de Goededcef3232008-07-10 10:40:53 -03001119static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001120{
1121 struct sd *sd = (struct sd *) gspca_dev;
1122
Hans de Goededcef3232008-07-10 10:40:53 -03001123 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001124 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001125 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001126 return 0;
1127}
1128
Hans de Goededcef3232008-07-10 10:40:53 -03001129static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132
Hans de Goededcef3232008-07-10 10:40:53 -03001133 *val = sd->gain;
1134 return 0;
1135}
1136
1137static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1138{
1139 struct sd *sd = (struct sd *) gspca_dev;
1140
1141 sd->exposure = val;
1142 if (gspca_dev->streaming)
1143 setexposure(gspca_dev);
1144 return 0;
1145}
1146
1147static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1148{
1149 struct sd *sd = (struct sd *) gspca_dev;
1150
1151 *val = sd->exposure;
1152 return 0;
1153}
1154
1155static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1156{
1157 struct sd *sd = (struct sd *) gspca_dev;
1158
1159 sd->autogain = val;
1160 /* when switching to autogain set defaults to make sure
1161 we are on a valid point of the autogain gain /
1162 exposure knee graph, and give this change time to
1163 take effect before doing autogain. */
1164 if (sd->autogain) {
1165 sd->exposure = EXPOSURE_DEF;
1166 sd->gain = GAIN_DEF;
1167 if (gspca_dev->streaming) {
1168 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1169 setexposure(gspca_dev);
1170 setgain(gspca_dev);
1171 }
1172 }
1173
1174 return 0;
1175}
1176
1177static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1178{
1179 struct sd *sd = (struct sd *) gspca_dev;
1180
1181 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 return 0;
1183}
1184
Hans de Goede66f35822008-07-16 10:16:28 -03001185static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1186{
1187 struct sd *sd = (struct sd *) gspca_dev;
1188
1189 sd->freq = val;
1190 if (gspca_dev->streaming)
1191 setfreq(gspca_dev);
1192 return 0;
1193}
1194
1195static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1196{
1197 struct sd *sd = (struct sd *) gspca_dev;
1198
1199 *val = sd->freq;
1200 return 0;
1201}
1202
1203static int sd_querymenu(struct gspca_dev *gspca_dev,
1204 struct v4l2_querymenu *menu)
1205{
1206 switch (menu->id) {
1207 case V4L2_CID_POWER_LINE_FREQUENCY:
1208 switch (menu->index) {
1209 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1210 strcpy((char *) menu->name, "NoFliker");
1211 return 0;
1212 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1213 strcpy((char *) menu->name, "50 Hz");
1214 return 0;
1215 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1216 strcpy((char *) menu->name, "60 Hz");
1217 return 0;
1218 }
1219 break;
1220 }
1221 return -EINVAL;
1222}
1223
Hans de Goedef65e93d2010-01-31 10:35:15 -03001224#ifdef CONFIG_INPUT
1225static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1226 u8 *data, /* interrupt packet data */
1227 int len) /* interrupt packet length */
1228{
1229 int ret = -EINVAL;
1230
1231 if (len == 1 && data[0] == 1) {
1232 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1233 input_sync(gspca_dev->input_dev);
1234 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1235 input_sync(gspca_dev->input_dev);
1236 ret = 0;
1237 }
1238
1239 return ret;
1240}
1241#endif
1242
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001243/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001244static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001245 .name = MODULE_NAME,
1246 .ctrls = sd_ctrls,
1247 .nctrls = ARRAY_SIZE(sd_ctrls),
1248 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001249 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001250 .start = sd_start,
1251 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001252 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001253 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001254 .dq_callback = do_autogain,
Hans de Goedef65e93d2010-01-31 10:35:15 -03001255#ifdef CONFIG_INPUT
1256 .int_pkt_scan = sd_int_pkt_scan,
1257#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001258};
1259
1260/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001261#define SB(sensor, bridge) \
1262 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1263
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001264
Márton Németh37b372e2009-12-10 11:31:09 -03001265static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001266 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1267 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goede222a07f2008-09-03 17:12:20 -03001268#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001269 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001270 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1271 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001272#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001273 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001274#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001275 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1276 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1277 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1278 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1279 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001280#endif
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001281 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001282 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001283#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001284 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001285#endif
Hans de Goede4cce1652008-09-04 16:22:57 -03001286 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1287#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1288 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1289#endif
1290 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001291 {}
1292};
1293MODULE_DEVICE_TABLE(usb, device_table);
1294
1295/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001296static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001297 const struct usb_device_id *id)
1298{
1299 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1300 THIS_MODULE);
1301}
1302
1303static struct usb_driver sd_driver = {
1304 .name = MODULE_NAME,
1305 .id_table = device_table,
1306 .probe = sd_probe,
1307 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001308#ifdef CONFIG_PM
1309 .suspend = gspca_suspend,
1310 .resume = gspca_resume,
1311#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001312};
1313
1314/* -- module insert / remove -- */
1315static int __init sd_mod_init(void)
1316{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001317 int ret;
1318 ret = usb_register(&sd_driver);
1319 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001320 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001321 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001322 return 0;
1323}
1324static void __exit sd_mod_exit(void)
1325{
1326 usb_deregister(&sd_driver);
1327 PDEBUG(D_PROBE, "deregistered");
1328}
1329
1330module_init(sd_mod_init);
1331module_exit(sd_mod_exit);