From: <hap...@us...> - 2007-06-22 19:19:11
|
Revision: 1044 http://svn.sourceforge.net/hackndev/?rev=1044&view=rev Author: happy-slapin Date: 2007-06-22 12:19:08 -0700 (Fri, 22 Jun 2007) Log Message: ----------- OV9640: Added i2c module code Added Paths: ----------- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h Added: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c (rev 0) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-22 19:19:08 UTC (rev 1044) @@ -0,0 +1,303 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <asm/hardware.h> +#include <asm/types.h> +#include <linux/delay.h> + +#include "i2c-ov9640.h" + +#define DEBUG 1 +#define DPRINTK(fmt,args...) do { if (DEBUG) printk("in function %s "fmt,__FUNCTION__,##args);} while(0) +extern int i2c_adapter_id(struct i2c_adapter *adap); + +int i2c_ov9640_cleanup(void); +void i2c_ov9640_inc_use (struct i2c_client *client); +void i2c_ov9640_dec_use (struct i2c_client *client); +int i2c_ov9640_attach_adapter(struct i2c_adapter *adapter); +int i2c_ov9640_detect_client(struct i2c_adapter *, int, unsigned short, int); +int i2c_ov9640_detach_client(struct i2c_client *client); + +struct i2c_driver ov9640_driver = +{ + name: "ov9640 driver", /* name */ + id: I2C_DRIVERID_OV9640, /* id */ + flags: I2C_DF_NOTIFY, /* flags */ + attach_adapter: &i2c_ov9640_attach_adapter, /* attach_adapter */ + detach_client: &i2c_ov9640_detach_client, /* detach_client */ + command: NULL, + inc_use: &i2c_ov9640_inc_use, + dec_use: &i2c_ov9640_dec_use +}; + +extern struct i2c_adapter *i2cdev_adaps[]; +/* Unique ID allocation */ +static int ov9640_id = 0; +struct i2c_client *g_client = NULL; +static unsigned short normal_i2c[] = {OV9640_SLAVE_ADDR ,I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; +I2C_CLIENT_INSMOD; + +/* + * This call returns a unique low identifier for each registered adapter, + * or -1 if the adapter was not registered. + */ +void i2c_ov9640_inc_use (struct i2c_client *client) +{ + MOD_INC_USE_COUNT; +#ifdef MODULE +#endif +} + +void i2c_ov9640_dec_use (struct i2c_client *client) +{ + MOD_DEC_USE_COUNT; +#ifdef MODULE +#endif +} + +char ov9640_read(u8 addr, u8 *pvalue) +{ + int res=0; + char buf=0; + struct i2c_msg msgs[2] = { + { 0, I2C_M_WR, 1, &addr }, + { 0, I2C_M_RD, 1, &buf }}; + + if( g_client == NULL ) + return -1; + i2c_ov9640_inc_use(g_client); + msgs[0].addr=msgs[1].addr=g_client->addr; + res=i2c_transfer(g_client->adapter,&msgs[0],1); + if (res<=0) + goto out; + res=i2c_transfer(g_client->adapter,&msgs[1],1); + if (res<=0) + goto out; + *pvalue = buf; + i2c_ov9640_dec_use(g_client); +out: + DPRINTK(KERN_INFO "In funtion %s addr:%x,value=%x\n", __FUNCTION__, addr,*pvalue); + if (res<=0) DPRINTK("res = %d \n",res); + return res; +} + +int ov9640_write(u8 addr, u8 value) +{ + int res=0; + if( g_client == NULL ) + return -1; + /* + char buf=0; + struct i2c_msg msgs[2] = { + { 0, I2C_M_WR, 1, &addr }, + { 0, I2C_M_WR, 1, &value }}; + msgs[0].addr=msgs[1].addr=g_client->addr; + res=i2c_transfer(g_client->adapter,&msgs[0],1); + if (res<=0) return res; + res=i2c_transfer(g_client->adapter,&msgs[1],1); + if (res<=0) return res; + + + res=i2c_smbus_write_byte_data(g_client, addr, value ); + */ + char buf[2]={addr,value}; + i2c_ov9640_inc_use(g_client); + res = i2c_master_send(g_client, buf, 2); + i2c_ov9640_dec_use(g_client); + if (res >0) res =0; + else res =-1; + DPRINTK(KERN_INFO "In funtion %s addr:%x value:%xreturn %d \n", __FUNCTION__, addr,value,res); + return res; +} + + +int i2c_ov9640_read(struct i2c_client *client, u8 reg) +{ + unsigned char msgbuf=0; + DPRINTK("in function %s\n",__FUNCTION__); + i2c_master_recv(client,&msgbuf,1); + return msgbuf; + /* + */ +// return i2c_smbus_read_word_data(client,reg); +// return i2c_smbus_read_byte_data(client,reg); +} + +int i2c_ov9640_write(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client,reg,value); +} + + +int i2c_ov9640_attach_adapter(struct i2c_adapter *adap) +{ + DPRINTK("In function %s.\n", __FUNCTION__); + return i2c_probe(adap,&addr_data,i2c_ov9640_detect_client); +} + + +int i2c_ov9640_detect_client(struct i2c_adapter *adapter, int address, unsigned short flags, int kind) +{ + struct i2c_client *new_client; + int err = 0; + struct ov9640_data *data; + + /*check if */ + if(g_client != NULL) { + err = -ENXIO; + goto ERROR0; + } + + + DPRINTK(KERN_INFO "In funtion %s. address=0X%X\n", __FUNCTION__, address); + /* Let's see whether this adapter can support what we need. + Please substitute the things you need here! */ + if ( !i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA) ) { + DPRINTK(KERN_INFO "Word op is not permited.\n"); + goto ERROR0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access several i2c functions safely */ + + /* Note that we reserve some space for ov9640_data too. If you don't + need it, remove it. We do it here to help to lessen memory + fragmentation. */ + + new_client=kmalloc(sizeof(struct i2c_client)+sizeof(struct ov9640_data), + GFP_KERNEL ); + + if ( !new_client ) { + err = -ENOMEM; + goto ERROR0; + } + + data = (struct ov9640_data *) (new_client + 1); + + new_client->addr = address; + new_client->data = data; + new_client->adapter = adapter; + new_client->driver = &ov9640_driver; + new_client->flags = 0; + + g_client = new_client; + + /* Now, we do the remaining detection. If no `force' parameter is used. */ + + /* First, the generic detection (if any), that is skipped if any force + parameter was used. */ + + if (kind <= 0) { + char res = -1; + mdelay(2000); + ov9640_read(REV,&res); + /* The below is of course bogus */ + DPRINTK("I2C: Probe ov9640 chip..addr=0x%x, REV=%d, res=0x%x\n", address, REV, res); + /*ov9640 chip id is 0x9648 + if(res != OV9640_CHIP_ID) { + DPRINTK(KERN_WARNING "Failed.product id =%d \n",res); + goto ERROR1; + } + else { + DPRINTK("OV9640 chip id is 0X%04X\n", OV9640_CHIP_ID); + if ( ov9640_id == 0 ) + DPRINTK(" detected.\n"); + }*/ + } + + strcpy(new_client->name, "ov9640"); + /* Automatically unique */ + new_client->id = ov9640_id++; + + /* Only if you use this field */ + data->valid = 0; + + /* Only if you use this field */ + init_MUTEX(&data->update_lock); + + /* Tell the i2c layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto ERROR3; + + /* This function can write default values to the client registers, if + needed. */ + /* ov9640_init_client(new_client); */ + return 0; + + /* OK, this is not exactly good programming practice, usually. But it is + very code-efficient in this case. */ + +ERROR3: +ERROR1: + kfree(new_client); + g_client = NULL; +ERROR0: + return err; +} + +int i2c_ov9640_detach_client(struct i2c_client *client) +{ + int err; + + /* Try to detach the client from i2c space */ + if ((err = i2c_detach_client(client))) { + DPRINTK("ov9640.o: Client deregistration failed, client not detached.\n"); + return err; + } + + kfree(client); /* Frees client data too, if allocated at the same time */ + g_client = NULL; + return 0; +} + +/* Keep track of how far we got in the initialization process. If several + things have to initialized, and we fail halfway, only those things + have to be cleaned up! */ +static int ov9640_initialized = 0; + +int i2c_ov9640_init(void) +{ + int res; + + if (ov9640_initialized) + return 0; + DPRINTK("I2C: driver for device ov9640.\n"); + if ( (res = i2c_add_driver(&ov9640_driver)) ) { + DPRINTK("ov9640: Driver registration failed, module not inserted.\n"); + i2c_ov9640_cleanup(); + return res; + } + ov9640_initialized ++; + if(g_client != NULL) + DPRINTK("I2C: driver for device %s registed!.\n", g_client->name); + else + DPRINTK("I2C: driver for device unregisted!.\n"); + return 0; +} + +int i2c_ov9640_cleanup(void) +{ + int res; + + if (ov9640_initialized == 1) { + if ((res = i2c_del_driver(&ov9640_driver))) { + DPRINTK("ov9640: Driver registration failed, module not removed.\n"); + return res; + } + ov9640_initialized --; + } + return 0; +} + +EXPORT_SYMBOL(i2c_ov9640_init); +EXPORT_SYMBOL(ov9640_write); +EXPORT_SYMBOL(ov9640_read); +EXPORT_SYMBOL(i2c_ov9640_cleanup); +//module_init(i2c_ov9640_init); +//module_exit(i2c_ov9640_cleanup); +MODULE_LICENSE("GPL"); + Added: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h (rev 0) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h 2007-06-22 19:19:08 UTC (rev 1044) @@ -0,0 +1,42 @@ +#ifndef __I2C_OV9640_H__ +#define __I2C_OV9640_H__ + +#define DEBUG + +/* Calculating the Module Block Number */ +#define BLOCK(a) (u8)((a) >> 7) /* register's module block address. */ +#define OFFSET(a) (u8)((a) & 0x7F ) /* register's offset to this block. */ + +/* Update the block address.*/ +#define BLOCK_SWITCH_CMD 0xFE + +#define OV9640_SLAVE_ADDR (0x60>>1) /* 60 for write , 61 for read */ +// #define SENSOR_SLAVE_ADDR 0x0055 /* tbd: */ + + +#define I2C_DRIVERID_OV9640 I2C_DRIVERID_EXP2 + +/*ov9640 chip id*/ +#define OV9640_CHIP_ID 0x9648 + +/* Register definitions in OV9640's chip. */ +#define PID 0xA +#define REV 0xA + +struct ov9640_data { + /* + * Because the i2c bus is slow, it is often useful to cache the read + * information of a chip for some time (for example, 1 or 2 seconds). + * It depends of course on the device whether this is really worthwhile + * or even sensible. + */ + struct semaphore update_lock; /* When we are reading lots of information, + another process should not update the + below information */ + + char valid; /* != 0 if the following fields are valid. */ + int blockaddr; /* current using block address. */ + unsigned long last_updated; /* In jiffies */ +}; +#endif + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <hap...@us...> - 2007-06-22 21:00:28
|
Revision: 1046 http://svn.sourceforge.net/hackndev/?rev=1046&view=rev Author: happy-slapin Date: 2007-06-22 14:00:23 -0700 (Fri, 22 Jun 2007) Log Message: ----------- OV9640: Fixed i2c driver Modified Paths: -------------- linux4palm/linux/trunk/drivers/i2c/chips/Kconfig linux4palm/linux/trunk/drivers/i2c/chips/Makefile linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h Modified: linux4palm/linux/trunk/drivers/i2c/chips/Kconfig =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/Kconfig 2007-06-22 20:03:14 UTC (rev 1045) +++ linux4palm/linux/trunk/drivers/i2c/chips/Kconfig 2007-06-22 21:00:23 UTC (rev 1046) @@ -150,4 +150,10 @@ This driver can also be built as a module. If so, the module will be called max6875. +config I2C_OV9640 + tristate "Support for OmniVision 9640 camera sensor" + depends on I2C + help + Say yes here to enable OV9640 sensor which is found in some + handhelds and phones endmenu Modified: linux4palm/linux/trunk/drivers/i2c/chips/Makefile =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/Makefile 2007-06-22 20:03:14 UTC (rev 1045) +++ linux4palm/linux/trunk/drivers/i2c/chips/Makefile 2007-06-22 21:00:23 UTC (rev 1046) @@ -15,8 +15,10 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o -obj-$(CONFIG_I2C_ADCM2650) +=adcm2650-i2c.o +obj-$(CONFIG_I2C_ADCM2650) += adcm2650-i2c.o +obj-$(CONFIG_I2C_OV9640) += i2c-ov9640.o + ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG endif Modified: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-22 20:03:14 UTC (rev 1045) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-22 21:00:23 UTC (rev 1046) @@ -13,63 +13,48 @@ #define DPRINTK(fmt,args...) do { if (DEBUG) printk("in function %s "fmt,__FUNCTION__,##args);} while(0) extern int i2c_adapter_id(struct i2c_adapter *adap); -int i2c_ov9640_cleanup(void); -void i2c_ov9640_inc_use (struct i2c_client *client); -void i2c_ov9640_dec_use (struct i2c_client *client); -int i2c_ov9640_attach_adapter(struct i2c_adapter *adapter); -int i2c_ov9640_detect_client(struct i2c_adapter *, int, unsigned short, int); -int i2c_ov9640_detach_client(struct i2c_client *client); +void i2c_ov9640_cleanup(void); +static int i2c_ov9640_attach_adapter(struct i2c_adapter *adapter); +static int i2c_ov9640_detect_client(struct i2c_adapter *, int, int); +static int i2c_ov9640_detach_client(struct i2c_client *client); struct i2c_driver ov9640_driver = { - name: "ov9640 driver", /* name */ - id: I2C_DRIVERID_OV9640, /* id */ - flags: I2C_DF_NOTIFY, /* flags */ - attach_adapter: &i2c_ov9640_attach_adapter, /* attach_adapter */ - detach_client: &i2c_ov9640_detach_client, /* detach_client */ - command: NULL, - inc_use: &i2c_ov9640_inc_use, - dec_use: &i2c_ov9640_dec_use + .driver = { + .name = "i2c-ov9640", /* name */ + }, + .attach_adapter = &i2c_ov9640_attach_adapter, /* attach_adapter */ + .detach_client = &i2c_ov9640_detach_client, /* detach_client */ }; extern struct i2c_adapter *i2cdev_adaps[]; -/* Unique ID allocation */ -static int ov9640_id = 0; struct i2c_client *g_client = NULL; static unsigned short normal_i2c[] = {OV9640_SLAVE_ADDR ,I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; +/* static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; */ I2C_CLIENT_INSMOD; -/* - * This call returns a unique low identifier for each registered adapter, - * or -1 if the adapter was not registered. - */ -void i2c_ov9640_inc_use (struct i2c_client *client) -{ - MOD_INC_USE_COUNT; -#ifdef MODULE -#endif -} - -void i2c_ov9640_dec_use (struct i2c_client *client) -{ - MOD_DEC_USE_COUNT; -#ifdef MODULE -#endif -} - char ov9640_read(u8 addr, u8 *pvalue) { - int res=0; - char buf=0; - struct i2c_msg msgs[2] = { - { 0, I2C_M_WR, 1, &addr }, - { 0, I2C_M_RD, 1, &buf }}; + int res = 0; + char buf = 0; + struct i2c_msg msgs[2]; + struct ov9640_data * p; if( g_client == NULL ) return -1; - i2c_ov9640_inc_use(g_client); - msgs[0].addr=msgs[1].addr=g_client->addr; + p = i2c_get_clientdata(g_client); + + msgs[0].addr = g_client->addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &addr; + + msgs[1].addr = g_client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = 1; + msgs[1].buf = &buf; + + down(&p->update_lock); res=i2c_transfer(g_client->adapter,&msgs[0],1); if (res<=0) goto out; @@ -77,7 +62,7 @@ if (res<=0) goto out; *pvalue = buf; - i2c_ov9640_dec_use(g_client); + up(&p->update_lock); out: DPRINTK(KERN_INFO "In funtion %s addr:%x,value=%x\n", __FUNCTION__, addr,*pvalue); if (res<=0) DPRINTK("res = %d \n",res); @@ -86,27 +71,16 @@ int ov9640_write(u8 addr, u8 value) { - int res=0; + int res = 0; + char buf[2] = {addr, value}; + + struct ov9640_data * p; if( g_client == NULL ) return -1; - /* - char buf=0; - struct i2c_msg msgs[2] = { - { 0, I2C_M_WR, 1, &addr }, - { 0, I2C_M_WR, 1, &value }}; - msgs[0].addr=msgs[1].addr=g_client->addr; - res=i2c_transfer(g_client->adapter,&msgs[0],1); - if (res<=0) return res; - res=i2c_transfer(g_client->adapter,&msgs[1],1); - if (res<=0) return res; - - - res=i2c_smbus_write_byte_data(g_client, addr, value ); - */ - char buf[2]={addr,value}; - i2c_ov9640_inc_use(g_client); + p = i2c_get_clientdata(g_client); + down(&p->update_lock); res = i2c_master_send(g_client, buf, 2); - i2c_ov9640_dec_use(g_client); + up(&p->update_lock); if (res >0) res =0; else res =-1; DPRINTK(KERN_INFO "In funtion %s addr:%x value:%xreturn %d \n", __FUNCTION__, addr,value,res); @@ -120,10 +94,6 @@ DPRINTK("in function %s\n",__FUNCTION__); i2c_master_recv(client,&msgbuf,1); return msgbuf; - /* - */ -// return i2c_smbus_read_word_data(client,reg); -// return i2c_smbus_read_byte_data(client,reg); } int i2c_ov9640_write(struct i2c_client *client, u8 reg, u16 value) @@ -139,7 +109,7 @@ } -int i2c_ov9640_detect_client(struct i2c_adapter *adapter, int address, unsigned short flags, int kind) +static int i2c_ov9640_detect_client(struct i2c_adapter *adapter, int address, int kind) { struct i2c_client *new_client; int err = 0; @@ -168,7 +138,7 @@ need it, remove it. We do it here to help to lessen memory fragmentation. */ - new_client=kmalloc(sizeof(struct i2c_client)+sizeof(struct ov9640_data), + new_client=kzalloc(sizeof(struct i2c_client)+sizeof(struct ov9640_data), GFP_KERNEL ); if ( !new_client ) { @@ -177,9 +147,8 @@ } data = (struct ov9640_data *) (new_client + 1); - new_client->addr = address; - new_client->data = data; + i2c_set_clientdata(new_client, data); new_client->adapter = adapter; new_client->driver = &ov9640_driver; new_client->flags = 0; @@ -210,8 +179,6 @@ } strcpy(new_client->name, "ov9640"); - /* Automatically unique */ - new_client->id = ov9640_id++; /* Only if you use this field */ data->valid = 0; @@ -232,7 +199,6 @@ very code-efficient in this case. */ ERROR3: -ERROR1: kfree(new_client); g_client = NULL; ERROR0: @@ -279,25 +245,22 @@ return 0; } -int i2c_ov9640_cleanup(void) +void i2c_ov9640_cleanup(void) { - int res; - if (ov9640_initialized == 1) { - if ((res = i2c_del_driver(&ov9640_driver))) { + if (i2c_del_driver(&ov9640_driver)) { DPRINTK("ov9640: Driver registration failed, module not removed.\n"); - return res; + return; } ov9640_initialized --; } - return 0; } -EXPORT_SYMBOL(i2c_ov9640_init); +//EXPORT_SYMBOL(i2c_ov9640_init); EXPORT_SYMBOL(ov9640_write); EXPORT_SYMBOL(ov9640_read); -EXPORT_SYMBOL(i2c_ov9640_cleanup); -//module_init(i2c_ov9640_init); -//module_exit(i2c_ov9640_cleanup); +//EXPORT_SYMBOL(i2c_ov9640_cleanup); +module_init(i2c_ov9640_init); +module_exit(i2c_ov9640_cleanup); MODULE_LICENSE("GPL"); Modified: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h 2007-06-22 20:03:14 UTC (rev 1045) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h 2007-06-22 21:00:23 UTC (rev 1046) @@ -1,7 +1,9 @@ #ifndef __I2C_OV9640_H__ #define __I2C_OV9640_H__ +#ifndef DEBUG #define DEBUG +#endif /* Calculating the Module Block Number */ #define BLOCK(a) (u8)((a) >> 7) /* register's module block address. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <hap...@us...> - 2007-06-26 11:59:36
|
Revision: 1081 http://svn.sourceforge.net/hackndev/?rev=1081&view=rev Author: happy-slapin Date: 2007-06-26 04:59:16 -0700 (Tue, 26 Jun 2007) Log Message: ----------- OV9640: moved platform code out Modified Paths: -------------- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h Modified: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-26 11:58:21 UTC (rev 1080) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-26 11:59:16 UTC (rev 1081) @@ -321,7 +321,7 @@ ov9640_write(0x36, 0x49); ov9640_write(0x12, 0x05); mdelay(800); - GPSR1 = GPIO_bit(50); + ov9640_set_powerdown_gpio(); } else { ov9640_write(0x39, 0xf0); @@ -329,7 +329,7 @@ ov9640_write(0x6b, 0x3f); ov9640_write(0x36, 0x49); ov9640_write(0x12, 0x10); - GPCR1 = GPIO_bit(50); + ov9640_clear_powerdown_gpio(); //GPSR0 = GPIO_bit(19); mdelay(20); //GPCR0 = GPIO_bit(19); Modified: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h 2007-06-26 11:58:21 UTC (rev 1080) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.h 2007-06-26 11:59:16 UTC (rev 1081) @@ -41,6 +41,7 @@ unsigned long last_updated; /* In jiffies */ }; void ov9640_gpio_init(void); - +void ov9640_set_powerdown_gpio(); +void ov9640_clear_powerdown_gpio(); #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <hap...@us...> - 2007-06-27 05:35:49
|
Revision: 1083 http://svn.sourceforge.net/hackndev/?rev=1083&view=rev Author: happy-slapin Date: 2007-06-26 22:35:39 -0700 (Tue, 26 Jun 2007) Log Message: ----------- OV9640: Fixed crash and several typos Modified Paths: -------------- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c Added Paths: ----------- linux4palm/linux/trunk/drivers/i2c/chips/ov9640_hw.h Modified: linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-26 16:32:57 UTC (rev 1082) +++ linux4palm/linux/trunk/drivers/i2c/chips/i2c-ov9640.c 2007-06-27 05:35:39 UTC (rev 1083) @@ -9,6 +9,7 @@ #include <asm/arch/palmz72-gpio.h> #include "i2c-ov9640.h" +#include "ov9640_hw.h" #define DEBUG 1 #define DPRINTK(fmt,args...) do { if (DEBUG) printk("in function %s "fmt,__FUNCTION__,##args);} while(0) @@ -30,7 +31,7 @@ extern struct i2c_adapter *i2cdev_adaps[]; struct i2c_client *g_client = NULL; -static unsigned short normal_i2c[] = {0x5d, OV9640_SLAVE_ADDR ,I2C_CLIENT_END }; +static unsigned short normal_i2c[] = {0x14, 0x50, 0x52, 0x54, 0x56, 0x5e, OV9640_SLAVE_ADDR ,I2C_CLIENT_END }; /* static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; */ I2C_CLIENT_INSMOD; @@ -79,6 +80,8 @@ if( g_client == NULL ) return -1; p = i2c_get_clientdata(g_client); + if(!p) + return -1; down(&p->update_lock); res = i2c_master_send(g_client, buf, 2); up(&p->update_lock); @@ -129,6 +132,7 @@ { struct i2c_client *new_client; int err = 0; + char res = -1; struct ov9640_data *data; /*check if */ @@ -154,20 +158,25 @@ need it, remove it. We do it here to help to lessen memory fragmentation. */ - new_client=kzalloc(sizeof(struct i2c_client)+sizeof(struct ov9640_data), - GFP_KERNEL ); + new_client=kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if ( !new_client ) { err = -ENOMEM; goto ERROR0; } + data=kzalloc(sizeof(struct ov9640_data), GFP_KERNEL ); - data = (struct ov9640_data *) (new_client + 1); + if ( !new_client ) { + err = -ENOMEM; + goto ERROR0; + } + new_client->addr = address; - i2c_set_clientdata(new_client, data); new_client->adapter = adapter; new_client->driver = &ov9640_driver; new_client->flags = 0; + init_MUTEX(&data->update_lock); + i2c_set_clientdata(new_client, data); g_client = new_client; ov9640_power_down(0); @@ -177,6 +186,10 @@ /* First, the generic detection (if any), that is skipped if any force parameter was used. */ + mdelay(2000); + ov9640_read(REV,&res); + /* The below is of course bogus */ + DPRINTK("I2C: Probe ov9640 chip..addr=0x%x, REV=%d, res=0x%x\n", address, REV, res); if (kind <= 0) { char res = -1; @@ -201,8 +214,6 @@ /* Only if you use this field */ data->valid = 0; - /* Only if you use this field */ - init_MUTEX(&data->update_lock); /* Tell the i2c layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -301,7 +312,7 @@ { u8 regValue; regValue = 0x80; - ov9640_write(OV9640_COM7, ®Value); + ov9640_write(OV9640_COM7, regValue); mdelay(10); return; } @@ -354,10 +365,11 @@ return res; } ov9640_initialized ++; - if(g_client != NULL) + if(g_client != NULL) { DPRINTK("I2C: driver for device %s registed!.\n", g_client->name); - else + } else { DPRINTK("I2C: driver for device unregisted!.\n"); + } return 0; } Added: linux4palm/linux/trunk/drivers/i2c/chips/ov9640_hw.h =================================================================== --- linux4palm/linux/trunk/drivers/i2c/chips/ov9640_hw.h (rev 0) +++ linux4palm/linux/trunk/drivers/i2c/chips/ov9640_hw.h 2007-06-27 05:35:39 UTC (rev 1083) @@ -0,0 +1,222 @@ +/* + ov9640_hw - Omnivision 9640 CMOS sensor driver + + Copyright (C) 2003, Intel Corporation + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _OV_9640_HW_H_ +#define _OV_9640_HW_H_ + +/*********************************************************************** + * + * Constants & Structures + * + ***********************************************************************/ +// Revision constants +#define PID_OV 0x96 +#define PID_9640 0x48 + +#define PID_OV_v3 0x96 +#define PID_9640_v3 0x49 + +// Return codes +#define OV_ERR_NONE 0x00 +#define OV_ERR_TIMEOUT -1 +#define OV_ERR_PARAMETER -2 +#define OV_COMM_ERR -3 + +#define CIBR0_PHY (0x50000000 + 0x28) +#define CIBR1_PHY (0x50000000 + 0x30) +#define CIBR2_PHY (0x50000000 + 0x38) +#define DPRINTK(fmt,args...) do { if (DEBUG) printk("in function %s "fmt,__FUNCTION__,##args);} while(0) + +// Output Size & Format +/* +#define OV_SIZE_NONE 0 +#define OV_SIZE_QQVGA 0x01 +#define OV_SIZE_QVGA ( OV_SIZE_QQVGA << 1 ) +#define OV_SIZE_VGA ( OV_SIZE_QQVGA << 2 ) +#define OV_SIZE_SXGA ( OV_SIZE_QQVGA << 3 ) +#define OV_SIZE_QQCIF 0x10 +#define OV_SIZE_QCIF ( OV_SIZE_QQCIF << 1 ) +#define OV_SIZE_CIF ( OV_SIZE_QQCIF << 2 ) +#define OV_FORMAT_NONE 0 +#define OV_FORMAT_YUV_422 1 +#define OV_FORMAT_RGB_565 2 +*/ +enum OV_SIZE { + OV_SIZE_NONE=0 , + OV_SIZE_QQVGA , + OV_SIZE_QVGA , + OV_SIZE_VGA , + OV_SIZE_SXGA , + OV_SIZE_QQCIF , + OV_SIZE_QCIF , + OV_SIZE_CIF +}; +enum OV_FORMAT { + OV_FORMAT_NONE=0 , + OV_FORMAT_YUV_422, + OV_FORMAT_RGB_565, +}; + +// Camera Mode +#define VIEWFINDER_MODE 0x10 +#define STILLFRAME_MODE 0x20 + +// Others +#define OV9640_TIMEOUT 1000 // ms to timeout. + +// OV9640 Register Definitions +#define OV9640_GAIN 0x0000 +#define OV9640_BLUE 0x0001 +#define OV9640_RED 0x0002 +#define OV9640_VREF 0x0003 +#define OV9640_COM1 0x0004 +#define OV9640_BAVE 0x0005 // U/B Average Level +#define OV9640_GEAVE 0x0006 // Y/Ge Average Level +#define OV9640_GOAVE 0x0007 // Y/Go Average Level +#define OV9640_RAVE 0x0008 // V/R Average level +#define OV9640_COM2 0x0009 // Common control 2 +#define OV9640_PID 0x000A // Product ID +#define OV9640_VER 0x000B // Version +#define OV9640_COM3 0x000C +#define OV9640_COM4 0x000D +#define OV9640_COM5 0x000E +#define OV9640_COM6 0x000F +#define OV9640_AECH 0x0010 +#define OV9640_CLKRC 0x0011 +#define OV9640_COM7 0x0012 +#define OV9640_COM8 0x0013 +#define OV9640_COM9 0x0014 +#define OV9640_COM10 0x0015 +#define OV9640_WS 0x0016 +#define OV9640_HSTART 0x0017 +#define OV9640_HSTOP 0x0018 +#define OV9640_VSTRT 0x0019 +#define OV9640_VSTOP 0x001A +#define OV9640_PSHFT 0x001B +#define OV9640_MIDH 0x001C +#define OV9640_MIDL 0x001D +#define OV9640_DLY 0x001E +#define OV9640_LAEC 0x001F +#define OV9640_BOS 0x0020 +#define OV9640_GBOS 0x0021 +#define OV9640_GROS 0x0022 +#define OV9640_ROS 0x0023 +#define OV9640_AEW 0x0024 +#define OV9640_AEB 0x0025 +#define OV9640_VPT 0x0026 +#define OV9640_BBIAS 0x0027 +#define OV9640_GbBIAS 0x0028 +#define OV9640_GrBIAS 0x0029 +#define OV9640_EXHCH 0x002A +#define OV9640_EXHCL 0x002B +#define OV9640_RBIAS 0x002C +#define OV9640_ADVFL 0x002D +#define OV9640_ADVFH 0x002E +#define OV9640_YAVE 0x002F +#define OV9640_HSYST 0x0030 +#define OV9640_HSYEN 0x0031 +#define OV9640_HREF 0x0032 +#define OV9640_CHLF 0x0033 +#define OV9640_ARBLM 0x0034 +#define OV9640_VRHL 0x0035 +#define OV9640_VIDO 0x0036 +#define OV9640_ADC 0x0037 +#define OV9640_ACOM 0x0038 +#define OV9640_OFON 0x0039 +#define OV9640_TSLB 0x003A +#define OV9640_COM11 0x003B +#define OV9640_COM12 0x003C +#define OV9640_COM13 0x003D +#define OV9640_COM14 0x003E +#define OV9640_EDGE 0x003F +#define OV9640_COM15 0x0040 +#define OV9640_COM16 0x0041 +#define OV9640_COM17 0x0042 +#define OV9640_AWBTH1 0x0043 +#define OV9640_AWBTH2 0x0044 +#define OV9640_AWBTH3 0x0045 +#define OV9640_AWBTH4 0x0046 +#define OV9640_AWBTH5 0x0047 +#define OV9640_AWBTH6 0x0048 +#define OV9640_MTX1 0x004F +#define OV9640_MTX2 0x0050 +#define OV9640_MTX3 0x0051 +#define OV9640_MTX4 0x0052 +#define OV9640_MTX5 0x0053 +#define OV9640_MTX6 0x0054 +#define OV9640_MTX7 0x0055 +#define OV9640_MTX8 0x0056 +#define OV9640_MTX9 0x0057 +#define OV9640_MTXS 0x0058 +#define OV9640_AWBC1 0x0059 +#define OV9640_AWBC2 0x005A +#define OV9640_AWBC3 0x005B +#define OV9640_AWBC4 0x005C +#define OV9640_AWBC5 0x005D +#define OV9640_AWBC6 0x005E +#define OV9640_AWBC7 0x005F +#define OV9640_AWBC8 0x0060 +#define OV9640_AWBC9 0x0061 +#define OV9640_LCC1 0x0062 +#define OV9640_LCC2 0x0063 +#define OV9640_LCC3 0x0064 +#define OV9640_LCC4 0x0065 +#define OV9640_LCC5 0x0066 +#define OV9640_MANU 0x0067 +#define OV9640_MANV 0x0068 +#define OV9640_HV 0x0069 +#define OV9640_MBD 0x006A +#define OV9640_DBLV 0x006B +#define OV9640_GSP0 0x006C +#define OV9640_GSP1 0x006D +#define OV9640_GSP2 0x006E +#define OV9640_GSP3 0x006F +#define OV9640_GSP4 0x0070 +#define OV9640_GSP5 0x0071 +#define OV9640_GSP6 0x0072 +#define OV9640_GSP7 0x0073 +#define OV9640_GSP8 0x0074 +#define OV9640_GSP9 0x0075 +#define OV9640_GSP10 0x0076 +#define OV9640_GSP11 0x0077 +#define OV9640_GSP12 0x0078 +#define OV9640_GSP13 0x0079 +#define OV9640_GSP14 0x007A +#define OV9640_GSP15 0x007B +#define OV9640_GST0 0x007C +#define OV9640_GST1 0x007D +#define OV9640_GST2 0x007E +#define OV9640_GST3 0x007F +#define OV9640_GST4 0x0080 +#define OV9640_GST5 0x0081 +#define OV9640_GST6 0x0082 +#define OV9640_GST7 0x0083 +#define OV9640_GST8 0x0084 +#define OV9640_GST9 0x0085 +#define OV9640_GST10 0x0086 +#define OV9640_GST11 0x0087 +#define OV9640_GST12 0x0088 +#define OV9640_GST13 0x0089 +#define OV9640_GST14 0x008A + +// End of OV9640 register +#define OV9640_REGEND ( OV9640_GST14 + 1 ) + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |