⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera_i2c.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 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 + -