linux/drivers/media/video/ovcamchip/ovcamchip_core.c
<<
>>
Prefs
   1/* Shared Code for OmniVision Camera Chip Drivers
   2 *
   3 * Copyright (c) 2004 Mark McClelland <mark@alpha.dyndns.org>
   4 * http://alpha.dyndns.org/ov511/
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License as published by the
   8 * Free Software Foundation; either version 2 of the License, or (at your
   9 * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
  10 */
  11
  12#define DEBUG
  13
  14#include <linux/init.h>
  15#include <linux/module.h>
  16#include <linux/slab.h>
  17#include <linux/delay.h>
  18#include "ovcamchip_priv.h"
  19
  20#define DRIVER_VERSION "v2.27 for Linux 2.6"
  21#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org>"
  22#define DRIVER_DESC "OV camera chip I2C driver"
  23
  24#define PINFO(fmt, args...) printk(KERN_INFO "ovcamchip: " fmt "\n" , ## args);
  25#define PERROR(fmt, args...) printk(KERN_ERR "ovcamchip: " fmt "\n" , ## args);
  26
  27#ifdef DEBUG
  28int ovcamchip_debug = 0;
  29static int debug;
  30module_param(debug, int, 0);
  31MODULE_PARM_DESC(debug,
  32  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=all");
  33#endif
  34
  35/* By default, let bridge driver tell us if chip is monochrome. mono=0
  36 * will ignore that and always treat chips as color. mono=1 will force
  37 * monochrome mode for all chips. */
  38static int mono = -1;
  39module_param(mono, int, 0);
  40MODULE_PARM_DESC(mono,
  41  "1=chips are monochrome (OVx1xx), 0=force color, -1=autodetect (default)");
  42
  43MODULE_AUTHOR(DRIVER_AUTHOR);
  44MODULE_DESCRIPTION(DRIVER_DESC);
  45MODULE_LICENSE("GPL");
  46
  47/* Registers common to all chips, that are needed for detection */
  48#define GENERIC_REG_ID_HIGH       0x1C  /* manufacturer ID MSB */
  49#define GENERIC_REG_ID_LOW        0x1D  /* manufacturer ID LSB */
  50#define GENERIC_REG_COM_I         0x29  /* misc ID bits */
  51
  52extern struct ovcamchip_ops ov6x20_ops;
  53extern struct ovcamchip_ops ov6x30_ops;
  54extern struct ovcamchip_ops ov7x10_ops;
  55extern struct ovcamchip_ops ov7x20_ops;
  56extern struct ovcamchip_ops ov76be_ops;
  57
  58static char *chip_names[NUM_CC_TYPES] = {
  59        [CC_UNKNOWN]    = "Unknown chip",
  60        [CC_OV76BE]     = "OV76BE",
  61        [CC_OV7610]     = "OV7610",
  62        [CC_OV7620]     = "OV7620",
  63        [CC_OV7620AE]   = "OV7620AE",
  64        [CC_OV6620]     = "OV6620",
  65        [CC_OV6630]     = "OV6630",
  66        [CC_OV6630AE]   = "OV6630AE",
  67        [CC_OV6630AF]   = "OV6630AF",
  68};
  69
  70/* Forward declarations */
  71static struct i2c_driver driver;
  72static struct i2c_client client_template;
  73
  74/* ----------------------------------------------------------------------- */
  75
  76int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals)
  77{
  78        int rc;
  79
  80        while (rvals->reg != 0xff) {
  81                rc = ov_write(c, rvals->reg, rvals->val);
  82                if (rc < 0)
  83                        return rc;
  84                rvals++;
  85        }
  86
  87        return 0;
  88}
  89
  90/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
  91 * the same position as 1's in "mask" are cleared and set to "value". Bits
  92 * that are in the same position as 0's in "mask" are preserved, regardless
  93 * of their respective state in "value".
  94 */
  95int ov_write_mask(struct i2c_client *c,
  96                  unsigned char reg,
  97                  unsigned char value,
  98                  unsigned char mask)
  99{
 100        int rc;
 101        unsigned char oldval, newval;
 102
 103        if (mask == 0xff) {
 104                newval = value;
 105        } else {
 106                rc = ov_read(c, reg, &oldval);
 107                if (rc < 0)
 108                        return rc;
 109
 110                oldval &= (~mask);              /* Clear the masked bits */
 111                value &= mask;                  /* Enforce mask on value */
 112                newval = oldval | value;        /* Set the desired bits */
 113        }
 114
 115        return ov_write(c, reg, newval);
 116}
 117
 118/* ----------------------------------------------------------------------- */
 119
 120/* Reset the chip and ensure that I2C is synchronized. Returns <0 if failure.
 121 */
 122static int init_camchip(struct i2c_client *c)
 123{
 124        int i, success;
 125        unsigned char high, low;
 126
 127        /* Reset the chip */
 128        ov_write(c, 0x12, 0x80);
 129
 130        /* Wait for it to initialize */
 131        msleep(150);
 132
 133        for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) {
 134                if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) {
 135                        if (ov_read(c, GENERIC_REG_ID_LOW, &low) >= 0) {
 136                                if (high == 0x7F && low == 0xA2) {
 137                                        success = 1;
 138                                        continue;
 139                                }
 140                        }
 141                }
 142
 143                /* Reset the chip */
 144                ov_write(c, 0x12, 0x80);
 145
 146                /* Wait for it to initialize */
 147                msleep(150);
 148
 149                /* Dummy read to sync I2C */
 150                ov_read(c, 0x00, &low);
 151        }
 152
 153        if (!success)
 154                return -EIO;
 155
 156        PDEBUG(1, "I2C synced in %d attempt(s)", i);
 157
 158        return 0;
 159}
 160
 161/* This detects the OV7610, OV7620, or OV76BE chip. */
 162static int ov7xx0_detect(struct i2c_client *c)
 163{
 164        struct ovcamchip *ov = i2c_get_clientdata(c);
 165        int rc;
 166        unsigned char val;
 167
 168        PDEBUG(4, "");
 169
 170        /* Detect chip (sub)type */
 171        rc = ov_read(c, GENERIC_REG_COM_I, &val);
 172        if (rc < 0) {
 173                PERROR("Error detecting ov7xx0 type");
 174                return rc;
 175        }
 176
 177        if ((val & 3) == 3) {
 178                PINFO("Camera chip is an OV7610");
 179                ov->subtype = CC_OV7610;
 180        } else if ((val & 3) == 1) {
 181                rc = ov_read(c, 0x15, &val);
 182                if (rc < 0) {
 183                        PERROR("Error detecting ov7xx0 type");
 184                        return rc;
 185                }
 186
 187                if (val & 1) {
 188                        PINFO("Camera chip is an OV7620AE");
 189                        /* OV7620 is a close enough match for now. There are
 190                         * some definite differences though, so this should be
 191                         * fixed */
 192                        ov->subtype = CC_OV7620;
 193                } else {
 194                        PINFO("Camera chip is an OV76BE");
 195                        ov->subtype = CC_OV76BE;
 196                }
 197        } else if ((val & 3) == 0) {
 198                PINFO("Camera chip is an OV7620");
 199                ov->subtype = CC_OV7620;
 200        } else {
 201                PERROR("Unknown camera chip version: %d", val & 3);
 202                return -ENOSYS;
 203        }
 204
 205        if (ov->subtype == CC_OV76BE)
 206                ov->sops = &ov76be_ops;
 207        else if (ov->subtype == CC_OV7620)
 208                ov->sops = &ov7x20_ops;
 209        else
 210                ov->sops = &ov7x10_ops;
 211
 212        return 0;
 213}
 214
 215/* This detects the OV6620, OV6630, OV6630AE, or OV6630AF chip. */
 216static int ov6xx0_detect(struct i2c_client *c)
 217{
 218        struct ovcamchip *ov = i2c_get_clientdata(c);
 219        int rc;
 220        unsigned char val;
 221
 222        PDEBUG(4, "");
 223
 224        /* Detect chip (sub)type */
 225        rc = ov_read(c, GENERIC_REG_COM_I, &val);
 226        if (rc < 0) {
 227                PERROR("Error detecting ov6xx0 type");
 228                return -1;
 229        }
 230
 231        if ((val & 3) == 0) {
 232                ov->subtype = CC_OV6630;
 233                PINFO("Camera chip is an OV6630");
 234        } else if ((val & 3) == 1) {
 235                ov->subtype = CC_OV6620;
 236                PINFO("Camera chip is an OV6620");
 237        } else if ((val & 3) == 2) {
 238                ov->subtype = CC_OV6630;
 239                PINFO("Camera chip is an OV6630AE");
 240        } else if ((val & 3) == 3) {
 241                ov->subtype = CC_OV6630;
 242                PINFO("Camera chip is an OV6630AF");
 243        }
 244
 245        if (ov->subtype == CC_OV6620)
 246                ov->sops = &ov6x20_ops;
 247        else
 248                ov->sops = &ov6x30_ops;
 249
 250        return 0;
 251}
 252
 253static int ovcamchip_detect(struct i2c_client *c)
 254{
 255        /* Ideally we would just try a single register write and see if it NAKs.
 256         * That isn't possible since the OV518 can't report I2C transaction
 257         * failures. So, we have to try to initialize the chip (i.e. reset it
 258         * and check the ID registers) to detect its presence. */
 259
 260        /* Test for 7xx0 */
 261        PDEBUG(3, "Testing for 0V7xx0");
 262        c->addr = OV7xx0_SID;
 263        if (init_camchip(c) < 0) {
 264                /* Test for 6xx0 */
 265                PDEBUG(3, "Testing for 0V6xx0");
 266                c->addr = OV6xx0_SID;
 267                if (init_camchip(c) < 0) {
 268                        return -ENODEV;
 269                } else {
 270                        if (ov6xx0_detect(c) < 0) {
 271                                PERROR("Failed to init OV6xx0");
 272                                return -EIO;
 273                        }
 274                }
 275        } else {
 276                if (ov7xx0_detect(c) < 0) {
 277                        PERROR("Failed to init OV7xx0");
 278                        return -EIO;
 279                }
 280        }
 281
 282        return 0;
 283}
 284
 285/* ----------------------------------------------------------------------- */
 286
 287static int ovcamchip_attach(struct i2c_adapter *adap)
 288{
 289        int rc = 0;
 290        struct ovcamchip *ov;
 291        struct i2c_client *c;
 292
 293        /* I2C is not a PnP bus, so we can never be certain that we're talking
 294         * to the right chip. To prevent damage to EEPROMS and such, only
 295         * attach to adapters that are known to contain OV camera chips. */
 296
 297        switch (adap->id) {
 298        case I2C_HW_SMBUS_OV511:
 299        case I2C_HW_SMBUS_OV518:
 300        case I2C_HW_SMBUS_OVFX2:
 301        case I2C_HW_SMBUS_W9968CF:
 302                PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
 303                break;
 304        default:
 305                PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id);
 306                return -ENODEV;
 307        }
 308
 309        c = kmalloc(sizeof *c, GFP_KERNEL);
 310        if (!c) {
 311                rc = -ENOMEM;
 312                goto no_client;
 313        }
 314        memcpy(c, &client_template, sizeof *c);
 315        c->adapter = adap;
 316        strcpy(c->name, "OV????");
 317
 318        ov = kzalloc(sizeof *ov, GFP_KERNEL);
 319        if (!ov) {
 320                rc = -ENOMEM;
 321                goto no_ov;
 322        }
 323        i2c_set_clientdata(c, ov);
 324
 325        rc = ovcamchip_detect(c);
 326        if (rc < 0)
 327                goto error;
 328
 329        strcpy(c->name, chip_names[ov->subtype]);
 330
 331        PDEBUG(1, "Camera chip detection complete");
 332
 333        i2c_attach_client(c);
 334
 335        return rc;
 336error:
 337        kfree(ov);
 338no_ov:
 339        kfree(c);
 340no_client:
 341        PDEBUG(1, "returning %d", rc);
 342        return rc;
 343}
 344
 345static int ovcamchip_detach(struct i2c_client *c)
 346{
 347        struct ovcamchip *ov = i2c_get_clientdata(c);
 348        int rc;
 349
 350        rc = ov->sops->free(c);
 351        if (rc < 0)
 352                return rc;
 353
 354        i2c_detach_client(c);
 355
 356        kfree(ov);
 357        kfree(c);
 358        return 0;
 359}
 360
 361static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
 362{
 363        struct ovcamchip *ov = i2c_get_clientdata(c);
 364
 365        if (!ov->initialized &&
 366            cmd != OVCAMCHIP_CMD_Q_SUBTYPE &&
 367            cmd != OVCAMCHIP_CMD_INITIALIZE) {
 368                dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n");
 369                return -EPERM;
 370        }
 371
 372        switch (cmd) {
 373        case OVCAMCHIP_CMD_Q_SUBTYPE:
 374        {
 375                *(int *)arg = ov->subtype;
 376                return 0;
 377        }
 378        case OVCAMCHIP_CMD_INITIALIZE:
 379        {
 380                int rc;
 381
 382                if (mono == -1)
 383                        ov->mono = *(int *)arg;
 384                else
 385                        ov->mono = mono;
 386
 387                if (ov->mono) {
 388                        if (ov->subtype != CC_OV7620)
 389                                dev_warn(&c->dev, "Warning: Monochrome not "
 390                                        "implemented for this chip\n");
 391                        else
 392                                dev_info(&c->dev, "Initializing chip as "
 393                                        "monochrome\n");
 394                }
 395
 396                rc = ov->sops->init(c);
 397                if (rc < 0)
 398                        return rc;
 399
 400                ov->initialized = 1;
 401                return 0;
 402        }
 403        default:
 404                return ov->sops->command(c, cmd, arg);
 405        }
 406}
 407
 408/* ----------------------------------------------------------------------- */
 409
 410static struct i2c_driver driver = {
 411        .driver = {
 412                .name =         "ovcamchip",
 413        },
 414        .id =                   I2C_DRIVERID_OVCAMCHIP,
 415        .class =                I2C_CLASS_CAM_DIGITAL,
 416        .attach_adapter =       ovcamchip_attach,
 417        .detach_client =        ovcamchip_detach,
 418        .command =              ovcamchip_command,
 419};
 420
 421static struct i2c_client client_template = {
 422        .name =         "(unset)",
 423        .driver =       &driver,
 424};
 425
 426static int __init ovcamchip_init(void)
 427{
 428#ifdef DEBUG
 429        ovcamchip_debug = debug;
 430#endif
 431
 432        PINFO(DRIVER_VERSION " : " DRIVER_DESC);
 433        return i2c_add_driver(&driver);
 434}
 435
 436static void __exit ovcamchip_exit(void)
 437{
 438        i2c_del_driver(&driver);
 439}
 440
 441module_init(ovcamchip_init);
 442module_exit(ovcamchip_exit);
 443