blob: 3f8418c7e5fd3235d9fd030ef72b361716ab225b [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},
363 /* Outformat ?? rawRGB */
364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
366/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367 /* GAIN BLUE RED VREF */
368 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
369 /* COM 1 BAVE GEAVE AECHH */
370 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
371 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300372 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
373/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374 /* AECH CLKRC COM7 COM8 */
375 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
376 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
377 /* HSTART HSTOP VSTRT VSTOP */
378 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
379 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
380 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
381 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300382 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
383/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384 /* AEW AEB VPT BBIAS */
385 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
386 /* GbBIAS RSVD EXHCH EXHCL */
387 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
388 /* RBIAS ADVFL ASDVFH YAVE */
389 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
390 /* HSYST HSYEN HREF */
391 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
392 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
393 /* ADC ACOM OFON TSLB */
394 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
395 /* COM11 COM12 COM13 COM14 */
396 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
397 /* EDGE COM15 COM16 COM17 */
398 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
400 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
402 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
403 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
404 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
406 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
408 /* LCC1 LCC2 LCC3 LCC4 */
409 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
410 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
411 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
412 /* band gap reference [0..3] DBLV */
413 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
420 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
421 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
422 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
423/****** (some exchanges in the win trace) ******/
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 /* bits[3..0]reserved */
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
428 /* VREF vertical frame ctrl */
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
431 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300433/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
434 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
435 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300436/****** (some exchanges in the win trace) ******/
437 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
438 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
439 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300441 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300442/****** (some exchanges in the win trace) ******/
443/**********startsensor KO if changed !!****/
444 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
448/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300449 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450};
451/* reg0x04 reg0x07 reg 0x10 */
452/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
453
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300454static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
456 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
459 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
460 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
461 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
462 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
464 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
465 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
466 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
467 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
468 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
469 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
471 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
472 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
473 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
474 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
475 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
476 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
477 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
478 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
479 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
480 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
481 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
482 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
483 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
484 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
486 * This is currently setting a
487 * blue tint, and some things more , i leave it here for future test if
488 * somene is having problems with color on this sensor
489 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
492 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
502 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
503 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
504 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
505 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
506/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300507 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508};
509
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300510static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
512 0x06, 0x08, 0x0A, 0x11,
513 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
514 0x19, 0x19, 0x17, 0x15,
515 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
516 0x21, 0x2E, 0x21, 0x23,
517 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
518 0x25, 0x29, 0x2C, 0x29,
519 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
520 0x17, 0x1B, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29
527};
528
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300529/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
530static void reg_r(struct gspca_dev *gspca_dev,
531 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300533 usb_control_msg(gspca_dev->dev,
534 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 0,
536 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
537 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300540 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541}
542
Jean-Francois Moine60017612008-07-18 08:46:19 -0300543static void reg_w1(struct gspca_dev *gspca_dev,
544 __u16 value,
545 __u8 data)
546{
547 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
548 gspca_dev->usb_buf[0] = data;
549 usb_control_msg(gspca_dev->dev,
550 usb_sndctrlpipe(gspca_dev->dev, 0),
551 0x08,
552 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
553 value,
554 0,
555 gspca_dev->usb_buf, 1,
556 500);
557}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300560 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 int len)
562{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300563 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
564 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300565 if (len <= sizeof gspca_dev->usb_buf) {
566 memcpy(gspca_dev->usb_buf, buffer, len);
567 usb_control_msg(gspca_dev->dev,
568 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569 0x08,
570 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
571 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300573 500);
574 } else {
575 __u8 *tmpbuf;
576
577 tmpbuf = kmalloc(len, GFP_KERNEL);
578 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300581 0x08,
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
583 value, 0,
584 tmpbuf, len,
585 500);
586 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300587 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588}
589
Jean-Francois Moine60017612008-07-18 08:46:19 -0300590/* I2C write 1 byte */
591static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300592{
593 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594
Jean-Francois Moine60017612008-07-18 08:46:19 -0300595 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
596 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
597 gspca_dev->usb_buf[1] = sd->i2c_base;
598 gspca_dev->usb_buf[2] = reg;
599 gspca_dev->usb_buf[3] = val;
600 gspca_dev->usb_buf[4] = 0;
601 gspca_dev->usb_buf[5] = 0;
602 gspca_dev->usb_buf[6] = 0;
603 gspca_dev->usb_buf[7] = 0x10;
604 usb_control_msg(gspca_dev->dev,
605 usb_sndctrlpipe(gspca_dev->dev, 0),
606 0x08,
607 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
608 0x08, /* value = i2c */
609 0,
610 gspca_dev->usb_buf, 8,
611 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612}
613
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300614/* I2C write 8 bytes */
615static void i2c_w8(struct gspca_dev *gspca_dev,
616 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300618 memcpy(gspca_dev->usb_buf, buffer, 8);
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
621 0x08,
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
623 0x08, 0, /* value, index */
624 gspca_dev->usb_buf, 8,
625 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626}
627
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628/* read 5 bytes in gspca_dev->usb_buf */
629static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630{
631 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 __u8 mode[8];
633
Hans de Goede3647fea2008-07-15 05:36:30 -0300634 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 mode[1] = sd->i2c_base;
636 mode[2] = reg;
637 mode[3] = 0;
638 mode[4] = 0;
639 mode[5] = 0;
640 mode[6] = 0;
641 mode[7] = 0x10;
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);
Hans de Goede3647fea2008-07-15 05:36:30 -0300644 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300646 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300647 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300648 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649}
650
651static int probesensor(struct gspca_dev *gspca_dev)
652{
653 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654
Jean-Francois Moine60017612008-07-18 08:46:19 -0300655 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300657 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300659 i2c_r5(gspca_dev, 0); /* read sensor id */
660 if (gspca_dev->usb_buf[0] == 0x02
661 && gspca_dev->usb_buf[1] == 0x09
662 && gspca_dev->usb_buf[2] == 0x01
663 && gspca_dev->usb_buf[3] == 0x00
664 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
666 sd->sensor = SENSOR_HV7131R;
667 return SENSOR_HV7131R;
668 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300669 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300670 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
671 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
673 return -ENODEV;
674}
675
676static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300677 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678{
679 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300680 const __u8 *reg9a;
681 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300683 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300685 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
687
Jean-Francois Moine60017612008-07-18 08:46:19 -0300688 reg_w1(gspca_dev, 0xf1, 0x00);
689 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690
691 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300692 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
693 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300694 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300695 switch (sd->bridge) {
696 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 reg9a = reg9a_sn9c325;
698 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300699 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700 reg9a = reg9a_sn9c120;
701 break;
702 default:
703 reg9a = reg9a_def;
704 break;
705 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
Jean-Francois Moine60017612008-07-18 08:46:19 -0300708 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300709
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300710 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711
Hans de Goede3647fea2008-07-15 05:36:30 -0300712 switch (sd->bridge) {
713 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300714 reg_w1(gspca_dev, 0x01, 0x61);
715 reg_w1(gspca_dev, 0x17, 0x20);
716 reg_w1(gspca_dev, 0x01, 0x60);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300718 case BRIDGE_SN9C325:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300719 reg_w1(gspca_dev, 0x01, 0x43);
720 reg_w1(gspca_dev, 0x17, 0xae);
721 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722 break;
723 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300724 reg_w1(gspca_dev, 0x01, 0x43);
725 reg_w1(gspca_dev, 0x17, 0x61);
726 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727 }
728
729 if (sd->sensor == SENSOR_HV7131R) {
730 if (probesensor(gspca_dev) < 0)
731 return -ENODEV;
732 }
733 return 0;
734}
735
736static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
737{
738 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300739 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
741
742 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300743 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744 i++;
745 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300746 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747}
748
749static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
750{
751 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752
753 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300754 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755 i++;
756 }
757}
758
759static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
760{
761 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762
763 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300764 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 i++;
766 }
767}
768
769static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
770{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 int i = 0;
772
773 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775 i++;
776 }
777}
778
779static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
780{
781 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782
Jean-Francois Moine60017612008-07-18 08:46:19 -0300783 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
784 i++;
785 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300787 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300788 i++;
789 }
790}
791
792/* this function is called at probe time */
793static int sd_config(struct gspca_dev *gspca_dev,
794 const struct usb_device_id *id)
795{
796 struct sd *sd = (struct sd *) gspca_dev;
797 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798 __u16 product;
799
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800 product = id->idProduct;
801 sd->sensor = -1;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300802 switch (id->idVendor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 case 0x0458: /* Genius */
804/* switch (product) {
805 case 0x7025: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300806 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808 sd->i2c_base = 0x5d;
809/* break;
810 } */
811 break;
812 case 0x045e:
813/* switch (product) {
814 case 0x00f5:
815 case 0x00f7: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300816 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 sd->i2c_base = 0x21;
819/* break;
820 } */
821 break;
822 case 0x0471: /* Philips */
823/* switch (product) {
824 case 0x0327:
825 case 0x0328:
826 case 0x0330: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300827 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 sd->i2c_base = 0x5d;
830/* break;
831 } */
832 break;
833 case 0x0c45: /* Sonix */
834 switch (product) {
835 case 0x6040:
Hans de Goede3647fea2008-07-15 05:36:30 -0300836 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300837/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
838/*fixme: MI0360 base=5d ? */
839 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 sd->i2c_base = 0x11;
841 break;
842/* case 0x607a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300843 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 sd->i2c_base = 0x??;
846 break; */
847 case 0x607c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300848 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 sd->i2c_base = 0x11;
851 break;
852/* case 0x607e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300853 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 sd->i2c_base = 0x??;
856 break; */
857 case 0x60c0:
Hans de Goede3647fea2008-07-15 05:36:30 -0300858 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860 sd->i2c_base = 0x5d;
861 break;
862/* case 0x60c8: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300863 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 sd->i2c_base = 0x??;
866 break; */
867/* case 0x60cc: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300868 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869 sd->sensor = SENSOR_HV7131GP;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870 sd->i2c_base = 0x??;
871 break; */
872 case 0x60ec:
Hans de Goede3647fea2008-07-15 05:36:30 -0300873 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875 sd->i2c_base = 0x21;
876 break;
877/* case 0x60ef: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300878 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880 sd->i2c_base = 0x??;
881 break; */
882/* case 0x60fa: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300883 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 sd->i2c_base = 0x??;
886 break; */
887 case 0x60fb:
Hans de Goede3647fea2008-07-15 05:36:30 -0300888 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 sd->i2c_base = 0x21;
891 break;
892 case 0x60fc:
Hans de Goede3647fea2008-07-15 05:36:30 -0300893 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300895 sd->i2c_base = 0x11;
896 break;
897/* case 0x60fe: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300898 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900 sd->i2c_base = 0x??;
901 break; */
902/* case 0x6108: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300903 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 sd->i2c_base = 0x??;
906 break; */
907/* case 0x6122: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300908 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 sd->i2c_base = 0x??;
911 break; */
912 case 0x612a:
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300913/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
Hans de Goede3647fea2008-07-15 05:36:30 -0300914 sd->bridge = BRIDGE_SN9C325;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 sd->i2c_base = 0x21;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300917/*fixme: sensor_init has base = 00 et 6e!*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 break;
919/* case 0x6123: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300920 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 sd->sensor = SENSOR_SanyoCCD;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 sd->i2c_base = 0x??;
923 break; */
924 case 0x612c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300925 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927 sd->i2c_base = 0x21;
928 break;
929/* case 0x612e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300930 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 sd->i2c_base = 0x??;
933 break; */
934/* case 0x612f: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300935 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 sd->i2c_base = 0x??;
938 break; */
939 case 0x6130:
Hans de Goede3647fea2008-07-15 05:36:30 -0300940 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 sd->i2c_base = 0x5d;
943 break;
944 case 0x6138:
Hans de Goede3647fea2008-07-15 05:36:30 -0300945 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300947 sd->i2c_base = 0x21;
948 break;
949/* case 0x613a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300950 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952 sd->i2c_base = 0x??;
953 break; */
954 case 0x613b:
Hans de Goede3647fea2008-07-15 05:36:30 -0300955 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957 sd->i2c_base = 0x21;
958 break;
959 case 0x613c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300960 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 sd->i2c_base = 0x11;
963 break;
964/* case 0x613e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300965 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300967 sd->i2c_base = 0x??;
968 break; */
969 }
970 break;
971 }
972 if (sd->sensor < 0) {
973 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
Jean-Francois Moine60017612008-07-18 08:46:19 -0300974 id->idVendor, product);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 return -EINVAL;
976 }
977
978 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979 cam->epaddr = 0x01;
980 cam->cam_mode = vga_mode;
981 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300982
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300984 sd->brightness = BRIGHTNESS_DEF;
985 sd->contrast = CONTRAST_DEF;
986 sd->colors = COLOR_DEF;
987 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988 return 0;
989}
990
991/* this function is called at open time */
992static int sd_open(struct gspca_dev *gspca_dev)
993{
994 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300995/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300997 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998
Hans de Goede3647fea2008-07-15 05:36:30 -0300999 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001000 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001001 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001002 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001003 reg_r(gspca_dev, 0x00, 1);
1004 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -03001005 switch (sd->bridge) {
1006 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007 if (regF1 != 0x11)
1008 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001009 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001010 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001011 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001012 if (regF1 != 0x11)
1013 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001014 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001016 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001017 if (regF1 != 0x12)
1018 return -ENODEV;
1019 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001020 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 break;
1022 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001023/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -03001024/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 if (regF1 != 0x12)
1026 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001027 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001028 break;
1029 }
1030
Jean-Francois Moine60017612008-07-18 08:46:19 -03001031 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032
1033 return 0;
1034}
1035
1036static unsigned int setexposure(struct gspca_dev *gspca_dev,
1037 unsigned int expo)
1038{
1039 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001040 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001041 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001042 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001043 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001044 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001045 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1046
1047 switch (sd->sensor) {
1048 case SENSOR_HV7131R: {
1049 __u8 Expodoit[] =
1050 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1051
1052 Expodoit[3] = expo >> 16;
1053 Expodoit[4] = expo >> 8;
1054 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001055 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 break;
1057 }
1058 case SENSOR_MI0360: {
1059 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1060 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1061
1062 if (expo > 0x0635)
1063 expo = 0x0635;
1064 else if (expo < 0x0001)
1065 expo = 0x0001;
1066 expoMi[3] = expo >> 8;
1067 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001068 i2c_w8(gspca_dev, expoMi);
1069 i2c_w8(gspca_dev, doit);
1070 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071 break;
1072 }
1073 case SENSOR_MO4000: {
1074 __u8 expoMof[] =
1075 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1076 __u8 expoMo10[] =
1077 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1078
1079 if (expo > 0x1fff)
1080 expo = 0x1fff;
1081 else if (expo < 0x0001)
1082 expo = 0x0001;
1083 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001084 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001085 expoMo10[3] = ((expo & 0x1c00) >> 10)
1086 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001087 i2c_w8(gspca_dev, expoMo10);
1088 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001089 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090 ((expoMo10[3] & 0x07) << 10)
1091 | (expoMof[3] << 2)
1092 | ((expoMo10[3] & 0x30) >> 4));
1093 break;
1094 }
1095 }
1096 return expo;
1097}
1098
1099static void setbrightness(struct gspca_dev *gspca_dev)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102 unsigned int expo;
1103 __u8 k2;
1104
1105 switch (sd->sensor) {
1106 case SENSOR_HV7131R:
1107 expo = sd->brightness << 4;
1108 if (expo > 0x002dc6c0)
1109 expo = 0x002dc6c0;
1110 else if (expo < 0x02a0)
1111 expo = 0x02a0;
1112 sd->exposure = setexposure(gspca_dev, expo);
1113 break;
1114 case SENSOR_MI0360:
1115 expo = sd->brightness >> 4;
1116 sd->exposure = setexposure(gspca_dev, expo);
1117 break;
1118 case SENSOR_MO4000:
1119 expo = sd->brightness >> 4;
1120 sd->exposure = setexposure(gspca_dev, expo);
1121 break;
1122 case SENSOR_OV7660:
1123 return; /*jfm??*/
1124 }
1125
1126 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001127 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001128}
1129
1130static void setcontrast(struct gspca_dev *gspca_dev)
1131{
1132 struct sd *sd = (struct sd *) gspca_dev;
1133 __u8 k2;
1134 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1135
1136 if (sd->sensor == SENSOR_OV7660)
1137 return; /*jfm??*/
1138 k2 = sd->contrast;
1139 contrast[2] = k2;
1140 contrast[0] = (k2 + 1) >> 1;
1141 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001142 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143}
1144
1145static void setcolors(struct gspca_dev *gspca_dev)
1146{
1147 struct sd *sd = (struct sd *) gspca_dev;
1148 __u8 data;
1149 int colour;
1150
1151 colour = sd->colors - 128;
1152 if (colour > 0)
1153 data = (colour + 32) & 0x7f; /* blue */
1154 else
1155 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001156 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001157}
1158
1159/* -- start the camera -- */
1160static void sd_start(struct gspca_dev *gspca_dev)
1161{
1162 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001163 int i;
1164 __u8 data;
1165 __u8 reg1;
1166 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001167 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001168 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001169 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1170 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1171 static const __u8 CA_sn9c120[] =
1172 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1173 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1174 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1176
1177 sn9c1xx = sn_tb[(int) sd->sensor];
1178 configure_gpio(gspca_dev, sn9c1xx);
1179
1180/*fixme:jfm this sequence should appear at end of sd_start */
1181/* with
Jean-Francois Moine60017612008-07-18 08:46:19 -03001182 reg_w1(gspca_dev, 0x01, 0x44); */
1183 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1184 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1185 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1186 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1187 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1188 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1189 reg_w1(gspca_dev, 0xd3, 0x50);
1190 reg_w1(gspca_dev, 0xc6, 0x00);
1191 reg_w1(gspca_dev, 0xc7, 0x00);
1192 reg_w1(gspca_dev, 0xc8, 0x50);
1193 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001194/*fixme:jfm end of ending sequence */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001195 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001196 switch (sd->bridge) {
1197 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001198 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001199 break;
1200 case BRIDGE_SN9C120:
1201 data = 0xa0;
1202 break;
1203 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001204 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001205 break;
1206 }
Jean-Francois Moine60017612008-07-18 08:46:19 -03001207 reg_w1(gspca_dev, 0x17, data);
1208 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1209 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1210 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1211 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001212 switch (sd->bridge) {
1213 case BRIDGE_SN9C325:
1214 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1215 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001216 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001217 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1218 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001219 reg_w1(gspca_dev, 0x9a, 0x0a);
1220 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001221 break;
1222 case BRIDGE_SN9C120:
1223 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1224 sizeof regsn20_sn9c120);
1225 for (i = 0; i < 2; i++)
1226 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1227 sizeof reg84_sn9c120_1);
1228 for (i = 0; i < 6; i++)
1229 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1230 sizeof reg84_sn9c120_2);
1231 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1232 sizeof reg84_sn9c120_3);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001233 reg_w1(gspca_dev, 0x9a, 0x05);
1234 reg_w1(gspca_dev, 0x99, 0x5b);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001235 break;
1236 default:
1237 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001239 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001240 reg_w1(gspca_dev, 0x9a, 0x08);
1241 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001242 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001243 }
1244
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001245 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001246 if (mode)
1247 reg1 = 0x46; /* 320 clk 48Mhz */
1248 else
1249 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001250 reg17 = 0x61;
1251 switch (sd->sensor) {
1252 case SENSOR_HV7131R:
1253 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001254 break;
1255 case SENSOR_MI0360:
1256 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001257 break;
1258 case SENSOR_MO4000:
1259 mo4000_InitSensor(gspca_dev);
1260 if (mode) {
1261/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1262 reg1 = 0x06; /* clk 24Mz */
1263 } else {
1264 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001265/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001266 }
1267 break;
1268 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001269 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001270 reg17 = 0xa2;
1271 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001272/* if (mode)
1273 ; * 320x2...
1274 else
1275 ; * 640x... */
1276 break;
1277 default:
1278/* case SENSOR_OV7660: */
1279 ov7660_InitSensor(gspca_dev);
1280 if (mode) {
1281/* reg17 = 0x21; * 320 */
1282/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001283/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001284 } else {
1285 reg17 = 0xa2; /* 640 */
1286 reg1 = 0x40;
1287 }
1288 break;
1289 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001290 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001291 switch (sd->bridge) {
1292 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001293 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001294 break;
1295 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001296 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001297 break;
1298 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001299 switch (sd->bridge) {
1300 case BRIDGE_SN9C120: /*jfm ?? */
1301 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001302 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001303 break;
1304 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001305 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001306 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1307 break;
1308 }
1309
1310 /* here change size mode 0 -> VGA; 1 -> CIF */
1311 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001312 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001313
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001314 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1315 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001316
1317 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001318 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001319
Jean-Francois Moine60017612008-07-18 08:46:19 -03001320 reg_w1(gspca_dev, 0x17, reg17);
1321 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001322 setbrightness(gspca_dev);
1323 setcontrast(gspca_dev);
1324}
1325
1326static void sd_stopN(struct gspca_dev *gspca_dev)
1327{
1328 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001329 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001330 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001331 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001332 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001333 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001334 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001335
1336 data = 0x0b;
1337 switch (sd->sensor) {
1338 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001339 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001340 data = 0x2b;
1341 break;
1342 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001343 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 data = 0x29;
1345 break;
1346 case SENSOR_MO4000:
1347 break;
1348 case SENSOR_OV7648:
1349 data = 0x29;
1350 break;
1351 default:
1352/* case SENSOR_OV7660: */
1353 break;
1354 }
1355 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001356 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1357 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1358 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1359 reg_w1(gspca_dev, 0x01, data);
1360 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001361}
1362
1363static void sd_stop0(struct gspca_dev *gspca_dev)
1364{
1365}
1366
1367static void sd_close(struct gspca_dev *gspca_dev)
1368{
1369}
1370
1371static void setautogain(struct gspca_dev *gspca_dev)
1372{
1373 struct sd *sd = (struct sd *) gspca_dev;
1374 /* Thanks S., without your advice, autobright should not work :) */
1375 int delta;
1376 int expotimes = 0;
1377 __u8 luma_mean = 130;
1378 __u8 luma_delta = 20;
1379
1380 delta = sd->avg_lum;
1381 if (delta < luma_mean - luma_delta ||
1382 delta > luma_mean + luma_delta) {
1383 switch (sd->sensor) {
1384 case SENSOR_HV7131R:
1385 expotimes = sd->exposure >> 8;
1386 expotimes += (luma_mean - delta) >> 4;
1387 if (expotimes < 0)
1388 expotimes = 0;
1389 sd->exposure = setexposure(gspca_dev,
1390 (unsigned int) (expotimes << 8));
1391 break;
1392 case SENSOR_MO4000:
1393 case SENSOR_MI0360:
1394 expotimes = sd->exposure;
1395 expotimes += (luma_mean - delta) >> 6;
1396 if (expotimes < 0)
1397 expotimes = 0;
1398 sd->exposure = setexposure(gspca_dev,
1399 (unsigned int) expotimes);
1400 setcolors(gspca_dev);
1401 break;
1402 }
1403 }
1404}
1405
1406static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1407 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001408 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001409 int len) /* iso packet length */
1410{
1411 struct sd *sd = (struct sd *) gspca_dev;
1412 int sof, avg_lum;
1413
1414 sof = len - 64;
1415 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1416
1417 /* end of frame */
1418 gspca_frame_add(gspca_dev, LAST_PACKET,
1419 frame, data, sof + 2);
1420 if (sd->ag_cnt < 0)
1421 return;
1422 if (--sd->ag_cnt >= 0)
1423 return;
1424 sd->ag_cnt = AG_CNT_START;
1425/* w1 w2 w3 */
1426/* w4 w5 w6 */
1427/* w7 w8 */
1428/* w4 */
1429 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1430/* w6 */
1431 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1432/* w2 */
1433 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1434/* w8 */
1435 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1436/* w5 */
1437 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1438 avg_lum >>= 4;
1439 sd->avg_lum = avg_lum;
1440 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1441 setautogain(gspca_dev);
1442 return;
1443 }
1444 if (gspca_dev->last_packet_type == LAST_PACKET) {
1445
1446 /* put the JPEG 422 header */
1447 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1448 }
1449 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1450}
1451
1452static unsigned int getexposure(struct gspca_dev *gspca_dev)
1453{
1454 struct sd *sd = (struct sd *) gspca_dev;
1455 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001456
1457 switch (sd->sensor) {
1458 case SENSOR_HV7131R:
1459 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001460 i2c_r5(gspca_dev, 0x25);
1461 return (gspca_dev->usb_buf[0] << 16)
1462 | (gspca_dev->usb_buf[1] << 8)
1463 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001464 case SENSOR_MI0360:
1465 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001466 i2c_r5(gspca_dev, 0x09);
1467 return (gspca_dev->usb_buf[0] << 8)
1468 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001469 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001470 i2c_r5(gspca_dev, 0x0e);
1471 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1472 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1473 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001474 PDEBUG(D_CONF, "exposure %d",
1475 (hexpo << 10) | (mexpo << 2) | lexpo);
1476 return (hexpo << 10) | (mexpo << 2) | lexpo;
1477 default:
1478/* case SENSOR_OV7660: */
1479 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001480 i2c_r5(gspca_dev, 0x04);
1481 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1482 lexpo = gspca_dev->usb_buf[0] & 0x02;
1483 i2c_r5(gspca_dev, 0x08);
1484 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001485 return (hexpo << 10) | (mexpo << 2) | lexpo;
1486 }
1487}
1488
1489static void getbrightness(struct gspca_dev *gspca_dev)
1490{
1491 struct sd *sd = (struct sd *) gspca_dev;
1492
1493 /* hardcoded registers seem not readable */
1494 switch (sd->sensor) {
1495 case SENSOR_HV7131R:
1496/* sd->brightness = 0x7fff; */
1497 sd->brightness = getexposure(gspca_dev) >> 4;
1498 break;
1499 case SENSOR_MI0360:
1500 sd->brightness = getexposure(gspca_dev) << 4;
1501 break;
1502 case SENSOR_MO4000:
1503/* sd->brightness = 0x1fff; */
1504 sd->brightness = getexposure(gspca_dev) << 4;
1505 break;
1506 }
1507}
1508
1509static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1510{
1511 struct sd *sd = (struct sd *) gspca_dev;
1512
1513 sd->brightness = val;
1514 if (gspca_dev->streaming)
1515 setbrightness(gspca_dev);
1516 return 0;
1517}
1518
1519static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1520{
1521 struct sd *sd = (struct sd *) gspca_dev;
1522
1523 getbrightness(gspca_dev);
1524 *val = sd->brightness;
1525 return 0;
1526}
1527
1528static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1529{
1530 struct sd *sd = (struct sd *) gspca_dev;
1531
1532 sd->contrast = val;
1533 if (gspca_dev->streaming)
1534 setcontrast(gspca_dev);
1535 return 0;
1536}
1537
1538static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1539{
1540 struct sd *sd = (struct sd *) gspca_dev;
1541
1542 *val = sd->contrast;
1543 return 0;
1544}
1545
1546static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1547{
1548 struct sd *sd = (struct sd *) gspca_dev;
1549
1550 sd->colors = val;
1551 if (gspca_dev->streaming)
1552 setcolors(gspca_dev);
1553 return 0;
1554}
1555
1556static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1557{
1558 struct sd *sd = (struct sd *) gspca_dev;
1559
1560 *val = sd->colors;
1561 return 0;
1562}
1563
1564static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1565{
1566 struct sd *sd = (struct sd *) gspca_dev;
1567
1568 sd->autogain = val;
1569 if (val)
1570 sd->ag_cnt = AG_CNT_START;
1571 else
1572 sd->ag_cnt = -1;
1573 return 0;
1574}
1575
1576static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1577{
1578 struct sd *sd = (struct sd *) gspca_dev;
1579
1580 *val = sd->autogain;
1581 return 0;
1582}
1583
1584/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001585static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001586 .name = MODULE_NAME,
1587 .ctrls = sd_ctrls,
1588 .nctrls = ARRAY_SIZE(sd_ctrls),
1589 .config = sd_config,
1590 .open = sd_open,
1591 .start = sd_start,
1592 .stopN = sd_stopN,
1593 .stop0 = sd_stop0,
1594 .close = sd_close,
1595 .pkt_scan = sd_pkt_scan,
1596};
1597
1598/* -- module initialisation -- */
1599#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001600static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001601#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001602 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1603 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1604 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1605 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1606 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001607#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001608 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1609 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1610 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1611 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1612 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1613 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1614 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1615 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1616 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001617#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001618 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1619 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1620 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1621 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001622#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001623 {}
1624};
1625MODULE_DEVICE_TABLE(usb, device_table);
1626
1627/* -- device connect -- */
1628static int sd_probe(struct usb_interface *intf,
1629 const struct usb_device_id *id)
1630{
1631 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1632 THIS_MODULE);
1633}
1634
1635static struct usb_driver sd_driver = {
1636 .name = MODULE_NAME,
1637 .id_table = device_table,
1638 .probe = sd_probe,
1639 .disconnect = gspca_disconnect,
1640};
1641
1642/* -- module insert / remove -- */
1643static int __init sd_mod_init(void)
1644{
1645 if (usb_register(&sd_driver) < 0)
1646 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001647 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001648 return 0;
1649}
1650static void __exit sd_mod_exit(void)
1651{
1652 usb_deregister(&sd_driver);
1653 info("deregistered");
1654}
1655
1656module_init(sd_mod_init);
1657module_exit(sd_mod_exit);