diff options
Diffstat (limited to 'drivers/media/video/gspca/tv8532.c')
-rw-r--r-- | drivers/media/video/gspca/tv8532.c | 227 |
1 files changed, 78 insertions, 149 deletions
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index c7b6eb1e04d5..d9c5bf3449d4 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -30,29 +30,46 @@ MODULE_LICENSE("GPL"); | |||
30 | struct sd { | 30 | struct sd { |
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 31 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
32 | 32 | ||
33 | __u16 brightness; | 33 | __u16 exposure; |
34 | __u16 gain; | ||
34 | 35 | ||
35 | __u8 packet; | 36 | __u8 packet; |
36 | }; | 37 | }; |
37 | 38 | ||
38 | /* V4L2 controls supported by the driver */ | 39 | /* V4L2 controls supported by the driver */ |
39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 40 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 41 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
42 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
41 | 44 | ||
42 | static const struct ctrl sd_ctrls[] = { | 45 | static const struct ctrl sd_ctrls[] = { |
43 | { | 46 | { |
44 | { | 47 | { |
45 | .id = V4L2_CID_BRIGHTNESS, | 48 | .id = V4L2_CID_EXPOSURE, |
46 | .type = V4L2_CTRL_TYPE_INTEGER, | 49 | .type = V4L2_CTRL_TYPE_INTEGER, |
47 | .name = "Brightness", | 50 | .name = "Exposure", |
48 | .minimum = 1, | 51 | .minimum = 1, |
49 | .maximum = 0x15f, /* = 352 - 1 */ | 52 | .maximum = 0x18f, |
50 | .step = 1, | 53 | .step = 1, |
51 | #define BRIGHTNESS_DEF 0x14c | 54 | #define EXPOSURE_DEF 0x18f |
52 | .default_value = BRIGHTNESS_DEF, | 55 | .default_value = EXPOSURE_DEF, |
53 | }, | 56 | }, |
54 | .set = sd_setbrightness, | 57 | .set = sd_setexposure, |
55 | .get = sd_getbrightness, | 58 | .get = sd_getexposure, |
59 | }, | ||
60 | { | ||
61 | { | ||
62 | .id = V4L2_CID_GAIN, | ||
63 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
64 | .name = "Gain", | ||
65 | .minimum = 0, | ||
66 | .maximum = 0x7ff, | ||
67 | .step = 1, | ||
68 | #define GAIN_DEF 0x100 | ||
69 | .default_value = GAIN_DEF, | ||
70 | }, | ||
71 | .set = sd_setgain, | ||
72 | .get = sd_getgain, | ||
56 | }, | 73 | }, |
57 | }; | 74 | }; |
58 | 75 | ||
@@ -92,6 +109,14 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
92 | #define R14_AD_ROW_BEGINL 0x14 | 109 | #define R14_AD_ROW_BEGINL 0x14 |
93 | #define R15_AD_ROWBEGINH 0x15 | 110 | #define R15_AD_ROWBEGINH 0x15 |
94 | #define R1C_AD_EXPOSE_TIMEL 0x1c | 111 | #define R1C_AD_EXPOSE_TIMEL 0x1c |
112 | #define R20_GAIN_G1L 0x20 | ||
113 | #define R21_GAIN_G1H 0x21 | ||
114 | #define R22_GAIN_RL 0x22 | ||
115 | #define R23_GAIN_RH 0x23 | ||
116 | #define R24_GAIN_BL 0x24 | ||
117 | #define R25_GAIN_BH 0x25 | ||
118 | #define R26_GAIN_G2L 0x26 | ||
119 | #define R27_GAIN_G2H 0x27 | ||
95 | #define R28_QUANT 0x28 | 120 | #define R28_QUANT 0x28 |
96 | #define R29_LINE 0x29 | 121 | #define R29_LINE 0x29 |
97 | #define R2C_POLARITY 0x2c | 122 | #define R2C_POLARITY 0x2c |
@@ -129,18 +154,6 @@ static const u8 eeprom_data[][3] = { | |||
129 | {0x05, 0x09, 0xf1}, | 154 | {0x05, 0x09, 0xf1}, |
130 | }; | 155 | }; |
131 | 156 | ||
132 | static int reg_r(struct gspca_dev *gspca_dev, | ||
133 | __u16 index) | ||
134 | { | ||
135 | usb_control_msg(gspca_dev->dev, | ||
136 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
137 | 0x03, | ||
138 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
139 | 0, /* value */ | ||
140 | index, gspca_dev->usb_buf, 1, | ||
141 | 500); | ||
142 | return gspca_dev->usb_buf[0]; | ||
143 | } | ||
144 | 157 | ||
145 | /* write 1 byte */ | 158 | /* write 1 byte */ |
146 | static void reg_w1(struct gspca_dev *gspca_dev, | 159 | static void reg_w1(struct gspca_dev *gspca_dev, |
@@ -183,7 +196,6 @@ static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev) | |||
183 | } | 196 | } |
184 | reg_w1(gspca_dev, R07_TABLE_LEN, i); | 197 | reg_w1(gspca_dev, R07_TABLE_LEN, i); |
185 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); | 198 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); |
186 | msleep(10); | ||
187 | } | 199 | } |
188 | 200 | ||
189 | /* this function is called at probe time */ | 201 | /* this function is called at probe time */ |
@@ -197,53 +209,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
197 | cam->cam_mode = sif_mode; | 209 | cam->cam_mode = sif_mode; |
198 | cam->nmodes = ARRAY_SIZE(sif_mode); | 210 | cam->nmodes = ARRAY_SIZE(sif_mode); |
199 | 211 | ||
200 | sd->brightness = BRIGHTNESS_DEF; | 212 | sd->exposure = EXPOSURE_DEF; |
213 | sd->gain = GAIN_DEF; | ||
201 | return 0; | 214 | return 0; |
202 | } | 215 | } |
203 | 216 | ||
204 | static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev) | ||
205 | { | ||
206 | int i; | ||
207 | static u8 reg_tb[] = { | ||
208 | R0C_AD_WIDTHL, | ||
209 | R0D_AD_WIDTHH, | ||
210 | R28_QUANT, | ||
211 | R29_LINE, | ||
212 | R2C_POLARITY, | ||
213 | R2D_POINT, | ||
214 | R2E_POINTH, | ||
215 | R2F_POINTB, | ||
216 | R30_POINTBH, | ||
217 | R2A_HIGH_BUDGET, | ||
218 | R2B_LOW_BUDGET, | ||
219 | R34_VID, | ||
220 | R35_VIDH, | ||
221 | R36_PID, | ||
222 | R37_PIDH, | ||
223 | R83_AD_IDH, | ||
224 | R10_AD_COL_BEGINL, | ||
225 | R11_AD_COL_BEGINH, | ||
226 | R14_AD_ROW_BEGINL, | ||
227 | R15_AD_ROWBEGINH, | ||
228 | 0 | ||
229 | }; | ||
230 | |||
231 | i = 0; | ||
232 | do { | ||
233 | reg_r(gspca_dev, reg_tb[i]); | ||
234 | i++; | ||
235 | } while (reg_tb[i] != 0); | ||
236 | } | ||
237 | |||
238 | static void tv_8532_setReg(struct gspca_dev *gspca_dev) | 217 | static void tv_8532_setReg(struct gspca_dev *gspca_dev) |
239 | { | 218 | { |
240 | reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); | ||
241 | /* begin active line */ | ||
242 | reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); | ||
243 | /* mirror and digital gain */ | ||
244 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | ||
245 | /* = 0x84 */ | ||
246 | |||
247 | reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ | 219 | reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ |
248 | /******************************************************/ | 220 | /******************************************************/ |
249 | reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); | 221 | reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); |
@@ -255,100 +227,43 @@ static void tv_8532_setReg(struct gspca_dev *gspca_dev) | |||
255 | /* mirror and digital gain */ | 227 | /* mirror and digital gain */ |
256 | reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); | 228 | reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); |
257 | 229 | ||
258 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); | ||
259 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); | 230 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); |
260 | |||
261 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); | ||
262 | |||
263 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); | 231 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); |
264 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 232 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); |
265 | /* = 0x84 */ | 233 | /* = 0x84 */ |
266 | } | 234 | } |
267 | 235 | ||
268 | static void tv_8532_PollReg(struct gspca_dev *gspca_dev) | ||
269 | { | ||
270 | int i; | ||
271 | |||
272 | /* strange polling from tgc */ | ||
273 | for (i = 0; i < 10; i++) { | ||
274 | reg_w1(gspca_dev, R2C_POLARITY, 0x10); | ||
275 | reg_w1(gspca_dev, R00_PART_CONTROL, | ||
276 | LATENT_CHANGE | EXPO_CHANGE); | ||
277 | reg_w1(gspca_dev, R31_UPD, 0x01); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* this function is called at probe and resume time */ | 236 | /* this function is called at probe and resume time */ |
282 | static int sd_init(struct gspca_dev *gspca_dev) | 237 | static int sd_init(struct gspca_dev *gspca_dev) |
283 | { | 238 | { |
284 | tv_8532WriteEEprom(gspca_dev); | 239 | tv_8532WriteEEprom(gspca_dev); |
285 | 240 | ||
286 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, | ||
287 | * slope rate 2 */ | ||
288 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); | ||
289 | tv_8532ReadRegisters(gspca_dev); | ||
290 | reg_w1(gspca_dev, R3B_Test3, 0x0b); | ||
291 | reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); | ||
292 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); | ||
293 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); | ||
294 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); | ||
295 | |||
296 | /*******************************************************************/ | ||
297 | reg_w1(gspca_dev, R28_QUANT, 0x90); | ||
298 | /* no compress - fixed Q - quant 0 */ | ||
299 | reg_w1(gspca_dev, R29_LINE, 0x81); | ||
300 | /* 0x84; // CIF | 4 packet 0x29 */ | ||
301 | |||
302 | /************************************************/ | ||
303 | reg_w1(gspca_dev, R2C_POLARITY, 0x10); | ||
304 | /* 0x48; //0x08; 0x2c */ | ||
305 | reg_w1(gspca_dev, R2D_POINT, 0x14); | ||
306 | /* 0x38; 0x2d */ | ||
307 | reg_w1(gspca_dev, R2E_POINTH, 0x01); | ||
308 | /* 0x04; 0x2e */ | ||
309 | reg_w1(gspca_dev, R2F_POINTB, 0x12); | ||
310 | /* 0x04; 0x2f */ | ||
311 | reg_w1(gspca_dev, R30_POINTBH, 0x01); | ||
312 | /* 0x04; 0x30 */ | ||
313 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | ||
314 | /* 0x00<-0x84 */ | ||
315 | /*************************************************/ | ||
316 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ | ||
317 | msleep(200); | ||
318 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | ||
319 | /*************************************************/ | ||
320 | tv_8532_setReg(gspca_dev); | ||
321 | /*************************************************/ | ||
322 | reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ | ||
323 | /*************************************************/ | ||
324 | tv_8532_setReg(gspca_dev); | ||
325 | /*************************************************/ | ||
326 | tv_8532_PollReg(gspca_dev); | ||
327 | return 0; | 241 | return 0; |
328 | } | 242 | } |
329 | 243 | ||
330 | static void setbrightness(struct gspca_dev *gspca_dev) | 244 | static void setexposure(struct gspca_dev *gspca_dev) |
331 | { | 245 | { |
332 | struct sd *sd = (struct sd *) gspca_dev; | 246 | struct sd *sd = (struct sd *) gspca_dev; |
333 | 247 | ||
334 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->brightness); | 248 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->exposure); |
335 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 249 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); |
336 | /* 0x84 */ | 250 | /* 0x84 */ |
337 | } | 251 | } |
338 | 252 | ||
339 | /* -- start the camera -- */ | 253 | static void setgain(struct gspca_dev *gspca_dev) |
340 | static int sd_start(struct gspca_dev *gspca_dev) | ||
341 | { | 254 | { |
342 | struct sd *sd = (struct sd *) gspca_dev; | 255 | struct sd *sd = (struct sd *) gspca_dev; |
343 | 256 | ||
344 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, | 257 | reg_w2(gspca_dev, R20_GAIN_G1L, sd->gain); |
345 | * slope rate 2 */ | 258 | reg_w2(gspca_dev, R22_GAIN_RL, sd->gain); |
346 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); | 259 | reg_w2(gspca_dev, R24_GAIN_BL, sd->gain); |
347 | tv_8532ReadRegisters(gspca_dev); | 260 | reg_w2(gspca_dev, R26_GAIN_G2L, sd->gain); |
348 | reg_w1(gspca_dev, R3B_Test3, 0x0b); | 261 | } |
349 | 262 | ||
350 | reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); | 263 | /* -- start the camera -- */ |
351 | setbrightness(gspca_dev); | 264 | static int sd_start(struct gspca_dev *gspca_dev) |
265 | { | ||
266 | struct sd *sd = (struct sd *) gspca_dev; | ||
352 | 267 | ||
353 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ | 268 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ |
354 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); | 269 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); |
@@ -371,19 +286,15 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
371 | reg_w1(gspca_dev, R2E_POINTH, 0x01); | 286 | reg_w1(gspca_dev, R2E_POINTH, 0x01); |
372 | reg_w1(gspca_dev, R2F_POINTB, 0x12); | 287 | reg_w1(gspca_dev, R2F_POINTB, 0x12); |
373 | reg_w1(gspca_dev, R30_POINTBH, 0x01); | 288 | reg_w1(gspca_dev, R30_POINTBH, 0x01); |
374 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 289 | |
290 | tv_8532_setReg(gspca_dev); | ||
291 | |||
292 | setexposure(gspca_dev); | ||
293 | setgain(gspca_dev); | ||
294 | |||
375 | /************************************************/ | 295 | /************************************************/ |
376 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ | 296 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ |
377 | msleep(200); | 297 | msleep(200); |
378 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | ||
379 | /************************************************/ | ||
380 | tv_8532_setReg(gspca_dev); | ||
381 | /************************************************/ | ||
382 | reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ | ||
383 | /************************************************/ | ||
384 | tv_8532_setReg(gspca_dev); | ||
385 | /************************************************/ | ||
386 | tv_8532_PollReg(gspca_dev); | ||
387 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | 298 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ |
388 | 299 | ||
389 | gspca_dev->empty_packet = 0; /* check the empty packets */ | 300 | gspca_dev->empty_packet = 0; /* check the empty packets */ |
@@ -428,21 +339,39 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
428 | data + gspca_dev->width + 5, gspca_dev->width); | 339 | data + gspca_dev->width + 5, gspca_dev->width); |
429 | } | 340 | } |
430 | 341 | ||
431 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 342 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) |
343 | { | ||
344 | struct sd *sd = (struct sd *) gspca_dev; | ||
345 | |||
346 | sd->exposure = val; | ||
347 | if (gspca_dev->streaming) | ||
348 | setexposure(gspca_dev); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
353 | { | ||
354 | struct sd *sd = (struct sd *) gspca_dev; | ||
355 | |||
356 | *val = sd->exposure; | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
432 | { | 361 | { |
433 | struct sd *sd = (struct sd *) gspca_dev; | 362 | struct sd *sd = (struct sd *) gspca_dev; |
434 | 363 | ||
435 | sd->brightness = val; | 364 | sd->gain = val; |
436 | if (gspca_dev->streaming) | 365 | if (gspca_dev->streaming) |
437 | setbrightness(gspca_dev); | 366 | setgain(gspca_dev); |
438 | return 0; | 367 | return 0; |
439 | } | 368 | } |
440 | 369 | ||
441 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 370 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
442 | { | 371 | { |
443 | struct sd *sd = (struct sd *) gspca_dev; | 372 | struct sd *sd = (struct sd *) gspca_dev; |
444 | 373 | ||
445 | *val = sd->brightness; | 374 | *val = sd->gain; |
446 | return 0; | 375 | return 0; |
447 | } | 376 | } |
448 | 377 | ||