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
]);
351 int ov9650_start(struct sd
*sd
)
355 struct cam
*cam
= &sd
->gspca_dev
.cam
;
356 s32
*sensor_settings
= sd
->sensor_priv
;
358 int width
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].width
;
359 int height
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].height
;
360 int ver_offs
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].priv
;
361 int hor_offs
= OV9650_LEFT_OFFSET
;
363 if (sensor_settings
[VFLIP_IDX
])
369 /* Synthesize the vsync/hsync setup */
370 for (i
= 0; i
< ARRAY_SIZE(res_init_ov9650
) && !err
; i
++) {
371 if (res_init_ov9650
[i
][0] == BRIDGE
)
372 err
= m5602_write_bridge(sd
, res_init_ov9650
[i
][1],
373 res_init_ov9650
[i
][2]);
374 else if (res_init_ov9650
[i
][0] == SENSOR
) {
375 u8 data
= res_init_ov9650
[i
][2];
376 err
= m5602_write_sensor(sd
,
377 res_init_ov9650
[i
][1], &data
, 1);
383 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
,
384 ((ver_offs
>> 8) & 0xff));
388 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (ver_offs
& 0xff));
392 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
396 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
>> 8) & 0xff);
400 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
& 0xff));
404 for (i
= 0; i
< 2 && !err
; i
++)
405 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
409 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
410 (hor_offs
>> 8) & 0xff);
414 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
, hor_offs
& 0xff);
418 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
419 ((width
+ hor_offs
) >> 8) & 0xff);
423 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
424 ((width
+ hor_offs
) & 0xff));
430 PDEBUG(D_V4L2
, "Configuring camera for VGA mode");
432 data
= OV9650_VGA_SELECT
| OV9650_RGB_SELECT
|
433 OV9650_RAW_RGB_SELECT
;
434 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
438 PDEBUG(D_V4L2
, "Configuring camera for CIF mode");
440 data
= OV9650_CIF_SELECT
| OV9650_RGB_SELECT
|
441 OV9650_RAW_RGB_SELECT
;
442 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
446 PDEBUG(D_V4L2
, "Configuring camera for QVGA mode");
448 data
= OV9650_QVGA_SELECT
| OV9650_RGB_SELECT
|
449 OV9650_RAW_RGB_SELECT
;
450 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
454 PDEBUG(D_V4L2
, "Configuring camera for QCIF mode");
456 data
= OV9650_QCIF_SELECT
| OV9650_RGB_SELECT
|
457 OV9650_RAW_RGB_SELECT
;
458 err
= m5602_write_sensor(sd
, OV9650_COM7
, &data
, 1);
464 int ov9650_stop(struct sd
*sd
)
466 u8 data
= OV9650_SOFT_SLEEP
| OV9650_OUTPUT_DRIVE_2X
;
467 return m5602_write_sensor(sd
, OV9650_COM2
, &data
, 1);
470 int ov9650_power_down(struct sd
*sd
)
473 for (i
= 0; i
< ARRAY_SIZE(power_down_ov9650
) && !err
; i
++) {
474 u8 data
= power_down_ov9650
[i
][2];
475 if (power_down_ov9650
[i
][0] == SENSOR
)
476 err
= m5602_write_sensor(sd
,
477 power_down_ov9650
[i
][1], &data
, 1);
479 err
= m5602_write_bridge(sd
, power_down_ov9650
[i
][1],
486 void ov9650_disconnect(struct sd
*sd
)
489 ov9650_power_down(sd
);
492 kfree(sd
->sensor_priv
);
495 int ov9650_get_exposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
497 struct sd
*sd
= (struct sd
*) gspca_dev
;
498 s32
*sensor_settings
= sd
->sensor_priv
;
500 *val
= sensor_settings
[EXPOSURE_IDX
];
501 PDEBUG(D_V4L2
, "Read exposure %d", *val
);
505 int ov9650_set_exposure(struct gspca_dev
*gspca_dev
, __s32 val
)
507 struct sd
*sd
= (struct sd
*) gspca_dev
;
508 s32
*sensor_settings
= sd
->sensor_priv
;
512 PDEBUG(D_V4L2
, "Set exposure to %d", val
);
514 sensor_settings
[EXPOSURE_IDX
] = val
;
516 i2c_data
= (val
>> 10) & 0x3f;
517 err
= m5602_write_sensor(sd
, OV9650_AECHM
,
522 /* The 8 middle bits */
523 i2c_data
= (val
>> 2) & 0xff;
524 err
= m5602_write_sensor(sd
, OV9650_AECH
,
530 i2c_data
= val
& 0x03;
531 err
= m5602_write_sensor(sd
, OV9650_COM1
, &i2c_data
, 1);
535 int ov9650_get_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
537 struct sd
*sd
= (struct sd
*) gspca_dev
;
538 s32
*sensor_settings
= sd
->sensor_priv
;
540 *val
= sensor_settings
[GAIN_IDX
];
541 PDEBUG(D_V4L2
, "Read gain %d", *val
);
545 int ov9650_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
549 struct sd
*sd
= (struct sd
*) gspca_dev
;
550 s32
*sensor_settings
= sd
->sensor_priv
;
552 PDEBUG(D_V4L2
, "Setting gain to %d", val
);
554 sensor_settings
[GAIN_IDX
] = val
;
557 /* Read the OV9650_VREF register first to avoid
558 corrupting the VREF high and low bits */
559 err
= m5602_read_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
563 /* Mask away all uninteresting bits */
564 i2c_data
= ((val
& 0x0300) >> 2) |
566 err
= m5602_write_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
571 i2c_data
= val
& 0xff;
572 err
= m5602_write_sensor(sd
, OV9650_GAIN
, &i2c_data
, 1);
576 int ov9650_get_red_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
578 struct sd
*sd
= (struct sd
*) gspca_dev
;
579 s32
*sensor_settings
= sd
->sensor_priv
;
581 *val
= sensor_settings
[RED_BALANCE_IDX
];
582 PDEBUG(D_V4L2
, "Read red gain %d", *val
);
586 int ov9650_set_red_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
590 struct sd
*sd
= (struct sd
*) gspca_dev
;
591 s32
*sensor_settings
= sd
->sensor_priv
;
593 PDEBUG(D_V4L2
, "Set red gain to %d", val
);
595 sensor_settings
[RED_BALANCE_IDX
] = val
;
597 i2c_data
= val
& 0xff;
598 err
= m5602_write_sensor(sd
, OV9650_RED
, &i2c_data
, 1);
602 int ov9650_get_blue_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
604 struct sd
*sd
= (struct sd
*) gspca_dev
;
605 s32
*sensor_settings
= sd
->sensor_priv
;
607 *val
= sensor_settings
[BLUE_BALANCE_IDX
];
608 PDEBUG(D_V4L2
, "Read blue gain %d", *val
);
613 int ov9650_set_blue_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
617 struct sd
*sd
= (struct sd
*) gspca_dev
;
618 s32
*sensor_settings
= sd
->sensor_priv
;
620 PDEBUG(D_V4L2
, "Set blue gain to %d", val
);
622 sensor_settings
[BLUE_BALANCE_IDX
] = val
;
624 i2c_data
= val
& 0xff;
625 err
= m5602_write_sensor(sd
, OV9650_BLUE
, &i2c_data
, 1);
629 int ov9650_get_hflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
631 struct sd
*sd
= (struct sd
*) gspca_dev
;
632 s32
*sensor_settings
= sd
->sensor_priv
;
634 *val
= sensor_settings
[HFLIP_IDX
];
635 PDEBUG(D_V4L2
, "Read horizontal flip %d", *val
);
639 int ov9650_set_hflip(struct gspca_dev
*gspca_dev
, __s32 val
)
643 struct sd
*sd
= (struct sd
*) gspca_dev
;
644 s32
*sensor_settings
= sd
->sensor_priv
;
646 PDEBUG(D_V4L2
, "Set horizontal flip to %d", val
);
648 sensor_settings
[HFLIP_IDX
] = val
;
649 i2c_data
= ((val
& 0x01) << 5) | (sensor_settings
[VFLIP_IDX
] << 4);
650 err
= m5602_write_sensor(sd
, OV9650_MVFP
, &i2c_data
, 1);
655 int ov9650_get_vflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
657 struct sd
*sd
= (struct sd
*) gspca_dev
;
658 s32
*sensor_settings
= sd
->sensor_priv
;
660 *val
= sensor_settings
[VFLIP_IDX
];
661 PDEBUG(D_V4L2
, "Read vertical flip %d", *val
);
666 int ov9650_set_vflip(struct gspca_dev
*gspca_dev
, __s32 val
)
670 struct sd
*sd
= (struct sd
*) gspca_dev
;
671 s32
*sensor_settings
= sd
->sensor_priv
;
673 PDEBUG(D_V4L2
, "Set vertical flip to %d", val
);
674 sensor_settings
[VFLIP_IDX
] = val
;
676 i2c_data
= ((val
& 0x01) << 4) | (sensor_settings
[VFLIP_IDX
] << 5);
677 err
= m5602_write_sensor(sd
, OV9650_MVFP
, &i2c_data
, 1);
681 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
682 if (gspca_dev
->streaming
)
683 err
= ov9650_start(sd
);
688 int ov9650_get_brightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
690 struct sd
*sd
= (struct sd
*) gspca_dev
;
691 s32
*sensor_settings
= sd
->sensor_priv
;
693 *val
= sensor_settings
[GAIN_IDX
];
694 PDEBUG(D_V4L2
, "Read gain %d", *val
);
699 int ov9650_set_brightness(struct gspca_dev
*gspca_dev
, __s32 val
)
703 struct sd
*sd
= (struct sd
*) gspca_dev
;
704 s32
*sensor_settings
= sd
->sensor_priv
;
706 PDEBUG(D_V4L2
, "Set gain to %d", val
);
708 sensor_settings
[GAIN_IDX
] = val
;
710 /* Read the OV9650_VREF register first to avoid
711 corrupting the VREF high and low bits */
712 err
= m5602_read_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
716 /* Mask away all uninteresting bits */
717 i2c_data
= ((val
& 0x0300) >> 2) | (i2c_data
& 0x3F);
718 err
= m5602_write_sensor(sd
, OV9650_VREF
, &i2c_data
, 1);
723 i2c_data
= val
& 0xff;
724 err
= m5602_write_sensor(sd
, OV9650_GAIN
, &i2c_data
, 1);
729 int ov9650_get_auto_white_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
731 struct sd
*sd
= (struct sd
*) gspca_dev
;
732 s32
*sensor_settings
= sd
->sensor_priv
;
734 *val
= sensor_settings
[AUTO_WHITE_BALANCE_IDX
];
738 int ov9650_set_auto_white_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
742 struct sd
*sd
= (struct sd
*) gspca_dev
;
743 s32
*sensor_settings
= sd
->sensor_priv
;
745 PDEBUG(D_V4L2
, "Set auto white balance to %d", val
);
747 sensor_settings
[AUTO_WHITE_BALANCE_IDX
] = val
;
748 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
752 i2c_data
= ((i2c_data
& 0xfd) | ((val
& 0x01) << 1));
753 err
= m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
758 int ov9650_get_auto_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
760 struct sd
*sd
= (struct sd
*) gspca_dev
;
761 s32
*sensor_settings
= sd
->sensor_priv
;
763 *val
= sensor_settings
[AUTO_GAIN_CTRL_IDX
];
764 PDEBUG(D_V4L2
, "Read auto gain control %d", *val
);
768 int ov9650_set_auto_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
772 struct sd
*sd
= (struct sd
*) gspca_dev
;
773 s32
*sensor_settings
= sd
->sensor_priv
;
775 PDEBUG(D_V4L2
, "Set auto gain control to %d", val
);
777 sensor_settings
[AUTO_GAIN_CTRL_IDX
] = val
;
778 err
= m5602_read_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
782 i2c_data
= ((i2c_data
& 0xfb) | ((val
& 0x01) << 2));
783 err
= m5602_write_sensor(sd
, OV9650_COM8
, &i2c_data
, 1);
788 static void ov9650_dump_registers(struct sd
*sd
)
791 info("Dumping the ov9650 register state");
792 for (address
= 0; address
< 0xa9; address
++) {
794 m5602_read_sensor(sd
, address
, &value
, 1);
795 info("register 0x%x contains 0x%x",
799 info("ov9650 register state dump complete");
801 info("Probing for which registers that are read/write");
802 for (address
= 0; address
< 0xff; address
++) {
803 u8 old_value
, ctrl_value
;
804 u8 test_value
[2] = {0xff, 0xff};
806 m5602_read_sensor(sd
, address
, &old_value
, 1);
807 m5602_write_sensor(sd
, address
, test_value
, 1);
808 m5602_read_sensor(sd
, address
, &ctrl_value
, 1);
810 if (ctrl_value
== test_value
[0])
811 info("register 0x%x is writeable", address
);
813 info("register 0x%x is read only", address
);
815 /* Restore original value */
816 m5602_write_sensor(sd
, address
, &old_value
, 1);