/* Shared Code for OmniVision Camera Chip Drivers * * Copyright (c) 2002 Mark McClelland * http://alpha.dyndns.org/ov511/ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ /* This file is not a module yet */ #define __NO_VERSION__ #include #include #if defined(OUTSIDE_KERNEL) #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) #define MODVERSIONS #endif #ifdef MODVERSIONS #include #endif #endif #include "ov511.h" extern int debug; /* Exists in ov511.c and ov518.c */ int ov_write_regvals(struct i2c_client *client, struct ovsensor_regvals *rvals) { int rc; while (rvals->reg != 0xff) { rc = ov_write(client, rvals->reg, rvals->val); if (rc < 0) return rc; rvals++; } return 0; } /* Writes bits at positions specified by mask to an I2C reg. Bits that are in * the same position as 1's in "mask" are cleared and set to "value". Bits * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ int ov_write_mask(struct i2c_client *client, unsigned char reg, unsigned char value, unsigned char mask) { int rc; unsigned char oldval, newval; if (mask == 0xff) { newval = value; } else { rc = ov_read(client, reg, &oldval); if (rc < 0) return rc; oldval &= (~mask); /* Clear the masked bits */ value &= mask; /* Enforce mask on value */ newval = oldval | value; /* Set the desired bits */ } return ov_write(client, reg, newval); } /* Reset the sensor and ensures that I2C is synchronized. Returns <0 if failure. */ int init_ov_sensor(struct i2c_client *client) { int i, success; unsigned char high, low; /* Reset the sensor */ ov_write(client, 0x12, 0x80); /* Wait for it to initialize */ schedule_timeout(1 + 150 * HZ / 1000); for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) { if (ov_read(client, OV7610_REG_ID_HIGH, &high) >= 0) { if (ov_read(client, OV7610_REG_ID_LOW, &low) >= 0) { if (high == 0x7F && low == 0xA2) { success = 1; continue; } } } /* Reset the sensor */ ov_write(client, 0x12, 0x80); /* Wait for it to initialize */ schedule_timeout(1 + 150 * HZ / 1000); /* Dummy read to sync I2C */ ov_read(client, 0x00, &low); } if (!success) return -EIO; PDEBUG(1, "I2C synced in %d attempt(s)", i); return 0; }