blob: 151e1b625b0d6ad0f1a4abc144244552b75015b5 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -030035 atomic_t avg_lum;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 unsigned int exposure;
37
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 signed char ag_cnt;
44#define AG_CNT_START 13
45
46 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030047 unsigned char bridge;
48#define BRIDGE_SN9C102P 0
49#define BRIDGE_SN9C105 1
50#define BRIDGE_SN9C110 2
51#define BRIDGE_SN9C120 3
52#define BRIDGE_SN9C325 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_MI0360 1
56#define SENSOR_MO4000 2
Jean-Francois Moined2d16e92008-09-03 16:47:23 -030057#define SENSOR_OM6802 3
58#define SENSOR_OV7648 4
59#define SENSOR_OV7660 5
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030061};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72
73static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030074 {
75 {
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "Brightness",
79 .minimum = 0,
80 .maximum = 0xffff,
81 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030082#define BRIGHTNESS_DEF 0x7fff
83 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030084 },
85 .set = sd_setbrightness,
86 .get = sd_getbrightness,
87 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030088 {
89 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
94 .maximum = 127,
95 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030096#define CONTRAST_DEF 63
97 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 },
99 .set = sd_setcontrast,
100 .get = sd_getcontrast,
101 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300102 {
103 {
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Color",
107 .minimum = 0,
108 .maximum = 255,
109 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300110#define COLOR_DEF 127
111 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300112 },
113 .set = sd_setcolors,
114 .get = sd_getcolors,
115 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300116 {
117 {
118 .id = V4L2_CID_AUTOGAIN,
119 .type = V4L2_CTRL_TYPE_BOOLEAN,
120 .name = "Auto Gain",
121 .minimum = 0,
122 .maximum = 1,
123 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300124#define AUTOGAIN_DEF 1
125 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126 },
127 .set = sd_setautogain,
128 .get = sd_getautogain,
129 },
130};
131
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300132static struct v4l2_pix_format vga_mode[] = {
133 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .bytesperline = 160,
135 .sizeimage = 160 * 120 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
137 .priv = 2},
138 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .bytesperline = 320,
140 .sizeimage = 320 * 240 * 3 / 8 + 590,
141 .colorspace = V4L2_COLORSPACE_JPEG,
142 .priv = 1},
143 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 640,
145 .sizeimage = 640 * 480 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300148};
149
150/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300151static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300152/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
153 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
154/* reg8 reg9 rega regb regc regd rege regf */
155 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
156/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
157 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
158/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
159 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160};
161
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300162static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300163/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
164 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
165/* reg8 reg9 rega regb regc regd rege regf */
166 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
167/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
168 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
169/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
170 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171};
172
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300173static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300174/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
175 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
176/* reg8 reg9 rega regb regc regd rege regf */
177 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
179 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
180/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
181 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182};
183
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300184static const __u8 sn_om6802[] = {
185/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
186 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
187/* reg8 reg9 rega regb regc regd rege regf */
188 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
190 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
191/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
192 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
194 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
195 0xf7
196};
197
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300198static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300199/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
200 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
201/* reg8 reg9 rega regb regc regd rege regf */
202 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
203/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
204 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
205/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
206 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207};
208
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300209static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300210/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
211 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
212/* reg8 reg9 rega regb regc regd rege regf */
213 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
214/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
215 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
216/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
217 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300218};
219
220/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300221static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300222 sn_hv7131,
223 sn_mi0360,
224 sn_mo4000,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300225 sn_om6802,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300226 sn_ov7648,
227 sn_ov7660
228};
229
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300230static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300231 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
232 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
233};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300234static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
236 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
237};
238
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300239static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300240 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
241 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
242/* 0x00, 0x00, 0x00, 0x00, 0x00 */
243 0xf7, 0x0f, 0x0a, 0x00, 0x00
244};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300245static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
248 0xf8, 0x0f, 0x00, 0x00, 0x00
249};
250
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300251static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
253 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
254 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
255 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
258 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
259
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
262 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
263 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
264 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
267 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
268
269 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
270 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
272 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
274
275 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300280 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300282static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
287 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
288 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
305 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
306 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
308 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
310 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
312 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
315 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
316
317 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
318 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
319 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
321 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
322
323 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
324 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
325 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
326 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
327
328 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
329 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
330/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
331/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
332 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
333 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300334 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300335};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300336static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300357 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358};
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300359static __u8 om6802_sensor_init[][8] = {
360 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
361 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
362 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
363 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
364/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
365 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
366 /* white balance & auto-exposure */
367/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
368 * set color mode */
369/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
370 * max AGC value in AE */
371/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
372 * preset AGC */
373/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
374 * preset brightness */
375/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
376 * preset contrast */
377/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
378 * preset gamma */
379 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
380 /* luminance mode (0x4f = AE) */
381 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
382 /* preset shutter */
383/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
384 * auto frame rate */
385/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
386
387/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
388/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
389/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
390/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
391 {}
392};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300393static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300394 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300395/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300397 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300398 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300399 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300400 /* GAIN BLUE RED VREF */
401 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
402 /* COM 1 BAVE GEAVE AECHH */
403 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
404 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300405 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300406 /* AECH CLKRC COM7 COM8 */
407 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
408 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
409 /* HSTART HSTOP VSTRT VSTOP */
410 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
411 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
412 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
413 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300414/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
415 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300416 /* AEW AEB VPT BBIAS */
417 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
418 /* GbBIAS RSVD EXHCH EXHCL */
419 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
420 /* RBIAS ADVFL ASDVFH YAVE */
421 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
422 /* HSYST HSYEN HREF */
423 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
424 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
425 /* ADC ACOM OFON TSLB */
426 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
427 /* COM11 COM12 COM13 COM14 */
428 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
429 /* EDGE COM15 COM16 COM17 */
430 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
431 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
432 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
433 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
434 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
435 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
436 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
437 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
438 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
439 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
440 /* LCC1 LCC2 LCC3 LCC4 */
441 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300442 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300443 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300444 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
446 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
447 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
448 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
449 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
450 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
451 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
452 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
453 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300454 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300456 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 /* bits[3..0]reserved */
458 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
459 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
460 /* VREF vertical frame ctrl */
461 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300462 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
463 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
464 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
465 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
466/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467/****** (some exchanges in the win trace) ******/
468 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300469 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
470 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
471 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
472/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300474/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
477 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
478 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300479 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300481/* reg 0x04 reg 0x07 reg 0x10 */
482/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300483
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300484static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300485 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
486 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
487 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
488 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
489 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
492 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
493 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
494 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
495 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
496 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
497 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
498 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
499 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
500 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
501 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
502 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
503 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
504 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
505 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
506 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
507 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
508 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
509 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
510 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
511 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
512 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
513 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
514 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
515 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
516 * This is currently setting a
517 * blue tint, and some things more , i leave it here for future test if
518 * somene is having problems with color on this sensor
519 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
520 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
521 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
522 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
523 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
524 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
525 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
526 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
527 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
528 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
529 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
530 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
531 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
532 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
533 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
534 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
535 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
536/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300537 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538};
539
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300540static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
542 0x06, 0x08, 0x0A, 0x11,
543 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
544 0x19, 0x19, 0x17, 0x15,
545 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
546 0x21, 0x2E, 0x21, 0x23,
547 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
548 0x25, 0x29, 0x2C, 0x29,
549 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
550 0x17, 0x1B, 0x29, 0x29,
551 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
552 0x29, 0x29, 0x29, 0x29,
553 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
554 0x29, 0x29, 0x29, 0x29,
555 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
556 0x29, 0x29, 0x29, 0x29
557};
558
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300559/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
560static void reg_r(struct gspca_dev *gspca_dev,
561 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300563 usb_control_msg(gspca_dev->dev,
564 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 0,
566 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300568 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300569 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300570 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571}
572
Jean-Francois Moine60017612008-07-18 08:46:19 -0300573static void reg_w1(struct gspca_dev *gspca_dev,
574 __u16 value,
575 __u8 data)
576{
577 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
578 gspca_dev->usb_buf[0] = data;
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
581 0x08,
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
583 value,
584 0,
585 gspca_dev->usb_buf, 1,
586 500);
587}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300588static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300589 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300590 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591 int len)
592{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300593 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
594 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300595 if (len <= sizeof gspca_dev->usb_buf) {
596 memcpy(gspca_dev->usb_buf, buffer, len);
597 usb_control_msg(gspca_dev->dev,
598 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300599 0x08,
600 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
601 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300602 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300603 500);
604 } else {
605 __u8 *tmpbuf;
606
607 tmpbuf = kmalloc(len, GFP_KERNEL);
608 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300609 usb_control_msg(gspca_dev->dev,
610 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300611 0x08,
612 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
613 value, 0,
614 tmpbuf, len,
615 500);
616 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300617 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618}
619
Jean-Francois Moine60017612008-07-18 08:46:19 -0300620/* I2C write 1 byte */
621static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622{
623 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624
Jean-Francois Moine60017612008-07-18 08:46:19 -0300625 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
626 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
627 gspca_dev->usb_buf[1] = sd->i2c_base;
628 gspca_dev->usb_buf[2] = reg;
629 gspca_dev->usb_buf[3] = val;
630 gspca_dev->usb_buf[4] = 0;
631 gspca_dev->usb_buf[5] = 0;
632 gspca_dev->usb_buf[6] = 0;
633 gspca_dev->usb_buf[7] = 0x10;
634 usb_control_msg(gspca_dev->dev,
635 usb_sndctrlpipe(gspca_dev->dev, 0),
636 0x08,
637 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
638 0x08, /* value = i2c */
639 0,
640 gspca_dev->usb_buf, 8,
641 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300642}
643
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644/* I2C write 8 bytes */
645static void i2c_w8(struct gspca_dev *gspca_dev,
646 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300648 memcpy(gspca_dev->usb_buf, buffer, 8);
649 usb_control_msg(gspca_dev->dev,
650 usb_sndctrlpipe(gspca_dev->dev, 0),
651 0x08,
652 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
653 0x08, 0, /* value, index */
654 gspca_dev->usb_buf, 8,
655 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656}
657
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300658/* read 5 bytes in gspca_dev->usb_buf */
659static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660{
661 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 __u8 mode[8];
663
Hans de Goede3647fea2008-07-15 05:36:30 -0300664 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665 mode[1] = sd->i2c_base;
666 mode[2] = reg;
667 mode[3] = 0;
668 mode[4] = 0;
669 mode[5] = 0;
670 mode[6] = 0;
671 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300673 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300674 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300676 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300677 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300678 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679}
680
681static int probesensor(struct gspca_dev *gspca_dev)
682{
683 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684
Jean-Francois Moine60017612008-07-18 08:46:19 -0300685 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300687 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300688 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 i2c_r5(gspca_dev, 0); /* read sensor id */
690 if (gspca_dev->usb_buf[0] == 0x02
691 && gspca_dev->usb_buf[1] == 0x09
692 && gspca_dev->usb_buf[2] == 0x01
693 && gspca_dev->usb_buf[3] == 0x00
694 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
696 sd->sensor = SENSOR_HV7131R;
697 return SENSOR_HV7131R;
698 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300699 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
701 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
703 return -ENODEV;
704}
705
706static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300707 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708{
709 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300710 const __u8 *reg9a;
711 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300713 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300715 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716
Jean-Francois Moine60017612008-07-18 08:46:19 -0300717 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300718 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719
720 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300721 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
722 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300723 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300724 switch (sd->bridge) {
725 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726 reg9a = reg9a_sn9c325;
727 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728 default:
729 reg9a = reg9a_def;
730 break;
731 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300732 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300733
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300734 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300736 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300738 switch (sd->sensor) {
739 case SENSOR_OM6802:
740 reg_w1(gspca_dev, 0x02, 0x71);
741 reg_w1(gspca_dev, 0x01, 0x42);
742 reg_w1(gspca_dev, 0x17, 0x64);
743 reg_w1(gspca_dev, 0x01, 0x42);
744 break;
745 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300746 reg_w1(gspca_dev, 0x01, 0x43);
747 reg_w1(gspca_dev, 0x17, 0xae);
748 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 break;
750 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300751 reg_w1(gspca_dev, 0x01, 0x43);
752 reg_w1(gspca_dev, 0x17, 0x61);
753 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300754 if (sd->sensor == SENSOR_HV7131R) {
755 if (probesensor(gspca_dev) < 0)
756 return -ENODEV;
757 }
758 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 }
760 return 0;
761}
762
763static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
764{
765 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300766 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
768
769 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300770 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 i++;
772 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300773 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774}
775
776static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
777{
778 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
780 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300781 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 i++;
783 }
784}
785
786static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
787{
788 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789
790 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300791 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 i++;
793 }
794}
795
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300796static void om6802_InitSensor(struct gspca_dev *gspca_dev)
797{
798 int i = 0;
799
800 while (om6802_sensor_init[i][0]) {
801 i2c_w8(gspca_dev, om6802_sensor_init[i]);
802 i++;
803 }
804}
805
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
807{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808 int i = 0;
809
810 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300811 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812 i++;
813 }
814}
815
816static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
817{
818 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300819
Jean-Francois Moine60017612008-07-18 08:46:19 -0300820 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
821 i++;
822 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300823 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 i++;
826 }
827}
828
829/* this function is called at probe time */
830static int sd_config(struct gspca_dev *gspca_dev,
831 const struct usb_device_id *id)
832{
833 struct sd *sd = (struct sd *) gspca_dev;
834 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
836 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 cam->epaddr = 0x01;
838 cam->cam_mode = vga_mode;
839 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300840
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300841 sd->bridge = id->driver_info >> 16;
842 sd->sensor = id->driver_info >> 8;
843 sd->i2c_base = id->driver_info;
844
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300846 sd->brightness = BRIGHTNESS_DEF;
847 sd->contrast = CONTRAST_DEF;
848 sd->colors = COLOR_DEF;
849 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300850 sd->ag_cnt = -1;
851
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 return 0;
853}
854
855/* this function is called at open time */
856static int sd_open(struct gspca_dev *gspca_dev)
857{
858 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300859/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300861 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862
Hans de Goede3647fea2008-07-15 05:36:30 -0300863 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300864 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300865 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300866 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
867 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300868 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300869 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300870 switch (sd->bridge) {
871 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872 if (regF1 != 0x11)
873 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300874 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300876 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 if (regF1 != 0x11)
878 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300879 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300881 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882 if (regF1 != 0x12)
883 return -ENODEV;
884 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300885 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886 break;
887 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300888/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300889/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 if (regF1 != 0x12)
891 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300892 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 break;
894 }
895
Jean-Francois Moine60017612008-07-18 08:46:19 -0300896 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300897
898 return 0;
899}
900
901static unsigned int setexposure(struct gspca_dev *gspca_dev,
902 unsigned int expo)
903{
904 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300905 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300907 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300909 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
911
912 switch (sd->sensor) {
913 case SENSOR_HV7131R: {
914 __u8 Expodoit[] =
915 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
916
917 Expodoit[3] = expo >> 16;
918 Expodoit[4] = expo >> 8;
919 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300920 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 break;
922 }
923 case SENSOR_MI0360: {
924 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
925 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
926
927 if (expo > 0x0635)
928 expo = 0x0635;
929 else if (expo < 0x0001)
930 expo = 0x0001;
931 expoMi[3] = expo >> 8;
932 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300933 i2c_w8(gspca_dev, expoMi);
934 i2c_w8(gspca_dev, doit);
935 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 break;
937 }
938 case SENSOR_MO4000: {
939 __u8 expoMof[] =
940 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
941 __u8 expoMo10[] =
942 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
943
944 if (expo > 0x1fff)
945 expo = 0x1fff;
946 else if (expo < 0x0001)
947 expo = 0x0001;
948 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300949 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950 expoMo10[3] = ((expo & 0x1c00) >> 10)
951 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 i2c_w8(gspca_dev, expoMo10);
953 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300954 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 ((expoMo10[3] & 0x07) << 10)
956 | (expoMof[3] << 2)
957 | ((expoMo10[3] & 0x30) >> 4));
958 break;
959 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300960 case SENSOR_OM6802: {
961 __u8 gainOm[] =
962 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
963
964 if (expo > 0x03ff)
965 expo = 0x03ff;
966 if (expo < 0x0001)
967 expo = 0x0001;
968 gainOm[3] = expo >> 2;
969 i2c_w8(gspca_dev, gainOm);
970 reg_w1(gspca_dev, 0x96, expo >> 5);
971 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
972 break;
973 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300974 }
975 return expo;
976}
977
978static void setbrightness(struct gspca_dev *gspca_dev)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981 unsigned int expo;
982 __u8 k2;
983
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300984 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 switch (sd->sensor) {
986 case SENSOR_HV7131R:
987 expo = sd->brightness << 4;
988 if (expo > 0x002dc6c0)
989 expo = 0x002dc6c0;
990 else if (expo < 0x02a0)
991 expo = 0x02a0;
992 sd->exposure = setexposure(gspca_dev, expo);
993 break;
994 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 case SENSOR_MO4000:
996 expo = sd->brightness >> 4;
997 sd->exposure = setexposure(gspca_dev, expo);
998 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300999 case SENSOR_OM6802:
1000 expo = sd->brightness >> 6;
1001 sd->exposure = setexposure(gspca_dev, expo);
1002 k2 = sd->brightness >> 11;
1003 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004 }
1005
Jean-Francois Moine60017612008-07-18 08:46:19 -03001006 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007}
1008
1009static void setcontrast(struct gspca_dev *gspca_dev)
1010{
1011 struct sd *sd = (struct sd *) gspca_dev;
1012 __u8 k2;
1013 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1014
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 k2 = sd->contrast;
1016 contrast[2] = k2;
1017 contrast[0] = (k2 + 1) >> 1;
1018 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001019 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001020}
1021
1022static void setcolors(struct gspca_dev *gspca_dev)
1023{
1024 struct sd *sd = (struct sd *) gspca_dev;
1025 __u8 data;
1026 int colour;
1027
1028 colour = sd->colors - 128;
1029 if (colour > 0)
1030 data = (colour + 32) & 0x7f; /* blue */
1031 else
1032 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001033 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001034}
1035
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001036static void setautogain(struct gspca_dev *gspca_dev)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039
1040 switch (sd->sensor) {
1041 case SENSOR_HV7131R:
1042 case SENSOR_MO4000:
1043 case SENSOR_MI0360:
1044 if (sd->autogain)
1045 sd->ag_cnt = AG_CNT_START;
1046 else
1047 sd->ag_cnt = -1;
1048 break;
1049 }
1050}
1051
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001052/* -- start the camera -- */
1053static void sd_start(struct gspca_dev *gspca_dev)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001057 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001058 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001060 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1061 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001062 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1063 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1065
1066 sn9c1xx = sn_tb[(int) sd->sensor];
1067 configure_gpio(gspca_dev, sn9c1xx);
1068
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001069/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
Jean-Francois Moine60017612008-07-18 08:46:19 -03001070 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1071 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1072 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1073 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1074 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1075 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1076 reg_w1(gspca_dev, 0xd3, 0x50);
1077 reg_w1(gspca_dev, 0xc6, 0x00);
1078 reg_w1(gspca_dev, 0xc7, 0x00);
1079 reg_w1(gspca_dev, 0xc8, 0x50);
1080 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001081 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001082 switch (sd->bridge) {
1083 case BRIDGE_SN9C325:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001084 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001085 break;
1086 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001087 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001088 break;
1089 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001090 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001091 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1092 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1093 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1094 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001095 switch (sd->bridge) {
1096 case BRIDGE_SN9C325:
1097 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1098 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001099 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001100 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1101 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001102 reg_w1(gspca_dev, 0x9a, 0x0a);
1103 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001104 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001105 default:
1106 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001107 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001108 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001109 reg_w1(gspca_dev, 0x9a, 0x08);
1110 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001111 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 }
1113
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001114 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001115 if (mode)
1116 reg1 = 0x46; /* 320 clk 48Mhz */
1117 else
1118 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119 reg17 = 0x61;
1120 switch (sd->sensor) {
1121 case SENSOR_HV7131R:
1122 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001123 break;
1124 case SENSOR_MI0360:
1125 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001126 break;
1127 case SENSOR_MO4000:
1128 mo4000_InitSensor(gspca_dev);
1129 if (mode) {
1130/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1131 reg1 = 0x06; /* clk 24Mz */
1132 } else {
1133 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001134/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001135 }
1136 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001137 case SENSOR_OM6802:
1138 om6802_InitSensor(gspca_dev);
1139 reg1 = 0x46; /* 640 clk 24Mz */
1140 reg17 = 0x64; /* 640 MCKSIZE */
1141 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001143 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144 reg17 = 0xa2;
1145 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001146/* if (mode)
1147 ; * 320x2...
1148 else
1149 ; * 640x... */
1150 break;
1151 default:
1152/* case SENSOR_OV7660: */
1153 ov7660_InitSensor(gspca_dev);
1154 if (mode) {
1155/* reg17 = 0x21; * 320 */
1156/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001157/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001159 reg17 = 0x22; /* 640 MCKSIZE */
1160 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161 }
1162 break;
1163 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001164 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001165 reg_w(gspca_dev, 0xca, CA, 4);
Hans de Goede3647fea2008-07-15 05:36:30 -03001166 switch (sd->bridge) {
Hans de Goede3647fea2008-07-15 05:36:30 -03001167 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001168 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001169 break;
1170 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001171 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001172 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1173 break;
1174 }
1175
1176 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001177 reg18 = sn9c1xx[0x18] | (mode << 4);
1178 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001179
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001180 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1181 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001183 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184
Jean-Francois Moine60017612008-07-18 08:46:19 -03001185 reg_w1(gspca_dev, 0x17, reg17);
1186 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001187 setbrightness(gspca_dev);
1188 setcontrast(gspca_dev);
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001189 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001190}
1191
1192static void sd_stopN(struct gspca_dev *gspca_dev)
1193{
1194 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001195 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001196 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001197 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001198 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001200 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201
1202 data = 0x0b;
1203 switch (sd->sensor) {
1204 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001205 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001206 data = 0x2b;
1207 break;
1208 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001209 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 data = 0x29;
1211 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212 case SENSOR_OV7648:
1213 data = 0x29;
1214 break;
1215 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001216/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217/* case SENSOR_OV7660: */
1218 break;
1219 }
1220 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001221 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1222 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1223 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1224 reg_w1(gspca_dev, 0x01, data);
1225 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001226}
1227
1228static void sd_stop0(struct gspca_dev *gspca_dev)
1229{
1230}
1231
1232static void sd_close(struct gspca_dev *gspca_dev)
1233{
1234}
1235
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001236static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001237{
1238 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001239 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001240 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001241 __u8 luma_mean = 130;
1242 __u8 luma_delta = 20;
1243
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001244 /* Thanks S., without your advice, autobright should not work :) */
1245 if (sd->ag_cnt < 0)
1246 return;
1247 if (--sd->ag_cnt >= 0)
1248 return;
1249 sd->ag_cnt = AG_CNT_START;
1250
1251 delta = atomic_read(&sd->avg_lum);
1252 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 if (delta < luma_mean - luma_delta ||
1254 delta > luma_mean + luma_delta) {
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 expotimes = sd->exposure >> 8;
1258 expotimes += (luma_mean - delta) >> 4;
1259 if (expotimes < 0)
1260 expotimes = 0;
1261 sd->exposure = setexposure(gspca_dev,
1262 (unsigned int) (expotimes << 8));
1263 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001264 default:
1265/* case SENSOR_MO4000: */
1266/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001267/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001268 expotimes = sd->exposure;
1269 expotimes += (luma_mean - delta) >> 6;
1270 if (expotimes < 0)
1271 expotimes = 0;
1272 sd->exposure = setexposure(gspca_dev,
1273 (unsigned int) expotimes);
1274 setcolors(gspca_dev);
1275 break;
1276 }
1277 }
1278}
1279
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001280/* scan the URB packets */
1281/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001282static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1283 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001284 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 int len) /* iso packet length */
1286{
1287 struct sd *sd = (struct sd *) gspca_dev;
1288 int sof, avg_lum;
1289
1290 sof = len - 64;
1291 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1292
1293 /* end of frame */
1294 gspca_frame_add(gspca_dev, LAST_PACKET,
1295 frame, data, sof + 2);
1296 if (sd->ag_cnt < 0)
1297 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001298/* w1 w2 w3 */
1299/* w4 w5 w6 */
1300/* w7 w8 */
1301/* w4 */
1302 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1303/* w6 */
1304 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1305/* w2 */
1306 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1307/* w8 */
1308 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1309/* w5 */
1310 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1311 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001312 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001313 return;
1314 }
1315 if (gspca_dev->last_packet_type == LAST_PACKET) {
1316
1317 /* put the JPEG 422 header */
1318 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1319 }
1320 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1321}
1322
1323static unsigned int getexposure(struct gspca_dev *gspca_dev)
1324{
1325 struct sd *sd = (struct sd *) gspca_dev;
1326 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001327
1328 switch (sd->sensor) {
1329 case SENSOR_HV7131R:
1330 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001331 i2c_r5(gspca_dev, 0x25);
1332 return (gspca_dev->usb_buf[0] << 16)
1333 | (gspca_dev->usb_buf[1] << 8)
1334 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001335 case SENSOR_MI0360:
1336 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001337 i2c_r5(gspca_dev, 0x09);
1338 return (gspca_dev->usb_buf[0] << 8)
1339 | gspca_dev->usb_buf[1];
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001340 default:
1341/* case SENSOR_MO4000: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001342 i2c_r5(gspca_dev, 0x0e);
1343 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1344 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1345 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001346 PDEBUG(D_CONF, "exposure %d",
1347 (hexpo << 10) | (mexpo << 2) | lexpo);
1348 return (hexpo << 10) | (mexpo << 2) | lexpo;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001349#if 0
1350/*jfm: not called*/
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001351/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001352/* case SENSOR_OV7660: */
1353 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001354 i2c_r5(gspca_dev, 0x04);
1355 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1356 lexpo = gspca_dev->usb_buf[0] & 0x02;
1357 i2c_r5(gspca_dev, 0x08);
1358 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001359 return (hexpo << 10) | (mexpo << 2) | lexpo;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001360#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001361 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001362 /* not reached */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001363}
1364
1365static void getbrightness(struct gspca_dev *gspca_dev)
1366{
1367 struct sd *sd = (struct sd *) gspca_dev;
1368
1369 /* hardcoded registers seem not readable */
1370 switch (sd->sensor) {
1371 case SENSOR_HV7131R:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001372 sd->brightness = getexposure(gspca_dev) >> 4;
1373 break;
1374 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001375 case SENSOR_MO4000:
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001376 case SENSOR_OM6802:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001377 sd->brightness = getexposure(gspca_dev) << 4;
1378 break;
1379 }
1380}
1381
1382static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1383{
1384 struct sd *sd = (struct sd *) gspca_dev;
1385
1386 sd->brightness = val;
1387 if (gspca_dev->streaming)
1388 setbrightness(gspca_dev);
1389 return 0;
1390}
1391
1392static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1393{
1394 struct sd *sd = (struct sd *) gspca_dev;
1395
1396 getbrightness(gspca_dev);
1397 *val = sd->brightness;
1398 return 0;
1399}
1400
1401static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1402{
1403 struct sd *sd = (struct sd *) gspca_dev;
1404
1405 sd->contrast = val;
1406 if (gspca_dev->streaming)
1407 setcontrast(gspca_dev);
1408 return 0;
1409}
1410
1411static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1412{
1413 struct sd *sd = (struct sd *) gspca_dev;
1414
1415 *val = sd->contrast;
1416 return 0;
1417}
1418
1419static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1420{
1421 struct sd *sd = (struct sd *) gspca_dev;
1422
1423 sd->colors = val;
1424 if (gspca_dev->streaming)
1425 setcolors(gspca_dev);
1426 return 0;
1427}
1428
1429static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1430{
1431 struct sd *sd = (struct sd *) gspca_dev;
1432
1433 *val = sd->colors;
1434 return 0;
1435}
1436
1437static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1438{
1439 struct sd *sd = (struct sd *) gspca_dev;
1440
1441 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001442 if (gspca_dev->streaming)
1443 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001444 return 0;
1445}
1446
1447static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1448{
1449 struct sd *sd = (struct sd *) gspca_dev;
1450
1451 *val = sd->autogain;
1452 return 0;
1453}
1454
1455/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001456static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001457 .name = MODULE_NAME,
1458 .ctrls = sd_ctrls,
1459 .nctrls = ARRAY_SIZE(sd_ctrls),
1460 .config = sd_config,
1461 .open = sd_open,
1462 .start = sd_start,
1463 .stopN = sd_stopN,
1464 .stop0 = sd_stop0,
1465 .close = sd_close,
1466 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001467 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001468};
1469
1470/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001471#define BSI(bridge, sensor, i2c_addr) \
1472 .driver_info = (BRIDGE_ ## bridge << 16) \
1473 | (SENSOR_ ## sensor << 8) \
1474 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001475static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001476#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001477 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1478 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1479 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1480 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1481 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001482#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001483 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1484 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1485/* bw600.inf:
1486 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1487/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1488/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1489 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1490/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1491 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1492/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1493/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1494 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1495/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1496/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1497 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1498 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1499/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1500/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1501/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1502/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001503 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1504/*bw600.inf:*/
1505 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001506 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1507/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1508/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001509#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001510 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1511 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1512/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1513 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1514 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1515/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001516#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001517 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001518 {}
1519};
1520MODULE_DEVICE_TABLE(usb, device_table);
1521
1522/* -- device connect -- */
1523static int sd_probe(struct usb_interface *intf,
1524 const struct usb_device_id *id)
1525{
1526 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1527 THIS_MODULE);
1528}
1529
1530static struct usb_driver sd_driver = {
1531 .name = MODULE_NAME,
1532 .id_table = device_table,
1533 .probe = sd_probe,
1534 .disconnect = gspca_disconnect,
1535};
1536
1537/* -- module insert / remove -- */
1538static int __init sd_mod_init(void)
1539{
1540 if (usb_register(&sd_driver) < 0)
1541 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001542 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001543 return 0;
1544}
1545static void __exit sd_mod_exit(void)
1546{
1547 usb_deregister(&sd_driver);
1548 info("deregistered");
1549}
1550
1551module_init(sd_mod_init);
1552module_exit(sd_mod_exit);