1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * sonix sn9c102 (bayer) library |
4 | * |
5 | * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr> |
6 | * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr |
7 | * Add Pas106 Stefano Mozzi (C) 2004 |
8 | */ |
9 | |
10 | /* Some documentation on known sonixb registers: |
11 | |
12 | Reg Use |
13 | sn9c101 / sn9c102: |
14 | 0x10 high nibble red gain low nibble blue gain |
15 | 0x11 low nibble green gain |
16 | sn9c103: |
17 | 0x05 red gain 0-127 |
18 | 0x06 blue gain 0-127 |
19 | 0x07 green gain 0-127 |
20 | all: |
21 | 0x08-0x0f i2c / 3wire registers |
22 | 0x12 hstart |
23 | 0x13 vstart |
24 | 0x15 hsize (hsize = register-value * 16) |
25 | 0x16 vsize (vsize = register-value * 16) |
26 | 0x17 bit 0 toggle compression quality (according to sn9c102 driver) |
27 | 0x18 bit 7 enables compression, bit 4-5 set image down scaling: |
28 | 00 scale 1, 01 scale 1/2, 10, scale 1/4 |
29 | 0x19 high-nibble is sensor clock divider, changes exposure on sensors which |
30 | use a clock generated by the bridge. Some sensors have their own clock. |
31 | 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) |
32 | 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) |
33 | 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) |
34 | 0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) |
35 | */ |
36 | |
37 | #define MODULE_NAME "sonixb" |
38 | |
39 | #include <linux/input.h> |
40 | #include "gspca.h" |
41 | |
42 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>" ); |
43 | MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver" ); |
44 | MODULE_LICENSE("GPL" ); |
45 | |
46 | /* specific webcam descriptor */ |
47 | struct sd { |
48 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
49 | |
50 | struct v4l2_ctrl *brightness; |
51 | struct v4l2_ctrl *plfreq; |
52 | |
53 | atomic_t avg_lum; |
54 | int prev_avg_lum; |
55 | int exposure_knee; |
56 | int ; |
57 | u8 [12]; /* Header without sof marker */ |
58 | |
59 | unsigned char autogain_ignore_frames; |
60 | unsigned char frames_to_drop; |
61 | |
62 | __u8 bridge; /* Type of bridge */ |
63 | #define BRIDGE_101 0 |
64 | #define BRIDGE_102 0 /* We make no difference between 101 and 102 */ |
65 | #define BRIDGE_103 1 |
66 | |
67 | __u8 sensor; /* Type of image sensor chip */ |
68 | #define SENSOR_HV7131D 0 |
69 | #define SENSOR_HV7131R 1 |
70 | #define SENSOR_OV6650 2 |
71 | #define SENSOR_OV7630 3 |
72 | #define SENSOR_PAS106 4 |
73 | #define SENSOR_PAS202 5 |
74 | #define SENSOR_TAS5110C 6 |
75 | #define SENSOR_TAS5110D 7 |
76 | #define SENSOR_TAS5130CXX 8 |
77 | __u8 reg11; |
78 | }; |
79 | |
80 | typedef const __u8 sensor_init_t[8]; |
81 | |
82 | struct sensor_data { |
83 | const __u8 *bridge_init; |
84 | sensor_init_t *sensor_init; |
85 | int sensor_init_size; |
86 | int flags; |
87 | __u8 sensor_addr; |
88 | }; |
89 | |
90 | /* sensor_data flags */ |
91 | #define F_SIF 0x01 /* sif or vga */ |
92 | |
93 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
94 | #define MODE_RAW 0x10 /* raw bayer mode */ |
95 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ |
96 | |
97 | #define COMP 0xc7 /* 0x87 //0x07 */ |
98 | #define COMP1 0xc9 /* 0x89 //0x09 */ |
99 | |
100 | #define MCK_INIT 0x63 |
101 | #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/ |
102 | |
103 | #define SYS_CLK 0x04 |
104 | |
105 | #define SENS(bridge, sensor, _flags, _sensor_addr) \ |
106 | { \ |
107 | .bridge_init = bridge, \ |
108 | .sensor_init = sensor, \ |
109 | .sensor_init_size = sizeof(sensor), \ |
110 | .flags = _flags, .sensor_addr = _sensor_addr \ |
111 | } |
112 | |
113 | /* We calculate the autogain at the end of the transfer of a frame, at this |
114 | moment a frame with the old settings is being captured and transmitted. So |
115 | if we adjust the gain or exposure we must ignore at least the next frame for |
116 | the new settings to come into effect before doing any other adjustments. */ |
117 | #define AUTOGAIN_IGNORE_FRAMES 1 |
118 | |
119 | static const struct v4l2_pix_format vga_mode[] = { |
120 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
121 | .bytesperline = 160, |
122 | .sizeimage = 160 * 120, |
123 | .colorspace = V4L2_COLORSPACE_SRGB, |
124 | .priv = 2 | MODE_RAW}, |
125 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
126 | .bytesperline = 160, |
127 | .sizeimage = 160 * 120 * 5 / 4, |
128 | .colorspace = V4L2_COLORSPACE_SRGB, |
129 | .priv = 2}, |
130 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
131 | .bytesperline = 320, |
132 | .sizeimage = 320 * 240 * 5 / 4, |
133 | .colorspace = V4L2_COLORSPACE_SRGB, |
134 | .priv = 1}, |
135 | {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
136 | .bytesperline = 640, |
137 | .sizeimage = 640 * 480 * 5 / 4, |
138 | .colorspace = V4L2_COLORSPACE_SRGB, |
139 | .priv = 0}, |
140 | }; |
141 | static const struct v4l2_pix_format sif_mode[] = { |
142 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
143 | .bytesperline = 160, |
144 | .sizeimage = 160 * 120, |
145 | .colorspace = V4L2_COLORSPACE_SRGB, |
146 | .priv = 1 | MODE_RAW | MODE_REDUCED_SIF}, |
147 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
148 | .bytesperline = 160, |
149 | .sizeimage = 160 * 120 * 5 / 4, |
150 | .colorspace = V4L2_COLORSPACE_SRGB, |
151 | .priv = 1 | MODE_REDUCED_SIF}, |
152 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
153 | .bytesperline = 176, |
154 | .sizeimage = 176 * 144, |
155 | .colorspace = V4L2_COLORSPACE_SRGB, |
156 | .priv = 1 | MODE_RAW}, |
157 | {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
158 | .bytesperline = 176, |
159 | .sizeimage = 176 * 144 * 5 / 4, |
160 | .colorspace = V4L2_COLORSPACE_SRGB, |
161 | .priv = 1}, |
162 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
163 | .bytesperline = 320, |
164 | .sizeimage = 320 * 240 * 5 / 4, |
165 | .colorspace = V4L2_COLORSPACE_SRGB, |
166 | .priv = 0 | MODE_REDUCED_SIF}, |
167 | {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
168 | .bytesperline = 352, |
169 | .sizeimage = 352 * 288 * 5 / 4, |
170 | .colorspace = V4L2_COLORSPACE_SRGB, |
171 | .priv = 0}, |
172 | }; |
173 | |
174 | static const __u8 initHv7131d[] = { |
175 | 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, |
176 | 0x00, 0x00, |
177 | 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, |
178 | 0x28, 0x1e, 0x60, 0x8e, 0x42, |
179 | }; |
180 | static const __u8 hv7131d_sensor_init[][8] = { |
181 | {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, |
182 | {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17}, |
183 | {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17}, |
184 | {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */ |
185 | {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */ |
186 | }; |
187 | |
188 | static const __u8 initHv7131r[] = { |
189 | 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, |
190 | 0x00, 0x00, |
191 | 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, |
192 | 0x28, 0x1e, 0x60, 0x8a, 0x20, |
193 | }; |
194 | static const __u8 hv7131r_sensor_init[][8] = { |
195 | {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, |
196 | {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, |
197 | {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, |
198 | {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16}, |
199 | {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15}, |
200 | }; |
201 | static const __u8 initOv6650[] = { |
202 | 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, |
203 | 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
204 | 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, |
205 | 0x10, |
206 | }; |
207 | static const __u8 ov6650_sensor_init[][8] = { |
208 | /* Bright, contrast, etc are set through SCBB interface. |
209 | * AVCAP on win2 do not send any data on this controls. */ |
210 | /* Anyway, some registers appears to alter bright and constrat */ |
211 | |
212 | /* Reset sensor */ |
213 | {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, |
214 | /* Set clock register 0x11 low nibble is clock divider */ |
215 | {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10}, |
216 | /* Next some unknown stuff */ |
217 | {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10}, |
218 | /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10}, |
219 | * THIS SET GREEN SCREEN |
220 | * (pixels could be innverted in decode kind of "brg", |
221 | * but blue wont be there. Avoid this data ... */ |
222 | {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ |
223 | {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, |
224 | {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10}, |
225 | /* Enable rgb brightness control */ |
226 | {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, |
227 | /* HDG: Note windows uses the line below, which sets both register 0x60 |
228 | and 0x61 I believe these registers of the ov6650 are identical as |
229 | those of the ov7630, because if this is true the windows settings |
230 | add a bit additional red gain and a lot additional blue gain, which |
231 | matches my findings that the windows settings make blue much too |
232 | blue and red a little too red. |
233 | {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */ |
234 | /* Some more unknown stuff */ |
235 | {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10}, |
236 | {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */ |
237 | }; |
238 | |
239 | static const __u8 initOv7630[] = { |
240 | 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */ |
241 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ |
242 | 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ |
243 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
244 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ |
245 | }; |
246 | static const __u8 ov7630_sensor_init[][8] = { |
247 | {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, |
248 | {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, |
249 | /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ |
250 | {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10}, /* jfm */ |
251 | {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10}, |
252 | {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10}, |
253 | {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10}, |
254 | {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10}, |
255 | {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10}, |
256 | {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10}, |
257 | {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10}, |
258 | {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, |
259 | /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */ |
260 | {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10}, |
261 | {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10}, |
262 | {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10}, |
263 | {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10}, |
264 | {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10}, |
265 | {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, |
266 | }; |
267 | |
268 | static const __u8 initPas106[] = { |
269 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, |
270 | 0x00, 0x00, |
271 | 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, |
272 | 0x16, 0x12, 0x24, COMP1, MCK_INIT1, |
273 | }; |
274 | /* compression 0x86 mckinit1 0x2b */ |
275 | |
276 | /* "Known" PAS106B registers: |
277 | 0x02 clock divider |
278 | 0x03 Variable framerate bits 4-11 |
279 | 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! |
280 | The variable framerate control must never be set lower then 300, |
281 | which sets the framerate at 90 / reg02, otherwise vsync is lost. |
282 | 0x05 Shutter Time Line Offset, this can be used as an exposure control: |
283 | 0 = use full frame time, 255 = no exposure at all |
284 | Note this may never be larger then "var-framerate control" / 2 - 2. |
285 | When var-framerate control is < 514, no exposure is reached at the max |
286 | allowed value for the framerate control value, rather then at 255. |
287 | 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but |
288 | only a very little bit, leave at 0xcd |
289 | 0x07 offset sign bit (bit0 1 > negative offset) |
290 | 0x08 offset |
291 | 0x09 Blue Gain |
292 | 0x0a Green1 Gain |
293 | 0x0b Green2 Gain |
294 | 0x0c Red Gain |
295 | 0x0e Global gain |
296 | 0x13 Write 1 to commit settings to sensor |
297 | */ |
298 | |
299 | static const __u8 pas106_sensor_init[][8] = { |
300 | /* Pixel Clock Divider 6 */ |
301 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
302 | /* Frame Time MSB (also seen as 0x12) */ |
303 | { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 }, |
304 | /* Frame Time LSB (also seen as 0x05) */ |
305 | { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
306 | /* Shutter Time Line Offset (also seen as 0x6d) */ |
307 | { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 }, |
308 | /* Shutter Time Pixel Offset (also seen as 0xb1) */ |
309 | { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 }, |
310 | /* Black Level Subtract Sign (also seen 0x00) */ |
311 | { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 }, |
312 | /* Black Level Subtract Level (also seen 0x01) */ |
313 | { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
314 | { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
315 | /* Color Gain B Pixel 5 a */ |
316 | { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 }, |
317 | /* Color Gain G1 Pixel 1 5 */ |
318 | { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
319 | /* Color Gain G2 Pixel 1 0 5 */ |
320 | { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
321 | /* Color Gain R Pixel 3 1 */ |
322 | { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 }, |
323 | /* Color GainH Pixel */ |
324 | { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 }, |
325 | /* Global Gain */ |
326 | { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 }, |
327 | /* Contrast */ |
328 | { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 }, |
329 | /* H&V synchro polarity */ |
330 | { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
331 | /* ?default */ |
332 | { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
333 | /* DAC scale */ |
334 | { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
335 | /* ?default */ |
336 | { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 }, |
337 | /* Validate Settings */ |
338 | { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 }, |
339 | }; |
340 | |
341 | static const __u8 initPas202[] = { |
342 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, |
343 | 0x00, 0x00, |
344 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, |
345 | 0x28, 0x1e, 0x20, 0x89, 0x20, |
346 | }; |
347 | |
348 | /* "Known" PAS202BCB registers: |
349 | 0x02 clock divider |
350 | 0x04 Variable framerate bits 6-11 (*) |
351 | 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! |
352 | 0x07 Blue Gain |
353 | 0x08 Green Gain |
354 | 0x09 Red Gain |
355 | 0x0b offset sign bit (bit0 1 > negative offset) |
356 | 0x0c offset |
357 | 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, |
358 | leave at 1 otherwise we get a jump in our exposure control |
359 | 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all |
360 | 0x10 Master gain 0 - 31 |
361 | 0x11 write 1 to apply changes |
362 | (*) The variable framerate control must never be set lower then 500 |
363 | which sets the framerate at 30 / reg02, otherwise vsync is lost. |
364 | */ |
365 | static const __u8 pas202_sensor_init[][8] = { |
366 | /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like |
367 | to set it lower, but for some reason the bridge starts missing |
368 | vsync's then */ |
369 | {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, |
370 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, |
371 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, |
372 | {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10}, |
373 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, |
374 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, |
375 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, |
376 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
377 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, |
378 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
379 | }; |
380 | |
381 | static const __u8 initTas5110c[] = { |
382 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
383 | 0x00, 0x00, |
384 | 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, |
385 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
386 | }; |
387 | /* Same as above, except a different hstart */ |
388 | static const __u8 initTas5110d[] = { |
389 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
390 | 0x00, 0x00, |
391 | 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, |
392 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
393 | }; |
394 | /* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */ |
395 | static const __u8 tas5110c_sensor_init[][8] = { |
396 | {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10}, |
397 | {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10}, |
398 | }; |
399 | /* Known TAS5110D registers |
400 | * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain |
401 | * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted) |
402 | * Note: writing reg03 seems to only work when written together with 02 |
403 | */ |
404 | static const __u8 tas5110d_sensor_init[][8] = { |
405 | {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */ |
406 | }; |
407 | |
408 | static const __u8 initTas5130[] = { |
409 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
410 | 0x00, 0x00, |
411 | 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, |
412 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, |
413 | }; |
414 | static const __u8 tas5130_sensor_init[][8] = { |
415 | /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10}, |
416 | * shutter 0x47 short exposure? */ |
417 | {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10}, |
418 | /* shutter 0x01 long exposure */ |
419 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, |
420 | }; |
421 | |
422 | static const struct sensor_data sensor_data[] = { |
423 | SENS(initHv7131d, hv7131d_sensor_init, 0, 0), |
424 | SENS(initHv7131r, hv7131r_sensor_init, 0, 0), |
425 | SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60), |
426 | SENS(initOv7630, ov7630_sensor_init, 0, 0x21), |
427 | SENS(initPas106, pas106_sensor_init, F_SIF, 0), |
428 | SENS(initPas202, pas202_sensor_init, 0, 0), |
429 | SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0), |
430 | SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0), |
431 | SENS(initTas5130, tas5130_sensor_init, 0, 0), |
432 | }; |
433 | |
434 | /* get one byte in gspca_dev->usb_buf */ |
435 | static void reg_r(struct gspca_dev *gspca_dev, |
436 | __u16 value) |
437 | { |
438 | int res; |
439 | |
440 | if (gspca_dev->usb_err < 0) |
441 | return; |
442 | |
443 | res = usb_control_msg(dev: gspca_dev->dev, |
444 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
445 | request: 0, /* request */ |
446 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
447 | value, |
448 | index: 0, /* index */ |
449 | data: gspca_dev->usb_buf, size: 1, |
450 | timeout: 500); |
451 | |
452 | if (res < 0) { |
453 | dev_err(gspca_dev->v4l2_dev.dev, |
454 | "Error reading register %02x: %d\n" , value, res); |
455 | gspca_dev->usb_err = res; |
456 | /* |
457 | * Make sure the result is zeroed to avoid uninitialized |
458 | * values. |
459 | */ |
460 | gspca_dev->usb_buf[0] = 0; |
461 | } |
462 | } |
463 | |
464 | static void reg_w(struct gspca_dev *gspca_dev, |
465 | __u16 value, |
466 | const __u8 *buffer, |
467 | int len) |
468 | { |
469 | int res; |
470 | |
471 | if (gspca_dev->usb_err < 0) |
472 | return; |
473 | |
474 | memcpy(gspca_dev->usb_buf, buffer, len); |
475 | res = usb_control_msg(dev: gspca_dev->dev, |
476 | usb_sndctrlpipe(gspca_dev->dev, 0), |
477 | request: 0x08, /* request */ |
478 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
479 | value, |
480 | index: 0, /* index */ |
481 | data: gspca_dev->usb_buf, size: len, |
482 | timeout: 500); |
483 | |
484 | if (res < 0) { |
485 | dev_err(gspca_dev->v4l2_dev.dev, |
486 | "Error writing register %02x: %d\n" , value, res); |
487 | gspca_dev->usb_err = res; |
488 | } |
489 | } |
490 | |
491 | static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) |
492 | { |
493 | int retry = 60; |
494 | |
495 | if (gspca_dev->usb_err < 0) |
496 | return; |
497 | |
498 | /* is i2c ready */ |
499 | reg_w(gspca_dev, value: 0x08, buffer: buf, len: 8); |
500 | while (retry--) { |
501 | if (gspca_dev->usb_err < 0) |
502 | return; |
503 | msleep(msecs: 1); |
504 | reg_r(gspca_dev, value: 0x08); |
505 | if (gspca_dev->usb_buf[0] & 0x04) { |
506 | if (gspca_dev->usb_buf[0] & 0x08) { |
507 | dev_err(gspca_dev->v4l2_dev.dev, |
508 | "i2c error writing %8ph\n" , buf); |
509 | gspca_dev->usb_err = -EIO; |
510 | } |
511 | return; |
512 | } |
513 | } |
514 | |
515 | dev_err(gspca_dev->v4l2_dev.dev, "i2c write timeout\n" ); |
516 | gspca_dev->usb_err = -EIO; |
517 | } |
518 | |
519 | static void i2c_w_vector(struct gspca_dev *gspca_dev, |
520 | const __u8 buffer[][8], int len) |
521 | { |
522 | for (;;) { |
523 | if (gspca_dev->usb_err < 0) |
524 | return; |
525 | i2c_w(gspca_dev, buf: *buffer); |
526 | len -= 8; |
527 | if (len <= 0) |
528 | break; |
529 | buffer++; |
530 | } |
531 | } |
532 | |
533 | static void setbrightness(struct gspca_dev *gspca_dev) |
534 | { |
535 | struct sd *sd = (struct sd *) gspca_dev; |
536 | |
537 | switch (sd->sensor) { |
538 | case SENSOR_OV6650: |
539 | case SENSOR_OV7630: { |
540 | __u8 i2cOV[] = |
541 | {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; |
542 | |
543 | /* change reg 0x06 */ |
544 | i2cOV[1] = sensor_data[sd->sensor].sensor_addr; |
545 | i2cOV[3] = sd->brightness->val; |
546 | i2c_w(gspca_dev, buf: i2cOV); |
547 | break; |
548 | } |
549 | case SENSOR_PAS106: |
550 | case SENSOR_PAS202: { |
551 | __u8 i2cpbright[] = |
552 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; |
553 | __u8 i2cpdoit[] = |
554 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
555 | |
556 | /* PAS106 uses reg 7 and 8 instead of b and c */ |
557 | if (sd->sensor == SENSOR_PAS106) { |
558 | i2cpbright[2] = 7; |
559 | i2cpdoit[2] = 0x13; |
560 | } |
561 | |
562 | if (sd->brightness->val < 127) { |
563 | /* change reg 0x0b, signreg */ |
564 | i2cpbright[3] = 0x01; |
565 | /* set reg 0x0c, offset */ |
566 | i2cpbright[4] = 127 - sd->brightness->val; |
567 | } else |
568 | i2cpbright[4] = sd->brightness->val - 127; |
569 | |
570 | i2c_w(gspca_dev, buf: i2cpbright); |
571 | i2c_w(gspca_dev, buf: i2cpdoit); |
572 | break; |
573 | } |
574 | default: |
575 | break; |
576 | } |
577 | } |
578 | |
579 | static void setgain(struct gspca_dev *gspca_dev) |
580 | { |
581 | struct sd *sd = (struct sd *) gspca_dev; |
582 | u8 gain = gspca_dev->gain->val; |
583 | |
584 | switch (sd->sensor) { |
585 | case SENSOR_HV7131D: { |
586 | __u8 i2c[] = |
587 | {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; |
588 | |
589 | i2c[3] = 0x3f - gain; |
590 | i2c[4] = 0x3f - gain; |
591 | i2c[5] = 0x3f - gain; |
592 | |
593 | i2c_w(gspca_dev, buf: i2c); |
594 | break; |
595 | } |
596 | case SENSOR_TAS5110C: |
597 | case SENSOR_TAS5130CXX: { |
598 | __u8 i2c[] = |
599 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; |
600 | |
601 | i2c[4] = 255 - gain; |
602 | i2c_w(gspca_dev, buf: i2c); |
603 | break; |
604 | } |
605 | case SENSOR_TAS5110D: { |
606 | __u8 i2c[] = { |
607 | 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 }; |
608 | gain = 255 - gain; |
609 | /* The bits in the register are the wrong way around!! */ |
610 | i2c[3] |= (gain & 0x80) >> 7; |
611 | i2c[3] |= (gain & 0x40) >> 5; |
612 | i2c[3] |= (gain & 0x20) >> 3; |
613 | i2c[3] |= (gain & 0x10) >> 1; |
614 | i2c[3] |= (gain & 0x08) << 1; |
615 | i2c[3] |= (gain & 0x04) << 3; |
616 | i2c[3] |= (gain & 0x02) << 5; |
617 | i2c[3] |= (gain & 0x01) << 7; |
618 | i2c_w(gspca_dev, buf: i2c); |
619 | break; |
620 | } |
621 | case SENSOR_OV6650: |
622 | case SENSOR_OV7630: { |
623 | __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; |
624 | |
625 | /* |
626 | * The ov7630's gain is weird, at 32 the gain drops to the |
627 | * same level as at 16, so skip 32-47 (of the 0-63 scale). |
628 | */ |
629 | if (sd->sensor == SENSOR_OV7630 && gain >= 32) |
630 | gain += 16; |
631 | |
632 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
633 | i2c[3] = gain; |
634 | i2c_w(gspca_dev, buf: i2c); |
635 | break; |
636 | } |
637 | case SENSOR_PAS106: |
638 | case SENSOR_PAS202: { |
639 | __u8 i2cpgain[] = |
640 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; |
641 | __u8 i2cpcolorgain[] = |
642 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; |
643 | __u8 i2cpdoit[] = |
644 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
645 | |
646 | /* PAS106 uses different regs (and has split green gains) */ |
647 | if (sd->sensor == SENSOR_PAS106) { |
648 | i2cpgain[2] = 0x0e; |
649 | i2cpcolorgain[0] = 0xd0; |
650 | i2cpcolorgain[2] = 0x09; |
651 | i2cpdoit[2] = 0x13; |
652 | } |
653 | |
654 | i2cpgain[3] = gain; |
655 | i2cpcolorgain[3] = gain >> 1; |
656 | i2cpcolorgain[4] = gain >> 1; |
657 | i2cpcolorgain[5] = gain >> 1; |
658 | i2cpcolorgain[6] = gain >> 1; |
659 | |
660 | i2c_w(gspca_dev, buf: i2cpgain); |
661 | i2c_w(gspca_dev, buf: i2cpcolorgain); |
662 | i2c_w(gspca_dev, buf: i2cpdoit); |
663 | break; |
664 | } |
665 | default: |
666 | if (sd->bridge == BRIDGE_103) { |
667 | u8 buf[3] = { gain, gain, gain }; /* R, G, B */ |
668 | reg_w(gspca_dev, value: 0x05, buffer: buf, len: 3); |
669 | } else { |
670 | u8 buf[2]; |
671 | buf[0] = gain << 4 | gain; /* Red and blue */ |
672 | buf[1] = gain; /* Green */ |
673 | reg_w(gspca_dev, value: 0x10, buffer: buf, len: 2); |
674 | } |
675 | } |
676 | } |
677 | |
678 | static void setexposure(struct gspca_dev *gspca_dev) |
679 | { |
680 | struct sd *sd = (struct sd *) gspca_dev; |
681 | |
682 | switch (sd->sensor) { |
683 | case SENSOR_HV7131D: { |
684 | /* Note the datasheet wrongly says line mode exposure uses reg |
685 | 0x26 and 0x27, testing has shown 0x25 + 0x26 */ |
686 | __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; |
687 | u16 reg = gspca_dev->exposure->val; |
688 | |
689 | i2c[3] = reg >> 8; |
690 | i2c[4] = reg & 0xff; |
691 | i2c_w(gspca_dev, buf: i2c); |
692 | break; |
693 | } |
694 | case SENSOR_TAS5110C: |
695 | case SENSOR_TAS5110D: { |
696 | /* register 19's high nibble contains the sn9c10x clock divider |
697 | The high nibble configures the no fps according to the |
698 | formula: 60 / high_nibble. With a maximum of 30 fps */ |
699 | u8 reg = gspca_dev->exposure->val; |
700 | |
701 | reg = (reg << 4) | 0x0b; |
702 | reg_w(gspca_dev, value: 0x19, buffer: ®, len: 1); |
703 | break; |
704 | } |
705 | case SENSOR_OV6650: |
706 | case SENSOR_OV7630: { |
707 | /* The ov6650 / ov7630 have 2 registers which both influence |
708 | exposure, register 11, whose low nibble sets the nr off fps |
709 | according to: fps = 30 / (low_nibble + 1) |
710 | |
711 | The fps configures the maximum exposure setting, but it is |
712 | possible to use less exposure then what the fps maximum |
713 | allows by setting register 10. register 10 configures the |
714 | actual exposure as quotient of the full exposure, with 0 |
715 | being no exposure at all (not very useful) and reg10_max |
716 | being max exposure possible at that framerate. |
717 | |
718 | The code maps our 0 - 510 ms exposure ctrl to these 2 |
719 | registers, trying to keep fps as high as possible. |
720 | */ |
721 | __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}; |
722 | int reg10, reg11, reg10_max; |
723 | |
724 | /* ov6645 datasheet says reg10_max is 9a, but that uses |
725 | tline * 2 * reg10 as formula for calculating texpo, the |
726 | ov6650 probably uses the same formula as the 7730 which uses |
727 | tline * 4 * reg10, which explains why the reg10max we've |
728 | found experimentally for the ov6650 is exactly half that of |
729 | the ov6645. The ov7630 datasheet says the max is 0x41. */ |
730 | if (sd->sensor == SENSOR_OV6650) { |
731 | reg10_max = 0x4d; |
732 | i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */ |
733 | } else |
734 | reg10_max = 0x41; |
735 | |
736 | reg11 = (15 * gspca_dev->exposure->val + 999) / 1000; |
737 | if (reg11 < 1) |
738 | reg11 = 1; |
739 | else if (reg11 > 16) |
740 | reg11 = 16; |
741 | |
742 | /* In 640x480, if the reg11 has less than 4, the image is |
743 | unstable (the bridge goes into a higher compression mode |
744 | which we have not reverse engineered yet). */ |
745 | if (gspca_dev->pixfmt.width == 640 && reg11 < 4) |
746 | reg11 = 4; |
747 | |
748 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
749 | reg10 = (gspca_dev->exposure->val / 2) * reg10_max |
750 | / (1000 * reg11 / 30) */ |
751 | reg10 = (gspca_dev->exposure->val * 15 * reg10_max) |
752 | / (1000 * reg11); |
753 | |
754 | /* Don't allow this to get below 10 when using autogain, the |
755 | steps become very large (relatively) when below 10 causing |
756 | the image to oscillate from much too dark, to much too bright |
757 | and back again. */ |
758 | if (gspca_dev->autogain->val && reg10 < 10) |
759 | reg10 = 10; |
760 | else if (reg10 > reg10_max) |
761 | reg10 = reg10_max; |
762 | |
763 | /* Write reg 10 and reg11 low nibble */ |
764 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
765 | i2c[3] = reg10; |
766 | i2c[4] |= reg11 - 1; |
767 | |
768 | /* If register 11 didn't change, don't change it */ |
769 | if (sd->reg11 == reg11) |
770 | i2c[0] = 0xa0; |
771 | |
772 | i2c_w(gspca_dev, buf: i2c); |
773 | if (gspca_dev->usb_err == 0) |
774 | sd->reg11 = reg11; |
775 | break; |
776 | } |
777 | case SENSOR_PAS202: { |
778 | __u8 i2cpframerate[] = |
779 | {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16}; |
780 | __u8 i2cpexpo[] = |
781 | {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16}; |
782 | const __u8 i2cpdoit[] = |
783 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
784 | int framerate_ctrl; |
785 | |
786 | /* The exposure knee for the autogain algorithm is 200 |
787 | (100 ms / 10 fps on other sensors), for values below this |
788 | use the control for setting the partial frame expose time, |
789 | above that use variable framerate. This way we run at max |
790 | framerate (640x480@7.5 fps, 320x240@10fps) until the knee |
791 | is reached. Using the variable framerate control above 200 |
792 | is better then playing around with both clockdiv + partial |
793 | frame exposure times (like we are doing with the ov chips), |
794 | as that sometimes leads to jumps in the exposure control, |
795 | which are bad for auto exposure. */ |
796 | if (gspca_dev->exposure->val < 200) { |
797 | i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255) |
798 | / 200; |
799 | framerate_ctrl = 500; |
800 | } else { |
801 | /* The PAS202's exposure control goes from 0 - 4095, |
802 | but anything below 500 causes vsync issues, so scale |
803 | our 200-1023 to 500-4095 */ |
804 | framerate_ctrl = (gspca_dev->exposure->val - 200) |
805 | * 1000 / 229 + 500; |
806 | } |
807 | |
808 | i2cpframerate[3] = framerate_ctrl >> 6; |
809 | i2cpframerate[4] = framerate_ctrl & 0x3f; |
810 | i2c_w(gspca_dev, buf: i2cpframerate); |
811 | i2c_w(gspca_dev, buf: i2cpexpo); |
812 | i2c_w(gspca_dev, buf: i2cpdoit); |
813 | break; |
814 | } |
815 | case SENSOR_PAS106: { |
816 | __u8 i2cpframerate[] = |
817 | {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; |
818 | __u8 i2cpexpo[] = |
819 | {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; |
820 | const __u8 i2cpdoit[] = |
821 | {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; |
822 | int framerate_ctrl; |
823 | |
824 | /* For values below 150 use partial frame exposure, above |
825 | that use framerate ctrl */ |
826 | if (gspca_dev->exposure->val < 150) { |
827 | i2cpexpo[3] = 150 - gspca_dev->exposure->val; |
828 | framerate_ctrl = 300; |
829 | } else { |
830 | /* The PAS106's exposure control goes from 0 - 4095, |
831 | but anything below 300 causes vsync issues, so scale |
832 | our 150-1023 to 300-4095 */ |
833 | framerate_ctrl = (gspca_dev->exposure->val - 150) |
834 | * 1000 / 230 + 300; |
835 | } |
836 | |
837 | i2cpframerate[3] = framerate_ctrl >> 4; |
838 | i2cpframerate[4] = framerate_ctrl & 0x0f; |
839 | i2c_w(gspca_dev, buf: i2cpframerate); |
840 | i2c_w(gspca_dev, buf: i2cpexpo); |
841 | i2c_w(gspca_dev, buf: i2cpdoit); |
842 | break; |
843 | } |
844 | default: |
845 | break; |
846 | } |
847 | } |
848 | |
849 | static void setfreq(struct gspca_dev *gspca_dev) |
850 | { |
851 | struct sd *sd = (struct sd *) gspca_dev; |
852 | |
853 | if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) { |
854 | /* Framerate adjust register for artificial light 50 hz flicker |
855 | compensation, for the ov6650 this is identical to ov6630 |
856 | 0x2b register, see ov6630 datasheet. |
857 | 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */ |
858 | __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; |
859 | switch (sd->plfreq->val) { |
860 | default: |
861 | /* case 0: * no filter*/ |
862 | /* case 2: * 60 hz */ |
863 | i2c[3] = 0; |
864 | break; |
865 | case 1: /* 50 hz */ |
866 | i2c[3] = (sd->sensor == SENSOR_OV6650) |
867 | ? 0x4f : 0x8a; |
868 | break; |
869 | } |
870 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
871 | i2c_w(gspca_dev, buf: i2c); |
872 | } |
873 | } |
874 | |
875 | static void do_autogain(struct gspca_dev *gspca_dev) |
876 | { |
877 | struct sd *sd = (struct sd *) gspca_dev; |
878 | int deadzone, desired_avg_lum, avg_lum; |
879 | |
880 | avg_lum = atomic_read(v: &sd->avg_lum); |
881 | if (avg_lum == -1) |
882 | return; |
883 | |
884 | if (sd->autogain_ignore_frames > 0) { |
885 | sd->autogain_ignore_frames--; |
886 | return; |
887 | } |
888 | |
889 | /* SIF / VGA sensors have a different autoexposure area and thus |
890 | different avg_lum values for the same picture brightness */ |
891 | if (sensor_data[sd->sensor].flags & F_SIF) { |
892 | deadzone = 500; |
893 | /* SIF sensors tend to overexpose, so keep this small */ |
894 | desired_avg_lum = 5000; |
895 | } else { |
896 | deadzone = 1500; |
897 | desired_avg_lum = 13000; |
898 | } |
899 | |
900 | if (sd->brightness) |
901 | desired_avg_lum = sd->brightness->val * desired_avg_lum / 127; |
902 | |
903 | if (gspca_dev->exposure->maximum < 500) { |
904 | if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, |
905 | desired_avg_lum, deadzone)) |
906 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
907 | } else { |
908 | int gain_knee = (s32)gspca_dev->gain->maximum * 9 / 10; |
909 | if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum, |
910 | deadzone, gain_knee, exposure_knee: sd->exposure_knee)) |
911 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
912 | } |
913 | } |
914 | |
915 | /* this function is called at probe time */ |
916 | static int sd_config(struct gspca_dev *gspca_dev, |
917 | const struct usb_device_id *id) |
918 | { |
919 | struct sd *sd = (struct sd *) gspca_dev; |
920 | struct cam *cam; |
921 | |
922 | reg_r(gspca_dev, value: 0x00); |
923 | if (gspca_dev->usb_buf[0] != 0x10) |
924 | return -ENODEV; |
925 | |
926 | /* copy the webcam info from the device id */ |
927 | sd->sensor = id->driver_info >> 8; |
928 | sd->bridge = id->driver_info & 0xff; |
929 | |
930 | cam = &gspca_dev->cam; |
931 | if (!(sensor_data[sd->sensor].flags & F_SIF)) { |
932 | cam->cam_mode = vga_mode; |
933 | cam->nmodes = ARRAY_SIZE(vga_mode); |
934 | } else { |
935 | cam->cam_mode = sif_mode; |
936 | cam->nmodes = ARRAY_SIZE(sif_mode); |
937 | } |
938 | cam->npkt = 36; /* 36 packets per ISOC message */ |
939 | |
940 | return 0; |
941 | } |
942 | |
943 | /* this function is called at probe and resume time */ |
944 | static int sd_init(struct gspca_dev *gspca_dev) |
945 | { |
946 | const __u8 stop = 0x09; /* Disable stream turn of LED */ |
947 | |
948 | reg_w(gspca_dev, value: 0x01, buffer: &stop, len: 1); |
949 | |
950 | return gspca_dev->usb_err; |
951 | } |
952 | |
953 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
954 | { |
955 | struct gspca_dev *gspca_dev = |
956 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
957 | struct sd *sd = (struct sd *)gspca_dev; |
958 | |
959 | gspca_dev->usb_err = 0; |
960 | |
961 | if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { |
962 | /* when switching to autogain set defaults to make sure |
963 | we are on a valid point of the autogain gain / |
964 | exposure knee graph, and give this change time to |
965 | take effect before doing autogain. */ |
966 | gspca_dev->gain->val = gspca_dev->gain->default_value; |
967 | gspca_dev->exposure->val = gspca_dev->exposure->default_value; |
968 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
969 | } |
970 | |
971 | if (!gspca_dev->streaming) |
972 | return 0; |
973 | |
974 | switch (ctrl->id) { |
975 | case V4L2_CID_BRIGHTNESS: |
976 | setbrightness(gspca_dev); |
977 | break; |
978 | case V4L2_CID_AUTOGAIN: |
979 | if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) |
980 | setexposure(gspca_dev); |
981 | if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) |
982 | setgain(gspca_dev); |
983 | break; |
984 | case V4L2_CID_POWER_LINE_FREQUENCY: |
985 | setfreq(gspca_dev); |
986 | break; |
987 | default: |
988 | return -EINVAL; |
989 | } |
990 | return gspca_dev->usb_err; |
991 | } |
992 | |
993 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
994 | .s_ctrl = sd_s_ctrl, |
995 | }; |
996 | |
997 | /* this function is called at probe time */ |
998 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
999 | { |
1000 | struct sd *sd = (struct sd *) gspca_dev; |
1001 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
1002 | |
1003 | gspca_dev->vdev.ctrl_handler = hdl; |
1004 | v4l2_ctrl_handler_init(hdl, 5); |
1005 | |
1006 | if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 || |
1007 | sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202) |
1008 | sd->brightness = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1009 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 127); |
1010 | |
1011 | /* Gain range is sensor dependent */ |
1012 | switch (sd->sensor) { |
1013 | case SENSOR_OV6650: |
1014 | case SENSOR_PAS106: |
1015 | case SENSOR_PAS202: |
1016 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1017 | V4L2_CID_GAIN, min: 0, max: 31, step: 1, def: 15); |
1018 | break; |
1019 | case SENSOR_OV7630: |
1020 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1021 | V4L2_CID_GAIN, min: 0, max: 47, step: 1, def: 31); |
1022 | break; |
1023 | case SENSOR_HV7131D: |
1024 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1025 | V4L2_CID_GAIN, min: 0, max: 63, step: 1, def: 31); |
1026 | break; |
1027 | case SENSOR_TAS5110C: |
1028 | case SENSOR_TAS5110D: |
1029 | case SENSOR_TAS5130CXX: |
1030 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1031 | V4L2_CID_GAIN, min: 0, max: 255, step: 1, def: 127); |
1032 | break; |
1033 | default: |
1034 | if (sd->bridge == BRIDGE_103) { |
1035 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1036 | V4L2_CID_GAIN, min: 0, max: 127, step: 1, def: 63); |
1037 | } else { |
1038 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1039 | V4L2_CID_GAIN, min: 0, max: 15, step: 1, def: 7); |
1040 | } |
1041 | } |
1042 | |
1043 | /* Exposure range is sensor dependent, and not all have exposure */ |
1044 | switch (sd->sensor) { |
1045 | case SENSOR_HV7131D: |
1046 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1047 | V4L2_CID_EXPOSURE, min: 0, max: 8191, step: 1, def: 482); |
1048 | sd->exposure_knee = 964; |
1049 | break; |
1050 | case SENSOR_OV6650: |
1051 | case SENSOR_OV7630: |
1052 | case SENSOR_PAS106: |
1053 | case SENSOR_PAS202: |
1054 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1055 | V4L2_CID_EXPOSURE, min: 0, max: 1023, step: 1, def: 66); |
1056 | sd->exposure_knee = 200; |
1057 | break; |
1058 | case SENSOR_TAS5110C: |
1059 | case SENSOR_TAS5110D: |
1060 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1061 | V4L2_CID_EXPOSURE, min: 2, max: 15, step: 1, def: 2); |
1062 | break; |
1063 | } |
1064 | |
1065 | if (gspca_dev->exposure) { |
1066 | gspca_dev->autogain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
1067 | V4L2_CID_AUTOGAIN, min: 0, max: 1, step: 1, def: 1); |
1068 | } |
1069 | |
1070 | if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) |
1071 | sd->plfreq = v4l2_ctrl_new_std_menu(hdl, ops: &sd_ctrl_ops, |
1072 | V4L2_CID_POWER_LINE_FREQUENCY, |
1073 | max: V4L2_CID_POWER_LINE_FREQUENCY_60HZ, mask: 0, |
1074 | def: V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); |
1075 | |
1076 | if (hdl->error) { |
1077 | pr_err("Could not initialize controls\n" ); |
1078 | return hdl->error; |
1079 | } |
1080 | |
1081 | if (gspca_dev->autogain) |
1082 | v4l2_ctrl_auto_cluster(ncontrols: 3, controls: &gspca_dev->autogain, manual_val: 0, set_volatile: false); |
1083 | |
1084 | return 0; |
1085 | } |
1086 | |
1087 | /* -- start the camera -- */ |
1088 | static int sd_start(struct gspca_dev *gspca_dev) |
1089 | { |
1090 | struct sd *sd = (struct sd *) gspca_dev; |
1091 | struct cam *cam = &gspca_dev->cam; |
1092 | int i, mode; |
1093 | __u8 regs[0x31]; |
1094 | |
1095 | mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; |
1096 | /* Copy registers 0x01 - 0x19 from the template */ |
1097 | memcpy(®s[0x01], sensor_data[sd->sensor].bridge_init, 0x19); |
1098 | /* Set the mode */ |
1099 | regs[0x18] |= mode << 4; |
1100 | |
1101 | /* Set bridge gain to 1.0 */ |
1102 | if (sd->bridge == BRIDGE_103) { |
1103 | regs[0x05] = 0x20; /* Red */ |
1104 | regs[0x06] = 0x20; /* Green */ |
1105 | regs[0x07] = 0x20; /* Blue */ |
1106 | } else { |
1107 | regs[0x10] = 0x00; /* Red and blue */ |
1108 | regs[0x11] = 0x00; /* Green */ |
1109 | } |
1110 | |
1111 | /* Setup pixel numbers and auto exposure window */ |
1112 | if (sensor_data[sd->sensor].flags & F_SIF) { |
1113 | regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */ |
1114 | regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */ |
1115 | regs[0x1c] = 0x02; /* AE H-start 64 */ |
1116 | regs[0x1d] = 0x02; /* AE V-start 64 */ |
1117 | regs[0x1e] = 0x09; /* AE H-end 288 */ |
1118 | regs[0x1f] = 0x07; /* AE V-end 224 */ |
1119 | } else { |
1120 | regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */ |
1121 | regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */ |
1122 | regs[0x1c] = 0x05; /* AE H-start 160 */ |
1123 | regs[0x1d] = 0x03; /* AE V-start 96 */ |
1124 | regs[0x1e] = 0x0f; /* AE H-end 480 */ |
1125 | regs[0x1f] = 0x0c; /* AE V-end 384 */ |
1126 | } |
1127 | |
1128 | /* Setup the gamma table (only used with the sn9c103 bridge) */ |
1129 | for (i = 0; i < 16; i++) |
1130 | regs[0x20 + i] = i * 16; |
1131 | regs[0x20 + i] = 255; |
1132 | |
1133 | /* Special cases where some regs depend on mode or bridge */ |
1134 | switch (sd->sensor) { |
1135 | case SENSOR_TAS5130CXX: |
1136 | /* FIXME / TESTME |
1137 | probably not mode specific at all most likely the upper |
1138 | nibble of 0x19 is exposure (clock divider) just as with |
1139 | the tas5110, we need someone to test this. */ |
1140 | regs[0x19] = mode ? 0x23 : 0x43; |
1141 | break; |
1142 | case SENSOR_OV7630: |
1143 | /* FIXME / TESTME for some reason with the 101/102 bridge the |
1144 | clock is set to 12 Mhz (reg1 == 0x04), rather then 24. |
1145 | Also the hstart needs to go from 1 to 2 when using a 103, |
1146 | which is likely related. This does not seem right. */ |
1147 | if (sd->bridge == BRIDGE_103) { |
1148 | regs[0x01] = 0x44; /* Select 24 Mhz clock */ |
1149 | regs[0x12] = 0x02; /* Set hstart to 2 */ |
1150 | } |
1151 | break; |
1152 | case SENSOR_PAS202: |
1153 | /* For some unknown reason we need to increase hstart by 1 on |
1154 | the sn9c103, otherwise we get wrong colors (bayer shift). */ |
1155 | if (sd->bridge == BRIDGE_103) |
1156 | regs[0x12] += 1; |
1157 | break; |
1158 | } |
1159 | /* Disable compression when the raw bayer format has been selected */ |
1160 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) |
1161 | regs[0x18] &= ~0x80; |
1162 | |
1163 | /* Vga mode emulation on SIF sensor? */ |
1164 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { |
1165 | regs[0x12] += 16; /* hstart adjust */ |
1166 | regs[0x13] += 24; /* vstart adjust */ |
1167 | regs[0x15] = 320 / 16; /* hsize */ |
1168 | regs[0x16] = 240 / 16; /* vsize */ |
1169 | } |
1170 | |
1171 | /* reg 0x01 bit 2 video transfert on */ |
1172 | reg_w(gspca_dev, value: 0x01, buffer: ®s[0x01], len: 1); |
1173 | /* reg 0x17 SensorClk enable inv Clk 0x60 */ |
1174 | reg_w(gspca_dev, value: 0x17, buffer: ®s[0x17], len: 1); |
1175 | /* Set the registers from the template */ |
1176 | reg_w(gspca_dev, value: 0x01, buffer: ®s[0x01], |
1177 | len: (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f); |
1178 | |
1179 | /* Init the sensor */ |
1180 | i2c_w_vector(gspca_dev, buffer: sensor_data[sd->sensor].sensor_init, |
1181 | len: sensor_data[sd->sensor].sensor_init_size); |
1182 | |
1183 | /* Mode / bridge specific sensor setup */ |
1184 | switch (sd->sensor) { |
1185 | case SENSOR_PAS202: { |
1186 | const __u8 i2cpclockdiv[] = |
1187 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}; |
1188 | /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ |
1189 | if (mode) |
1190 | i2c_w(gspca_dev, buf: i2cpclockdiv); |
1191 | break; |
1192 | } |
1193 | case SENSOR_OV7630: |
1194 | /* FIXME / TESTME We should be able to handle this identical |
1195 | for the 101/102 and the 103 case */ |
1196 | if (sd->bridge == BRIDGE_103) { |
1197 | const __u8 i2c[] = { 0xa0, 0x21, 0x13, |
1198 | 0x80, 0x00, 0x00, 0x00, 0x10 }; |
1199 | i2c_w(gspca_dev, buf: i2c); |
1200 | } |
1201 | break; |
1202 | } |
1203 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
1204 | reg_w(gspca_dev, value: 0x15, buffer: ®s[0x15], len: 2); |
1205 | /* compression register */ |
1206 | reg_w(gspca_dev, value: 0x18, buffer: ®s[0x18], len: 1); |
1207 | /* H_start */ |
1208 | reg_w(gspca_dev, value: 0x12, buffer: ®s[0x12], len: 1); |
1209 | /* V_START */ |
1210 | reg_w(gspca_dev, value: 0x13, buffer: ®s[0x13], len: 1); |
1211 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ |
1212 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ |
1213 | reg_w(gspca_dev, value: 0x17, buffer: ®s[0x17], len: 1); |
1214 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ |
1215 | reg_w(gspca_dev, value: 0x19, buffer: ®s[0x19], len: 1); |
1216 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ |
1217 | reg_w(gspca_dev, value: 0x1c, buffer: ®s[0x1c], len: 4); |
1218 | /* Enable video transfert */ |
1219 | reg_w(gspca_dev, value: 0x01, buffer: ®s[0x01], len: 1); |
1220 | /* Compression */ |
1221 | reg_w(gspca_dev, value: 0x18, buffer: ®s[0x18], len: 2); |
1222 | msleep(msecs: 20); |
1223 | |
1224 | sd->reg11 = -1; |
1225 | |
1226 | setgain(gspca_dev); |
1227 | setbrightness(gspca_dev); |
1228 | setexposure(gspca_dev); |
1229 | setfreq(gspca_dev); |
1230 | |
1231 | sd->frames_to_drop = 0; |
1232 | sd->autogain_ignore_frames = 0; |
1233 | gspca_dev->exp_too_high_cnt = 0; |
1234 | gspca_dev->exp_too_low_cnt = 0; |
1235 | atomic_set(v: &sd->avg_lum, i: -1); |
1236 | return gspca_dev->usb_err; |
1237 | } |
1238 | |
1239 | static void sd_stopN(struct gspca_dev *gspca_dev) |
1240 | { |
1241 | sd_init(gspca_dev); |
1242 | } |
1243 | |
1244 | static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) |
1245 | { |
1246 | struct sd *sd = (struct sd *) gspca_dev; |
1247 | int i, = (sd->bridge == BRIDGE_103) ? 18 : 12; |
1248 | |
1249 | /* frames start with: |
1250 | * ff ff 00 c4 c4 96 synchro |
1251 | * 00 (unknown) |
1252 | * xx (frame sequence / size / compression) |
1253 | * (xx) (idem - extra byte for sn9c103) |
1254 | * ll mm brightness sum inside auto exposure |
1255 | * ll mm brightness sum outside auto exposure |
1256 | * (xx xx xx xx xx) audio values for snc103 |
1257 | */ |
1258 | for (i = 0; i < len; i++) { |
1259 | switch (sd->header_read) { |
1260 | case 0: |
1261 | if (data[i] == 0xff) |
1262 | sd->header_read++; |
1263 | break; |
1264 | case 1: |
1265 | if (data[i] == 0xff) |
1266 | sd->header_read++; |
1267 | else |
1268 | sd->header_read = 0; |
1269 | break; |
1270 | case 2: |
1271 | if (data[i] == 0x00) |
1272 | sd->header_read++; |
1273 | else if (data[i] != 0xff) |
1274 | sd->header_read = 0; |
1275 | break; |
1276 | case 3: |
1277 | if (data[i] == 0xc4) |
1278 | sd->header_read++; |
1279 | else if (data[i] == 0xff) |
1280 | sd->header_read = 1; |
1281 | else |
1282 | sd->header_read = 0; |
1283 | break; |
1284 | case 4: |
1285 | if (data[i] == 0xc4) |
1286 | sd->header_read++; |
1287 | else if (data[i] == 0xff) |
1288 | sd->header_read = 1; |
1289 | else |
1290 | sd->header_read = 0; |
1291 | break; |
1292 | case 5: |
1293 | if (data[i] == 0x96) |
1294 | sd->header_read++; |
1295 | else if (data[i] == 0xff) |
1296 | sd->header_read = 1; |
1297 | else |
1298 | sd->header_read = 0; |
1299 | break; |
1300 | default: |
1301 | sd->header[sd->header_read - 6] = data[i]; |
1302 | sd->header_read++; |
1303 | if (sd->header_read == header_size) { |
1304 | sd->header_read = 0; |
1305 | return data + i + 1; |
1306 | } |
1307 | } |
1308 | } |
1309 | return NULL; |
1310 | } |
1311 | |
1312 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1313 | u8 *data, /* isoc packet */ |
1314 | int len) /* iso packet length */ |
1315 | { |
1316 | int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0; |
1317 | struct sd *sd = (struct sd *) gspca_dev; |
1318 | struct cam *cam = &gspca_dev->cam; |
1319 | u8 *sof; |
1320 | |
1321 | sof = find_sof(gspca_dev, data, len); |
1322 | if (sof) { |
1323 | if (sd->bridge == BRIDGE_103) { |
1324 | fr_h_sz = 18; |
1325 | lum_offset = 3; |
1326 | } else { |
1327 | fr_h_sz = 12; |
1328 | lum_offset = 2; |
1329 | } |
1330 | |
1331 | len_after_sof = len - (sof - data); |
1332 | len = (sof - data) - fr_h_sz; |
1333 | if (len < 0) |
1334 | len = 0; |
1335 | } |
1336 | |
1337 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { |
1338 | /* In raw mode we sometimes get some garbage after the frame |
1339 | ignore this */ |
1340 | int used; |
1341 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; |
1342 | |
1343 | used = gspca_dev->image_len; |
1344 | if (used + len > size) |
1345 | len = size - used; |
1346 | } |
1347 | |
1348 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len); |
1349 | |
1350 | if (sof) { |
1351 | int lum = sd->header[lum_offset] + |
1352 | (sd->header[lum_offset + 1] << 8); |
1353 | |
1354 | /* When exposure changes midway a frame we |
1355 | get a lum of 0 in this case drop 2 frames |
1356 | as the frames directly after an exposure |
1357 | change have an unstable image. Sometimes lum |
1358 | *really* is 0 (cam used in low light with |
1359 | low exposure setting), so do not drop frames |
1360 | if the previous lum was 0 too. */ |
1361 | if (lum == 0 && sd->prev_avg_lum != 0) { |
1362 | lum = -1; |
1363 | sd->frames_to_drop = 2; |
1364 | sd->prev_avg_lum = 0; |
1365 | } else |
1366 | sd->prev_avg_lum = lum; |
1367 | atomic_set(v: &sd->avg_lum, i: lum); |
1368 | |
1369 | if (sd->frames_to_drop) |
1370 | sd->frames_to_drop--; |
1371 | else |
1372 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, NULL, len: 0); |
1373 | |
1374 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, data: sof, len: len_after_sof); |
1375 | } |
1376 | } |
1377 | |
1378 | #if IS_ENABLED(CONFIG_INPUT) |
1379 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, |
1380 | u8 *data, /* interrupt packet data */ |
1381 | int len) /* interrupt packet length */ |
1382 | { |
1383 | int ret = -EINVAL; |
1384 | |
1385 | if (len == 1 && data[0] == 1) { |
1386 | input_report_key(dev: gspca_dev->input_dev, KEY_CAMERA, value: 1); |
1387 | input_sync(dev: gspca_dev->input_dev); |
1388 | input_report_key(dev: gspca_dev->input_dev, KEY_CAMERA, value: 0); |
1389 | input_sync(dev: gspca_dev->input_dev); |
1390 | ret = 0; |
1391 | } |
1392 | |
1393 | return ret; |
1394 | } |
1395 | #endif |
1396 | |
1397 | /* sub-driver description */ |
1398 | static const struct sd_desc sd_desc = { |
1399 | .name = MODULE_NAME, |
1400 | .config = sd_config, |
1401 | .init = sd_init, |
1402 | .init_controls = sd_init_controls, |
1403 | .start = sd_start, |
1404 | .stopN = sd_stopN, |
1405 | .pkt_scan = sd_pkt_scan, |
1406 | .dq_callback = do_autogain, |
1407 | #if IS_ENABLED(CONFIG_INPUT) |
1408 | .int_pkt_scan = sd_int_pkt_scan, |
1409 | #endif |
1410 | }; |
1411 | |
1412 | /* -- module initialisation -- */ |
1413 | #define SB(sensor, bridge) \ |
1414 | .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge |
1415 | |
1416 | |
1417 | static const struct usb_device_id device_table[] = { |
1418 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ |
1419 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ |
1420 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ |
1421 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, |
1422 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, |
1423 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, |
1424 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, |
1425 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, |
1426 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, |
1427 | {USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */ |
1428 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, |
1429 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, |
1430 | {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)}, |
1431 | /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */ |
1432 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, |
1433 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, |
1434 | {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, |
1435 | /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ |
1436 | /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */ |
1437 | {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)}, |
1438 | {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)}, |
1439 | /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */ |
1440 | {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, |
1441 | {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)}, |
1442 | {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)}, |
1443 | {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, |
1444 | {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, |
1445 | {} |
1446 | }; |
1447 | MODULE_DEVICE_TABLE(usb, device_table); |
1448 | |
1449 | /* -- device connect -- */ |
1450 | static int sd_probe(struct usb_interface *intf, |
1451 | const struct usb_device_id *id) |
1452 | { |
1453 | return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd), |
1454 | THIS_MODULE); |
1455 | } |
1456 | |
1457 | static struct usb_driver sd_driver = { |
1458 | .name = MODULE_NAME, |
1459 | .id_table = device_table, |
1460 | .probe = sd_probe, |
1461 | .disconnect = gspca_disconnect, |
1462 | #ifdef CONFIG_PM |
1463 | .suspend = gspca_suspend, |
1464 | .resume = gspca_resume, |
1465 | .reset_resume = gspca_resume, |
1466 | #endif |
1467 | }; |
1468 | |
1469 | module_usb_driver(sd_driver); |
1470 | |