root/drivers/media/usb/gspca/m5602/m5602_ov7660.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ov7660_probe
  2. ov7660_init
  3. ov7660_init_controls
  4. ov7660_start
  5. ov7660_stop
  6. ov7660_disconnect
  7. ov7660_set_gain
  8. ov7660_set_auto_white_balance
  9. ov7660_set_auto_gain
  10. ov7660_set_auto_exposure
  11. ov7660_set_hvflip
  12. ov7660_s_ctrl
  13. ov7660_dump_registers

   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 
  19 static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl);
  20 static void ov7660_dump_registers(struct sd *sd);
  21 
  22 static 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 
  56 static 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 
 175 static 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 
 189 static const struct v4l2_ctrl_ops ov7660_ctrl_ops = {
 190         .s_ctrl = ov7660_s_ctrl,
 191 };
 192 
 193 int 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 
 239 sensor_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 
 246 int 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 
 273 int 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 
 306 int ov7660_start(struct sd *sd)
 307 {
 308         return 0;
 309 }
 310 
 311 int ov7660_stop(struct sd *sd)
 312 {
 313         return 0;
 314 }
 315 
 316 void ov7660_disconnect(struct sd *sd)
 317 {
 318         ov7660_stop(sd);
 319 
 320         sd->sensor = NULL;
 321 }
 322 
 323 static 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 
 335 static 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 
 354 static 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 
 371 static 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 
 390 static 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 
 406 static 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 
 439 static 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 }

/* [<][>][^][v][top][bottom][index][help] */