📄 camera_i2c.c
字号:
/*
* linux/drivers/media/video/omap/camera_i2c.c
*
* Copyright (C) 2004 Texas Instruments Inc
*
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* camera_i2c.c */
#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include "camera_i2c.h"
/* Global structure to store the i2c driver info */
static struct camera_i2c_param camera_i2c_dev;
/*
* Read a value from a register in an OV9640 sensor device. The value is
* returned in 'val'.
* Returns zero if successful, or non-zero otherwise.
*/
static int
camera_i2c_read_reg(u8 reg, u8 *val)
{
int err;
struct i2c_client *client = &camera_i2c_dev.client;
struct i2c_msg msg[1];
unsigned char data[1];
if (!client->adapter)
return -ENODEV;
msg->addr = client->addr;
msg->flags = 0;
msg->len = 1;
msg->buf = data;
*data = reg;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
msg->flags = I2C_M_RD;
err = i2c_transfer(client->adapter, msg, 1);
}
if (err >= 0) {
*val = *data;
return 0;
}
return err;
}
/* Write a value to a register in an OV9640 sensor device.
* Returns zero if successful, or non-zero otherwise.
*/
static int
camera_i2c_write_reg(u8 reg, u8 val)
{
int err;
struct i2c_client *client = &camera_i2c_dev.client;
struct i2c_msg msg[1];
unsigned char data[2];
if (!client->adapter)
return -ENODEV;
msg->addr = client->addr;
msg->flags = 0;
msg->len = 2;
msg->buf = data;
data[0] = reg;
data[1] = val;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0)
return 0;
return err;
}
/* This function registers an I2C client via i2c_attach_client() for an OV9640
* sensor device. If 'probe' is non-zero, then the I2C client is only
* registered if the device can be detected. If 'probe' is zero, then no
* device detection is attempted and the I2C client is always registered.
* Returns zero if an I2C client is successfully registered, or non-zero
* otherwise.
*/
static int
camera_i2c_attach_client(struct i2c_adapter *adap, int addr)
{
struct camera_i2c_param *camera_i2c_if = &camera_i2c_dev;
struct i2c_client *client = &camera_i2c_if->client;
int err;
if (client->adapter)
return -EBUSY; /* our client is already attached */
client->addr = addr;
client->flags = I2C_CLIENT_ALLOW_USE;
client->driver = &camera_i2c_if->driver;
client->adapter = adap;
err = i2c_attach_client(client);
if (err) {
client->adapter = NULL;
return err;
}
return 0;
}
/* This function is called by i2c_del_adapter() and i2c_del_driver()
* if the adapter or driver with which this I2C client is associated is
* removed. This function unregisters the client via i2c_detach_client().
* Returns zero if the client is successfully detached, or non-zero
* otherwise.
*/
static int
camera_i2c_detach_client(struct i2c_client *client)
{
int err;
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
err = i2c_detach_client(client);
client->adapter = NULL;
return err;
}
/* This function will be called for each registered I2C bus adapter when our
* I2C driver is registered via i2c_add_driver(). It will also be called
* whenever a new I2C adapter is registered after our I2C driver is registered.
* This function probes the specified I2C bus adapter to determine if an
* OV9640 sensor device is present. If a device is detected, an I2C client
* is registered for it via ov9640_i2c_attach_client(). Note that we can't use
* the standard i2c_probe() function to look for the sensor because the OMAP
* I2C controller doesn't support probing.
* Returns zero if an OV9640 device is detected and an I2C client successfully
* registered for it, or non-zero otherwise.
*/
static int
camera_i2c_probe_adapter(struct i2c_adapter *adap)
{
return camera_i2c_attach_client(adap, OV9640_I2C_ADDR);
}
static int
camera_i2c_init(void)
{
int err;
struct i2c_driver *driver = &camera_i2c_dev.driver;
driver->owner = THIS_MODULE;
strlcpy(driver->name, "Camera Sensor I2C driver", sizeof(driver->name));
driver->id = I2C_DRIVERID_EXP0;
driver->flags = I2C_DF_NOTIFY;
driver->attach_adapter = camera_i2c_probe_adapter;
driver->detach_client = camera_i2c_detach_client;
err = i2c_add_driver(driver);
if (err) {
printk(KERN_ERR "Failed to register Camera Sensor I2C client.\n");
return err;
}
return 0;
}
static void camera_i2c_cleanup (void)
{
i2c_detach_client(&camera_i2c_dev.client);
camera_i2c_dev.client.adapter = NULL;
return;
}
struct camera_serial_bus_ops camera_i2c_fops = {
version : 0x01,
init : camera_i2c_init,
cleanup : camera_i2c_cleanup,
read : camera_i2c_read_reg,
write : camera_i2c_write_reg,
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -