3 * Driver for the ov9650 sensor
5 * Copyright (C) 2008 Erik Andrén
6 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
7 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
9 * Portions of code to USB interface and ALi driver software,
10 * Copyright (c) 2006 Willem Duinker
11 * v4l2 interface modeled after the V4L2 driver
12 * for SN9C10x PC Camera Controllers
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation, version 2.
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include "m5602_ov9650.h"
24 static int ov9650_s_ctrl(struct v4l2_ctrl
*ctrl
);
25 static void ov9650_dump_registers(struct sd
*sd
);
27 static const unsigned char preinit_ov9650
[][3] = {
29 {BRIDGE
, M5602_XB_MCU_CLK_DIV
, 0x02},
30 {BRIDGE
, M5602_XB_MCU_CLK_CTRL
, 0xb0},
31 {BRIDGE
, M5602_XB_SEN_CLK_DIV
, 0x00},
32 {BRIDGE
, M5602_XB_SEN_CLK_CTRL
, 0xb0},
33 {BRIDGE
, M5602_XB_ADC_CTRL
, 0xc0},
34 {BRIDGE
, M5602_XB_SENSOR_CTRL
, 0x00},
36 {BRIDGE
, M5602_XB_SENSOR_TYPE
, 0x08},
37 {BRIDGE
, M5602_XB_GPIO_DIR
, 0x05},
38 {BRIDGE
, M5602_XB_GPIO_DAT
, 0x04},
39 {BRIDGE
, M5602_XB_GPIO_EN_H
, 0x06},
40 {BRIDGE
, M5602_XB_GPIO_DIR_H
, 0x06},
41 {BRIDGE
, M5602_XB_GPIO_DAT_H
, 0x00},
42 {BRIDGE
, M5602_XB_GPIO_DAT
, 0x00},
43 {BRIDGE
, M5602_XB_I2C_CLK_DIV
, 0x0a},
45 {SENSOR
, OV9650_COM7
, OV9650_REGISTER_RESET
},
46 /* Enable double clock */
47 {SENSOR
, OV9650_CLKRC
, 0x80},
48 /* Do something out of spec with the power */
49 {SENSOR
, OV9650_OFON
, 0x40}
52 static const unsigned char init_ov9650
[][3] = {
54 {BRIDGE
, M5602_XB_MCU_CLK_DIV
, 0x02},
55 {BRIDGE
, M5602_XB_MCU_CLK_CTRL
, 0xb0},
56 {BRIDGE
, M5602_XB_SEN_CLK_DIV
, 0x00},
57 {BRIDGE
, M5602_XB_SEN_CLK_CTRL
, 0xb0},
58 {BRIDGE
, M5602_XB_ADC_CTRL
, 0xc0},
59 {BRIDGE
, M5602_XB_SENSOR_CTRL
, 0x00},
61 {BRIDGE
, M5602_XB_SENSOR_TYPE
, 0x08},
62 {BRIDGE
, M5602_XB_GPIO_DIR
, 0x05},
63 {BRIDGE
, M5602_XB_GPIO_DAT
, 0x04},
64 {BRIDGE
, M5602_XB_GPIO_EN_H
, 0x06},
65 {BRIDGE
, M5602_XB_GPIO_DIR_H
, 0x06},
66 {BRIDGE
, M5602_XB_GPIO_DAT_H
, 0x00},
67 {BRIDGE
, M5602_XB_GPIO_DAT
, 0x00},
68 {BRIDGE
, M5602_XB_I2C_CLK_DIV
, 0x0a},
71 {SENSOR
, OV9650_COM7
, OV9650_REGISTER_RESET
},
72 /* One extra reset is needed in order to make the sensor behave
73 properly when resuming from ram, could be a timing issue */
74 {SENSOR
, OV9650_COM7
, OV9650_REGISTER_RESET
},
76 /* Enable double clock */
77 {SENSOR
, OV9650_CLKRC
, 0x80},
78 /* Do something out of spec with the power */
79 {SENSOR
, OV9650_OFON
, 0x40},
81 /* Set fast AGC/AEC algorithm with unlimited step size */
82 {SENSOR
, OV9650_COM8
, OV9650_FAST_AGC_AEC
|
83 OV9650_AEC_UNLIM_STEP_SIZE
},
85 {SENSOR
, OV9650_CHLF
, 0x10},
86 {SENSOR
, OV9650_ARBLM
, 0xbf},
87 {SENSOR
, OV9650_ACOM38
, 0x81},
88 /* Turn off color matrix coefficient double option */
89 {SENSOR
, OV9650_COM16
, 0x00},
90 /* Enable color matrix for RGB/YUV, Delay Y channel,
91 set output Y/UV delay to 1 */
92 {SENSOR
, OV9650_COM13
, 0x19},
93 /* Enable digital BLC, Set output mode to U Y V Y */
94 {SENSOR
, OV9650_TSLB
, 0x0c},
95 /* Limit the AGC/AEC stable upper region */
96 {SENSOR
, OV9650_COM24
, 0x00},
97 /* Enable HREF and some out of spec things */
98 {SENSOR
, OV9650_COM12
, 0x73},
99 /* Set all DBLC offset signs to positive and
100 do some out of spec stuff */
101 {SENSOR
, OV9650_DBLC1
, 0xdf},
102 {SENSOR
, OV9650_COM21
, 0x06},
103 {SENSOR
, OV9650_RSVD35
, 0x91},
104 /* Necessary, no camera stream without it */
105 {SENSOR
, OV9650_RSVD16
, 0x06},
106 {SENSOR
, OV9650_RSVD94
, 0x99},
107 {SENSOR
, OV9650_RSVD95
, 0x99},
108 {SENSOR
, OV9650_RSVD96
, 0x04},
109 /* Enable full range output */
110 {SENSOR
, OV9650_COM15
, 0x0},
111 /* Enable HREF at optical black, enable ADBLC bias,
112 enable ADBLC, reset timings at format change */
113 {SENSOR
, OV9650_COM6
, 0x4b},
114 /* Subtract 32 from the B channel bias */
115 {SENSOR
, OV9650_BBIAS
, 0xa0},
116 /* Subtract 32 from the Gb channel bias */
117 {SENSOR
, OV9650_GbBIAS
, 0xa0},
118 /* Do not bypass the analog BLC and to some out of spec stuff */
119 {SENSOR
, OV9650_Gr_COM
, 0x00},
120 /* Subtract 32 from the R channel bias */
121 {SENSOR
, OV9650_RBIAS
, 0xa0},
122 /* Subtract 32 from the R channel bias */
123 {SENSOR
, OV9650_RBIAS
, 0x0},
124 {SENSOR
, OV9650_COM26
, 0x80},
125 {SENSOR
, OV9650_ACOMA9
, 0x98},
126 /* Set the AGC/AEC stable region upper limit */
127 {SENSOR
, OV9650_AEW
, 0x68},
128 /* Set the AGC/AEC stable region lower limit */
129 {SENSOR
, OV9650_AEB
, 0x5c},
130 /* Set the high and low limit nibbles to 3 */
131 {SENSOR
, OV9650_VPT
, 0xc3},
132 /* Set the Automatic Gain Ceiling (AGC) to 128x,
133 drop VSYNC at frame drop,
134 limit exposure timing,
135 drop frame when the AEC step is larger than the exposure gap */
136 {SENSOR
, OV9650_COM9
, 0x6e},
137 /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
138 and set PWDN to SLVS (slave mode vertical sync) */
139 {SENSOR
, OV9650_COM10
, 0x42},
140 /* Set horizontal column start high to default value */
141 {SENSOR
, OV9650_HSTART
, 0x1a}, /* 210 */
142 /* Set horizontal column end */
143 {SENSOR
, OV9650_HSTOP
, 0xbf}, /* 1534 */
144 /* Complementing register to the two writes above */
145 {SENSOR
, OV9650_HREF
, 0xb2},
146 /* Set vertical row start high bits */
147 {SENSOR
, OV9650_VSTRT
, 0x02},
148 /* Set vertical row end low bits */
149 {SENSOR
, OV9650_VSTOP
, 0x7e},
150 /* Set complementing vertical frame control */
151 {SENSOR
, OV9650_VREF
, 0x10},
152 {SENSOR
, OV9650_ADC
, 0x04},
153 {SENSOR
, OV9650_HV
, 0x40},
155 /* Enable denoise, and white-pixel erase */
156 {SENSOR
, OV9650_COM22
, OV9650_DENOISE_ENABLE
|
157 OV9650_WHITE_PIXEL_ENABLE
|
158 OV9650_WHITE_PIXEL_OPTION
},
160 /* Enable VARIOPIXEL */
161 {SENSOR
, OV9650_COM3
, OV9650_VARIOPIXEL
},
162 {SENSOR
, OV9650_COM4
, OV9650_QVGA_VARIOPIXEL
},
164 /* Put the sensor in soft sleep mode */
165 {SENSOR
, OV9650_COM2
, OV9650_SOFT_SLEEP
| OV9650_OUTPUT_DRIVE_2X
},
168 static const unsigned char res_init_ov9650
[][3] = {
169 {SENSOR
, OV9650_COM2
, OV9650_OUTPUT_DRIVE_2X
},
171 {BRIDGE
, M5602_XB_LINE_OF_FRAME_H
, 0x82},
172 {BRIDGE
, M5602_XB_LINE_OF_FRAME_L
, 0x00},
173 {BRIDGE
, M5602_XB_PIX_OF_LINE_H
, 0x82},
174 {BRIDGE
, M5602_XB_PIX_OF_LINE_L
, 0x00},
175 {BRIDGE
, M5602_XB_SIG_INI
, 0x01}
178 /* Vertically and horizontally flips the image if matched, needed for machines
179 where the sensor is mounted upside down */
182 struct dmi_system_id ov9650_flip_dmi_table
[] = {
184 .ident
= "ASUS A6Ja",
186 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
187 DMI_MATCH(DMI_PRODUCT_NAME
, "A6J")
191 .ident
= "ASUS A6JC",
193 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
194 DMI_MATCH(DMI_PRODUCT_NAME
, "A6JC")
200 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
201 DMI_MATCH(DMI_PRODUCT_NAME
, "A6K")
205 .ident
= "ASUS A6Kt",
207 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME
, "A6Kt")
212 .ident
= "ASUS A6VA",
214 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
215 DMI_MATCH(DMI_PRODUCT_NAME
, "A6VA")
220 .ident
= "ASUS A6VC",
222 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
223 DMI_MATCH(DMI_PRODUCT_NAME
, "A6VC")
227 .ident
= "ASUS A6VM",
229 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
230 DMI_MATCH(DMI_PRODUCT_NAME
, "A6VM")
236 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
237 DMI_MATCH(DMI_PRODUCT_NAME
, "A7V")
241 .ident
= "Alienware Aurora m9700",
243 DMI_MATCH(DMI_SYS_VENDOR
, "alienware"),
244 DMI_MATCH(DMI_PRODUCT_NAME
, "Aurora m9700")
250 static struct v4l2_pix_format ov9650_modes
[] = {
259 .colorspace
= V4L2_COLORSPACE_SRGB
,
269 .colorspace
= V4L2_COLORSPACE_SRGB
,
279 .colorspace
= V4L2_COLORSPACE_SRGB
,
289 .colorspace
= V4L2_COLORSPACE_SRGB
,
294 static const struct v4l2_ctrl_ops ov9650_ctrl_ops
= {
295 .s_ctrl
= ov9650_s_ctrl
,
298 int ov9650_probe(struct sd
*sd
)
301 u8 prod_id
= 0, ver_id
= 0, i
;
302 struct gspca_dev
*gspca_dev
= (struct gspca_dev
*)sd
;
305 if (force_sensor
== OV9650_SENSOR
) {
306 pr_info("Forcing an %s sensor\n", ov9650
.name
);
309 /* If we want to force another sensor,
310 don't try to probe this one */
314 gspca_dbg(gspca_dev
, D_PROBE
, "Probing for an ov9650 sensor\n");
316 /* Run the pre-init before probing the sensor */
317 for (i
= 0; i
< ARRAY_SIZE(preinit_ov9650
) && !err
; i
++) {
318 u8 data
= preinit_ov9650
[i
][2];
319 if (preinit_ov9650
[i
][0] == SENSOR
)
320 err
= m5602_write_sensor(sd
,
321 preinit_ov9650
[i
][1], &data
, 1);
323 err
= m5602_write_bridge(sd
,
324 preinit_ov9650
[i
][1], data
);
330 if (m5602_read_sensor(sd
, OV9650_PID
, &prod_id
, 1))
333 if (m5602_read_sensor(sd
, OV9650_VER
, &ver_id
, 1))
336 if ((prod_id
== 0x96) && (ver_id
== 0x52)) {
337 pr_info("Detected an ov9650 sensor\n");
343 sd
->gspca_dev
.cam
.cam_mode
= ov9650_modes
;
344 sd
->gspca_dev
.cam
.nmodes
= ARRAY_SIZE(ov9650_modes
);
349 int ov9650_init(struct sd
*sd
)
355 ov9650_dump_registers(sd
);
357 for (i
= 0; i
< ARRAY_SIZE(init_ov9650
) && !err
; i
++) {
358 data
= init_ov9650
[i
][2];
359 if (init_ov9650
[i
][0] == SENSOR
)
360 err
= m5602_write_sensor(sd
, init_ov9650
[i
][1],
363 err
= m5602_write_bridge(sd
, init_ov9650
[i
][1], data
);
369 int ov9650_init_controls(struct sd
*sd
)
371 struct v4l2_ctrl_handler
*hdl
= &sd
->gspca_dev
.ctrl_handler
;
373 sd
->gspca_dev
.vdev
.ctrl_handler
= hdl
;
374 v4l2_ctrl_handler_init(hdl
, 9);
376 sd
->auto_white_bal
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
,
377 V4L2_CID_AUTO_WHITE_BALANCE
,
379 sd
->red_bal
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
,
380 V4L2_CID_RED_BALANCE
, 0, 255, 1,
382 sd
->blue_bal
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
,
383 V4L2_CID_BLUE_BALANCE
, 0, 255, 1,
386 sd
->autoexpo
= v4l2_ctrl_new_std_menu(hdl
, &ov9650_ctrl_ops
,
387 V4L2_CID_EXPOSURE_AUTO
, 1, 0, V4L2_EXPOSURE_AUTO
);
388 sd
->expo
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
, V4L2_CID_EXPOSURE
,
389 0, 0x1ff, 4, EXPOSURE_DEFAULT
);
391 sd
->autogain
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
,
392 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
393 sd
->gain
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
, V4L2_CID_GAIN
, 0,
394 0x3ff, 1, GAIN_DEFAULT
);
396 sd
->hflip
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
, V4L2_CID_HFLIP
,
398 sd
->vflip
= v4l2_ctrl_new_std(hdl
, &ov9650_ctrl_ops
, V4L2_CID_VFLIP
,
402 pr_err("Could not initialize controls\n");
406 v4l2_ctrl_auto_cluster(3, &sd
->auto_white_bal
, 0, false);
407 v4l2_ctrl_auto_cluster(2, &sd
->autoexpo
, 0, false);
408 v4l2_ctrl_auto_cluster(2, &sd
->autogain
, 0, false);
409 v4l2_ctrl_cluster(2, &sd
->hflip
);
414 int ov9650_start(struct sd
*sd
)
418 struct cam
*cam
= &sd
->gspca_dev
.cam
;
420 int width
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].width
;
421 int height
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].height
;
422 int ver_offs
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].priv
;
423 int hor_offs
= OV9650_LEFT_OFFSET
;
424 struct gspca_dev
*gspca_dev
= (struct gspca_dev
*)sd
;
426 if ((!dmi_check_system(ov9650_flip_dmi_table
) &&
428 (dmi_check_system(ov9650_flip_dmi_table
) &&
435 /* Synthesize the vsync/hsync setup */
436 for (i
= 0; i
< ARRAY_SIZE(res_init_ov9650
) && !err
; i
++) {
437 if (res_init_ov9650
[i
][0] == BRIDGE
)
438 err
= m5602_write_bridge(sd
, res_init_ov9650
[i
][1],
439 res_init_ov9650
[i
][2]);
440 else if (res_init_ov9650
[i
][0] == SENSOR
) {
441 data
= res_init_ov9650
[i
][2];
442 err
= m5602_write_sensor(sd
,
443 res_init_ov9650
[i
][1], &data
, 1);
449 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
,
450 ((ver_offs
>> 8) & 0xff));
454 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (ver_offs
& 0xff));
458 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
462 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
>> 8) & 0xff);
466 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
& 0xff));
470 for (i
= 0; i
< 2 && !err
; i
++)
471 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
475 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 0);
479 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 2);
483 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
484 (hor_offs
>> 8) & 0xff);
488 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
, hor_offs
& 0xff);
492 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
493 ((width
+ hor_offs
) >> 8) & 0xff);
497 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
498 ((width
+ hor_offs
) & 0xff));
502 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 0);
508 gspca_dbg(gspca_dev
, D_CONF
, "Configuring camera for VGA mode\n");
510 data
= OV9650_VGA_SELECT
| OV9650_RGB_SELECT
|
511 OV9650_RAW_RGB_SELECT
;
512 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
516 gspca_dbg(gspca_dev
, D_CONF
, "Configuring camera for CIF mode\n");
518 data
= OV9650_CIF_SELECT
| OV9650_RGB_SELECT
|
519 OV9650_RAW_RGB_SELECT
;
520 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
524 gspca_dbg(gspca_dev
, D_CONF
, "Configuring camera for QVGA mode\n");
526 data
= OV9650_QVGA_SELECT
| OV9650_RGB_SELECT
|
527 OV9650_RAW_RGB_SELECT
;
528 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
532 gspca_dbg(gspca_dev
, D_CONF
, "Configuring camera for QCIF mode\n");
534 data
= OV9650_QCIF_SELECT
| OV9650_RGB_SELECT
|
535 OV9650_RAW_RGB_SELECT
;
536 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
542 int ov9650_stop(struct sd
*sd
)
544 u8 data
= OV9650_SOFT_SLEEP
| OV9650_OUTPUT_DRIVE_2X
;
545 return m5602_write_sensor(sd
, OV9650_COM2
, &data
, 1);
548 void ov9650_disconnect(struct sd
*sd
)
555 static int ov9650_set_exposure(struct gspca_dev
*gspca_dev
, __s32 val
)
557 struct sd
*sd
= (struct sd
*) gspca_dev
;
561 gspca_dbg(gspca_dev
, D_CONF
, "Set exposure to %d\n", val
);
564 i2c_data
= (val
>> 10) & 0x3f;
565 err
= m5602_write_sensor(sd
, OV9650_AECHM
,
570 /* The 8 middle bits */
571 i2c_data
= (val
>> 2) & 0xff;
572 err
= m5602_write_sensor(sd
, OV9650_AECH
,
578 i2c_data
= val
& 0x03;
579 err
= m5602_write_sensor(sd
, OV9650_COM1
, &i2c_data
, 1);
583 static int ov9650_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
587 struct sd
*sd
= (struct sd
*) gspca_dev
;
589 gspca_dbg(gspca_dev
, D_CONF
, "Setting gain to %d\n", val
);
592 /* Read the OV9650_VREF register first to avoid
593 corrupting the VREF high and low bits */
594 err
= m5602_read_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
598 /* Mask away all uninteresting bits */
599 i2c_data
= ((val
& 0x0300) >> 2) |
601 err
= m5602_write_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
606 i2c_data
= val
& 0xff;
607 err
= m5602_write_sensor(sd
, OV9650_GAIN
, &i2c_data
, 1);
611 static int ov9650_set_red_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
615 struct sd
*sd
= (struct sd
*) gspca_dev
;
617 gspca_dbg(gspca_dev
, D_CONF
, "Set red gain to %d\n", val
);
619 i2c_data
= val
& 0xff;
620 err
= m5602_write_sensor(sd
, OV9650_RED
, &i2c_data
, 1);
624 static int ov9650_set_blue_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
628 struct sd
*sd
= (struct sd
*) gspca_dev
;
630 gspca_dbg(gspca_dev
, D_CONF
, "Set blue gain to %d\n", val
);
632 i2c_data
= val
& 0xff;
633 err
= m5602_write_sensor(sd
, OV9650_BLUE
, &i2c_data
, 1);
637 static int ov9650_set_hvflip(struct gspca_dev
*gspca_dev
)
641 struct sd
*sd
= (struct sd
*) gspca_dev
;
642 int hflip
= sd
->hflip
->val
;
643 int vflip
= sd
->vflip
->val
;
645 gspca_dbg(gspca_dev
, D_CONF
, "Set hvflip to %d %d\n", hflip
, vflip
);
647 if (dmi_check_system(ov9650_flip_dmi_table
))
650 i2c_data
= (hflip
<< 5) | (vflip
<< 4);
651 err
= m5602_write_sensor(sd
, OV9650_MVFP
, &i2c_data
, 1);
655 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
656 if (gspca_dev
->streaming
)
657 err
= ov9650_start(sd
);
662 static int ov9650_set_auto_exposure(struct gspca_dev
*gspca_dev
,
667 struct sd
*sd
= (struct sd
*) gspca_dev
;
669 gspca_dbg(gspca_dev
, D_CONF
, "Set auto exposure control to %d\n", val
);
671 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
675 val
= (val
== V4L2_EXPOSURE_AUTO
);
676 i2c_data
= ((i2c_data
& 0xfe) | ((val
& 0x01) << 0));
678 return m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
681 static int ov9650_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
686 struct sd
*sd
= (struct sd
*) gspca_dev
;
688 gspca_dbg(gspca_dev
, D_CONF
, "Set auto white balance to %d\n", val
);
690 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
694 i2c_data
= ((i2c_data
& 0xfd) | ((val
& 0x01) << 1));
695 err
= m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
700 static int ov9650_set_auto_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
704 struct sd
*sd
= (struct sd
*) gspca_dev
;
706 gspca_dbg(gspca_dev
, D_CONF
, "Set auto gain control to %d\n", val
);
708 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
712 i2c_data
= ((i2c_data
& 0xfb) | ((val
& 0x01) << 2));
714 return m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
717 static int ov9650_s_ctrl(struct v4l2_ctrl
*ctrl
)
719 struct gspca_dev
*gspca_dev
=
720 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
721 struct sd
*sd
= (struct sd
*) gspca_dev
;
724 if (!gspca_dev
->streaming
)
728 case V4L2_CID_AUTO_WHITE_BALANCE
:
729 err
= ov9650_set_auto_white_balance(gspca_dev
, ctrl
->val
);
730 if (err
|| ctrl
->val
)
732 err
= ov9650_set_red_balance(gspca_dev
, sd
->red_bal
->val
);
735 err
= ov9650_set_blue_balance(gspca_dev
, sd
->blue_bal
->val
);
737 case V4L2_CID_EXPOSURE_AUTO
:
738 err
= ov9650_set_auto_exposure(gspca_dev
, ctrl
->val
);
739 if (err
|| ctrl
->val
== V4L2_EXPOSURE_AUTO
)
741 err
= ov9650_set_exposure(gspca_dev
, sd
->expo
->val
);
743 case V4L2_CID_AUTOGAIN
:
744 err
= ov9650_set_auto_gain(gspca_dev
, ctrl
->val
);
745 if (err
|| ctrl
->val
)
747 err
= ov9650_set_gain(gspca_dev
, sd
->gain
->val
);
750 err
= ov9650_set_hvflip(gspca_dev
);
759 static void ov9650_dump_registers(struct sd
*sd
)
762 pr_info("Dumping the ov9650 register state\n");
763 for (address
= 0; address
< 0xa9; address
++) {
765 m5602_read_sensor(sd
, address
, &value
, 1);
766 pr_info("register 0x%x contains 0x%x\n", address
, value
);
769 pr_info("ov9650 register state dump complete\n");
771 pr_info("Probing for which registers that are read/write\n");
772 for (address
= 0; address
< 0xff; address
++) {
773 u8 old_value
, ctrl_value
;
774 u8 test_value
[2] = {0xff, 0xff};
776 m5602_read_sensor(sd
, address
, &old_value
, 1);
777 m5602_write_sensor(sd
, address
, test_value
, 1);
778 m5602_read_sensor(sd
, address
, &ctrl_value
, 1);
780 if (ctrl_value
== test_value
[0])
781 pr_info("register 0x%x is writeable\n", address
);
783 pr_info("register 0x%x is read only\n", address
);
785 /* Restore original value */
786 m5602_write_sensor(sd
, address
, &old_value
, 1);