blob: 65452f3b194537bc7413dbb13d8bf0809c01f36b [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
35 int avg_lum;
36 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
57#define SENSOR_OV7648 3
58#define SENSOR_OV7660 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060};
61
62/* V4L2 controls supported by the driver */
63static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 0xffff,
80 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081#define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 127,
94 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095#define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 255,
108 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109#define COLOR_DEF 127
110 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 {
116 {
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300123#define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 },
126 .set = sd_setautogain,
127 .get = sd_getautogain,
128 },
129};
130
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300131static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 160,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 320,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 640,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147};
148
149/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300150static const __u8 sn_hv7131[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300152 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300153/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300154 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300156 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300159};
160
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300161static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300164/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300165 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300167 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170};
171
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300172static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300174 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175/* reg9 rega regb regc regd rege regf reg10 reg11*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300176 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300178 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300180 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
182 0xd3, 0xdf, 0xea, 0xf5
183};
184
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300185static const __u8 sn_ov7648[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300186 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
187 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
188 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
189};
190
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300191static const __u8 sn_ov7660[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
193 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
194/* reg9 rega regb regc regd rege regf reg10 reg11*/
195 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
196/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300197 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300198/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
200};
201
202/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300203static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 sn_hv7131,
205 sn_mi0360,
206 sn_mo4000,
207 sn_ov7648,
208 sn_ov7660
209};
210
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300211static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
213 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
214};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300215static const __u8 regsn20_sn9c120[] = {
216 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
217 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
218};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300219static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300220 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
221 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
222};
223
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300224static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300225 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
226 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
227/* 0x00, 0x00, 0x00, 0x00, 0x00 */
228 0xf7, 0x0f, 0x0a, 0x00, 0x00
229};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300230static const __u8 reg84_sn9c120_1[] = {
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x0c, 0x00, 0x00
234};
235static const __u8 reg84_sn9c120_2[] = {
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x0c, 0x02, 0x3b
239};
240static const __u8 reg84_sn9c120_3[] = {
241 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
242 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
243 0xf5, 0x0f, 0x0c, 0x02, 0x3b
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 Moinea5ae2062008-07-04 11:16:16 -0300359static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300361/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300363 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366 /* GAIN BLUE RED VREF */
367 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
368 /* COM 1 BAVE GEAVE AECHH */
369 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
370 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300371 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 /* AECH CLKRC COM7 COM8 */
373 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
374 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
375 /* HSTART HSTOP VSTRT VSTOP */
376 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
377 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
378 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
379 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300380/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
381 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 /* AEW AEB VPT BBIAS */
383 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
384 /* GbBIAS RSVD EXHCH EXHCL */
385 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
386 /* RBIAS ADVFL ASDVFH YAVE */
387 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
388 /* HSYST HSYEN HREF */
389 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
390 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
391 /* ADC ACOM OFON TSLB */
392 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
393 /* COM11 COM12 COM13 COM14 */
394 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
395 /* EDGE COM15 COM16 COM17 */
396 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
397 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
398 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
400 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
401 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
402 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
404 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
406 /* LCC1 LCC2 LCC3 LCC4 */
407 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300408 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300409 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300410 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
412 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
413 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
418 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
419 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300420 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300421/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300422 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300423 /* bits[3..0]reserved */
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
426 /* VREF vertical frame ctrl */
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300428 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
429 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
430 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
431 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
432/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433/****** (some exchanges in the win trace) ******/
434 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300435 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
436 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
437 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
438/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300440/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300441 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300445 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300446};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300447/* reg 0x04 reg 0x07 reg 0x10 */
448/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300449
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300450static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
452 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
453 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
454 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
455 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
456 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
457 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
458 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
459 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
460 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
461 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
462 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
464 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
465 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
466 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
467 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
468 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
469 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
470 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
471 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
472 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
473 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
474 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
475 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
476 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
477 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
478 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
479 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
480 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
481 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
482 * This is currently setting a
483 * blue tint, and some things more , i leave it here for future test if
484 * somene is having problems with color on this sensor
485 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
486 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
487 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
488 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
489 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
490 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
491 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
492 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
494 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
498 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
499 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
500 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
501 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
502/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300503 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504};
505
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300506static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
508 0x06, 0x08, 0x0A, 0x11,
509 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
510 0x19, 0x19, 0x17, 0x15,
511 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
512 0x21, 0x2E, 0x21, 0x23,
513 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
514 0x25, 0x29, 0x2C, 0x29,
515 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
516 0x17, 0x1B, 0x29, 0x29,
517 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
518 0x29, 0x29, 0x29, 0x29,
519 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
520 0x29, 0x29, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29
523};
524
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300525/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
526static void reg_r(struct gspca_dev *gspca_dev,
527 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300529 usb_control_msg(gspca_dev->dev,
530 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300531 0,
532 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
533 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300536 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537}
538
Jean-Francois Moine60017612008-07-18 08:46:19 -0300539static void reg_w1(struct gspca_dev *gspca_dev,
540 __u16 value,
541 __u8 data)
542{
543 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
544 gspca_dev->usb_buf[0] = data;
545 usb_control_msg(gspca_dev->dev,
546 usb_sndctrlpipe(gspca_dev->dev, 0),
547 0x08,
548 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
549 value,
550 0,
551 gspca_dev->usb_buf, 1,
552 500);
553}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300554static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300556 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 int len)
558{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300559 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
560 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300561 if (len <= sizeof gspca_dev->usb_buf) {
562 memcpy(gspca_dev->usb_buf, buffer, len);
563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300565 0x08,
566 USB_DIR_OUT | 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 Moinea5ae2062008-07-04 11:16:16 -0300569 500);
570 } else {
571 __u8 *tmpbuf;
572
573 tmpbuf = kmalloc(len, GFP_KERNEL);
574 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300575 usb_control_msg(gspca_dev->dev,
576 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300577 0x08,
578 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
579 value, 0,
580 tmpbuf, len,
581 500);
582 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300583 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584}
585
Jean-Francois Moine60017612008-07-18 08:46:19 -0300586/* I2C write 1 byte */
587static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588{
589 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590
Jean-Francois Moine60017612008-07-18 08:46:19 -0300591 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
592 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
593 gspca_dev->usb_buf[1] = sd->i2c_base;
594 gspca_dev->usb_buf[2] = reg;
595 gspca_dev->usb_buf[3] = val;
596 gspca_dev->usb_buf[4] = 0;
597 gspca_dev->usb_buf[5] = 0;
598 gspca_dev->usb_buf[6] = 0;
599 gspca_dev->usb_buf[7] = 0x10;
600 usb_control_msg(gspca_dev->dev,
601 usb_sndctrlpipe(gspca_dev->dev, 0),
602 0x08,
603 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
604 0x08, /* value = i2c */
605 0,
606 gspca_dev->usb_buf, 8,
607 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608}
609
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300610/* I2C write 8 bytes */
611static void i2c_w8(struct gspca_dev *gspca_dev,
612 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300613{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300614 memcpy(gspca_dev->usb_buf, buffer, 8);
615 usb_control_msg(gspca_dev->dev,
616 usb_sndctrlpipe(gspca_dev->dev, 0),
617 0x08,
618 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
619 0x08, 0, /* value, index */
620 gspca_dev->usb_buf, 8,
621 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622}
623
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300624/* read 5 bytes in gspca_dev->usb_buf */
625static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626{
627 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 __u8 mode[8];
629
Hans de Goede3647fea2008-07-15 05:36:30 -0300630 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 mode[1] = sd->i2c_base;
632 mode[2] = reg;
633 mode[3] = 0;
634 mode[4] = 0;
635 mode[5] = 0;
636 mode[6] = 0;
637 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300638 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300639 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300640 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300642 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300643 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645}
646
647static int probesensor(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650
Jean-Francois Moine60017612008-07-18 08:46:19 -0300651 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300653 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300655 i2c_r5(gspca_dev, 0); /* read sensor id */
656 if (gspca_dev->usb_buf[0] == 0x02
657 && gspca_dev->usb_buf[1] == 0x09
658 && gspca_dev->usb_buf[2] == 0x01
659 && gspca_dev->usb_buf[3] == 0x00
660 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300661 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
662 sd->sensor = SENSOR_HV7131R;
663 return SENSOR_HV7131R;
664 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300665 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300666 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
667 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
669 return -ENODEV;
670}
671
672static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300673 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300674{
675 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300676 const __u8 *reg9a;
677 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300679 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300681 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
683
Jean-Francois Moine60017612008-07-18 08:46:19 -0300684 reg_w1(gspca_dev, 0xf1, 0x00);
685 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686
687 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300688 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
689 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300690 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300691 switch (sd->bridge) {
692 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 reg9a = reg9a_sn9c325;
694 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300695 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696 reg9a = reg9a_sn9c120;
697 break;
698 default:
699 reg9a = reg9a_def;
700 break;
701 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300702 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703
Jean-Francois Moine60017612008-07-18 08:46:19 -0300704 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300705
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
Hans de Goede3647fea2008-07-15 05:36:30 -0300708 switch (sd->bridge) {
709 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300710 reg_w1(gspca_dev, 0x01, 0x61);
711 reg_w1(gspca_dev, 0x17, 0x20);
712 reg_w1(gspca_dev, 0x01, 0x60);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300714 case BRIDGE_SN9C325:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300715 reg_w1(gspca_dev, 0x01, 0x43);
716 reg_w1(gspca_dev, 0x17, 0xae);
717 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718 break;
719 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300720 reg_w1(gspca_dev, 0x01, 0x43);
721 reg_w1(gspca_dev, 0x17, 0x61);
722 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723 }
724
725 if (sd->sensor == SENSOR_HV7131R) {
726 if (probesensor(gspca_dev) < 0)
727 return -ENODEV;
728 }
729 return 0;
730}
731
732static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
733{
734 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300735 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
737
738 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740 i++;
741 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300742 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743}
744
745static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
746{
747 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748
749 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300750 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 i++;
752 }
753}
754
755static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
756{
757 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758
759 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761 i++;
762 }
763}
764
765static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
766{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767 int i = 0;
768
769 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300770 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 i++;
772 }
773}
774
775static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
776{
777 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778
Jean-Francois Moine60017612008-07-18 08:46:19 -0300779 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
780 i++;
781 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300783 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 i++;
785 }
786}
787
788/* this function is called at probe time */
789static int sd_config(struct gspca_dev *gspca_dev,
790 const struct usb_device_id *id)
791{
792 struct sd *sd = (struct sd *) gspca_dev;
793 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794
795 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300796 cam->epaddr = 0x01;
797 cam->cam_mode = vga_mode;
798 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300799
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300800 sd->bridge = id->driver_info >> 16;
801 sd->sensor = id->driver_info >> 8;
802 sd->i2c_base = id->driver_info;
803
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300805 sd->brightness = BRIGHTNESS_DEF;
806 sd->contrast = CONTRAST_DEF;
807 sd->colors = COLOR_DEF;
808 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809 return 0;
810}
811
812/* this function is called at open time */
813static int sd_open(struct gspca_dev *gspca_dev)
814{
815 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300816/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300818 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300819
Hans de Goede3647fea2008-07-15 05:36:30 -0300820 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300821 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300822 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300823 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300824 reg_r(gspca_dev, 0x00, 1);
825 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -0300826 switch (sd->bridge) {
827 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828 if (regF1 != 0x11)
829 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300830 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300832 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 if (regF1 != 0x11)
834 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300835 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300836 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300837 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 if (regF1 != 0x12)
839 return -ENODEV;
840 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300841 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 break;
843 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300844/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300845/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846 if (regF1 != 0x12)
847 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300848 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 break;
850 }
851
Jean-Francois Moine60017612008-07-18 08:46:19 -0300852 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853
854 return 0;
855}
856
857static unsigned int setexposure(struct gspca_dev *gspca_dev,
858 unsigned int expo)
859{
860 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300861 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300863 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300865 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
867
868 switch (sd->sensor) {
869 case SENSOR_HV7131R: {
870 __u8 Expodoit[] =
871 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
872
873 Expodoit[3] = expo >> 16;
874 Expodoit[4] = expo >> 8;
875 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300876 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 break;
878 }
879 case SENSOR_MI0360: {
880 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
881 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
882
883 if (expo > 0x0635)
884 expo = 0x0635;
885 else if (expo < 0x0001)
886 expo = 0x0001;
887 expoMi[3] = expo >> 8;
888 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300889 i2c_w8(gspca_dev, expoMi);
890 i2c_w8(gspca_dev, doit);
891 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300892 break;
893 }
894 case SENSOR_MO4000: {
895 __u8 expoMof[] =
896 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
897 __u8 expoMo10[] =
898 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
899
900 if (expo > 0x1fff)
901 expo = 0x1fff;
902 else if (expo < 0x0001)
903 expo = 0x0001;
904 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300905 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906 expoMo10[3] = ((expo & 0x1c00) >> 10)
907 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300908 i2c_w8(gspca_dev, expoMo10);
909 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300910 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911 ((expoMo10[3] & 0x07) << 10)
912 | (expoMof[3] << 2)
913 | ((expoMo10[3] & 0x30) >> 4));
914 break;
915 }
916 }
917 return expo;
918}
919
920static void setbrightness(struct gspca_dev *gspca_dev)
921{
922 struct sd *sd = (struct sd *) gspca_dev;
923 unsigned int expo;
924 __u8 k2;
925
926 switch (sd->sensor) {
927 case SENSOR_HV7131R:
928 expo = sd->brightness << 4;
929 if (expo > 0x002dc6c0)
930 expo = 0x002dc6c0;
931 else if (expo < 0x02a0)
932 expo = 0x02a0;
933 sd->exposure = setexposure(gspca_dev, expo);
934 break;
935 case SENSOR_MI0360:
936 expo = sd->brightness >> 4;
937 sd->exposure = setexposure(gspca_dev, expo);
938 break;
939 case SENSOR_MO4000:
940 expo = sd->brightness >> 4;
941 sd->exposure = setexposure(gspca_dev, expo);
942 break;
943 case SENSOR_OV7660:
944 return; /*jfm??*/
945 }
946
947 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300948 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300949}
950
951static void setcontrast(struct gspca_dev *gspca_dev)
952{
953 struct sd *sd = (struct sd *) gspca_dev;
954 __u8 k2;
955 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
956
957 if (sd->sensor == SENSOR_OV7660)
958 return; /*jfm??*/
959 k2 = sd->contrast;
960 contrast[2] = k2;
961 contrast[0] = (k2 + 1) >> 1;
962 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300963 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964}
965
966static void setcolors(struct gspca_dev *gspca_dev)
967{
968 struct sd *sd = (struct sd *) gspca_dev;
969 __u8 data;
970 int colour;
971
972 colour = sd->colors - 128;
973 if (colour > 0)
974 data = (colour + 32) & 0x7f; /* blue */
975 else
976 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300977 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978}
979
980/* -- start the camera -- */
981static void sd_start(struct gspca_dev *gspca_dev)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 int i;
985 __u8 data;
986 __u8 reg1;
987 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300988 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300990 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
991 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
992 static const __u8 CA_sn9c120[] =
993 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
994 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
995 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
997
998 sn9c1xx = sn_tb[(int) sd->sensor];
999 configure_gpio(gspca_dev, sn9c1xx);
1000
1001/*fixme:jfm this sequence should appear at end of sd_start */
1002/* with
Jean-Francois Moine60017612008-07-18 08:46:19 -03001003 reg_w1(gspca_dev, 0x01, 0x44); */
1004 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1005 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1006 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1007 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1008 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1009 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1010 reg_w1(gspca_dev, 0xd3, 0x50);
1011 reg_w1(gspca_dev, 0xc6, 0x00);
1012 reg_w1(gspca_dev, 0xc7, 0x00);
1013 reg_w1(gspca_dev, 0xc8, 0x50);
1014 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015/*fixme:jfm end of ending sequence */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001016 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001017 switch (sd->bridge) {
1018 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001020 break;
1021 case BRIDGE_SN9C120:
1022 data = 0xa0;
1023 break;
1024 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001026 break;
1027 }
Jean-Francois Moine60017612008-07-18 08:46:19 -03001028 reg_w1(gspca_dev, 0x17, data);
1029 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1030 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1031 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1032 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001033 switch (sd->bridge) {
1034 case BRIDGE_SN9C325:
1035 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1036 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001037 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001038 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1039 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001040 reg_w1(gspca_dev, 0x9a, 0x0a);
1041 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001042 break;
1043 case BRIDGE_SN9C120:
1044 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1045 sizeof regsn20_sn9c120);
1046 for (i = 0; i < 2; i++)
1047 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1048 sizeof reg84_sn9c120_1);
1049 for (i = 0; i < 6; i++)
1050 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1051 sizeof reg84_sn9c120_2);
1052 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1053 sizeof reg84_sn9c120_3);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001054 reg_w1(gspca_dev, 0x9a, 0x05);
1055 reg_w1(gspca_dev, 0x99, 0x5b);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001056 break;
1057 default:
1058 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001060 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001061 reg_w1(gspca_dev, 0x9a, 0x08);
1062 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001063 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064 }
1065
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001066 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001067 if (mode)
1068 reg1 = 0x46; /* 320 clk 48Mhz */
1069 else
1070 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071 reg17 = 0x61;
1072 switch (sd->sensor) {
1073 case SENSOR_HV7131R:
1074 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 break;
1076 case SENSOR_MI0360:
1077 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001078 break;
1079 case SENSOR_MO4000:
1080 mo4000_InitSensor(gspca_dev);
1081 if (mode) {
1082/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1083 reg1 = 0x06; /* clk 24Mz */
1084 } else {
1085 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001086/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001087 }
1088 break;
1089 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001090 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 reg17 = 0xa2;
1092 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001093/* if (mode)
1094 ; * 320x2...
1095 else
1096 ; * 640x... */
1097 break;
1098 default:
1099/* case SENSOR_OV7660: */
1100 ov7660_InitSensor(gspca_dev);
1101 if (mode) {
1102/* reg17 = 0x21; * 320 */
1103/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001104/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001105 } else {
1106 reg17 = 0xa2; /* 640 */
1107 reg1 = 0x40;
1108 }
1109 break;
1110 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001111 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001112 switch (sd->bridge) {
1113 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001114 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001115 break;
1116 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001117 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001118 break;
1119 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001120 switch (sd->bridge) {
1121 case BRIDGE_SN9C120: /*jfm ?? */
1122 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001123 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001124 break;
1125 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001126 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1128 break;
1129 }
1130
1131 /* here change size mode 0 -> VGA; 1 -> CIF */
1132 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001133 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001134
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001135 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1136 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001137
1138 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001139 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140
Jean-Francois Moine60017612008-07-18 08:46:19 -03001141 reg_w1(gspca_dev, 0x17, reg17);
1142 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143 setbrightness(gspca_dev);
1144 setcontrast(gspca_dev);
1145}
1146
1147static void sd_stopN(struct gspca_dev *gspca_dev)
1148{
1149 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001150 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001151 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001152 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001153 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001154 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001155 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001156
1157 data = 0x0b;
1158 switch (sd->sensor) {
1159 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001160 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161 data = 0x2b;
1162 break;
1163 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001164 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001165 data = 0x29;
1166 break;
1167 case SENSOR_MO4000:
1168 break;
1169 case SENSOR_OV7648:
1170 data = 0x29;
1171 break;
1172 default:
1173/* case SENSOR_OV7660: */
1174 break;
1175 }
1176 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001177 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1178 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1179 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1180 reg_w1(gspca_dev, 0x01, data);
1181 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182}
1183
1184static void sd_stop0(struct gspca_dev *gspca_dev)
1185{
1186}
1187
1188static void sd_close(struct gspca_dev *gspca_dev)
1189{
1190}
1191
1192static void setautogain(struct gspca_dev *gspca_dev)
1193{
1194 struct sd *sd = (struct sd *) gspca_dev;
1195 /* Thanks S., without your advice, autobright should not work :) */
1196 int delta;
1197 int expotimes = 0;
1198 __u8 luma_mean = 130;
1199 __u8 luma_delta = 20;
1200
1201 delta = sd->avg_lum;
1202 if (delta < luma_mean - luma_delta ||
1203 delta > luma_mean + luma_delta) {
1204 switch (sd->sensor) {
1205 case SENSOR_HV7131R:
1206 expotimes = sd->exposure >> 8;
1207 expotimes += (luma_mean - delta) >> 4;
1208 if (expotimes < 0)
1209 expotimes = 0;
1210 sd->exposure = setexposure(gspca_dev,
1211 (unsigned int) (expotimes << 8));
1212 break;
1213 case SENSOR_MO4000:
1214 case SENSOR_MI0360:
1215 expotimes = sd->exposure;
1216 expotimes += (luma_mean - delta) >> 6;
1217 if (expotimes < 0)
1218 expotimes = 0;
1219 sd->exposure = setexposure(gspca_dev,
1220 (unsigned int) expotimes);
1221 setcolors(gspca_dev);
1222 break;
1223 }
1224 }
1225}
1226
1227static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1228 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001229 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001230 int len) /* iso packet length */
1231{
1232 struct sd *sd = (struct sd *) gspca_dev;
1233 int sof, avg_lum;
1234
1235 sof = len - 64;
1236 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1237
1238 /* end of frame */
1239 gspca_frame_add(gspca_dev, LAST_PACKET,
1240 frame, data, sof + 2);
1241 if (sd->ag_cnt < 0)
1242 return;
1243 if (--sd->ag_cnt >= 0)
1244 return;
1245 sd->ag_cnt = AG_CNT_START;
1246/* w1 w2 w3 */
1247/* w4 w5 w6 */
1248/* w7 w8 */
1249/* w4 */
1250 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1251/* w6 */
1252 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1253/* w2 */
1254 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1255/* w8 */
1256 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1257/* w5 */
1258 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1259 avg_lum >>= 4;
1260 sd->avg_lum = avg_lum;
1261 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1262 setautogain(gspca_dev);
1263 return;
1264 }
1265 if (gspca_dev->last_packet_type == LAST_PACKET) {
1266
1267 /* put the JPEG 422 header */
1268 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1269 }
1270 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1271}
1272
1273static unsigned int getexposure(struct gspca_dev *gspca_dev)
1274{
1275 struct sd *sd = (struct sd *) gspca_dev;
1276 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001277
1278 switch (sd->sensor) {
1279 case SENSOR_HV7131R:
1280 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001281 i2c_r5(gspca_dev, 0x25);
1282 return (gspca_dev->usb_buf[0] << 16)
1283 | (gspca_dev->usb_buf[1] << 8)
1284 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 case SENSOR_MI0360:
1286 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001287 i2c_r5(gspca_dev, 0x09);
1288 return (gspca_dev->usb_buf[0] << 8)
1289 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001290 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 i2c_r5(gspca_dev, 0x0e);
1292 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1293 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1294 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001295 PDEBUG(D_CONF, "exposure %d",
1296 (hexpo << 10) | (mexpo << 2) | lexpo);
1297 return (hexpo << 10) | (mexpo << 2) | lexpo;
1298 default:
1299/* case SENSOR_OV7660: */
1300 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001301 i2c_r5(gspca_dev, 0x04);
1302 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1303 lexpo = gspca_dev->usb_buf[0] & 0x02;
1304 i2c_r5(gspca_dev, 0x08);
1305 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001306 return (hexpo << 10) | (mexpo << 2) | lexpo;
1307 }
1308}
1309
1310static void getbrightness(struct gspca_dev *gspca_dev)
1311{
1312 struct sd *sd = (struct sd *) gspca_dev;
1313
1314 /* hardcoded registers seem not readable */
1315 switch (sd->sensor) {
1316 case SENSOR_HV7131R:
1317/* sd->brightness = 0x7fff; */
1318 sd->brightness = getexposure(gspca_dev) >> 4;
1319 break;
1320 case SENSOR_MI0360:
1321 sd->brightness = getexposure(gspca_dev) << 4;
1322 break;
1323 case SENSOR_MO4000:
1324/* sd->brightness = 0x1fff; */
1325 sd->brightness = getexposure(gspca_dev) << 4;
1326 break;
1327 }
1328}
1329
1330static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 sd->brightness = val;
1335 if (gspca_dev->streaming)
1336 setbrightness(gspca_dev);
1337 return 0;
1338}
1339
1340static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343
1344 getbrightness(gspca_dev);
1345 *val = sd->brightness;
1346 return 0;
1347}
1348
1349static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1350{
1351 struct sd *sd = (struct sd *) gspca_dev;
1352
1353 sd->contrast = val;
1354 if (gspca_dev->streaming)
1355 setcontrast(gspca_dev);
1356 return 0;
1357}
1358
1359static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1360{
1361 struct sd *sd = (struct sd *) gspca_dev;
1362
1363 *val = sd->contrast;
1364 return 0;
1365}
1366
1367static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1368{
1369 struct sd *sd = (struct sd *) gspca_dev;
1370
1371 sd->colors = val;
1372 if (gspca_dev->streaming)
1373 setcolors(gspca_dev);
1374 return 0;
1375}
1376
1377static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1378{
1379 struct sd *sd = (struct sd *) gspca_dev;
1380
1381 *val = sd->colors;
1382 return 0;
1383}
1384
1385static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388
1389 sd->autogain = val;
1390 if (val)
1391 sd->ag_cnt = AG_CNT_START;
1392 else
1393 sd->ag_cnt = -1;
1394 return 0;
1395}
1396
1397static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400
1401 *val = sd->autogain;
1402 return 0;
1403}
1404
1405/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001406static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1411 .open = sd_open,
1412 .start = sd_start,
1413 .stopN = sd_stopN,
1414 .stop0 = sd_stop0,
1415 .close = sd_close,
1416 .pkt_scan = sd_pkt_scan,
1417};
1418
1419/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001420#define BSI(bridge, sensor, i2c_addr) \
1421 .driver_info = (BRIDGE_ ## bridge << 16) \
1422 | (SENSOR_ ## sensor << 8) \
1423 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001424static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001425#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001426 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1427 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1428 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1429 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1430 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001431#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001432 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1433 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1434/* bw600.inf:
1435 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1436/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1437/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1438 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1439/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1440 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1441/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1442/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1443 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1444/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1445/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1446 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1447 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1448/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1449/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1450/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1451/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1452 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1453/* bw600.inf:
1454 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1455 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1456/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1457/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001458#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001459 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1460 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1461/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1462 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1463 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1464/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001465#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001466 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001467 {}
1468};
1469MODULE_DEVICE_TABLE(usb, device_table);
1470
1471/* -- device connect -- */
1472static int sd_probe(struct usb_interface *intf,
1473 const struct usb_device_id *id)
1474{
1475 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1476 THIS_MODULE);
1477}
1478
1479static struct usb_driver sd_driver = {
1480 .name = MODULE_NAME,
1481 .id_table = device_table,
1482 .probe = sd_probe,
1483 .disconnect = gspca_disconnect,
1484};
1485
1486/* -- module insert / remove -- */
1487static int __init sd_mod_init(void)
1488{
1489 if (usb_register(&sd_driver) < 0)
1490 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001491 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001492 return 0;
1493}
1494static void __exit sd_mod_exit(void)
1495{
1496 usb_deregister(&sd_driver);
1497 info("deregistered");
1498}
1499
1500module_init(sd_mod_init);
1501module_exit(sd_mod_exit);