1/* 2 * Driver for the ov7660 sensor 3 * 4 * Copyright (C) 2009 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> 7 * 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 12 * 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. 16 * 17 */ 18 19#include "m5602_ov7660.h" 20 21static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 22static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); 23static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, 24 __s32 *val); 25static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 26 __s32 val); 27static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); 28static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); 29static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); 30static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); 31static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 32static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 33static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 34static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 35 36static const struct ctrl ov7660_ctrls[] = { 37#define GAIN_IDX 1 38 { 39 { 40 .id = V4L2_CID_GAIN, 41 .type = V4L2_CTRL_TYPE_INTEGER, 42 .name = "gain", 43 .minimum = 0x00, 44 .maximum = 0xff, 45 .step = 0x1, 46 .default_value = OV7660_DEFAULT_GAIN, 47 .flags = V4L2_CTRL_FLAG_SLIDER 48 }, 49 .set = ov7660_set_gain, 50 .get = ov7660_get_gain 51 }, 52#define BLUE_BALANCE_IDX 2 53#define RED_BALANCE_IDX 3 54#define AUTO_WHITE_BALANCE_IDX 4 55 { 56 { 57 .id = V4L2_CID_AUTO_WHITE_BALANCE, 58 .type = V4L2_CTRL_TYPE_BOOLEAN, 59 .name = "auto white balance", 60 .minimum = 0, 61 .maximum = 1, 62 .step = 1, 63 .default_value = 1 64 }, 65 .set = ov7660_set_auto_white_balance, 66 .get = ov7660_get_auto_white_balance 67 }, 68#define AUTO_GAIN_CTRL_IDX 5 69 { 70 { 71 .id = V4L2_CID_AUTOGAIN, 72 .type = V4L2_CTRL_TYPE_BOOLEAN, 73 .name = "auto gain control", 74 .minimum = 0, 75 .maximum = 1, 76 .step = 1, 77 .default_value = 1 78 }, 79 .set = ov7660_set_auto_gain, 80 .get = ov7660_get_auto_gain 81 }, 82#define AUTO_EXPOSURE_IDX 6 83 { 84 { 85 .id = V4L2_CID_EXPOSURE_AUTO, 86 .type = V4L2_CTRL_TYPE_BOOLEAN, 87 .name = "auto exposure", 88 .minimum = 0, 89 .maximum = 1, 90 .step = 1, 91 .default_value = 1 92 }, 93 .set = ov7660_set_auto_exposure, 94 .get = ov7660_get_auto_exposure 95 }, 96#define HFLIP_IDX 7 97 { 98 { 99 .id = V4L2_CID_HFLIP, 100 .type = V4L2_CTRL_TYPE_BOOLEAN, 101 .name = "horizontal flip", 102 .minimum = 0, 103 .maximum = 1, 104 .step = 1, 105 .default_value = 0 106 }, 107 .set = ov7660_set_hflip, 108 .get = ov7660_get_hflip 109 }, 110#define VFLIP_IDX 8 111 { 112 { 113 .id = V4L2_CID_VFLIP, 114 .type = V4L2_CTRL_TYPE_BOOLEAN, 115 .name = "vertical flip", 116 .minimum = 0, 117 .maximum = 1, 118 .step = 1, 119 .default_value = 0 120 }, 121 .set = ov7660_set_vflip, 122 .get = ov7660_get_vflip 123 }, 124 125}; 126 127static struct v4l2_pix_format ov7660_modes[] = { 128 { 129 640, 130 480, 131 V4L2_PIX_FMT_SBGGR8, 132 V4L2_FIELD_NONE, 133 .sizeimage = 134 640 * 480, 135 .bytesperline = 640, 136 .colorspace = V4L2_COLORSPACE_SRGB, 137 .priv = 0 138 } 139}; 140 141static void ov7660_dump_registers(struct sd *sd); 142 143int ov7660_probe(struct sd *sd) 144{ 145 int err = 0, i; 146 u8 prod_id = 0, ver_id = 0; 147 148 s32 *sensor_settings; 149 150 if (force_sensor) { 151 if (force_sensor == OV7660_SENSOR) { 152 info("Forcing an %s sensor", ov7660.name); 153 goto sensor_found; 154 } 155 /* If we want to force another sensor, 156 don't try to probe this one */ 157 return -ENODEV; 158 } 159 160 /* Do the preinit */ 161 for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { 162 u8 data[2]; 163 164 if (preinit_ov7660[i][0] == BRIDGE) { 165 err = m5602_write_bridge(sd, 166 preinit_ov7660[i][1], 167 preinit_ov7660[i][2]); 168 } else { 169 data[0] = preinit_ov7660[i][2]; 170 err = m5602_write_sensor(sd, 171 preinit_ov7660[i][1], data, 1); 172 } 173 } 174 if (err < 0) 175 return err; 176 177 if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) 178 return -ENODEV; 179 180 if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) 181 return -ENODEV; 182 183 info("Sensor reported 0x%x%x", prod_id, ver_id); 184 185 if ((prod_id == 0x76) && (ver_id == 0x60)) { 186 info("Detected a ov7660 sensor"); 187 goto sensor_found; 188 } 189 return -ENODEV; 190 191sensor_found: 192 sensor_settings = kmalloc( 193 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); 194 if (!sensor_settings) 195 return -ENOMEM; 196 197 sd->gspca_dev.cam.cam_mode = ov7660_modes; 198 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); 199 sd->desc->ctrls = ov7660_ctrls; 200 sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls); 201 202 for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++) 203 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value; 204 sd->sensor_priv = sensor_settings; 205 206 return 0; 207} 208 209int ov7660_init(struct sd *sd) 210{ 211 int i, err = 0; 212 s32 *sensor_settings = sd->sensor_priv; 213 214 /* Init the sensor */ 215 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { 216 u8 data[2]; 217 218 if (init_ov7660[i][0] == BRIDGE) { 219 err = m5602_write_bridge(sd, 220 init_ov7660[i][1], 221 init_ov7660[i][2]); 222 } else { 223 data[0] = init_ov7660[i][2]; 224 err = m5602_write_sensor(sd, 225 init_ov7660[i][1], data, 1); 226 } 227 } 228 229 if (dump_sensor) 230 ov7660_dump_registers(sd); 231 232 err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 233 if (err < 0) 234 return err; 235 236 err = ov7660_set_auto_white_balance(&sd->gspca_dev, 237 sensor_settings[AUTO_WHITE_BALANCE_IDX]); 238 if (err < 0) 239 return err; 240 241 err = ov7660_set_auto_gain(&sd->gspca_dev, 242 sensor_settings[AUTO_GAIN_CTRL_IDX]); 243 if (err < 0) 244 return err; 245 246 err = ov7660_set_auto_exposure(&sd->gspca_dev, 247 sensor_settings[AUTO_EXPOSURE_IDX]); 248 if (err < 0) 249 return err; 250 err = ov7660_set_hflip(&sd->gspca_dev, 251 sensor_settings[HFLIP_IDX]); 252 if (err < 0) 253 return err; 254 255 err = ov7660_set_vflip(&sd->gspca_dev, 256 sensor_settings[VFLIP_IDX]); 257 258 return err; 259} 260 261int ov7660_start(struct sd *sd) 262{ 263 return 0; 264} 265 266int ov7660_stop(struct sd *sd) 267{ 268 return 0; 269} 270 271void ov7660_disconnect(struct sd *sd) 272{ 273 ov7660_stop(sd); 274 275 sd->sensor = NULL; 276 kfree(sd->sensor_priv); 277} 278 279static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 280{ 281 struct sd *sd = (struct sd *) gspca_dev; 282 s32 *sensor_settings = sd->sensor_priv; 283 284 *val = sensor_settings[GAIN_IDX]; 285 PDEBUG(D_V4L2, "Read gain %d", *val); 286 return 0; 287} 288 289static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) 290{ 291 int err; 292 u8 i2c_data; 293 struct sd *sd = (struct sd *) gspca_dev; 294 s32 *sensor_settings = sd->sensor_priv; 295 296 PDEBUG(D_V4L2, "Setting gain to %d", val); 297 298 sensor_settings[GAIN_IDX] = val; 299 300 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); 301 return err; 302} 303 304 305static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, 306 __s32 *val) 307{ 308 struct sd *sd = (struct sd *) gspca_dev; 309 s32 *sensor_settings = sd->sensor_priv; 310 311 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; 312 return 0; 313} 314 315static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 316 __s32 val) 317{ 318 int err; 319 u8 i2c_data; 320 struct sd *sd = (struct sd *) gspca_dev; 321 s32 *sensor_settings = sd->sensor_priv; 322 323 PDEBUG(D_V4L2, "Set auto white balance to %d", val); 324 325 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; 326 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 327 if (err < 0) 328 return err; 329 330 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); 331 err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 332 333 return err; 334} 335 336static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) 337{ 338 struct sd *sd = (struct sd *) gspca_dev; 339 s32 *sensor_settings = sd->sensor_priv; 340 341 *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; 342 PDEBUG(D_V4L2, "Read auto gain control %d", *val); 343 return 0; 344} 345 346static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) 347{ 348 int err; 349 u8 i2c_data; 350 struct sd *sd = (struct sd *) gspca_dev; 351 s32 *sensor_settings = sd->sensor_priv; 352 353 PDEBUG(D_V4L2, "Set auto gain control to %d", val); 354 355 sensor_settings[AUTO_GAIN_CTRL_IDX] = val; 356 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 357 if (err < 0) 358 return err; 359 360 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); 361 362 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 363} 364 365static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val) 366{ 367 struct sd *sd = (struct sd *) gspca_dev; 368 s32 *sensor_settings = sd->sensor_priv; 369 370 *val = sensor_settings[AUTO_EXPOSURE_IDX]; 371 PDEBUG(D_V4L2, "Read auto exposure control %d", *val); 372 return 0; 373} 374 375static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, 376 __s32 val) 377{ 378 int err; 379 u8 i2c_data; 380 struct sd *sd = (struct sd *) gspca_dev; 381 s32 *sensor_settings = sd->sensor_priv; 382 383 PDEBUG(D_V4L2, "Set auto exposure control to %d", val); 384 385 sensor_settings[AUTO_EXPOSURE_IDX] = val; 386 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 387 if (err < 0) 388 return err; 389 390 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); 391 392 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 393} 394 395static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 396{ 397 struct sd *sd = (struct sd *) gspca_dev; 398 s32 *sensor_settings = sd->sensor_priv; 399 400 *val = sensor_settings[HFLIP_IDX]; 401 PDEBUG(D_V4L2, "Read horizontal flip %d", *val); 402 return 0; 403} 404 405static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 406{ 407 int err; 408 u8 i2c_data; 409 struct sd *sd = (struct sd *) gspca_dev; 410 s32 *sensor_settings = sd->sensor_priv; 411 412 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 413 414 sensor_settings[HFLIP_IDX] = val; 415 416 i2c_data = ((val & 0x01) << 5) | 417 (sensor_settings[VFLIP_IDX] << 4); 418 419 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 420 421 return err; 422} 423 424static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 425{ 426 struct sd *sd = (struct sd *) gspca_dev; 427 s32 *sensor_settings = sd->sensor_priv; 428 429 *val = sensor_settings[VFLIP_IDX]; 430 PDEBUG(D_V4L2, "Read vertical flip %d", *val); 431 432 return 0; 433} 434 435static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 436{ 437 int err; 438 u8 i2c_data; 439 struct sd *sd = (struct sd *) gspca_dev; 440 s32 *sensor_settings = sd->sensor_priv; 441 442 PDEBUG(D_V4L2, "Set vertical flip to %d", val); 443 sensor_settings[VFLIP_IDX] = val; 444 445 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); 446 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 447 if (err < 0) 448 return err; 449 450 /* When vflip is toggled we need to readjust the bridge hsync/vsync */ 451 if (gspca_dev->streaming) 452 err = ov7660_start(sd); 453 454 return err; 455} 456 457static void ov7660_dump_registers(struct sd *sd) 458{ 459 int address; 460 info("Dumping the ov7660 register state"); 461 for (address = 0; address < 0xa9; address++) { 462 u8 value; 463 m5602_read_sensor(sd, address, &value, 1); 464 info("register 0x%x contains 0x%x", 465 address, value); 466 } 467 468 info("ov7660 register state dump complete"); 469 470 info("Probing for which registers that are read/write"); 471 for (address = 0; address < 0xff; address++) { 472 u8 old_value, ctrl_value; 473 u8 test_value[2] = {0xff, 0xff}; 474 475 m5602_read_sensor(sd, address, &old_value, 1); 476 m5602_write_sensor(sd, address, test_value, 1); 477 m5602_read_sensor(sd, address, &ctrl_value, 1); 478 479 if (ctrl_value == test_value[0]) 480 info("register 0x%x is writeable", address); 481 else 482 info("register 0x%x is read only", address); 483 484 /* Restore original value */ 485 m5602_write_sensor(sd, address, &old_value, 1); 486 } 487} 488