m5602_ov7660.c (12442B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Driver for the ov7660 sensor 4 * 5 * Copyright (C) 2009 Erik Andrén 6 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. 7 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> 8 * 9 * Portions of code to USB interface and ALi driver software, 10 * Copyright (c) 2006 Willem Duinker 11 * v4l2 interface modeled after the V4L2 driver 12 * for SN9C10x PC Camera Controllers 13 */ 14 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 17#include "m5602_ov7660.h" 18 19static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl); 20static void ov7660_dump_registers(struct sd *sd); 21 22static const unsigned char preinit_ov7660[][4] = { 23 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, 24 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, 25 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 26 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 27 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 28 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, 29 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, 30 {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, 31 {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, 32 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 33 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 34 35 {SENSOR, OV7660_OFON, 0x0c}, 36 {SENSOR, OV7660_COM2, 0x11}, 37 {SENSOR, OV7660_COM7, 0x05}, 38 39 {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, 40 {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, 41 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 42 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, 43 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, 44 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, 45 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 46 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 47 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 48 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 49 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 50 {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, 51 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, 52 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 53 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00} 54}; 55 56static const unsigned char init_ov7660[][4] = { 57 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, 58 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, 59 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 60 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 61 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 62 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, 63 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, 64 {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, 65 {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, 66 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 67 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 68 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 69 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 70 {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, 71 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, 72 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 73 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, 74 {SENSOR, OV7660_COM7, 0x80}, 75 {SENSOR, OV7660_CLKRC, 0x80}, 76 {SENSOR, OV7660_COM9, 0x4c}, 77 {SENSOR, OV7660_OFON, 0x43}, 78 {SENSOR, OV7660_COM12, 0x28}, 79 {SENSOR, OV7660_COM8, 0x00}, 80 {SENSOR, OV7660_COM10, 0x40}, 81 {SENSOR, OV7660_HSTART, 0x0c}, 82 {SENSOR, OV7660_HSTOP, 0x61}, 83 {SENSOR, OV7660_HREF, 0xa4}, 84 {SENSOR, OV7660_PSHFT, 0x0b}, 85 {SENSOR, OV7660_VSTART, 0x01}, 86 {SENSOR, OV7660_VSTOP, 0x7a}, 87 {SENSOR, OV7660_VSTOP, 0x00}, 88 {SENSOR, OV7660_COM7, 0x05}, 89 {SENSOR, OV7660_COM6, 0x42}, 90 {SENSOR, OV7660_BBIAS, 0x94}, 91 {SENSOR, OV7660_GbBIAS, 0x94}, 92 {SENSOR, OV7660_RSVD29, 0x94}, 93 {SENSOR, OV7660_RBIAS, 0x94}, 94 {SENSOR, OV7660_COM1, 0x00}, 95 {SENSOR, OV7660_AECH, 0x00}, 96 {SENSOR, OV7660_AECHH, 0x00}, 97 {SENSOR, OV7660_ADC, 0x05}, 98 {SENSOR, OV7660_COM13, 0x00}, 99 {SENSOR, OV7660_RSVDA1, 0x23}, 100 {SENSOR, OV7660_TSLB, 0x0d}, 101 {SENSOR, OV7660_HV, 0x80}, 102 {SENSOR, OV7660_LCC1, 0x00}, 103 {SENSOR, OV7660_LCC2, 0x00}, 104 {SENSOR, OV7660_LCC3, 0x10}, 105 {SENSOR, OV7660_LCC4, 0x40}, 106 {SENSOR, OV7660_LCC5, 0x01}, 107 108 {SENSOR, OV7660_AECH, 0x20}, 109 {SENSOR, OV7660_COM1, 0x00}, 110 {SENSOR, OV7660_OFON, 0x0c}, 111 {SENSOR, OV7660_COM2, 0x11}, 112 {SENSOR, OV7660_COM7, 0x05}, 113 {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, 114 {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, 115 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 116 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, 117 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, 118 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, 119 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 120 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 121 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 122 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 123 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 124 {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, 125 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, 126 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 127 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, 128 {SENSOR, OV7660_AECH, 0x5f}, 129 {SENSOR, OV7660_COM1, 0x03}, 130 {SENSOR, OV7660_OFON, 0x0c}, 131 {SENSOR, OV7660_COM2, 0x11}, 132 {SENSOR, OV7660_COM7, 0x05}, 133 {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, 134 {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, 135 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 136 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, 137 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, 138 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, 139 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 140 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 141 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 142 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 143 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 144 {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, 145 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, 146 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, 147 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, 148 149 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, 150 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 151 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, 152 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, 153 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, 154 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, 155 {BRIDGE, M5602_XB_SIG_INI, 0x01}, 156 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, 157 {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, 158 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, 159 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, 160 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, 161 {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, 162 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, 163 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, 164 {BRIDGE, M5602_XB_SIG_INI, 0x00}, 165 {BRIDGE, M5602_XB_SIG_INI, 0x02}, 166 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, 167 {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, 168 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, 169 {BRIDGE, M5602_XB_HSYNC_PARA, 0xa7}, 170 {BRIDGE, M5602_XB_SIG_INI, 0x00}, 171 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, 172 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, 173}; 174 175static struct v4l2_pix_format ov7660_modes[] = { 176 { 177 640, 178 480, 179 V4L2_PIX_FMT_SBGGR8, 180 V4L2_FIELD_NONE, 181 .sizeimage = 182 640 * 480, 183 .bytesperline = 640, 184 .colorspace = V4L2_COLORSPACE_SRGB, 185 .priv = 0 186 } 187}; 188 189static const struct v4l2_ctrl_ops ov7660_ctrl_ops = { 190 .s_ctrl = ov7660_s_ctrl, 191}; 192 193int ov7660_probe(struct sd *sd) 194{ 195 int err = 0, i; 196 u8 prod_id = 0, ver_id = 0; 197 198 if (force_sensor) { 199 if (force_sensor == OV7660_SENSOR) { 200 pr_info("Forcing an %s sensor\n", ov7660.name); 201 goto sensor_found; 202 } 203 /* If we want to force another sensor, 204 don't try to probe this one */ 205 return -ENODEV; 206 } 207 208 /* Do the preinit */ 209 for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { 210 u8 data[2]; 211 212 if (preinit_ov7660[i][0] == BRIDGE) { 213 err = m5602_write_bridge(sd, 214 preinit_ov7660[i][1], 215 preinit_ov7660[i][2]); 216 } else { 217 data[0] = preinit_ov7660[i][2]; 218 err = m5602_write_sensor(sd, 219 preinit_ov7660[i][1], data, 1); 220 } 221 } 222 if (err < 0) 223 return err; 224 225 if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) 226 return -ENODEV; 227 228 if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) 229 return -ENODEV; 230 231 pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id); 232 233 if ((prod_id == 0x76) && (ver_id == 0x60)) { 234 pr_info("Detected a ov7660 sensor\n"); 235 goto sensor_found; 236 } 237 return -ENODEV; 238 239sensor_found: 240 sd->gspca_dev.cam.cam_mode = ov7660_modes; 241 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); 242 243 return 0; 244} 245 246int ov7660_init(struct sd *sd) 247{ 248 int i, err; 249 250 /* Init the sensor */ 251 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { 252 u8 data[2]; 253 254 if (init_ov7660[i][0] == BRIDGE) { 255 err = m5602_write_bridge(sd, 256 init_ov7660[i][1], 257 init_ov7660[i][2]); 258 } else { 259 data[0] = init_ov7660[i][2]; 260 err = m5602_write_sensor(sd, 261 init_ov7660[i][1], data, 1); 262 } 263 if (err < 0) 264 return err; 265 } 266 267 if (dump_sensor) 268 ov7660_dump_registers(sd); 269 270 return 0; 271} 272 273int ov7660_init_controls(struct sd *sd) 274{ 275 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; 276 277 sd->gspca_dev.vdev.ctrl_handler = hdl; 278 v4l2_ctrl_handler_init(hdl, 6); 279 280 v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 281 0, 1, 1, 1); 282 v4l2_ctrl_new_std_menu(hdl, &ov7660_ctrl_ops, 283 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO); 284 285 sd->autogain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, 286 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 287 sd->gain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_GAIN, 0, 288 255, 1, OV7660_DEFAULT_GAIN); 289 290 sd->hflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_HFLIP, 291 0, 1, 1, 0); 292 sd->vflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_VFLIP, 293 0, 1, 1, 0); 294 295 if (hdl->error) { 296 pr_err("Could not initialize controls\n"); 297 return hdl->error; 298 } 299 300 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false); 301 v4l2_ctrl_cluster(2, &sd->hflip); 302 303 return 0; 304} 305 306int ov7660_start(struct sd *sd) 307{ 308 return 0; 309} 310 311int ov7660_stop(struct sd *sd) 312{ 313 return 0; 314} 315 316void ov7660_disconnect(struct sd *sd) 317{ 318 ov7660_stop(sd); 319 320 sd->sensor = NULL; 321} 322 323static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) 324{ 325 int err; 326 u8 i2c_data = val; 327 struct sd *sd = (struct sd *) gspca_dev; 328 329 gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val); 330 331 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); 332 return err; 333} 334 335static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 336 __s32 val) 337{ 338 int err; 339 u8 i2c_data; 340 struct sd *sd = (struct sd *) gspca_dev; 341 342 gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val); 343 344 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 345 if (err < 0) 346 return err; 347 348 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); 349 err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 350 351 return err; 352} 353 354static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) 355{ 356 int err; 357 u8 i2c_data; 358 struct sd *sd = (struct sd *) gspca_dev; 359 360 gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val); 361 362 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 363 if (err < 0) 364 return err; 365 366 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); 367 368 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 369} 370 371static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, 372 __s32 val) 373{ 374 int err; 375 u8 i2c_data; 376 struct sd *sd = (struct sd *) gspca_dev; 377 378 gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val); 379 380 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 381 if (err < 0) 382 return err; 383 384 val = (val == V4L2_EXPOSURE_AUTO); 385 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); 386 387 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 388} 389 390static int ov7660_set_hvflip(struct gspca_dev *gspca_dev) 391{ 392 int err; 393 u8 i2c_data; 394 struct sd *sd = (struct sd *) gspca_dev; 395 396 gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d, %d\n", 397 sd->hflip->val, sd->vflip->val); 398 399 i2c_data = (sd->hflip->val << 5) | (sd->vflip->val << 4); 400 401 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 402 403 return err; 404} 405 406static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl) 407{ 408 struct gspca_dev *gspca_dev = 409 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 410 struct sd *sd = (struct sd *) gspca_dev; 411 int err; 412 413 if (!gspca_dev->streaming) 414 return 0; 415 416 switch (ctrl->id) { 417 case V4L2_CID_AUTO_WHITE_BALANCE: 418 err = ov7660_set_auto_white_balance(gspca_dev, ctrl->val); 419 break; 420 case V4L2_CID_EXPOSURE_AUTO: 421 err = ov7660_set_auto_exposure(gspca_dev, ctrl->val); 422 break; 423 case V4L2_CID_AUTOGAIN: 424 err = ov7660_set_auto_gain(gspca_dev, ctrl->val); 425 if (err || ctrl->val) 426 return err; 427 err = ov7660_set_gain(gspca_dev, sd->gain->val); 428 break; 429 case V4L2_CID_HFLIP: 430 err = ov7660_set_hvflip(gspca_dev); 431 break; 432 default: 433 return -EINVAL; 434 } 435 436 return err; 437} 438 439static void ov7660_dump_registers(struct sd *sd) 440{ 441 int address; 442 pr_info("Dumping the ov7660 register state\n"); 443 for (address = 0; address < 0xa9; address++) { 444 u8 value; 445 m5602_read_sensor(sd, address, &value, 1); 446 pr_info("register 0x%x contains 0x%x\n", address, value); 447 } 448 449 pr_info("ov7660 register state dump complete\n"); 450 451 pr_info("Probing for which registers that are read/write\n"); 452 for (address = 0; address < 0xff; address++) { 453 u8 old_value, ctrl_value; 454 u8 test_value[2] = {0xff, 0xff}; 455 456 m5602_read_sensor(sd, address, &old_value, 1); 457 m5602_write_sensor(sd, address, test_value, 1); 458 m5602_read_sensor(sd, address, &ctrl_value, 1); 459 460 if (ctrl_value == test_value[0]) 461 pr_info("register 0x%x is writeable\n", address); 462 else 463 pr_info("register 0x%x is read only\n", address); 464 465 /* Restore original value */ 466 m5602_write_sensor(sd, address, &old_value, 1); 467 } 468}