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