📄 omnivision_sbus.c
字号:
/* * drivers/media/video/mx2ads/omnivision_sbus.c * * Description: * Link to OmniVision camera "Serial Bus" (I2C). * Tested with OV9640 camera. * * Author: Monta Vista Software, Inc., <source@mvista.com> * * 2005 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/config.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/system.h>#include "common.h"#include "camif.h"#include <linux/i2c.h>#define MODULE_NAME "MX2 OV CAM I2C"static struct camera_serial_bus *this;static char __initstate_i2c;static unsigned short __normal_i2c_addr[] = { 0 /*initialized dynamically*/, I2C_CLIENT_END};static unsigned short __ignore_i2c_addr[] = { I2C_CLIENT_END };static struct i2c_client_address_data __i2c_addr_data = { .normal_i2c = __normal_i2c_addr, .normal_i2c_range = __ignore_i2c_addr, .probe = __ignore_i2c_addr, .probe_range = __ignore_i2c_addr, .ignore = __ignore_i2c_addr, .ignore_range = __ignore_i2c_addr, .force = __ignore_i2c_addr};static int __i2c_probe(struct i2c_adapter *adap);static int __i2c_detach(struct i2c_client *client);static int __i2c_command(struct i2c_client *client, unsigned int cmd, void *arg);static struct i2c_client *__i2c_client;static struct i2c_driver __i2c_driver = { .name = "MX2ADS OV CAM", .id = I2C_DRIVERID_EXP0, /* Fake Id */ .flags = I2C_DF_NOTIFY, .attach_adapter = __i2c_probe, .detach_client = __i2c_detach, .command = __i2c_command};static int__i2c_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind){ struct i2c_client *c; c = (struct i2c_client *) kmalloc(sizeof (*c), GFP_KERNEL); if (!c) return -ENOMEM; strcpy(c->name, "OV9640 CAM"); c->id = __i2c_driver.id; c->flags = 0; c->addr = addr; c->adapter = adap; c->driver = &__i2c_driver; c->data = NULL; __i2c_client = c; return i2c_attach_client(c);}static int__i2c_probe(struct i2c_adapter *adap){ return i2c_probe(adap, &__i2c_addr_data, __i2c_attach);}static int__i2c_detach(struct i2c_client *client){ i2c_detach_client(client); kfree(__i2c_client); return 0;}/* No commands defined */static int__i2c_command(struct i2c_client *client, unsigned int cmd, void *arg){ return 0;}static voidi2c_close(void){ if (__initstate_i2c) { i2c_del_driver(&__i2c_driver); __initstate_i2c = 0; }}static inti2c_configure(void){ int tmp; __initstate_i2c = 0; this = &camera_mx2ads_omnivision_i2c; tmp = i2c_add_driver(&__i2c_driver); if (tmp < 0) { err("cannot initialize I2C\n"); i2c_close(); return tmp; } __initstate_i2c = 1; if (!__i2c_client) { i2c_close(); return -ENODEV; } return 0;}static inti2c_set_devid(int id){ this = &camera_mx2ads_omnivision_i2c; this->dev_id = id >> 1; __normal_i2c_addr[0] = this->dev_id; return 0;}static inti2c_read(u8 subaddr, u8 * buf, int len){ struct i2c_msg msg; msg.addr = this->dev_id; msg.flags = I2C_M_WR | I2C_M_NOSTART; msg.len = 1; msg.buf = &subaddr; if (i2c_transfer(__i2c_client->adapter, &msg, 1) != 1) return -EIO; /*ov9640 doesn't like repeat start, need to send a separate message*/ msg.addr = this->dev_id; msg.flags = I2C_M_RD | I2C_M_NOSTART; msg.len = len; msg.buf = buf; if (i2c_transfer(__i2c_client->adapter, &msg, 1) != 1) return -EIO; return 0;}static inti2c_write(u8 subaddr, u8 * buf, int len){ struct i2c_msg msg; u8 wbuf[2]; wbuf[0] = subaddr; wbuf[1] = buf[0]; msg.addr = this->dev_id; msg.flags = I2C_M_WR | I2C_M_NOSTART; msg.len = 2; msg.buf = wbuf; if (i2c_transfer(__i2c_client->adapter, &msg, 1) != 1) return -EIO; return 0;}#define WRITE_VERIFY_RETRIES 5static inti2c_write_verify(u8 subaddr, u8 val){ int count = 0; u8 readval; do { i2c_write(subaddr, &val, 1); readval = ~val; i2c_read(subaddr, &readval, 1); if (readval != val) dbg(": failed to verify data, count %d, " "subaddr %x, written %x, read %x\n", count, subaddr, val, readval); } while (readval != val && count++ < WRITE_VERIFY_RETRIES); if (readval != val && count >= WRITE_VERIFY_RETRIES) { err("%d attempts to write %02x to reg %02x failed\n", WRITE_VERIFY_RETRIES, val, subaddr); return -ENXIO; } return 0;}struct camera_serial_bus camera_mx2ads_omnivision_i2c = { init: i2c_configure, cleanup: i2c_close, set_devid: i2c_set_devid, read: i2c_read, write: i2c_write, write_verify: i2c_write_verify,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -