2 * Driver for the ov9650 sensor
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
19 #include "m5602_ov9650.h"
21 /* Vertically and horizontally flips the image if matched, needed for machines
22 where the sensor is mounted upside down */
25 struct dmi_system_id ov9650_flip_dmi_table
[] = {
29 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
30 DMI_MATCH(DMI_PRODUCT_NAME
, "A6VC")
36 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
37 DMI_MATCH(DMI_PRODUCT_NAME
, "A6VM")
43 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
44 DMI_MATCH(DMI_PRODUCT_NAME
, "A6JC")
50 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
51 DMI_MATCH(DMI_PRODUCT_NAME
, "A6J")
57 DMI_MATCH(DMI_SYS_VENDOR
, "ASUSTeK Computer Inc."),
58 DMI_MATCH(DMI_PRODUCT_NAME
, "A6Kt")
62 .ident
= "Alienware Aurora m9700",
64 DMI_MATCH(DMI_SYS_VENDOR
, "alienware"),
65 DMI_MATCH(DMI_PRODUCT_NAME
, "Aurora m9700")
71 const static struct ctrl ov9650_ctrls
[] = {
72 #define EXPOSURE_IDX 0
75 .id
= V4L2_CID_EXPOSURE
,
76 .type
= V4L2_CTRL_TYPE_INTEGER
,
81 .default_value
= EXPOSURE_DEFAULT
,
82 .flags
= V4L2_CTRL_FLAG_SLIDER
84 .set
= ov9650_set_exposure
,
85 .get
= ov9650_get_exposure
91 .type
= V4L2_CTRL_TYPE_INTEGER
,
96 .default_value
= GAIN_DEFAULT
,
97 .flags
= V4L2_CTRL_FLAG_SLIDER
99 .set
= ov9650_set_gain
,
100 .get
= ov9650_get_gain
102 #define RED_BALANCE_IDX 2
105 .type
= V4L2_CTRL_TYPE_INTEGER
,
106 .name
= "red balance",
110 .default_value
= RED_GAIN_DEFAULT
,
111 .flags
= V4L2_CTRL_FLAG_SLIDER
113 .set
= ov9650_set_red_balance
,
114 .get
= ov9650_get_red_balance
116 #define BLUE_BALANCE_IDX 3
119 .type
= V4L2_CTRL_TYPE_INTEGER
,
120 .name
= "blue balance",
124 .default_value
= BLUE_GAIN_DEFAULT
,
125 .flags
= V4L2_CTRL_FLAG_SLIDER
127 .set
= ov9650_set_blue_balance
,
128 .get
= ov9650_get_blue_balance
133 .id
= V4L2_CID_HFLIP
,
134 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
135 .name
= "horizontal flip",
141 .set
= ov9650_set_hflip
,
142 .get
= ov9650_get_hflip
147 .id
= V4L2_CID_VFLIP
,
148 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
149 .name
= "vertical flip",
155 .set
= ov9650_set_vflip
,
156 .get
= ov9650_get_vflip
158 #define AUTO_WHITE_BALANCE_IDX 6
161 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
162 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
163 .name
= "auto white balance",
169 .set
= ov9650_set_auto_white_balance
,
170 .get
= ov9650_get_auto_white_balance
172 #define AUTO_GAIN_CTRL_IDX 7
175 .id
= V4L2_CID_AUTOGAIN
,
176 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
177 .name
= "auto gain control",
183 .set
= ov9650_set_auto_gain
,
184 .get
= ov9650_get_auto_gain
188 static struct v4l2_pix_format ov9650_modes
[] = {
197 .colorspace
= V4L2_COLORSPACE_SRGB
,
207 .colorspace
= V4L2_COLORSPACE_SRGB
,
217 .colorspace
= V4L2_COLORSPACE_SRGB
,
227 .colorspace
= V4L2_COLORSPACE_SRGB
,
232 static void ov9650_dump_registers(struct sd
*sd
);
234 int ov9650_probe(struct sd
*sd
)
237 u8 prod_id
= 0, ver_id
= 0, i
;
238 s32
*sensor_settings
;
241 if (force_sensor
== OV9650_SENSOR
) {
242 info("Forcing an %s sensor", ov9650
.name
);
245 /* If we want to force another sensor,
246 don't try to probe this one */
250 info("Probing for an ov9650 sensor");
252 /* Run the pre-init before probing the sensor */
253 for (i
= 0; i
< ARRAY_SIZE(preinit_ov9650
) && !err
; i
++) {
254 u8 data
= preinit_ov9650
[i
][2];
255 if (preinit_ov9650
[i
][0] == SENSOR
)
256 err
= m5602_write_sensor(sd
,
257 preinit_ov9650
[i
][1], &data
, 1);
259 err
= m5602_write_bridge(sd
,
260 preinit_ov9650
[i
][1], data
);
266 if (m5602_read_sensor(sd
, OV9650_PID
, &prod_id
, 1))
269 if (m5602_read_sensor(sd
, OV9650_VER
, &ver_id
, 1))
272 if ((prod_id
== 0x96) && (ver_id
== 0x52)) {
273 info("Detected an ov9650 sensor");
279 sensor_settings
= kmalloc(
280 ARRAY_SIZE(ov9650_ctrls
) * sizeof(s32
), GFP_KERNEL
);
281 if (!sensor_settings
)
284 sd
->gspca_dev
.cam
.cam_mode
= ov9650_modes
;
285 sd
->gspca_dev
.cam
.nmodes
= ARRAY_SIZE(ov9650_modes
);
286 sd
->desc
->ctrls
= ov9650_ctrls
;
287 sd
->desc
->nctrls
= ARRAY_SIZE(ov9650_ctrls
);
289 for (i
= 0; i
< ARRAY_SIZE(ov9650_ctrls
); i
++)
290 sensor_settings
[i
] = ov9650_ctrls
[i
].qctrl
.default_value
;
291 sd
->sensor_priv
= sensor_settings
;
293 if (dmi_check_system(ov9650_flip_dmi_table
) && !err
) {
294 info("vflip quirk active");
295 sensor_settings
[VFLIP_IDX
] = 1;
301 int ov9650_init(struct sd
*sd
)
305 s32
*sensor_settings
= sd
->sensor_priv
;
308 ov9650_dump_registers(sd
);
310 for (i
= 0; i
< ARRAY_SIZE(init_ov9650
) && !err
; i
++) {
311 data
= init_ov9650
[i
][2];
312 if (init_ov9650
[i
][0] == SENSOR
)
313 err
= m5602_write_sensor(sd
, init_ov9650
[i
][1],
316 err
= m5602_write_bridge(sd
, init_ov9650
[i
][1], data
);
319 err
= ov9650_set_exposure(&sd
->gspca_dev
, sensor_settings
[EXPOSURE_IDX
]);
323 err
= ov9650_set_gain(&sd
->gspca_dev
, sensor_settings
[GAIN_IDX
]);
327 err
= ov9650_set_red_balance(&sd
->gspca_dev
, sensor_settings
[RED_BALANCE_IDX
]);
331 err
= ov9650_set_blue_balance(&sd
->gspca_dev
, sensor_settings
[BLUE_BALANCE_IDX
]);
335 err
= ov9650_set_hflip(&sd
->gspca_dev
, sensor_settings
[HFLIP_IDX
]);
339 err
= ov9650_set_vflip(&sd
->gspca_dev
, sensor_settings
[VFLIP_IDX
]);
343 err
= ov9650_set_auto_white_balance(&sd
->gspca_dev
, sensor_settings
[AUTO_WHITE_BALANCE_IDX
]);
347 err
= ov9650_set_auto_gain(&sd
->gspca_dev
, sensor_settings
[AUTO_GAIN_CTRL_IDX
]);
352 int ov9650_start(struct sd
*sd
)
356 struct cam
*cam
= &sd
->gspca_dev
.cam
;
357 s32
*sensor_settings
= sd
->sensor_priv
;
359 int width
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].width
;
360 int height
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].height
;
361 int ver_offs
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].priv
;
362 int hor_offs
= OV9650_LEFT_OFFSET
;
364 if (sensor_settings
[VFLIP_IDX
])
373 /* Synthesize the vsync/hsync setup */
374 for (i
= 0; i
< ARRAY_SIZE(res_init_ov9650
) && !err
; i
++) {
375 if (res_init_ov9650
[i
][0] == BRIDGE
)
376 err
= m5602_write_bridge(sd
, res_init_ov9650
[i
][1],
377 res_init_ov9650
[i
][2]);
378 else if (res_init_ov9650
[i
][0] == SENSOR
) {
379 u8 data
= res_init_ov9650
[i
][2];
380 err
= m5602_write_sensor(sd
,
381 res_init_ov9650
[i
][1], &data
, 1);
387 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
,
388 ((ver_offs
>> 8) & 0xff));
392 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (ver_offs
& 0xff));
396 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
400 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
>> 8) & 0xff);
404 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
& 0xff));
408 for (i
= 0; i
< 2 && !err
; i
++)
409 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
413 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
414 (hor_offs
>> 8) & 0xff);
418 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
, hor_offs
& 0xff);
422 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
423 ((width
+ hor_offs
) >> 8) & 0xff);
427 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
428 ((width
+ hor_offs
) & 0xff));
434 PDEBUG(D_V4L2
, "Configuring camera for VGA mode");
436 data
= OV9650_VGA_SELECT
| OV9650_RGB_SELECT
|
437 OV9650_RAW_RGB_SELECT
;
439 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
444 PDEBUG(D_V4L2
, "Configuring camera for CIF mode");
446 data
= OV9650_CIF_SELECT
| OV9650_RGB_SELECT
|
447 OV9650_RAW_RGB_SELECT
;
449 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
454 PDEBUG(D_V4L2
, "Configuring camera for QVGA mode");
456 data
= OV9650_QVGA_SELECT
| OV9650_RGB_SELECT
|
457 OV9650_RAW_RGB_SELECT
;
459 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
464 PDEBUG(D_V4L2
, "Configuring camera for QCIF mode");
466 data
= OV9650_QCIF_SELECT
| OV9650_RGB_SELECT
|
467 OV9650_RAW_RGB_SELECT
;
469 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
475 int ov9650_stop(struct sd
*sd
)
477 u8 data
= OV9650_SOFT_SLEEP
| OV9650_OUTPUT_DRIVE_2X
;
478 return m5602_write_sensor(sd
, OV9650_COM2
, &data
, 1);
481 int ov9650_power_down(struct sd
*sd
)
484 for (i
= 0; i
< ARRAY_SIZE(power_down_ov9650
) && !err
; i
++) {
485 u8 data
= power_down_ov9650
[i
][2];
486 if (power_down_ov9650
[i
][0] == SENSOR
)
487 err
= m5602_write_sensor(sd
,
488 power_down_ov9650
[i
][1], &data
, 1);
490 err
= m5602_write_bridge(sd
, power_down_ov9650
[i
][1],
497 void ov9650_disconnect(struct sd
*sd
)
500 ov9650_power_down(sd
);
504 kfree(sd
->sensor_priv
);
507 int ov9650_get_exposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
509 struct sd
*sd
= (struct sd
*) gspca_dev
;
510 s32
*sensor_settings
= sd
->sensor_priv
;
512 *val
= sensor_settings
[EXPOSURE_IDX
];
513 PDEBUG(D_V4L2
, "Read exposure %d", *val
);
517 int ov9650_set_exposure(struct gspca_dev
*gspca_dev
, __s32 val
)
519 struct sd
*sd
= (struct sd
*) gspca_dev
;
520 s32
*sensor_settings
= sd
->sensor_priv
;
524 PDEBUG(D_V4L2
, "Set exposure to %d", val
);
526 sensor_settings
[EXPOSURE_IDX
] = val
;
529 i2c_data
= (val
>> 10) & 0x3f;
530 err
= m5602_write_sensor(sd
, OV9650_AECHM
,
535 /* The 8 middle bits */
536 i2c_data
= (val
>> 2) & 0xff;
537 err
= m5602_write_sensor(sd
, OV9650_AECH
,
543 i2c_data
= val
& 0x03;
544 err
= m5602_write_sensor(sd
, OV9650_COM1
, &i2c_data
, 1);
549 int ov9650_get_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
551 struct sd
*sd
= (struct sd
*) gspca_dev
;
552 s32
*sensor_settings
= sd
->sensor_priv
;
554 *val
= sensor_settings
[GAIN_IDX
];
555 PDEBUG(D_V4L2
, "Read gain %d", *val
);
559 int ov9650_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
563 struct sd
*sd
= (struct sd
*) gspca_dev
;
564 s32
*sensor_settings
= sd
->sensor_priv
;
566 PDEBUG(D_V4L2
, "Setting gain to %d", val
);
568 sensor_settings
[GAIN_IDX
] = val
;
571 /* Read the OV9650_VREF register first to avoid
572 corrupting the VREF high and low bits */
573 err
= m5602_read_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
577 /* Mask away all uninteresting bits */
578 i2c_data
= ((val
& 0x0300) >> 2) |
580 err
= m5602_write_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
585 i2c_data
= val
& 0xff;
586 err
= m5602_write_sensor(sd
, OV9650_GAIN
, &i2c_data
, 1);
590 int ov9650_get_red_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
592 struct sd
*sd
= (struct sd
*) gspca_dev
;
593 s32
*sensor_settings
= sd
->sensor_priv
;
595 *val
= sensor_settings
[RED_BALANCE_IDX
];
596 PDEBUG(D_V4L2
, "Read red gain %d", *val
);
600 int ov9650_set_red_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
604 struct sd
*sd
= (struct sd
*) gspca_dev
;
605 s32
*sensor_settings
= sd
->sensor_priv
;
607 PDEBUG(D_V4L2
, "Set red gain to %d", val
);
609 sensor_settings
[RED_BALANCE_IDX
] = val
;
611 i2c_data
= val
& 0xff;
612 err
= m5602_write_sensor(sd
, OV9650_RED
, &i2c_data
, 1);
617 int ov9650_get_blue_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
619 struct sd
*sd
= (struct sd
*) gspca_dev
;
620 s32
*sensor_settings
= sd
->sensor_priv
;
622 *val
= sensor_settings
[BLUE_BALANCE_IDX
];
623 PDEBUG(D_V4L2
, "Read blue gain %d", *val
);
628 int ov9650_set_blue_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
632 struct sd
*sd
= (struct sd
*) gspca_dev
;
633 s32
*sensor_settings
= sd
->sensor_priv
;
635 PDEBUG(D_V4L2
, "Set blue gain to %d", val
);
637 sensor_settings
[BLUE_BALANCE_IDX
] = val
;
639 i2c_data
= val
& 0xff;
640 err
= m5602_write_sensor(sd
, OV9650_BLUE
, &i2c_data
, 1);
645 int ov9650_get_hflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
647 struct sd
*sd
= (struct sd
*) gspca_dev
;
648 s32
*sensor_settings
= sd
->sensor_priv
;
649 *val
= sensor_settings
[HFLIP_IDX
];
650 PDEBUG(D_V4L2
, "Read horizontal flip %d", *val
);
655 int ov9650_set_hflip(struct gspca_dev
*gspca_dev
, __s32 val
)
659 struct sd
*sd
= (struct sd
*) gspca_dev
;
660 s32
*sensor_settings
= sd
->sensor_priv
;
662 PDEBUG(D_V4L2
, "Set horizontal flip to %d", val
);
664 sensor_settings
[HFLIP_IDX
] = val
;
665 i2c_data
= ((val
& 0x01) << 5) | (sensor_settings
[VFLIP_IDX
] << 4);
666 err
= m5602_write_sensor(sd
, OV9650_MVFP
, &i2c_data
, 1);
671 int ov9650_get_vflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
673 struct sd
*sd
= (struct sd
*) gspca_dev
;
674 s32
*sensor_settings
= sd
->sensor_priv
;
676 *val
= sensor_settings
[VFLIP_IDX
];
677 PDEBUG(D_V4L2
, "Read vertical flip %d", *val
);
682 int ov9650_set_vflip(struct gspca_dev
*gspca_dev
, __s32 val
)
686 struct sd
*sd
= (struct sd
*) gspca_dev
;
687 s32
*sensor_settings
= sd
->sensor_priv
;
689 PDEBUG(D_V4L2
, "Set vertical flip to %d", val
);
690 sensor_settings
[VFLIP_IDX
] = val
;
692 i2c_data
= ((val
& 0x01) << 4) | (sensor_settings
[VFLIP_IDX
] << 5);
693 err
= m5602_write_sensor(sd
, OV9650_MVFP
, &i2c_data
, 1);
697 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
698 if (gspca_dev
->streaming
)
699 err
= ov9650_start(sd
);
704 int ov9650_get_brightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
706 struct sd
*sd
= (struct sd
*) gspca_dev
;
707 s32
*sensor_settings
= sd
->sensor_priv
;
709 *val
= sensor_settings
[GAIN_IDX
];
710 PDEBUG(D_V4L2
, "Read gain %d", *val
);
715 int ov9650_set_brightness(struct gspca_dev
*gspca_dev
, __s32 val
)
719 struct sd
*sd
= (struct sd
*) gspca_dev
;
720 s32
*sensor_settings
= sd
->sensor_priv
;
722 PDEBUG(D_V4L2
, "Set gain to %d", val
);
724 sensor_settings
[GAIN_IDX
] = val
;
726 /* Read the OV9650_VREF register first to avoid
727 corrupting the VREF high and low bits */
728 err
= m5602_read_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
732 /* Mask away all uninteresting bits */
733 i2c_data
= ((val
& 0x0300) >> 2) | (i2c_data
& 0x3F);
734 err
= m5602_write_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
739 i2c_data
= val
& 0xff;
740 err
= m5602_write_sensor(sd
, OV9650_GAIN
, &i2c_data
, 1);
745 int ov9650_get_auto_white_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
747 struct sd
*sd
= (struct sd
*) gspca_dev
;
748 s32
*sensor_settings
= sd
->sensor_priv
;
750 *val
= sensor_settings
[AUTO_WHITE_BALANCE_IDX
];
754 int ov9650_set_auto_white_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
758 struct sd
*sd
= (struct sd
*) gspca_dev
;
759 s32
*sensor_settings
= sd
->sensor_priv
;
761 PDEBUG(D_V4L2
, "Set auto white balance to %d", val
);
763 sensor_settings
[AUTO_WHITE_BALANCE_IDX
] = val
;
764 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
768 i2c_data
= ((i2c_data
& 0xfd) | ((val
& 0x01) << 1));
769 err
= m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
774 int ov9650_get_auto_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
776 struct sd
*sd
= (struct sd
*) gspca_dev
;
777 s32
*sensor_settings
= sd
->sensor_priv
;
779 *val
= sensor_settings
[AUTO_GAIN_CTRL_IDX
];
780 PDEBUG(D_V4L2
, "Read auto gain control %d", *val
);
784 int ov9650_set_auto_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
788 struct sd
*sd
= (struct sd
*) gspca_dev
;
789 s32
*sensor_settings
= sd
->sensor_priv
;
791 PDEBUG(D_V4L2
, "Set auto gain control to %d", val
);
793 sensor_settings
[AUTO_GAIN_CTRL_IDX
] = val
;
794 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
798 i2c_data
= ((i2c_data
& 0xfb) | ((val
& 0x01) << 2));
799 err
= m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
804 static void ov9650_dump_registers(struct sd
*sd
)
807 info("Dumping the ov9650 register state");
808 for (address
= 0; address
< 0xa9; address
++) {
810 m5602_read_sensor(sd
, address
, &value
, 1);
811 info("register 0x%x contains 0x%x",
815 info("ov9650 register state dump complete");
817 info("Probing for which registers that are read/write");
818 for (address
= 0; address
< 0xff; address
++) {
819 u8 old_value
, ctrl_value
;
820 u8 test_value
[2] = {0xff, 0xff};
822 m5602_read_sensor(sd
, address
, &old_value
, 1);
823 m5602_write_sensor(sd
, address
, test_value
, 1);
824 m5602_read_sensor(sd
, address
, &ctrl_value
, 1);
826 if (ctrl_value
== test_value
[0])
827 info("register 0x%x is writeable", address
);
829 info("register 0x%x is read only", address
);
831 /* Restore original value */
832 m5602_write_sensor(sd
, address
, &old_value
, 1);