diff options
Diffstat (limited to 'drivers/media/video/gspca/sonixb.c')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 594 |
1 files changed, 310 insertions, 284 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 11210c71f66c..5dd78c6766ea 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -20,6 +20,26 @@ | |||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* Some documentation on known sonixb registers: | ||
24 | |||
25 | Reg Use | ||
26 | 0x10 high nibble red gain low nibble blue gain | ||
27 | 0x11 low nibble green gain | ||
28 | 0x12 hstart | ||
29 | 0x13 vstart | ||
30 | 0x15 hsize (hsize = register-value * 16) | ||
31 | 0x16 vsize (vsize = register-value * 16) | ||
32 | 0x17 bit 0 toggle compression quality (according to sn9c102 driver) | ||
33 | 0x18 bit 7 enables compression, bit 4-5 set image down scaling: | ||
34 | 00 scale 1, 01 scale 1/2, 10, scale 1/4 | ||
35 | 0x19 high-nibble is sensor clock divider, changes exposure on sensors which | ||
36 | use a clock generated by the bridge. Some sensors have their own clock. | ||
37 | 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) | ||
38 | 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) | ||
39 | 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) | ||
40 | 0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) | ||
41 | */ | ||
42 | |||
23 | #define MODULE_NAME "sonixb" | 43 | #define MODULE_NAME "sonixb" |
24 | 44 | ||
25 | #include "gspca.h" | 45 | #include "gspca.h" |
@@ -31,10 +51,8 @@ MODULE_LICENSE("GPL"); | |||
31 | /* specific webcam descriptor */ | 51 | /* specific webcam descriptor */ |
32 | struct sd { | 52 | struct sd { |
33 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 53 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
34 | |||
35 | struct sd_desc sd_desc; /* our nctrls differ dependend upon the | ||
36 | sensor, so we use a per cam copy */ | ||
37 | atomic_t avg_lum; | 54 | atomic_t avg_lum; |
55 | int prev_avg_lum; | ||
38 | 56 | ||
39 | unsigned char gain; | 57 | unsigned char gain; |
40 | unsigned char exposure; | 58 | unsigned char exposure; |
@@ -44,8 +62,12 @@ struct sd { | |||
44 | unsigned char frames_to_drop; | 62 | unsigned char frames_to_drop; |
45 | unsigned char freq; /* light freq filter setting */ | 63 | unsigned char freq; /* light freq filter setting */ |
46 | 64 | ||
47 | unsigned char fr_h_sz; /* size of frame header */ | 65 | __u8 bridge; /* Type of bridge */ |
48 | char sensor; /* Type of image sensor chip */ | 66 | #define BRIDGE_101 0 |
67 | #define BRIDGE_102 0 /* We make no difference between 101 and 102 */ | ||
68 | #define BRIDGE_103 1 | ||
69 | |||
70 | __u8 sensor; /* Type of image sensor chip */ | ||
49 | #define SENSOR_HV7131R 0 | 71 | #define SENSOR_HV7131R 0 |
50 | #define SENSOR_OV6650 1 | 72 | #define SENSOR_OV6650 1 |
51 | #define SENSOR_OV7630 2 | 73 | #define SENSOR_OV7630 2 |
@@ -53,16 +75,35 @@ struct sd { | |||
53 | #define SENSOR_PAS202 4 | 75 | #define SENSOR_PAS202 4 |
54 | #define SENSOR_TAS5110 5 | 76 | #define SENSOR_TAS5110 5 |
55 | #define SENSOR_TAS5130CXX 6 | 77 | #define SENSOR_TAS5130CXX 6 |
56 | char sensor_has_gain; | ||
57 | __u8 sensor_addr; | ||
58 | __u8 reg11; | 78 | __u8 reg11; |
59 | }; | 79 | }; |
60 | 80 | ||
61 | /* flags used in the device id table */ | 81 | typedef const __u8 sensor_init_t[8]; |
82 | |||
83 | struct sensor_data { | ||
84 | const __u8 *bridge_init[2]; | ||
85 | int bridge_init_size[2]; | ||
86 | sensor_init_t *sensor_init; | ||
87 | int sensor_init_size; | ||
88 | sensor_init_t *sensor_bridge_init[2]; | ||
89 | int sensor_bridge_init_size[2]; | ||
90 | int flags; | ||
91 | unsigned ctrl_dis; | ||
92 | __u8 sensor_addr; | ||
93 | }; | ||
94 | |||
95 | /* sensor_data flags */ | ||
62 | #define F_GAIN 0x01 /* has gain */ | 96 | #define F_GAIN 0x01 /* has gain */ |
63 | #define F_AUTO 0x02 /* has autogain */ | 97 | #define F_SIF 0x02 /* sif or vga */ |
64 | #define F_SIF 0x04 /* sif or vga */ | 98 | |
65 | #define F_H18 0x08 /* long (18 b) or short (12 b) frame header */ | 99 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
100 | #define MODE_RAW 0x10 /* raw bayer mode */ | ||
101 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | ||
102 | |||
103 | /* ctrl_dis helper macros */ | ||
104 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) | ||
105 | #define NO_FREQ (1 << FREQ_IDX) | ||
106 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) | ||
66 | 107 | ||
67 | #define COMP2 0x8f | 108 | #define COMP2 0x8f |
68 | #define COMP 0xc7 /* 0x87 //0x07 */ | 109 | #define COMP 0xc7 /* 0x87 //0x07 */ |
@@ -73,6 +114,18 @@ struct sd { | |||
73 | 114 | ||
74 | #define SYS_CLK 0x04 | 115 | #define SYS_CLK 0x04 |
75 | 116 | ||
117 | #define SENS(bridge_1, bridge_3, sensor, sensor_1, \ | ||
118 | sensor_3, _flags, _ctrl_dis, _sensor_addr) \ | ||
119 | { \ | ||
120 | .bridge_init = { bridge_1, bridge_3 }, \ | ||
121 | .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \ | ||
122 | .sensor_init = sensor, \ | ||
123 | .sensor_init_size = sizeof(sensor), \ | ||
124 | .sensor_bridge_init = { sensor_1, sensor_3,}, \ | ||
125 | .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \ | ||
126 | .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \ | ||
127 | } | ||
128 | |||
76 | /* We calculate the autogain at the end of the transfer of a frame, at this | 129 | /* We calculate the autogain at the end of the transfer of a frame, at this |
77 | moment a frame with the old settings is being transmitted, and a frame is | 130 | moment a frame with the old settings is being transmitted, and a frame is |
78 | being captured with the old settings. So if we adjust the autogain we must | 131 | being captured with the old settings. So if we adjust the autogain we must |
@@ -95,6 +148,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | |||
95 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 148 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
96 | 149 | ||
97 | static struct ctrl sd_ctrls[] = { | 150 | static struct ctrl sd_ctrls[] = { |
151 | #define BRIGHTNESS_IDX 0 | ||
98 | { | 152 | { |
99 | { | 153 | { |
100 | .id = V4L2_CID_BRIGHTNESS, | 154 | .id = V4L2_CID_BRIGHTNESS, |
@@ -109,6 +163,7 @@ static struct ctrl sd_ctrls[] = { | |||
109 | .set = sd_setbrightness, | 163 | .set = sd_setbrightness, |
110 | .get = sd_getbrightness, | 164 | .get = sd_getbrightness, |
111 | }, | 165 | }, |
166 | #define GAIN_IDX 1 | ||
112 | { | 167 | { |
113 | { | 168 | { |
114 | .id = V4L2_CID_GAIN, | 169 | .id = V4L2_CID_GAIN, |
@@ -124,6 +179,7 @@ static struct ctrl sd_ctrls[] = { | |||
124 | .set = sd_setgain, | 179 | .set = sd_setgain, |
125 | .get = sd_getgain, | 180 | .get = sd_getgain, |
126 | }, | 181 | }, |
182 | #define EXPOSURE_IDX 2 | ||
127 | { | 183 | { |
128 | { | 184 | { |
129 | .id = V4L2_CID_EXPOSURE, | 185 | .id = V4L2_CID_EXPOSURE, |
@@ -140,6 +196,7 @@ static struct ctrl sd_ctrls[] = { | |||
140 | .set = sd_setexposure, | 196 | .set = sd_setexposure, |
141 | .get = sd_getexposure, | 197 | .get = sd_getexposure, |
142 | }, | 198 | }, |
199 | #define AUTOGAIN_IDX 3 | ||
143 | { | 200 | { |
144 | { | 201 | { |
145 | .id = V4L2_CID_AUTOGAIN, | 202 | .id = V4L2_CID_AUTOGAIN, |
@@ -155,6 +212,7 @@ static struct ctrl sd_ctrls[] = { | |||
155 | .set = sd_setautogain, | 212 | .set = sd_setautogain, |
156 | .get = sd_getautogain, | 213 | .get = sd_getautogain, |
157 | }, | 214 | }, |
215 | #define FREQ_IDX 4 | ||
158 | { | 216 | { |
159 | { | 217 | { |
160 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 218 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -172,31 +230,56 @@ static struct ctrl sd_ctrls[] = { | |||
172 | }; | 230 | }; |
173 | 231 | ||
174 | static struct v4l2_pix_format vga_mode[] = { | 232 | static struct v4l2_pix_format vga_mode[] = { |
233 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
234 | .bytesperline = 160, | ||
235 | .sizeimage = 160 * 120 * 5 / 4, | ||
236 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
237 | .priv = 2 | MODE_RAW}, | ||
175 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 238 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
176 | .bytesperline = 160, | 239 | .bytesperline = 160, |
177 | .sizeimage = 160 * 120, | 240 | .sizeimage = 160 * 120 * 5 / 4, |
178 | .colorspace = V4L2_COLORSPACE_SRGB, | 241 | .colorspace = V4L2_COLORSPACE_SRGB, |
179 | .priv = 2}, | 242 | .priv = 2}, |
180 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 243 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
181 | .bytesperline = 320, | 244 | .bytesperline = 320, |
182 | .sizeimage = 320 * 240, | 245 | .sizeimage = 320 * 240 * 5 / 4, |
183 | .colorspace = V4L2_COLORSPACE_SRGB, | 246 | .colorspace = V4L2_COLORSPACE_SRGB, |
184 | .priv = 1}, | 247 | .priv = 1}, |
185 | {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 248 | {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
186 | .bytesperline = 640, | 249 | .bytesperline = 640, |
187 | .sizeimage = 640 * 480, | 250 | .sizeimage = 640 * 480 * 5 / 4, |
188 | .colorspace = V4L2_COLORSPACE_SRGB, | 251 | .colorspace = V4L2_COLORSPACE_SRGB, |
189 | .priv = 0}, | 252 | .priv = 0}, |
190 | }; | 253 | }; |
191 | static struct v4l2_pix_format sif_mode[] = { | 254 | static struct v4l2_pix_format sif_mode[] = { |
255 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
256 | .bytesperline = 160, | ||
257 | .sizeimage = 160 * 120, | ||
258 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
259 | .priv = 1 | MODE_RAW | MODE_REDUCED_SIF}, | ||
260 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | ||
261 | .bytesperline = 160, | ||
262 | .sizeimage = 160 * 120 * 5 / 4, | ||
263 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
264 | .priv = 1 | MODE_REDUCED_SIF}, | ||
265 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
266 | .bytesperline = 176, | ||
267 | .sizeimage = 176 * 144 * 5 / 4, | ||
268 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
269 | .priv = 1 | MODE_RAW}, | ||
192 | {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 270 | {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
193 | .bytesperline = 176, | 271 | .bytesperline = 176, |
194 | .sizeimage = 176 * 144, | 272 | .sizeimage = 176 * 144 * 5 / 4, |
195 | .colorspace = V4L2_COLORSPACE_SRGB, | 273 | .colorspace = V4L2_COLORSPACE_SRGB, |
196 | .priv = 1}, | 274 | .priv = 1}, |
275 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | ||
276 | .bytesperline = 320, | ||
277 | .sizeimage = 320 * 240 * 5 / 4, | ||
278 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
279 | .priv = 0 | MODE_REDUCED_SIF}, | ||
197 | {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 280 | {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
198 | .bytesperline = 352, | 281 | .bytesperline = 352, |
199 | .sizeimage = 352 * 288, | 282 | .sizeimage = 352 * 288 * 5 / 4, |
200 | .colorspace = V4L2_COLORSPACE_SRGB, | 283 | .colorspace = V4L2_COLORSPACE_SRGB, |
201 | .priv = 0}, | 284 | .priv = 0}, |
202 | }; | 285 | }; |
@@ -204,7 +287,7 @@ static struct v4l2_pix_format sif_mode[] = { | |||
204 | static const __u8 initHv7131[] = { | 287 | static const __u8 initHv7131[] = { |
205 | 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, | 288 | 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, |
206 | 0x00, 0x00, | 289 | 0x00, 0x00, |
207 | 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */ | 290 | 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, |
208 | 0x28, 0x1e, 0x60, 0x8a, 0x20, | 291 | 0x28, 0x1e, 0x60, 0x8a, 0x20, |
209 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c | 292 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c |
210 | }; | 293 | }; |
@@ -218,8 +301,8 @@ static const __u8 hv7131_sensor_init[][8] = { | |||
218 | static const __u8 initOv6650[] = { | 301 | static const __u8 initOv6650[] = { |
219 | 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | 302 | 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, |
220 | 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 303 | 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
221 | 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b, | 304 | 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, |
222 | 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 | 305 | 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07 |
223 | }; | 306 | }; |
224 | static const __u8 ov6650_sensor_init[][8] = | 307 | static const __u8 ov6650_sensor_init[][8] = |
225 | { | 308 | { |
@@ -257,15 +340,15 @@ static const __u8 ov6650_sensor_init[][8] = | |||
257 | static const __u8 initOv7630[] = { | 340 | static const __u8 initOv7630[] = { |
258 | 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */ | 341 | 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */ |
259 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ | 342 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ |
260 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ | 343 | 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ |
261 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ | 344 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
262 | 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */ | 345 | 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */ |
263 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */ | 346 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */ |
264 | }; | 347 | }; |
265 | static const __u8 initOv7630_3[] = { | 348 | static const __u8 initOv7630_3[] = { |
266 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ | 349 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ |
267 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ | 350 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ |
268 | 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ | 351 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ |
269 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ | 352 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
270 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ | 353 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ |
271 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */ | 354 | 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */ |
@@ -294,47 +377,65 @@ static const __u8 ov7630_sensor_init[][8] = { | |||
294 | {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, | 377 | {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, |
295 | }; | 378 | }; |
296 | 379 | ||
380 | static const __u8 ov7630_sensor_init_3[][8] = { | ||
381 | {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, | ||
382 | }; | ||
383 | |||
297 | static const __u8 initPas106[] = { | 384 | static const __u8 initPas106[] = { |
298 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, | 385 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, |
299 | 0x00, 0x00, | 386 | 0x00, 0x00, |
300 | 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, | 387 | 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, |
301 | 0x16, 0x12, 0x28, COMP1, MCK_INIT1, | 388 | 0x16, 0x12, 0x24, COMP1, MCK_INIT1, |
302 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 389 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
303 | }; | 390 | }; |
304 | /* compression 0x86 mckinit1 0x2b */ | 391 | /* compression 0x86 mckinit1 0x2b */ |
305 | static const __u8 pas106_data[][2] = { | 392 | static const __u8 pas106_sensor_init[][8] = { |
306 | {0x02, 0x04}, /* Pixel Clock Divider 6 */ | 393 | /* Pixel Clock Divider 6 */ |
307 | {0x03, 0x13}, /* Frame Time MSB */ | 394 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
308 | /* {0x03, 0x12}, * Frame Time MSB */ | 395 | /* Frame Time MSB (also seen as 0x12) */ |
309 | {0x04, 0x06}, /* Frame Time LSB */ | 396 | { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 }, |
310 | /* {0x04, 0x05}, * Frame Time LSB */ | 397 | /* Frame Time LSB (also seen as 0x05) */ |
311 | {0x05, 0x65}, /* Shutter Time Line Offset */ | 398 | { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
312 | /* {0x05, 0x6d}, * Shutter Time Line Offset */ | 399 | /* Shutter Time Line Offset (also seen as 0x6d) */ |
313 | /* {0x06, 0xb1}, * Shutter Time Pixel Offset */ | 400 | { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 }, |
314 | {0x06, 0xcd}, /* Shutter Time Pixel Offset */ | 401 | /* Shutter Time Pixel Offset (also seen as 0xb1) */ |
315 | {0x07, 0xc1}, /* Black Level Subtract Sign */ | 402 | { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 }, |
316 | /* {0x07, 0x00}, * Black Level Subtract Sign */ | 403 | /* Black Level Subtract Sign (also seen 0x00) */ |
317 | {0x08, 0x06}, /* Black Level Subtract Level */ | 404 | { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 }, |
318 | {0x08, 0x06}, /* Black Level Subtract Level */ | 405 | /* Black Level Subtract Level (also seen 0x01) */ |
319 | /* {0x08, 0x01}, * Black Level Subtract Level */ | 406 | { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
320 | {0x09, 0x05}, /* Color Gain B Pixel 5 a */ | 407 | { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, |
321 | {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */ | 408 | /* Color Gain B Pixel 5 a */ |
322 | {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */ | 409 | { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 }, |
323 | {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */ | 410 | /* Color Gain G1 Pixel 1 5 */ |
324 | {0x0d, 0x00}, /* Color GainH Pixel */ | 411 | { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
325 | {0x0e, 0x0e}, /* Global Gain */ | 412 | /* Color Gain G2 Pixel 1 0 5 */ |
326 | {0x0f, 0x00}, /* Contrast */ | 413 | { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
327 | {0x10, 0x06}, /* H&V synchro polarity */ | 414 | /* Color Gain R Pixel 3 1 */ |
328 | {0x11, 0x06}, /* ?default */ | 415 | { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 }, |
329 | {0x12, 0x06}, /* DAC scale */ | 416 | /* Color GainH Pixel */ |
330 | {0x14, 0x02}, /* ?default */ | 417 | { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 }, |
331 | {0x13, 0x01}, /* Validate Settings */ | 418 | /* Global Gain */ |
419 | { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 }, | ||
420 | /* Contrast */ | ||
421 | { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 }, | ||
422 | /* H&V synchro polarity */ | ||
423 | { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 }, | ||
424 | /* ?default */ | ||
425 | { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 }, | ||
426 | /* DAC scale */ | ||
427 | { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 }, | ||
428 | /* ?default */ | ||
429 | { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 }, | ||
430 | /* Validate Settings */ | ||
431 | { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 }, | ||
332 | }; | 432 | }; |
433 | |||
333 | static const __u8 initPas202[] = { | 434 | static const __u8 initPas202[] = { |
334 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, | 435 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, |
335 | 0x00, 0x00, | 436 | 0x00, 0x00, |
336 | 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */ | 437 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, |
337 | 0x28, 0x1e, 0x28, 0x89, 0x30, | 438 | 0x28, 0x1e, 0x28, 0x89, 0x20, |
338 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c | 439 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c |
339 | }; | 440 | }; |
340 | static const __u8 pas202_sensor_init[][8] = { | 441 | static const __u8 pas202_sensor_init[][8] = { |
@@ -364,7 +465,7 @@ static const __u8 pas202_sensor_init[][8] = { | |||
364 | static const __u8 initTas5110[] = { | 465 | static const __u8 initTas5110[] = { |
365 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 466 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
366 | 0x00, 0x00, | 467 | 0x00, 0x00, |
367 | 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */ | 468 | 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a, |
368 | 0x16, 0x12, 0x60, 0x86, 0x2b, | 469 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
369 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | 470 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 |
370 | }; | 471 | }; |
@@ -377,7 +478,7 @@ static const __u8 tas5110_sensor_init[][8] = { | |||
377 | static const __u8 initTas5130[] = { | 478 | static const __u8 initTas5130[] = { |
378 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 479 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
379 | 0x00, 0x00, | 480 | 0x00, 0x00, |
380 | 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a, | 481 | 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a, |
381 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, | 482 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, |
382 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 483 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c |
383 | }; | 484 | }; |
@@ -389,6 +490,21 @@ static const __u8 tas5130_sensor_init[][8] = { | |||
389 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, | 490 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, |
390 | }; | 491 | }; |
391 | 492 | ||
493 | struct sensor_data sensor_data[] = { | ||
494 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | ||
495 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | ||
496 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | ||
497 | F_GAIN, 0, 0x21), | ||
498 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | ||
499 | 0), | ||
500 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, | ||
501 | NO_EXPO|NO_FREQ, 0), | ||
502 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, | ||
503 | NO_BRIGHTNESS|NO_FREQ, 0), | ||
504 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, | ||
505 | 0), | ||
506 | }; | ||
507 | |||
392 | /* get one byte in gspca_dev->usb_buf */ | 508 | /* get one byte in gspca_dev->usb_buf */ |
393 | static void reg_r(struct gspca_dev *gspca_dev, | 509 | static void reg_r(struct gspca_dev *gspca_dev, |
394 | __u16 value) | 510 | __u16 value) |
@@ -409,7 +525,7 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
409 | int len) | 525 | int len) |
410 | { | 526 | { |
411 | #ifdef GSPCA_DEBUG | 527 | #ifdef GSPCA_DEBUG |
412 | if (len > sizeof gspca_dev->usb_buf) { | 528 | if (len > USB_BUF_SZ) { |
413 | PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow"); | 529 | PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow"); |
414 | return; | 530 | return; |
415 | } | 531 | } |
@@ -425,26 +541,6 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
425 | 500); | 541 | 500); |
426 | } | 542 | } |
427 | 543 | ||
428 | static void reg_w_big(struct gspca_dev *gspca_dev, | ||
429 | __u16 value, | ||
430 | const __u8 *buffer, | ||
431 | int len) | ||
432 | { | ||
433 | __u8 *tmpbuf; | ||
434 | |||
435 | tmpbuf = kmalloc(len, GFP_KERNEL); | ||
436 | memcpy(tmpbuf, buffer, len); | ||
437 | usb_control_msg(gspca_dev->dev, | ||
438 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
439 | 0x08, /* request */ | ||
440 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
441 | value, | ||
442 | 0, /* index */ | ||
443 | tmpbuf, len, | ||
444 | 500); | ||
445 | kfree(tmpbuf); | ||
446 | } | ||
447 | |||
448 | static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) | 544 | static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) |
449 | { | 545 | { |
450 | int retry = 60; | 546 | int retry = 60; |
@@ -487,7 +583,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
487 | {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; | 583 | {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; |
488 | 584 | ||
489 | /* change reg 0x06 */ | 585 | /* change reg 0x06 */ |
490 | i2cOV[1] = sd->sensor_addr; | 586 | i2cOV[1] = sensor_data[sd->sensor].sensor_addr; |
491 | i2cOV[3] = sd->brightness; | 587 | i2cOV[3] = sd->brightness; |
492 | if (i2c_w(gspca_dev, i2cOV) < 0) | 588 | if (i2c_w(gspca_dev, i2cOV) < 0) |
493 | goto err; | 589 | goto err; |
@@ -545,9 +641,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
545 | goto err; | 641 | goto err; |
546 | break; | 642 | break; |
547 | } | 643 | } |
548 | case SENSOR_TAS5110: | ||
549 | /* FIXME figure out howto control brightness on TAS5110 */ | ||
550 | break; | ||
551 | } | 644 | } |
552 | return; | 645 | return; |
553 | err: | 646 | err: |
@@ -577,7 +670,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
577 | case SENSOR_OV7630: { | 670 | case SENSOR_OV7630: { |
578 | __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; | 671 | __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; |
579 | 672 | ||
580 | i2c[1] = sd->sensor_addr; | 673 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
581 | i2c[3] = gain >> 2; | 674 | i2c[3] = gain >> 2; |
582 | if (i2c_w(gspca_dev, i2c) < 0) | 675 | if (i2c_w(gspca_dev, i2c) < 0) |
583 | goto err; | 676 | goto err; |
@@ -604,7 +697,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
604 | rgb_value = gain; | 697 | rgb_value = gain; |
605 | reg_w(gspca_dev, 0x11, &rgb_value, 1); | 698 | reg_w(gspca_dev, 0x11, &rgb_value, 1); |
606 | 699 | ||
607 | if (sd->sensor_has_gain) | 700 | if (sensor_data[sd->sensor].flags & F_GAIN) |
608 | setsensorgain(gspca_dev); | 701 | setsensorgain(gspca_dev); |
609 | } | 702 | } |
610 | 703 | ||
@@ -665,6 +758,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
665 | else if (reg11 > 16) | 758 | else if (reg11 > 16) |
666 | reg11 = 16; | 759 | reg11 = 16; |
667 | 760 | ||
761 | /* In 640x480, if the reg11 has less than 3, the image is | ||
762 | unstable (not enough bandwidth). */ | ||
763 | if (gspca_dev->width == 640 && reg11 < 3) | ||
764 | reg11 = 3; | ||
765 | |||
668 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | 766 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
669 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ | 767 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ |
670 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); | 768 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); |
@@ -678,13 +776,8 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
678 | else if (reg10 > reg10_max) | 776 | else if (reg10 > reg10_max) |
679 | reg10 = reg10_max; | 777 | reg10 = reg10_max; |
680 | 778 | ||
681 | /* In 640x480, if the reg11 has less than 3, the image is | ||
682 | unstable (not enough bandwidth). */ | ||
683 | if (gspca_dev->width == 640 && reg11 < 3) | ||
684 | reg11 = 3; | ||
685 | |||
686 | /* Write reg 10 and reg11 low nibble */ | 779 | /* Write reg 10 and reg11 low nibble */ |
687 | i2c[1] = sd->sensor_addr; | 780 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
688 | i2c[3] = reg10; | 781 | i2c[3] = reg10; |
689 | i2c[4] |= reg11 - 1; | 782 | i2c[4] |= reg11 - 1; |
690 | 783 | ||
@@ -724,7 +817,7 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
724 | ? 0x4f : 0x8a; | 817 | ? 0x4f : 0x8a; |
725 | break; | 818 | break; |
726 | } | 819 | } |
727 | i2c[1] = sd->sensor_addr; | 820 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
728 | if (i2c_w(gspca_dev, i2c) < 0) | 821 | if (i2c_w(gspca_dev, i2c) < 0) |
729 | PDEBUG(D_ERR, "i2c error setfreq"); | 822 | PDEBUG(D_ERR, "i2c error setfreq"); |
730 | break; | 823 | break; |
@@ -757,30 +850,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
757 | { | 850 | { |
758 | struct sd *sd = (struct sd *) gspca_dev; | 851 | struct sd *sd = (struct sd *) gspca_dev; |
759 | struct cam *cam; | 852 | struct cam *cam; |
760 | int sif = 0; | ||
761 | 853 | ||
762 | /* nctrls depends upon the sensor, so we use a per cam copy */ | 854 | reg_r(gspca_dev, 0x00); |
763 | memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc)); | 855 | if (gspca_dev->usb_buf[0] != 0x10) |
764 | gspca_dev->sd_desc = &sd->sd_desc; | 856 | return -ENODEV; |
765 | 857 | ||
766 | /* copy the webcam info from the device id */ | 858 | /* copy the webcam info from the device id */ |
767 | sd->sensor = (id->driver_info >> 24) & 0xff; | 859 | sd->sensor = id->driver_info >> 8; |
768 | if (id->driver_info & (F_GAIN << 16)) | 860 | sd->bridge = id->driver_info & 0xff; |
769 | sd->sensor_has_gain = 1; | 861 | gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; |
770 | if (id->driver_info & (F_AUTO << 16)) | ||
771 | sd->sd_desc.dq_callback = do_autogain; | ||
772 | if (id->driver_info & (F_SIF << 16)) | ||
773 | sif = 1; | ||
774 | if (id->driver_info & (F_H18 << 16)) | ||
775 | sd->fr_h_sz = 18; /* size of frame header */ | ||
776 | else | ||
777 | sd->fr_h_sz = 12; | ||
778 | sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff; | ||
779 | sd->sensor_addr = id->driver_info & 0xff; | ||
780 | 862 | ||
781 | cam = &gspca_dev->cam; | 863 | cam = &gspca_dev->cam; |
782 | cam->epaddr = 0x01; | 864 | cam->epaddr = 0x01; |
783 | if (!sif) { | 865 | if (!(sensor_data[sd->sensor].flags & F_SIF)) { |
784 | cam->cam_mode = vga_mode; | 866 | cam->cam_mode = vga_mode; |
785 | cam->nmodes = ARRAY_SIZE(vga_mode); | 867 | cam->nmodes = ARRAY_SIZE(vga_mode); |
786 | } else { | 868 | } else { |
@@ -790,157 +872,98 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
790 | sd->brightness = BRIGHTNESS_DEF; | 872 | sd->brightness = BRIGHTNESS_DEF; |
791 | sd->gain = GAIN_DEF; | 873 | sd->gain = GAIN_DEF; |
792 | sd->exposure = EXPOSURE_DEF; | 874 | sd->exposure = EXPOSURE_DEF; |
793 | sd->autogain = AUTOGAIN_DEF; | 875 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) |
876 | sd->autogain = 0; /* Disable do_autogain callback */ | ||
877 | else | ||
878 | sd->autogain = AUTOGAIN_DEF; | ||
794 | sd->freq = FREQ_DEF; | 879 | sd->freq = FREQ_DEF; |
795 | 880 | ||
796 | return 0; | 881 | return 0; |
797 | } | 882 | } |
798 | 883 | ||
799 | /* this function is called at open time */ | 884 | /* this function is called at probe and resume time */ |
800 | static int sd_open(struct gspca_dev *gspca_dev) | 885 | static int sd_init(struct gspca_dev *gspca_dev) |
801 | { | 886 | { |
802 | reg_r(gspca_dev, 0x00); | 887 | const __u8 stop = 0x09; /* Disable stream turn of LED */ |
803 | if (gspca_dev->usb_buf[0] != 0x10) | ||
804 | return -ENODEV; | ||
805 | return 0; | ||
806 | } | ||
807 | 888 | ||
808 | static void pas106_i2cinit(struct gspca_dev *gspca_dev) | 889 | reg_w(gspca_dev, 0x01, &stop, 1); |
809 | { | 890 | |
810 | int i; | 891 | return 0; |
811 | const __u8 *data; | ||
812 | __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 }; | ||
813 | |||
814 | i = ARRAY_SIZE(pas106_data); | ||
815 | data = pas106_data[0]; | ||
816 | while (--i >= 0) { | ||
817 | memcpy(&i2c1[2], data, 2); | ||
818 | /* copy 2 bytes from the template */ | ||
819 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
820 | PDEBUG(D_ERR, "i2c error pas106"); | ||
821 | data += 2; | ||
822 | } | ||
823 | } | 892 | } |
824 | 893 | ||
825 | /* -- start the camera -- */ | 894 | /* -- start the camera -- */ |
826 | static void sd_start(struct gspca_dev *gspca_dev) | 895 | static void sd_start(struct gspca_dev *gspca_dev) |
827 | { | 896 | { |
828 | struct sd *sd = (struct sd *) gspca_dev; | 897 | struct sd *sd = (struct sd *) gspca_dev; |
829 | int mode, l = 0x1f; | 898 | struct cam *cam = &gspca_dev->cam; |
899 | int mode, l; | ||
830 | const __u8 *sn9c10x; | 900 | const __u8 *sn9c10x; |
831 | __u8 reg17_19[3]; | 901 | __u8 reg12_19[8]; |
832 | 902 | ||
833 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 903 | mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; |
904 | sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; | ||
905 | l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; | ||
906 | memcpy(reg12_19, &sn9c10x[0x12 - 1], 8); | ||
907 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); | ||
908 | /* Special cases where reg 17 and or 19 value depends on mode */ | ||
834 | switch (sd->sensor) { | 909 | switch (sd->sensor) { |
835 | case SENSOR_HV7131R: | ||
836 | sn9c10x = initHv7131; | ||
837 | reg17_19[0] = 0x60; | ||
838 | reg17_19[1] = (mode << 4) | 0x8a; | ||
839 | reg17_19[2] = 0x20; | ||
840 | break; | ||
841 | case SENSOR_OV6650: | ||
842 | sn9c10x = initOv6650; | ||
843 | reg17_19[0] = 0x68; | ||
844 | reg17_19[1] = (mode << 4) | 0x8b; | ||
845 | reg17_19[2] = 0x20; | ||
846 | break; | ||
847 | case SENSOR_OV7630: | ||
848 | if (sd->fr_h_sz == 18) { /* SN9C103 */ | ||
849 | sn9c10x = initOv7630_3; | ||
850 | l = sizeof initOv7630_3; | ||
851 | } else | ||
852 | sn9c10x = initOv7630; | ||
853 | reg17_19[0] = 0x68; | ||
854 | reg17_19[1] = (mode << 4) | COMP2; | ||
855 | reg17_19[2] = MCK_INIT1; | ||
856 | break; | ||
857 | case SENSOR_PAS106: | ||
858 | sn9c10x = initPas106; | ||
859 | reg17_19[0] = 0x24; /* 0x28 */ | ||
860 | reg17_19[1] = (mode << 4) | COMP1; | ||
861 | reg17_19[2] = MCK_INIT1; | ||
862 | break; | ||
863 | case SENSOR_PAS202: | 910 | case SENSOR_PAS202: |
864 | sn9c10x = initPas202; | 911 | reg12_19[5] = mode ? 0x24 : 0x20; |
865 | reg17_19[0] = mode ? 0x24 : 0x20; | ||
866 | reg17_19[1] = (mode << 4) | 0x89; | ||
867 | reg17_19[2] = 0x20; | ||
868 | break; | 912 | break; |
869 | case SENSOR_TAS5110: | 913 | case SENSOR_TAS5130CXX: |
870 | sn9c10x = initTas5110; | 914 | /* probably not mode specific at all most likely the upper |
871 | reg17_19[0] = 0x60; | 915 | nibble of 0x19 is exposure (clock divider) just as with |
872 | reg17_19[1] = (mode << 4) | 0x86; | 916 | the tas5110, we need someone to test this. */ |
873 | reg17_19[2] = 0x2b; /* 0xf3; */ | 917 | reg12_19[7] = mode ? 0x23 : 0x43; |
874 | break; | ||
875 | default: | ||
876 | /* case SENSOR_TAS5130CXX: */ | ||
877 | sn9c10x = initTas5130; | ||
878 | reg17_19[0] = 0x60; | ||
879 | reg17_19[1] = (mode << 4) | COMP; | ||
880 | reg17_19[2] = mode ? 0x23 : 0x43; | ||
881 | break; | 918 | break; |
882 | } | 919 | } |
920 | /* Disable compression when the raw bayer format has been selected */ | ||
921 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) | ||
922 | reg12_19[6] &= ~0x80; | ||
923 | |||
924 | /* Vga mode emulation on SIF sensor? */ | ||
925 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { | ||
926 | reg12_19[0] += 16; /* 0x12: hstart adjust */ | ||
927 | reg12_19[1] += 24; /* 0x13: vstart adjust */ | ||
928 | reg12_19[3] = 320 / 16; /* 0x15: hsize */ | ||
929 | reg12_19[4] = 240 / 16; /* 0x16: vsize */ | ||
930 | } | ||
883 | 931 | ||
884 | /* reg 0x01 bit 2 video transfert on */ | 932 | /* reg 0x01 bit 2 video transfert on */ |
885 | reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); | 933 | reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); |
886 | /* reg 0x17 SensorClk enable inv Clk 0x60 */ | 934 | /* reg 0x17 SensorClk enable inv Clk 0x60 */ |
887 | reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); | 935 | reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); |
888 | /* Set the registers from the template */ | 936 | /* Set the registers from the template */ |
889 | reg_w_big(gspca_dev, 0x01, sn9c10x, l); | 937 | reg_w(gspca_dev, 0x01, sn9c10x, l); |
890 | switch (sd->sensor) { | 938 | |
891 | case SENSOR_HV7131R: | 939 | /* Init the sensor */ |
892 | i2c_w_vector(gspca_dev, hv7131_sensor_init, | 940 | i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init, |
893 | sizeof hv7131_sensor_init); | 941 | sensor_data[sd->sensor].sensor_init_size); |
894 | break; | 942 | if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge]) |
895 | case SENSOR_OV6650: | 943 | i2c_w_vector(gspca_dev, |
896 | i2c_w_vector(gspca_dev, ov6650_sensor_init, | 944 | sensor_data[sd->sensor].sensor_bridge_init[sd->bridge], |
897 | sizeof ov6650_sensor_init); | 945 | sensor_data[sd->sensor].sensor_bridge_init_size[ |
898 | break; | 946 | sd->bridge]); |
899 | case SENSOR_OV7630: | 947 | |
900 | i2c_w_vector(gspca_dev, ov7630_sensor_init, | ||
901 | sizeof ov7630_sensor_init); | ||
902 | if (sd->fr_h_sz == 18) { /* SN9C103 */ | ||
903 | const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00, | ||
904 | 0x00, 0x00, 0x10 }; | ||
905 | i2c_w(gspca_dev, i2c); | ||
906 | } | ||
907 | break; | ||
908 | case SENSOR_PAS106: | ||
909 | pas106_i2cinit(gspca_dev); | ||
910 | break; | ||
911 | case SENSOR_PAS202: | ||
912 | i2c_w_vector(gspca_dev, pas202_sensor_init, | ||
913 | sizeof pas202_sensor_init); | ||
914 | break; | ||
915 | case SENSOR_TAS5110: | ||
916 | i2c_w_vector(gspca_dev, tas5110_sensor_init, | ||
917 | sizeof tas5110_sensor_init); | ||
918 | break; | ||
919 | default: | ||
920 | /* case SENSOR_TAS5130CXX: */ | ||
921 | i2c_w_vector(gspca_dev, tas5130_sensor_init, | ||
922 | sizeof tas5130_sensor_init); | ||
923 | break; | ||
924 | } | ||
925 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ | 948 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
926 | reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); | 949 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); |
927 | /* compression register */ | 950 | /* compression register */ |
928 | reg_w(gspca_dev, 0x18, ®17_19[1], 1); | 951 | reg_w(gspca_dev, 0x18, ®12_19[6], 1); |
929 | /* H_start */ | 952 | /* H_start */ |
930 | reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); | 953 | reg_w(gspca_dev, 0x12, ®12_19[0], 1); |
931 | /* V_START */ | 954 | /* V_START */ |
932 | reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); | 955 | reg_w(gspca_dev, 0x13, ®12_19[1], 1); |
933 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ | 956 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ |
934 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ | 957 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ |
935 | reg_w(gspca_dev, 0x17, ®17_19[0], 1); | 958 | reg_w(gspca_dev, 0x17, ®12_19[5], 1); |
936 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ | 959 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ |
937 | reg_w(gspca_dev, 0x19, ®17_19[2], 1); | 960 | reg_w(gspca_dev, 0x19, ®12_19[7], 1); |
938 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ | 961 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ |
939 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); | 962 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); |
940 | /* Enable video transfert */ | 963 | /* Enable video transfert */ |
941 | reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); | 964 | reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); |
942 | /* Compression */ | 965 | /* Compression */ |
943 | reg_w(gspca_dev, 0x18, ®17_19[1], 2); | 966 | reg_w(gspca_dev, 0x18, ®12_19[6], 2); |
944 | msleep(20); | 967 | msleep(20); |
945 | 968 | ||
946 | sd->reg11 = -1; | 969 | sd->reg11 = -1; |
@@ -957,18 +980,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
957 | 980 | ||
958 | static void sd_stopN(struct gspca_dev *gspca_dev) | 981 | static void sd_stopN(struct gspca_dev *gspca_dev) |
959 | { | 982 | { |
960 | __u8 ByteSend; | 983 | sd_init(gspca_dev); |
961 | |||
962 | ByteSend = 0x09; /* 0X00 */ | ||
963 | reg_w(gspca_dev, 0x01, &ByteSend, 1); | ||
964 | } | ||
965 | |||
966 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
967 | { | ||
968 | } | ||
969 | |||
970 | static void sd_close(struct gspca_dev *gspca_dev) | ||
971 | { | ||
972 | } | 984 | } |
973 | 985 | ||
974 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 986 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
@@ -978,6 +990,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
978 | { | 990 | { |
979 | int i; | 991 | int i; |
980 | struct sd *sd = (struct sd *) gspca_dev; | 992 | struct sd *sd = (struct sd *) gspca_dev; |
993 | struct cam *cam = &gspca_dev->cam; | ||
981 | 994 | ||
982 | /* frames start with: | 995 | /* frames start with: |
983 | * ff ff 00 c4 c4 96 synchro | 996 | * ff ff 00 c4 c4 96 synchro |
@@ -998,20 +1011,31 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
998 | && data[5 + i] == 0x96) { /* start of frame */ | 1011 | && data[5 + i] == 0x96) { /* start of frame */ |
999 | int lum = -1; | 1012 | int lum = -1; |
1000 | int pkt_type = LAST_PACKET; | 1013 | int pkt_type = LAST_PACKET; |
1014 | int fr_h_sz = (sd->bridge == BRIDGE_103) ? | ||
1015 | 18 : 12; | ||
1001 | 1016 | ||
1002 | if (len - i < sd->fr_h_sz) { | 1017 | if (len - i < fr_h_sz) { |
1003 | PDEBUG(D_STREAM, "packet too short to" | 1018 | PDEBUG(D_STREAM, "packet too short to" |
1004 | " get avg brightness"); | 1019 | " get avg brightness"); |
1005 | } else if (sd->fr_h_sz == 12) { | 1020 | } else if (sd->bridge == BRIDGE_103) { |
1006 | lum = data[i + 8] + (data[i + 9] << 8); | ||
1007 | } else { | ||
1008 | lum = data[i + 9] + | 1021 | lum = data[i + 9] + |
1009 | (data[i + 10] << 8); | 1022 | (data[i + 10] << 8); |
1023 | } else { | ||
1024 | lum = data[i + 8] + (data[i + 9] << 8); | ||
1010 | } | 1025 | } |
1011 | if (lum == 0) { | 1026 | /* When exposure changes midway a frame we |
1027 | get a lum of 0 in this case drop 2 frames | ||
1028 | as the frames directly after an exposure | ||
1029 | change have an unstable image. Sometimes lum | ||
1030 | *really* is 0 (cam used in low light with | ||
1031 | low exposure setting), so do not drop frames | ||
1032 | if the previous lum was 0 too. */ | ||
1033 | if (lum == 0 && sd->prev_avg_lum != 0) { | ||
1012 | lum = -1; | 1034 | lum = -1; |
1013 | sd->frames_to_drop = 2; | 1035 | sd->frames_to_drop = 2; |
1014 | } | 1036 | sd->prev_avg_lum = 0; |
1037 | } else | ||
1038 | sd->prev_avg_lum = lum; | ||
1015 | atomic_set(&sd->avg_lum, lum); | 1039 | atomic_set(&sd->avg_lum, lum); |
1016 | 1040 | ||
1017 | if (sd->frames_to_drop) { | 1041 | if (sd->frames_to_drop) { |
@@ -1021,14 +1045,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1021 | 1045 | ||
1022 | frame = gspca_frame_add(gspca_dev, pkt_type, | 1046 | frame = gspca_frame_add(gspca_dev, pkt_type, |
1023 | frame, data, 0); | 1047 | frame, data, 0); |
1024 | data += i + sd->fr_h_sz; | 1048 | data += i + fr_h_sz; |
1025 | len -= i + sd->fr_h_sz; | 1049 | len -= i + fr_h_sz; |
1026 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 1050 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
1027 | frame, data, len); | 1051 | frame, data, len); |
1028 | return; | 1052 | return; |
1029 | } | 1053 | } |
1030 | } | 1054 | } |
1031 | } | 1055 | } |
1056 | |||
1057 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { | ||
1058 | /* In raw mode we sometimes get some garbage after the frame | ||
1059 | ignore this */ | ||
1060 | int used = frame->data_end - frame->data; | ||
1061 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; | ||
1062 | |||
1063 | if (used + len > size) | ||
1064 | len = size - used; | ||
1065 | } | ||
1066 | |||
1032 | gspca_frame_add(gspca_dev, INTER_PACKET, | 1067 | gspca_frame_add(gspca_dev, INTER_PACKET, |
1033 | frame, data, len); | 1068 | frame, data, len); |
1034 | } | 1069 | } |
@@ -1162,58 +1197,45 @@ static const struct sd_desc sd_desc = { | |||
1162 | .ctrls = sd_ctrls, | 1197 | .ctrls = sd_ctrls, |
1163 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1198 | .nctrls = ARRAY_SIZE(sd_ctrls), |
1164 | .config = sd_config, | 1199 | .config = sd_config, |
1165 | .open = sd_open, | 1200 | .init = sd_init, |
1166 | .start = sd_start, | 1201 | .start = sd_start, |
1167 | .stopN = sd_stopN, | 1202 | .stopN = sd_stopN, |
1168 | .stop0 = sd_stop0, | ||
1169 | .close = sd_close, | ||
1170 | .pkt_scan = sd_pkt_scan, | 1203 | .pkt_scan = sd_pkt_scan, |
1171 | .querymenu = sd_querymenu, | 1204 | .querymenu = sd_querymenu, |
1205 | .dq_callback = do_autogain, | ||
1172 | }; | 1206 | }; |
1173 | 1207 | ||
1174 | /* -- module initialisation -- */ | 1208 | /* -- module initialisation -- */ |
1175 | #define SFCI(sensor, flags, nctrls, i2c_addr) \ | 1209 | #define SB(sensor, bridge) \ |
1176 | .driver_info = (SENSOR_ ## sensor << 24) \ | 1210 | .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge |
1177 | | ((flags) << 16) \ | 1211 | |
1178 | | ((nctrls) << 8) \ | 1212 | |
1179 | | (i2c_addr) | ||
1180 | static __devinitdata struct usb_device_id device_table[] = { | 1213 | static __devinitdata struct usb_device_id device_table[] = { |
1181 | #ifndef CONFIG_USB_SN9C102 | 1214 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ |
1182 | {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */ | 1215 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ |
1183 | SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, | 1216 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1184 | {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */ | 1217 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ |
1185 | SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, | 1218 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, |
1186 | {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */ | 1219 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, |
1187 | SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, | ||
1188 | {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */ | ||
1189 | SFCI(PAS106, F_SIF, 2, 0)}, | ||
1190 | {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */ | ||
1191 | SFCI(PAS106, F_SIF, 2, 0)}, | ||
1192 | #endif | 1220 | #endif |
1193 | {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */ | 1221 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, |
1194 | SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)}, | 1222 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1195 | #ifndef CONFIG_USB_SN9C102 | 1223 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, |
1196 | {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */ | 1224 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, |
1197 | SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, | 1225 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, |
1198 | {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */ | 1226 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, |
1199 | SFCI(TAS5130CXX, 0, 2, 0)}, | 1227 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, |
1200 | {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */ | 1228 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, |
1201 | SFCI(TAS5130CXX, 0, 2, 0)}, | ||
1202 | {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */ | ||
1203 | SFCI(PAS202, 0, 2, 0)}, | ||
1204 | {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */ | ||
1205 | SFCI(PAS106, F_SIF, 2, 0)}, | ||
1206 | {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */ | ||
1207 | SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, | ||
1208 | {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */ | ||
1209 | SFCI(HV7131R, 0, 2, 0)}, | ||
1210 | {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */ | ||
1211 | SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, | ||
1212 | {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */ | ||
1213 | SFCI(PAS202, F_H18, 2, 0)}, | ||
1214 | {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */ | ||
1215 | SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)}, | ||
1216 | #endif | 1229 | #endif |
1230 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, | ||
1231 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | ||
1232 | {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, | ||
1233 | #endif | ||
1234 | {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, | ||
1235 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | ||
1236 | {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, | ||
1237 | #endif | ||
1238 | {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, | ||
1217 | {} | 1239 | {} |
1218 | }; | 1240 | }; |
1219 | MODULE_DEVICE_TABLE(usb, device_table); | 1241 | MODULE_DEVICE_TABLE(usb, device_table); |
@@ -1231,6 +1253,10 @@ static struct usb_driver sd_driver = { | |||
1231 | .id_table = device_table, | 1253 | .id_table = device_table, |
1232 | .probe = sd_probe, | 1254 | .probe = sd_probe, |
1233 | .disconnect = gspca_disconnect, | 1255 | .disconnect = gspca_disconnect, |
1256 | #ifdef CONFIG_PM | ||
1257 | .suspend = gspca_suspend, | ||
1258 | .resume = gspca_resume, | ||
1259 | #endif | ||
1234 | }; | 1260 | }; |
1235 | 1261 | ||
1236 | /* -- module insert / remove -- */ | 1262 | /* -- module insert / remove -- */ |