1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22#include "m5602_ov9650.h"
23
24static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
25static void ov9650_dump_registers(struct sd *sd);
26
27static const unsigned char preinit_ov9650[][3] = {
28
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},
35
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},
44
45 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
46
47 {SENSOR, OV9650_CLKRC, 0x80},
48
49 {SENSOR, OV9650_OFON, 0x40}
50};
51
52static const unsigned char init_ov9650[][3] = {
53
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},
60
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},
69
70
71 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
72
73
74 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
75
76
77 {SENSOR, OV9650_CLKRC, 0x80},
78
79 {SENSOR, OV9650_OFON, 0x40},
80
81
82 {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
83 OV9650_AEC_UNLIM_STEP_SIZE},
84
85 {SENSOR, OV9650_CHLF, 0x10},
86 {SENSOR, OV9650_ARBLM, 0xbf},
87 {SENSOR, OV9650_ACOM38, 0x81},
88
89 {SENSOR, OV9650_COM16, 0x00},
90
91
92 {SENSOR, OV9650_COM13, 0x19},
93
94 {SENSOR, OV9650_TSLB, 0x0c},
95
96 {SENSOR, OV9650_COM24, 0x00},
97
98 {SENSOR, OV9650_COM12, 0x73},
99
100
101 {SENSOR, OV9650_DBLC1, 0xdf},
102 {SENSOR, OV9650_COM21, 0x06},
103 {SENSOR, OV9650_RSVD35, 0x91},
104
105 {SENSOR, OV9650_RSVD16, 0x06},
106 {SENSOR, OV9650_RSVD94, 0x99},
107 {SENSOR, OV9650_RSVD95, 0x99},
108 {SENSOR, OV9650_RSVD96, 0x04},
109
110 {SENSOR, OV9650_COM15, 0x0},
111
112
113 {SENSOR, OV9650_COM6, 0x4b},
114
115 {SENSOR, OV9650_BBIAS, 0xa0},
116
117 {SENSOR, OV9650_GbBIAS, 0xa0},
118
119 {SENSOR, OV9650_Gr_COM, 0x00},
120
121 {SENSOR, OV9650_RBIAS, 0xa0},
122
123 {SENSOR, OV9650_RBIAS, 0x0},
124 {SENSOR, OV9650_COM26, 0x80},
125 {SENSOR, OV9650_ACOMA9, 0x98},
126
127 {SENSOR, OV9650_AEW, 0x68},
128
129 {SENSOR, OV9650_AEB, 0x5c},
130
131 {SENSOR, OV9650_VPT, 0xc3},
132
133
134
135
136 {SENSOR, OV9650_COM9, 0x6e},
137
138
139 {SENSOR, OV9650_COM10, 0x42},
140
141 {SENSOR, OV9650_HSTART, 0x1a},
142
143 {SENSOR, OV9650_HSTOP, 0xbf},
144
145 {SENSOR, OV9650_HREF, 0xb2},
146
147 {SENSOR, OV9650_VSTRT, 0x02},
148
149 {SENSOR, OV9650_VSTOP, 0x7e},
150
151 {SENSOR, OV9650_VREF, 0x10},
152 {SENSOR, OV9650_ADC, 0x04},
153 {SENSOR, OV9650_HV, 0x40},
154
155
156 {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
157 OV9650_WHITE_PIXEL_ENABLE |
158 OV9650_WHITE_PIXEL_OPTION},
159
160
161 {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
162 {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
163
164
165 {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
166};
167
168static const unsigned char res_init_ov9650[][3] = {
169 {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
170
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}
176};
177
178
179
180static
181 const
182 struct dmi_system_id ov9650_flip_dmi_table[] = {
183 {
184 .ident = "ASUS A6Ja",
185 .matches = {
186 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
187 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
188 }
189 },
190 {
191 .ident = "ASUS A6JC",
192 .matches = {
193 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
194 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
195 }
196 },
197 {
198 .ident = "ASUS A6K",
199 .matches = {
200 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
201 DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
202 }
203 },
204 {
205 .ident = "ASUS A6Kt",
206 .matches = {
207 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
209 }
210 },
211 {
212 .ident = "ASUS A6VA",
213 .matches = {
214 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
215 DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
216 }
217 },
218 {
219
220 .ident = "ASUS A6VC",
221 .matches = {
222 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
223 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
224 }
225 },
226 {
227 .ident = "ASUS A6VM",
228 .matches = {
229 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
230 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
231 }
232 },
233 {
234 .ident = "ASUS A7V",
235 .matches = {
236 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
237 DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
238 }
239 },
240 {
241 .ident = "Alienware Aurora m9700",
242 .matches = {
243 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
244 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
245 }
246 },
247 {}
248};
249
250static struct v4l2_pix_format ov9650_modes[] = {
251 {
252 176,
253 144,
254 V4L2_PIX_FMT_SBGGR8,
255 V4L2_FIELD_NONE,
256 .sizeimage =
257 176 * 144,
258 .bytesperline = 176,
259 .colorspace = V4L2_COLORSPACE_SRGB,
260 .priv = 9
261 }, {
262 320,
263 240,
264 V4L2_PIX_FMT_SBGGR8,
265 V4L2_FIELD_NONE,
266 .sizeimage =
267 320 * 240,
268 .bytesperline = 320,
269 .colorspace = V4L2_COLORSPACE_SRGB,
270 .priv = 8
271 }, {
272 352,
273 288,
274 V4L2_PIX_FMT_SBGGR8,
275 V4L2_FIELD_NONE,
276 .sizeimage =
277 352 * 288,
278 .bytesperline = 352,
279 .colorspace = V4L2_COLORSPACE_SRGB,
280 .priv = 9
281 }, {
282 640,
283 480,
284 V4L2_PIX_FMT_SBGGR8,
285 V4L2_FIELD_NONE,
286 .sizeimage =
287 640 * 480,
288 .bytesperline = 640,
289 .colorspace = V4L2_COLORSPACE_SRGB,
290 .priv = 9
291 }
292};
293
294static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
295 .s_ctrl = ov9650_s_ctrl,
296};
297
298int ov9650_probe(struct sd *sd)
299{
300 int err = 0;
301 u8 prod_id = 0, ver_id = 0, i;
302 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
303
304 if (force_sensor) {
305 if (force_sensor == OV9650_SENSOR) {
306 pr_info("Forcing an %s sensor\n", ov9650.name);
307 goto sensor_found;
308 }
309
310
311 return -ENODEV;
312 }
313
314 gspca_dbg(gspca_dev, D_PROBE, "Probing for an ov9650 sensor\n");
315
316
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);
322 else
323 err = m5602_write_bridge(sd,
324 preinit_ov9650[i][1], data);
325 }
326
327 if (err < 0)
328 return err;
329
330 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
331 return -ENODEV;
332
333 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
334 return -ENODEV;
335
336 if ((prod_id == 0x96) && (ver_id == 0x52)) {
337 pr_info("Detected an ov9650 sensor\n");
338 goto sensor_found;
339 }
340 return -ENODEV;
341
342sensor_found:
343 sd->gspca_dev.cam.cam_mode = ov9650_modes;
344 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
345
346 return 0;
347}
348
349int ov9650_init(struct sd *sd)
350{
351 int i, err = 0;
352 u8 data;
353
354 if (dump_sensor)
355 ov9650_dump_registers(sd);
356
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],
361 &data, 1);
362 else
363 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
364 }
365
366 return 0;
367}
368
369int ov9650_init_controls(struct sd *sd)
370{
371 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
372
373 sd->gspca_dev.vdev.ctrl_handler = hdl;
374 v4l2_ctrl_handler_init(hdl, 9);
375
376 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
377 V4L2_CID_AUTO_WHITE_BALANCE,
378 0, 1, 1, 1);
379 sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
380 V4L2_CID_RED_BALANCE, 0, 255, 1,
381 RED_GAIN_DEFAULT);
382 sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
383 V4L2_CID_BLUE_BALANCE, 0, 255, 1,
384 BLUE_GAIN_DEFAULT);
385
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);
390
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);
395
396 sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
397 0, 1, 1, 0);
398 sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
399 0, 1, 1, 0);
400
401 if (hdl->error) {
402 pr_err("Could not initialize controls\n");
403 return hdl->error;
404 }
405
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);
410
411 return 0;
412}
413
414int ov9650_start(struct sd *sd)
415{
416 u8 data;
417 int i, err = 0;
418 struct cam *cam = &sd->gspca_dev.cam;
419
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;
425
426 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
427 sd->vflip->val) ||
428 (dmi_check_system(ov9650_flip_dmi_table) &&
429 !sd->vflip->val))
430 ver_offs--;
431
432 if (width <= 320)
433 hor_offs /= 2;
434
435
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);
444 }
445 }
446 if (err < 0)
447 return err;
448
449 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
450 ((ver_offs >> 8) & 0xff));
451 if (err < 0)
452 return err;
453
454 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
455 if (err < 0)
456 return err;
457
458 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
459 if (err < 0)
460 return err;
461
462 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
463 if (err < 0)
464 return err;
465
466 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
467 if (err < 0)
468 return err;
469
470 for (i = 0; i < 2 && !err; i++)
471 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
472 if (err < 0)
473 return err;
474
475 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
476 if (err < 0)
477 return err;
478
479 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
480 if (err < 0)
481 return err;
482
483 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
484 (hor_offs >> 8) & 0xff);
485 if (err < 0)
486 return err;
487
488 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
489 if (err < 0)
490 return err;
491
492 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
493 ((width + hor_offs) >> 8) & 0xff);
494 if (err < 0)
495 return err;
496
497 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
498 ((width + hor_offs) & 0xff));
499 if (err < 0)
500 return err;
501
502 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
503 if (err < 0)
504 return err;
505
506 switch (width) {
507 case 640:
508 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
509
510 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
511 OV9650_RAW_RGB_SELECT;
512 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
513 break;
514
515 case 352:
516 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for CIF mode\n");
517
518 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
519 OV9650_RAW_RGB_SELECT;
520 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
521 break;
522
523 case 320:
524 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n");
525
526 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
527 OV9650_RAW_RGB_SELECT;
528 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
529 break;
530
531 case 176:
532 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QCIF mode\n");
533
534 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
535 OV9650_RAW_RGB_SELECT;
536 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
537 break;
538 }
539 return err;
540}
541
542int ov9650_stop(struct sd *sd)
543{
544 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
545 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
546}
547
548void ov9650_disconnect(struct sd *sd)
549{
550 ov9650_stop(sd);
551
552 sd->sensor = NULL;
553}
554
555static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
558 u8 i2c_data;
559 int err;
560
561 gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d\n", val);
562
563
564 i2c_data = (val >> 10) & 0x3f;
565 err = m5602_write_sensor(sd, OV9650_AECHM,
566 &i2c_data, 1);
567 if (err < 0)
568 return err;
569
570
571 i2c_data = (val >> 2) & 0xff;
572 err = m5602_write_sensor(sd, OV9650_AECH,
573 &i2c_data, 1);
574 if (err < 0)
575 return err;
576
577
578 i2c_data = val & 0x03;
579 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
580 return err;
581}
582
583static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
584{
585 int err;
586 u8 i2c_data;
587 struct sd *sd = (struct sd *) gspca_dev;
588
589 gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val);
590
591
592
593
594 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
595 if (err < 0)
596 return err;
597
598
599 i2c_data = ((val & 0x0300) >> 2) |
600 (i2c_data & 0x3f);
601 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
602 if (err < 0)
603 return err;
604
605
606 i2c_data = val & 0xff;
607 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
608 return err;
609}
610
611static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
612{
613 int err;
614 u8 i2c_data;
615 struct sd *sd = (struct sd *) gspca_dev;
616
617 gspca_dbg(gspca_dev, D_CONF, "Set red gain to %d\n", val);
618
619 i2c_data = val & 0xff;
620 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
621 return err;
622}
623
624static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
625{
626 int err;
627 u8 i2c_data;
628 struct sd *sd = (struct sd *) gspca_dev;
629
630 gspca_dbg(gspca_dev, D_CONF, "Set blue gain to %d\n", val);
631
632 i2c_data = val & 0xff;
633 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
634 return err;
635}
636
637static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
638{
639 int err;
640 u8 i2c_data;
641 struct sd *sd = (struct sd *) gspca_dev;
642 int hflip = sd->hflip->val;
643 int vflip = sd->vflip->val;
644
645 gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n", hflip, vflip);
646
647 if (dmi_check_system(ov9650_flip_dmi_table))
648 vflip = !vflip;
649
650 i2c_data = (hflip << 5) | (vflip << 4);
651 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
652 if (err < 0)
653 return err;
654
655
656 if (gspca_dev->streaming)
657 err = ov9650_start(sd);
658
659 return err;
660}
661
662static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
663 __s32 val)
664{
665 int err;
666 u8 i2c_data;
667 struct sd *sd = (struct sd *) gspca_dev;
668
669 gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val);
670
671 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
672 if (err < 0)
673 return err;
674
675 val = (val == V4L2_EXPOSURE_AUTO);
676 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
677
678 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
679}
680
681static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
682 __s32 val)
683{
684 int err;
685 u8 i2c_data;
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val);
689
690 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
691 if (err < 0)
692 return err;
693
694 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
695 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
696
697 return err;
698}
699
700static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
701{
702 int err;
703 u8 i2c_data;
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val);
707
708 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
709 if (err < 0)
710 return err;
711
712 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
713
714 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
715}
716
717static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
718{
719 struct gspca_dev *gspca_dev =
720 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
721 struct sd *sd = (struct sd *) gspca_dev;
722 int err;
723
724 if (!gspca_dev->streaming)
725 return 0;
726
727 switch (ctrl->id) {
728 case V4L2_CID_AUTO_WHITE_BALANCE:
729 err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
730 if (err || ctrl->val)
731 return err;
732 err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
733 if (err)
734 return err;
735 err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
736 break;
737 case V4L2_CID_EXPOSURE_AUTO:
738 err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
739 if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
740 return err;
741 err = ov9650_set_exposure(gspca_dev, sd->expo->val);
742 break;
743 case V4L2_CID_AUTOGAIN:
744 err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
745 if (err || ctrl->val)
746 return err;
747 err = ov9650_set_gain(gspca_dev, sd->gain->val);
748 break;
749 case V4L2_CID_HFLIP:
750 err = ov9650_set_hvflip(gspca_dev);
751 break;
752 default:
753 return -EINVAL;
754 }
755
756 return err;
757}
758
759static void ov9650_dump_registers(struct sd *sd)
760{
761 int address;
762 pr_info("Dumping the ov9650 register state\n");
763 for (address = 0; address < 0xa9; address++) {
764 u8 value;
765 m5602_read_sensor(sd, address, &value, 1);
766 pr_info("register 0x%x contains 0x%x\n", address, value);
767 }
768
769 pr_info("ov9650 register state dump complete\n");
770
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};
775
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);
779
780 if (ctrl_value == test_value[0])
781 pr_info("register 0x%x is writeable\n", address);
782 else
783 pr_info("register 0x%x is read only\n", address);
784
785
786 m5602_write_sensor(sd, address, &old_value, 1);
787 }
788}
789