469 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for the ov7660 sensor4 *5 * Copyright (C) 2009 Erik Andrén6 * 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 Duinker11 * v4l2 interface modeled after the V4L2 driver12 * for SN9C10x PC Camera Controllers13 */14 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt16 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 = 0186 }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 else463 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}469