treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 372
[linux-2.6-block.git] / drivers / media / usb / gspca / m5602 / m5602_ov9650.c
CommitLineData
a10e763b 1// SPDX-License-Identifier: GPL-2.0-only
14ccffa3 2
c109f816
EA
3/*
4 * Driver for the ov9650 sensor
5 *
0c505e68 6 * Copyright (C) 2008 Erik Andrén
c109f816
EA
7 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
8 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
9 *
10 * Portions of code to USB interface and ALi driver software,
11 * Copyright (c) 2006 Willem Duinker
12 * v4l2 interface modeled after the V4L2 driver
13 * for SN9C10x PC Camera Controllers
c109f816
EA
14 */
15
bdfe91f4
JP
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
c109f816
EA
18#include "m5602_ov9650.h"
19
c84e412f
HG
20static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
21static void ov9650_dump_registers(struct sd *sd);
cf811d50 22
14ccffa3
MCC
23static const unsigned char preinit_ov9650[][3] = {
24 /* [INITCAM] */
25 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
26 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
27 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
28 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
29 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
30 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
31
32 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
33 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
34 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
35 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
36 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
37 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
38 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
39 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
40 /* Reset chip */
41 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
42 /* Enable double clock */
43 {SENSOR, OV9650_CLKRC, 0x80},
44 /* Do something out of spec with the power */
45 {SENSOR, OV9650_OFON, 0x40}
46};
47
48static const unsigned char init_ov9650[][3] = {
49 /* [INITCAM] */
50 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
51 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
52 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
53 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
54 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
55 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
56
57 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
58 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
59 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
60 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
61 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
62 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
63 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
64 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
65
66 /* Reset chip */
67 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
68 /* One extra reset is needed in order to make the sensor behave
69 properly when resuming from ram, could be a timing issue */
70 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
71
72 /* Enable double clock */
73 {SENSOR, OV9650_CLKRC, 0x80},
74 /* Do something out of spec with the power */
75 {SENSOR, OV9650_OFON, 0x40},
76
77 /* Set fast AGC/AEC algorithm with unlimited step size */
78 {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
79 OV9650_AEC_UNLIM_STEP_SIZE},
80
81 {SENSOR, OV9650_CHLF, 0x10},
82 {SENSOR, OV9650_ARBLM, 0xbf},
83 {SENSOR, OV9650_ACOM38, 0x81},
84 /* Turn off color matrix coefficient double option */
85 {SENSOR, OV9650_COM16, 0x00},
86 /* Enable color matrix for RGB/YUV, Delay Y channel,
87 set output Y/UV delay to 1 */
88 {SENSOR, OV9650_COM13, 0x19},
89 /* Enable digital BLC, Set output mode to U Y V Y */
90 {SENSOR, OV9650_TSLB, 0x0c},
91 /* Limit the AGC/AEC stable upper region */
92 {SENSOR, OV9650_COM24, 0x00},
93 /* Enable HREF and some out of spec things */
94 {SENSOR, OV9650_COM12, 0x73},
95 /* Set all DBLC offset signs to positive and
96 do some out of spec stuff */
97 {SENSOR, OV9650_DBLC1, 0xdf},
98 {SENSOR, OV9650_COM21, 0x06},
99 {SENSOR, OV9650_RSVD35, 0x91},
100 /* Necessary, no camera stream without it */
101 {SENSOR, OV9650_RSVD16, 0x06},
102 {SENSOR, OV9650_RSVD94, 0x99},
103 {SENSOR, OV9650_RSVD95, 0x99},
104 {SENSOR, OV9650_RSVD96, 0x04},
105 /* Enable full range output */
106 {SENSOR, OV9650_COM15, 0x0},
107 /* Enable HREF at optical black, enable ADBLC bias,
108 enable ADBLC, reset timings at format change */
109 {SENSOR, OV9650_COM6, 0x4b},
110 /* Subtract 32 from the B channel bias */
111 {SENSOR, OV9650_BBIAS, 0xa0},
112 /* Subtract 32 from the Gb channel bias */
113 {SENSOR, OV9650_GbBIAS, 0xa0},
114 /* Do not bypass the analog BLC and to some out of spec stuff */
115 {SENSOR, OV9650_Gr_COM, 0x00},
116 /* Subtract 32 from the R channel bias */
117 {SENSOR, OV9650_RBIAS, 0xa0},
118 /* Subtract 32 from the R channel bias */
119 {SENSOR, OV9650_RBIAS, 0x0},
120 {SENSOR, OV9650_COM26, 0x80},
121 {SENSOR, OV9650_ACOMA9, 0x98},
122 /* Set the AGC/AEC stable region upper limit */
123 {SENSOR, OV9650_AEW, 0x68},
124 /* Set the AGC/AEC stable region lower limit */
125 {SENSOR, OV9650_AEB, 0x5c},
126 /* Set the high and low limit nibbles to 3 */
127 {SENSOR, OV9650_VPT, 0xc3},
128 /* Set the Automatic Gain Ceiling (AGC) to 128x,
129 drop VSYNC at frame drop,
130 limit exposure timing,
131 drop frame when the AEC step is larger than the exposure gap */
132 {SENSOR, OV9650_COM9, 0x6e},
133 /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
134 and set PWDN to SLVS (slave mode vertical sync) */
135 {SENSOR, OV9650_COM10, 0x42},
136 /* Set horizontal column start high to default value */
137 {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
138 /* Set horizontal column end */
139 {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
140 /* Complementing register to the two writes above */
141 {SENSOR, OV9650_HREF, 0xb2},
142 /* Set vertical row start high bits */
143 {SENSOR, OV9650_VSTRT, 0x02},
144 /* Set vertical row end low bits */
145 {SENSOR, OV9650_VSTOP, 0x7e},
146 /* Set complementing vertical frame control */
147 {SENSOR, OV9650_VREF, 0x10},
148 {SENSOR, OV9650_ADC, 0x04},
149 {SENSOR, OV9650_HV, 0x40},
150
151 /* Enable denoise, and white-pixel erase */
152 {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
153 OV9650_WHITE_PIXEL_ENABLE |
154 OV9650_WHITE_PIXEL_OPTION},
155
156 /* Enable VARIOPIXEL */
157 {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
158 {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
159
160 /* Put the sensor in soft sleep mode */
161 {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
162};
163
164static const unsigned char res_init_ov9650[][3] = {
165 {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
166
167 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
168 {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
169 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
170 {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
171 {BRIDGE, M5602_XB_SIG_INI, 0x01}
172};
173
30881ab7
EA
174/* Vertically and horizontally flips the image if matched, needed for machines
175 where the sensor is mounted upside down */
176static
177 const
178 struct dmi_system_id ov9650_flip_dmi_table[] = {
179 {
926b3b41 180 .ident = "ASUS A6Ja",
201a8a6c
JK
181 .matches = {
182 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 183 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
201a8a6c
JK
184 }
185 },
186 {
926b3b41 187 .ident = "ASUS A6JC",
30881ab7
EA
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 190 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
30881ab7
EA
191 }
192 },
193 {
926b3b41 194 .ident = "ASUS A6K",
30881ab7
EA
195 .matches = {
196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 197 DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
30881ab7
EA
198 }
199 },
200 {
926b3b41 201 .ident = "ASUS A6Kt",
30881ab7
EA
202 .matches = {
203 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 204 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
30881ab7
EA
205 }
206 },
3efb6bda 207 {
926b3b41 208 .ident = "ASUS A6VA",
3efb6bda
EA
209 .matches = {
210 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 211 DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
3efb6bda
EA
212 }
213 },
30881ab7 214 {
926b3b41
EA
215
216 .ident = "ASUS A6VC",
30881ab7
EA
217 .matches = {
218 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 219 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
30881ab7
EA
220 }
221 },
951872a8 222 {
926b3b41 223 .ident = "ASUS A6VM",
951872a8
EA
224 .matches = {
225 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 226 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
951872a8
EA
227 }
228 },
40a4f2fc 229 {
926b3b41 230 .ident = "ASUS A7V",
40a4f2fc
EA
231 .matches = {
232 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
926b3b41 233 DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
40a4f2fc
EA
234 }
235 },
7e08e66a
EA
236 {
237 .ident = "Alienware Aurora m9700",
238 .matches = {
239 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
240 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
241 }
242 },
7460f524 243 {}
30881ab7
EA
244};
245
74cadfe1
EA
246static struct v4l2_pix_format ov9650_modes[] = {
247 {
248 176,
249 144,
250 V4L2_PIX_FMT_SBGGR8,
251 V4L2_FIELD_NONE,
252 .sizeimage =
253 176 * 144,
254 .bytesperline = 176,
255 .colorspace = V4L2_COLORSPACE_SRGB,
bd99ffbd 256 .priv = 9
74cadfe1
EA
257 }, {
258 320,
259 240,
260 V4L2_PIX_FMT_SBGGR8,
261 V4L2_FIELD_NONE,
262 .sizeimage =
263 320 * 240,
264 .bytesperline = 320,
265 .colorspace = V4L2_COLORSPACE_SRGB,
bd99ffbd 266 .priv = 8
74cadfe1
EA
267 }, {
268 352,
269 288,
270 V4L2_PIX_FMT_SBGGR8,
271 V4L2_FIELD_NONE,
272 .sizeimage =
273 352 * 288,
274 .bytesperline = 352,
275 .colorspace = V4L2_COLORSPACE_SRGB,
bd99ffbd 276 .priv = 9
74cadfe1
EA
277 }, {
278 640,
279 480,
280 V4L2_PIX_FMT_SBGGR8,
281 V4L2_FIELD_NONE,
282 .sizeimage =
283 640 * 480,
284 .bytesperline = 640,
285 .colorspace = V4L2_COLORSPACE_SRGB,
bd99ffbd 286 .priv = 9
74cadfe1
EA
287 }
288};
289
c84e412f
HG
290static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
291 .s_ctrl = ov9650_s_ctrl,
292};
658efb63 293
c109f816
EA
294int ov9650_probe(struct sd *sd)
295{
6b055500 296 int err = 0;
c109f816 297 u8 prod_id = 0, ver_id = 0, i;
c93396e1 298 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
c109f816
EA
299
300 if (force_sensor) {
301 if (force_sensor == OV9650_SENSOR) {
bdfe91f4 302 pr_info("Forcing an %s sensor\n", ov9650.name);
c109f816
EA
303 goto sensor_found;
304 }
305 /* If we want to force another sensor,
306 don't try to probe this one */
307 return -ENODEV;
308 }
309
37d5efb0 310 gspca_dbg(gspca_dev, D_PROBE, "Probing for an ov9650 sensor\n");
c109f816 311
7460f524 312 /* Run the pre-init before probing the sensor */
6b055500 313 for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
c109f816
EA
314 u8 data = preinit_ov9650[i][2];
315 if (preinit_ov9650[i][0] == SENSOR)
6b055500 316 err = m5602_write_sensor(sd,
d9c700d4 317 preinit_ov9650[i][1], &data, 1);
c109f816 318 else
d9c700d4
EA
319 err = m5602_write_bridge(sd,
320 preinit_ov9650[i][1], data);
c109f816
EA
321 }
322
6b055500
EA
323 if (err < 0)
324 return err;
325
905aabaf 326 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
c109f816
EA
327 return -ENODEV;
328
905aabaf 329 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
c109f816
EA
330 return -ENODEV;
331
332 if ((prod_id == 0x96) && (ver_id == 0x52)) {
bdfe91f4 333 pr_info("Detected an ov9650 sensor\n");
c109f816
EA
334 goto sensor_found;
335 }
c109f816
EA
336 return -ENODEV;
337
338sensor_found:
74cadfe1
EA
339 sd->gspca_dev.cam.cam_mode = ov9650_modes;
340 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
d9c700d4 341
c109f816
EA
342 return 0;
343}
344
345int ov9650_init(struct sd *sd)
346{
347 int i, err = 0;
348 u8 data;
349
350 if (dump_sensor)
351 ov9650_dump_registers(sd);
352
353 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
354 data = init_ov9650[i][2];
355 if (init_ov9650[i][0] == SENSOR)
6dc4cff0 356 err = m5602_write_sensor(sd, init_ov9650[i][1],
c109f816
EA
357 &data, 1);
358 else
359 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
360 }
361
c84e412f
HG
362 return 0;
363}
7460f524 364
c84e412f
HG
365int ov9650_init_controls(struct sd *sd)
366{
367 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
368
369 sd->gspca_dev.vdev.ctrl_handler = hdl;
370 v4l2_ctrl_handler_init(hdl, 9);
371
372 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
373 V4L2_CID_AUTO_WHITE_BALANCE,
374 0, 1, 1, 1);
375 sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
376 V4L2_CID_RED_BALANCE, 0, 255, 1,
377 RED_GAIN_DEFAULT);
378 sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
379 V4L2_CID_BLUE_BALANCE, 0, 255, 1,
380 BLUE_GAIN_DEFAULT);
381
382 sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &ov9650_ctrl_ops,
383 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
384 sd->expo = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_EXPOSURE,
385 0, 0x1ff, 4, EXPOSURE_DEFAULT);
386
387 sd->autogain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
388 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
389 sd->gain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_GAIN, 0,
390 0x3ff, 1, GAIN_DEFAULT);
391
392 sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
393 0, 1, 1, 0);
394 sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
395 0, 1, 1, 0);
396
397 if (hdl->error) {
398 pr_err("Could not initialize controls\n");
399 return hdl->error;
400 }
9ae16577 401
c84e412f
HG
402 v4l2_ctrl_auto_cluster(3, &sd->auto_white_bal, 0, false);
403 v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
404 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
405 v4l2_ctrl_cluster(2, &sd->hflip);
7460f524 406
c84e412f 407 return 0;
c109f816
EA
408}
409
082aa893
EA
410int ov9650_start(struct sd *sd)
411{
bd99ffbd 412 u8 data;
082aa893
EA
413 int i, err = 0;
414 struct cam *cam = &sd->gspca_dev.cam;
be63b722 415
bd99ffbd
EA
416 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
417 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
418 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
419 int hor_offs = OV9650_LEFT_OFFSET;
c93396e1 420 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
bd99ffbd 421
6f02d761 422 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
c84e412f 423 sd->vflip->val) ||
6f02d761 424 (dmi_check_system(ov9650_flip_dmi_table) &&
c84e412f 425 !sd->vflip->val))
be63b722
EA
426 ver_offs--;
427
bd99ffbd
EA
428 if (width <= 320)
429 hor_offs /= 2;
082aa893 430
bd99ffbd 431 /* Synthesize the vsync/hsync setup */
3d3ec926
EA
432 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
433 if (res_init_ov9650[i][0] == BRIDGE)
4eecb176
EA
434 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
435 res_init_ov9650[i][2]);
3d3ec926 436 else if (res_init_ov9650[i][0] == SENSOR) {
83955556 437 data = res_init_ov9650[i][2];
4eecb176
EA
438 err = m5602_write_sensor(sd,
439 res_init_ov9650[i][1], &data, 1);
3d3ec926
EA
440 }
441 }
27b1e4ca
EA
442 if (err < 0)
443 return err;
444
d9c700d4
EA
445 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
446 ((ver_offs >> 8) & 0xff));
bd99ffbd
EA
447 if (err < 0)
448 return err;
449
450 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
451 if (err < 0)
452 return err;
453
454 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
455 if (err < 0)
456 return err;
457
458 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
459 if (err < 0)
460 return err;
461
462 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
463 if (err < 0)
464 return err;
465
d9c700d4 466 for (i = 0; i < 2 && !err; i++)
bd99ffbd 467 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
bd99ffbd
EA
468 if (err < 0)
469 return err;
470
b05a4ad9
EA
471 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
472 if (err < 0)
473 return err;
474
475 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
476 if (err < 0)
477 return err;
478
d9c700d4
EA
479 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
480 (hor_offs >> 8) & 0xff);
bd99ffbd
EA
481 if (err < 0)
482 return err;
483
484 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
485 if (err < 0)
486 return err;
487
d9c700d4
EA
488 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
489 ((width + hor_offs) >> 8) & 0xff);
bd99ffbd
EA
490 if (err < 0)
491 return err;
492
d9c700d4
EA
493 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
494 ((width + hor_offs) & 0xff));
bd99ffbd
EA
495 if (err < 0)
496 return err;
497
b05a4ad9
EA
498 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
499 if (err < 0)
500 return err;
501
bd99ffbd 502 switch (width) {
082aa893 503 case 640:
37d5efb0 504 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
082aa893 505
bd99ffbd
EA
506 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
507 OV9650_RAW_RGB_SELECT;
bd99ffbd 508 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
082aa893 509 break;
3b2f3327 510
03f46de9 511 case 352:
37d5efb0 512 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for CIF mode\n");
03f46de9 513
bd99ffbd
EA
514 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
515 OV9650_RAW_RGB_SELECT;
bd99ffbd 516 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
03f46de9
EA
517 break;
518
3b2f3327 519 case 320:
37d5efb0 520 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n");
3b2f3327 521
bd99ffbd
EA
522 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
523 OV9650_RAW_RGB_SELECT;
bd99ffbd 524 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
3b2f3327 525 break;
e31f9dd6
EA
526
527 case 176:
37d5efb0 528 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QCIF mode\n");
e31f9dd6 529
bd99ffbd
EA
530 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
531 OV9650_RAW_RGB_SELECT;
bd99ffbd
EA
532 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
533 break;
082aa893
EA
534 }
535 return err;
536}
537
3d3ec926
EA
538int ov9650_stop(struct sd *sd)
539{
540 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
541 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
542}
543
d9c700d4
EA
544void ov9650_disconnect(struct sd *sd)
545{
546 ov9650_stop(sd);
d9c700d4
EA
547
548 sd->sensor = NULL;
c109f816
EA
549}
550
cf811d50 551static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 u8 i2c_data;
555 int err;
556
37d5efb0 557 gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d\n", val);
be63b722 558
c109f816
EA
559 /* The 6 MSBs */
560 i2c_data = (val >> 10) & 0x3f;
6dc4cff0 561 err = m5602_write_sensor(sd, OV9650_AECHM,
c109f816
EA
562 &i2c_data, 1);
563 if (err < 0)
051781b3 564 return err;
c109f816
EA
565
566 /* The 8 middle bits */
567 i2c_data = (val >> 2) & 0xff;
6dc4cff0 568 err = m5602_write_sensor(sd, OV9650_AECH,
c109f816
EA
569 &i2c_data, 1);
570 if (err < 0)
051781b3 571 return err;
c109f816
EA
572
573 /* The 2 LSBs */
574 i2c_data = val & 0x03;
6dc4cff0 575 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
e07b14e8 576 return err;
c109f816
EA
577}
578
cf811d50 579static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
580{
581 int err;
582 u8 i2c_data;
583 struct sd *sd = (struct sd *) gspca_dev;
be63b722 584
37d5efb0 585 gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val);
be63b722 586
c109f816
EA
587 /* The 2 MSB */
588 /* Read the OV9650_VREF register first to avoid
589 corrupting the VREF high and low bits */
6b055500
EA
590 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
591 if (err < 0)
592 return err;
593
c109f816
EA
594 /* Mask away all uninteresting bits */
595 i2c_data = ((val & 0x0300) >> 2) |
1d00d6c1 596 (i2c_data & 0x3f);
6dc4cff0 597 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
6b055500
EA
598 if (err < 0)
599 return err;
c109f816
EA
600
601 /* The 8 LSBs */
602 i2c_data = val & 0xff;
6dc4cff0 603 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
e07b14e8 604 return err;
c109f816
EA
605}
606
cf811d50 607static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
608{
609 int err;
610 u8 i2c_data;
611 struct sd *sd = (struct sd *) gspca_dev;
612
37d5efb0 613 gspca_dbg(gspca_dev, D_CONF, "Set red gain to %d\n", val);
be63b722 614
c109f816 615 i2c_data = val & 0xff;
6dc4cff0 616 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
e07b14e8 617 return err;
c109f816
EA
618}
619
cf811d50 620static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
621{
622 int err;
623 u8 i2c_data;
624 struct sd *sd = (struct sd *) gspca_dev;
be63b722 625
37d5efb0 626 gspca_dbg(gspca_dev, D_CONF, "Set blue gain to %d\n", val);
c109f816 627
c109f816 628 i2c_data = val & 0xff;
6dc4cff0 629 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
e07b14e8 630 return err;
c109f816
EA
631}
632
c84e412f 633static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
c109f816
EA
634{
635 int err;
636 u8 i2c_data;
637 struct sd *sd = (struct sd *) gspca_dev;
c84e412f
HG
638 int hflip = sd->hflip->val;
639 int vflip = sd->vflip->val;
c109f816 640
37d5efb0 641 gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n", hflip, vflip);
c109f816 642
6f02d761 643 if (dmi_check_system(ov9650_flip_dmi_table))
c84e412f 644 vflip = !vflip;
6f02d761 645
c84e412f 646 i2c_data = (hflip << 5) | (vflip << 4);
6dc4cff0 647 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
be63b722
EA
648 if (err < 0)
649 return err;
650
5196d7c6 651 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
be63b722
EA
652 if (gspca_dev->streaming)
653 err = ov9650_start(sd);
654
e07b14e8 655 return err;
c109f816
EA
656}
657
9ae16577
EA
658static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
659 __s32 val)
660{
661 int err;
662 u8 i2c_data;
663 struct sd *sd = (struct sd *) gspca_dev;
9ae16577 664
37d5efb0 665 gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val);
9ae16577 666
9ae16577
EA
667 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
668 if (err < 0)
669 return err;
670
c84e412f 671 val = (val == V4L2_EXPOSURE_AUTO);
9ae16577
EA
672 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
673
674 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
675}
676
cf811d50
EA
677static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
678 __s32 val)
c109f816
EA
679{
680 int err;
681 u8 i2c_data;
682 struct sd *sd = (struct sd *) gspca_dev;
683
37d5efb0 684 gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val);
be63b722 685
905aabaf 686 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 687 if (err < 0)
051781b3 688 return err;
c109f816
EA
689
690 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
6dc4cff0 691 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
051781b3 692
e07b14e8 693 return err;
c109f816
EA
694}
695
cf811d50 696static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
697{
698 int err;
699 u8 i2c_data;
700 struct sd *sd = (struct sd *) gspca_dev;
701
37d5efb0 702 gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val);
be63b722 703
905aabaf 704 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 705 if (err < 0)
051781b3 706 return err;
c109f816
EA
707
708 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
051781b3 709
9ae16577 710 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816
EA
711}
712
c84e412f
HG
713static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
714{
715 struct gspca_dev *gspca_dev =
716 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
717 struct sd *sd = (struct sd *) gspca_dev;
718 int err;
719
720 if (!gspca_dev->streaming)
721 return 0;
722
723 switch (ctrl->id) {
724 case V4L2_CID_AUTO_WHITE_BALANCE:
725 err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
726 if (err || ctrl->val)
727 return err;
728 err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
729 if (err)
730 return err;
731 err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
732 break;
733 case V4L2_CID_EXPOSURE_AUTO:
734 err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
735 if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
736 return err;
737 err = ov9650_set_exposure(gspca_dev, sd->expo->val);
738 break;
739 case V4L2_CID_AUTOGAIN:
740 err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
741 if (err || ctrl->val)
742 return err;
743 err = ov9650_set_gain(gspca_dev, sd->gain->val);
744 break;
745 case V4L2_CID_HFLIP:
746 err = ov9650_set_hvflip(gspca_dev);
747 break;
748 default:
749 return -EINVAL;
750 }
751
752 return err;
753}
754
658efb63 755static void ov9650_dump_registers(struct sd *sd)
c109f816
EA
756{
757 int address;
bdfe91f4 758 pr_info("Dumping the ov9650 register state\n");
c109f816
EA
759 for (address = 0; address < 0xa9; address++) {
760 u8 value;
905aabaf 761 m5602_read_sensor(sd, address, &value, 1);
bdfe91f4 762 pr_info("register 0x%x contains 0x%x\n", address, value);
c109f816
EA
763 }
764
bdfe91f4 765 pr_info("ov9650 register state dump complete\n");
c109f816 766
bdfe91f4 767 pr_info("Probing for which registers that are read/write\n");
c109f816
EA
768 for (address = 0; address < 0xff; address++) {
769 u8 old_value, ctrl_value;
770 u8 test_value[2] = {0xff, 0xff};
771
905aabaf 772 m5602_read_sensor(sd, address, &old_value, 1);
6dc4cff0 773 m5602_write_sensor(sd, address, test_value, 1);
905aabaf 774 m5602_read_sensor(sd, address, &ctrl_value, 1);
c109f816
EA
775
776 if (ctrl_value == test_value[0])
bdfe91f4 777 pr_info("register 0x%x is writeable\n", address);
c109f816 778 else
bdfe91f4 779 pr_info("register 0x%x is read only\n", address);
c109f816
EA
780
781 /* Restore original value */
6dc4cff0 782 m5602_write_sensor(sd, address, &old_value, 1);
c109f816
EA
783 }
784}