linux/drivers/media/usb/gspca/m5602/m5602_ov7660.c
<<
>>
Prefs
   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}
 469