EZX phone platform device drivers for camera diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/Kconfig linux-2.6.16.5-exz/drivers/i2c/chips/Kconfig --- linux-2.6.16.5/drivers/i2c/chips/Kconfig 2006-04-12 22:27:57.000000000 +0200 +++ linux-2.6.16.5-exz/drivers/i2c/chips/Kconfig 2006-04-16 18:49:29.000000000 +0200 @@ -135,4 +135,25 @@ This driver can also be built as a module. If so, the module will be called x1205. +config I2C_ADCM2700 + tristate "ADCM2700 support" + depends on I2C_PXA + +config I2C_A780_CAMERA + tristate "A780 camera support" + depends on I2C_PXA + +config I2C_OV9640 + depends on I2C_A780_CAMERA + bool "OV9640 support" +config I2C_OV9650 + depends on I2C_A780_CAMERA + bool "OV9650 support" +config I2C_MT9M111 + depends on I2C_A780_CAMERA + bool "MT9M111 support" +config I2C_ADCM3800 + depends on I2C_A780_CAMERA + bool "ADCM3800 support" + endmenu diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/Makefile linux-2.6.16.5-exz/drivers/i2c/chips/Makefile --- linux-2.6.16.5/drivers/i2c/chips/Makefile 2006-04-12 22:27:57.000000000 +0200 +++ linux-2.6.16.5-exz/drivers/i2c/chips/Makefile 2006-04-16 18:49:29.000000000 +0200 @@ -15,6 +15,10 @@ obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_RTC_X1205_I2C) += x1205.o +obj-$(CONFIG_I2C_ADCM2700) += e680_camera.o +obj-$(CONFIG_I2C_A780_CAMERA) += a780_camera.o +obj-$(CONFIG_PXA_EZX_E680) += boomer.o + ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG endif diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/a780_camera.c linux-2.6.16.5-exz/drivers/i2c/chips/a780_camera.c --- linux-2.6.16.5/drivers/i2c/chips/a780_camera.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/a780_camera.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,905 @@ +/* + * linux/drivers/i2c/a780_camera.c + * + * Support for the Motorola Ezx A780 Development Platform. + * + * Author: Jay Jia + * Created: Nov 25, 2003 + * Copyright: Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Major 10, Minor 244, /dev/camerai2c */ +#define CAM_NAME "cami2c" +#define CAM_MINOR 244 + +#define TESTCODE +#undef TESTCODE +#define I2C_A780_CAMERA 0x86 + +//#define DEBUG 2 + +/*-----------------------------------------------------------*/ +#define err_print(fmt, args...) printk(KERN_ERR "I2C-CAMERA in fun:%s "fmt"\n", __FUNCTION__, ##args) + +#ifndef NDEBUG +#define dbg_print(fmt, args...) printk(KERN_INFO "I2C-CAMERA in fun:%s "fmt"\n", __FUNCTION__, ##args) +#if DEBUG > 1 +#define ddbg_print(fmt, args...) dbg_print(fmt, ##args) +#else +#define ddbg_print(fmt, args...) ; +#endif +#else +#define dbg_print(fmt, args...) ; +#define ddbg_print(fmt, args...) ; +#endif +/*-----------------------------------------------------------*/ + +#define I2C_CLIENT_NONE 100 +#define I2C_CLIENT_MT9M111 101 +#define I2C_CLIENT_OV9640 102 +#define I2C_CLIENT_OV9650 103 +#define I2C_CLIENT_ADCM3800 104 +static int i2c_camera_client_type = I2C_CLIENT_NONE; +static unsigned long i2c_camera_chipid = 0; + + +static int a780_camera_adapter_attach(struct i2c_adapter *adap); +static int a780_camera_detach(struct i2c_client *client); +static int a780_camera_client_register(struct i2c_client *client); +static int a780_camera_client_unregister(struct i2c_client *client); +/* ----------------------------------------------------------------------- */ +static struct i2c_driver driver = { + .name = "a780 camera driver", + .id = I2C_A780_CAMERA, + //flags: I2C_DF_DUMMY, + .attach_adapter = a780_camera_adapter_attach, + .detach_client = a780_camera_detach, + .owner = THIS_MODULE, +}; + +static struct i2c_adapter a780_camera_adapter = { + name: "a780 camera adapter", + id: I2C_A780_CAMERA, + client_register: a780_camera_client_register, + client_unregister: a780_camera_client_unregister, +}; + +static struct i2c_client client_template = +{ + name: "(unset)", + adapter:&a780_camera_adapter, +}; + +struct i2c_client *a780_camera_client; +unsigned int a780_camera_minor; + +static int a780_camera_open(void) +{ + //MOD_INC_USE_COUNT; + + return 0; +} + +static int a780_camera_release(void) +{ + //MOD_DEC_USE_COUNT; + return 0; +} + + +int a780_camera_read(char *buf, size_t count) +{ + int ret; + unsigned int flags; + + a780_camera_open(); + local_irq_save(flags); + enable_irq(IRQ_I2C); + ret = i2c_master_recv(a780_camera_client, buf, count); + local_irq_restore(flags); + a780_camera_release(); + return ret; + +} + +int a780_camera_write(const char *buf, size_t count) +{ + int ret; + unsigned int flags; + + a780_camera_open(); + local_irq_save(flags); + enable_irq(IRQ_I2C); + ret = i2c_master_send(a780_camera_client, buf, count); + local_irq_restore(flags); + a780_camera_release(); + return ret; +} + +static int a780_camera_client_register(struct i2c_client *client) +{ + + return 0; +} + +static int a780_camera_client_unregister(struct i2c_client *client) +{ + + return 0; +} +/* ----------------------------------------------------------------------- */ + +static int a780_camera_adapter_attach(struct i2c_adapter *adap) +{ + if(! (a780_camera_client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + memcpy(a780_camera_client,&client_template,sizeof(struct i2c_client)); + a780_camera_client->adapter = adap; + + a780_camera_client->addr = 0x5D; + + i2c_attach_client(a780_camera_client); + return 0; +} + +static int a780_camera_detach(struct i2c_client *client) +{ + i2c_detach_client(a780_camera_client); + return 0; +} +/* ----------------------------------------------------------------------- */ +static int cam_open(struct inode *inode, struct file *file) +{ + if(i2c_camera_client_type == I2C_CLIENT_NONE) + return -EINVAL; + + //MOD_INC_USE_COUNT; + return 0; +} + +static int i2c_camera_readw(unsigned short addr, unsigned short *pvalue); +static int i2c_camera_readb(unsigned short addr, unsigned char *pvalue); +static int i2c_camera_writew(unsigned short addr, unsigned short value); +static int i2c_camera_writeb(unsigned short addr, unsigned char value); + +static int cam_close(struct inode * inode, struct file *file) +{ + //MOD_DEC_USE_COUNT; + return 0; +} + +#define DETECT_BUFLEN 256 +static int cam_ioctl_detectid (void * arg) +{ + int buflen, idlen; + char* id; + struct camera_i2c_detectid * param = arg; + if(copy_from_user(&buflen, &(param->buflen), sizeof(buflen))) + { + return -EFAULT; + } + if(buflen > DETECT_BUFLEN) + { + return -ENOMEM; + } + id = kmalloc(DETECT_BUFLEN, GFP_KERNEL); + if(id == NULL) + { + return -ENOMEM; + } + + idlen = 0; + switch(i2c_camera_client_type) + { +#ifdef CONFIG_I2C_MT9M111 + case I2C_CLIENT_MT9M111: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "MICRON", "MT9M111", i2c_camera_chipid); + break; +#endif +#ifdef CONFIG_I2C_ADCM3800 + case I2C_CLIENT_ADCM3800: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "AGILENT", "ADCM3800", i2c_camera_chipid); + break; +#endif +#ifdef CONFIG_I2C_OV9640 + case I2C_CLIENT_OV9640: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "OMNIVISION", "OV9640", i2c_camera_chipid); + break; +#endif +#ifdef CONFIG_I2C_OV9650 + case I2C_CLIENT_OV9650: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "OMNIVISION", "OV9650", i2c_camera_chipid); + break; +#endif + default: + break; + } + id[DETECT_BUFLEN-1] = 0; + idlen = strlen(id)+1; + if(buflen < idlen) + { + kfree(id); + return -ENOMEM; + } + if(copy_to_user(param->data, id, idlen)) + { + kfree(id); + return -EFAULT; + } + kfree(id); + return 0; +} + +static int cam_ioctl_register_rw (unsigned int cmd, void * arg) +{ + int ret = -ENOTSUPP; + struct camera_i2c_register reg; + if(copy_from_user(®, arg, sizeof(reg))) + { + return -EFAULT; + } + switch(cmd) + { + case CAMERA_I2C_WRITEW: + ret=i2c_camera_writew(reg.addr, reg.value.w); + break; + case CAMERA_I2C_WRITEB: + ret=i2c_camera_writeb(reg.addr, reg.value.b); + break; + case CAMERA_I2C_READW: + if((ret=i2c_camera_readw(reg.addr, &(reg.value.w)))>=0) + { + if(copy_to_user(arg, ®, sizeof(reg))) + ret = -EFAULT; + } + break; + case CAMERA_I2C_READB: + if((ret=i2c_camera_readb(reg.addr, &(reg.value.b)))>=0) + { + if(copy_to_user(arg, ®, sizeof(reg))) + ret = -EFAULT; + } + break; + default: + break; + } + return ret; +} + +static int cam_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOTSUPP; + switch (cmd) + { + case CAMERA_I2C_WRITEW: + case CAMERA_I2C_WRITEB: + case CAMERA_I2C_READW: + case CAMERA_I2C_READB: + ret = cam_ioctl_register_rw(cmd, (void *)arg); + break; + case CAMERA_I2C_DETECTID: + ret = cam_ioctl_detectid((void *)arg); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static struct file_operations cam_fops = { + ioctl: cam_ioctl, + open: cam_open, + release: cam_close, +}; + +static struct miscdevice cam_misc_device = { + CAM_MINOR, + CAM_NAME, + &cam_fops, +}; + +/* ----------------------------------------------------------------------- */ +static int a780_camera_init_module(void) +{ + int res; + + res = i2c_add_driver(&driver); + if( res < 0 ) + { + printk("error in add i2c driver\n"); + return res; + } + if (misc_register (&cam_misc_device)) + { + printk(KERN_ERR "Couldn't register cam driver\n"); + return -EIO; + } + + return 0; +} + +static void a780_camera_cleanup_module(void) +{ + i2c_del_driver(&driver); + misc_deregister(&cam_misc_device); +} + + +#ifdef CONFIG_I2C_MT9M111 + +/*-----------------------------------------------------------*/ +#define MT9M111_PAGE(a) ((u8)(((a) >> 8) & 0xFF)) +#define MT9M111_OFFSET(a) ((u8)((a) & 0xFF)) + +//#define MT9M111_LOG + +#ifdef MT9M111_LOG +#define mt9m111_dbg_print(fmt, args...) dbg_print(fmt, ##args) +#else +#define mt9m111_dbg_print(fmt, args...) ; +#endif + +static int mt9m111_ChangePage(unsigned char page) +{ + static unsigned char old_page = 0xFF; + int res; + char tmp[3]={0xF0, 0, page}; + + if(page == old_page) + { + return 0; + } + + res = a780_camera_write(tmp, 3); + if(res < 0) + { + return res; + } + old_page = page; + + return 0; +} + +int mt9m111_read(unsigned short addr, unsigned short *pvalue) +{ + unsigned char pageaddr = MT9M111_PAGE(addr); + unsigned char offset = MT9M111_OFFSET(addr); + unsigned short value; + int ret; + + if((ret = mt9m111_ChangePage(pageaddr)) != 0) + { + mt9m111_dbg_print("Change block address failed. block = 0x%2x", pageaddr); + mt9m111_dbg_print("Error code = 0x%x", ret); + return ret; + } + if(a780_camera_write(&offset, 1) < 0) + { + mt9m111_dbg_print("read error!"); + return ret; + } + + ret = a780_camera_read((char *)&value, 2); + if(ret < 0) + { + mt9m111_dbg_print("read error"); + return ret; + } + + *pvalue = (value >> 8) | (value << 8); + mt9m111_dbg_print("addr = 0x%04x, value = 0x%04x", addr, *pvalue); + return 0; +} + +int mt9m111_write(unsigned short addr, unsigned short value) +{ + unsigned char pageaddr = MT9M111_PAGE(addr); + unsigned char offset = MT9M111_OFFSET(addr); + char tmp[3]={offset, (char)(value>>8), (char)(value&0xFF)}; + int ret; + + if((ret = mt9m111_ChangePage(pageaddr)) != 0) + { + mt9m111_dbg_print("Change block address failed. block = 0x%2x", pageaddr); + mt9m111_dbg_print("error code = 0x%x", ret); + return ret; + } + ret = a780_camera_write(tmp, 3); + if(ret < 0) + { + return ret; + } + mt9m111_dbg_print("addr = 0x%04x, value = 0x%04x", addr,value); + return 0; +} + +int i2c_mt9m111_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} +int i2c_mt9m111_init(void) +{ + //unsigned short chipid; + a780_camera_client->addr = 0x5D; + + //mt9m111_read(0, &chipid); + //mt9m111_dbg_print("mt9m111 chip id is 0x%x", chipid); + + i2c_camera_client_type = I2C_CLIENT_MT9M111; + return 0; +} + +#endif // CONFIG_I2C_MT9M111 + +#ifdef CONFIG_I2C_OV9650 + +#define OV_REG_PID 0x0a +#define OV_REG_VER 0x0b +#define OV9650_CHIPID_M 0x96 +#define OV9650_CHIPID_L_0 0x51 +#define OV9650_CHIPID_L 0x52 + +int i2c_ov9650_read(u8 addr, u8 *pvalue) +{ + int ret; + + if((ret = a780_camera_write(&addr, 1)) < 0) + { + err_print("i2c write error code =%d", ret); + return -EIO; + } + + ret = a780_camera_read((char *)pvalue, 1); + if(ret < 0) + { + err_print("i2c read error code =%d", ret); + return -EIO; + } + + ddbg_print("addr = 0x%02x, value = 0x%02x", addr, *pvalue); + return 0; +} + +int i2c_ov9650_write(u8 addr, u8 value) +{ + char tmp[2]={addr, value}; + int ret; + + ret = a780_camera_write(tmp, 2); + if(ret < 0) + { + err_print("i2c write error code =%d", ret); + return -EIO; + } + + ddbg_print("addr = 0x%02x, value = 0x%02x", addr,value); + return 0; +} + +int i2c_ov9650_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} + +int i2c_ov9650_init(void) +{ + unsigned char chipid; + unsigned char ver; + // setup i2c address + a780_camera_client->addr = 0x30; //0x60; + + if( i2c_ov9650_read(OV_REG_PID, &chipid) < 0 ) + { + err_print("error: failed to read chipid"); + return -EIO; + } + if( chipid != OV9650_CHIPID_M ) + { + err_print("chip is not Omnivision"); + return -EIO; + } + + i2c_ov9650_read(OV_REG_VER, &ver); + dbg_print("ov chip id is 0x%x:0x%x", chipid, ver); + + if( ver != OV9650_CHIPID_L && ver != OV9650_CHIPID_L_0 ) + { + err_print("chip is not OV9650"); + return -EIO; + } + i2c_camera_client_type = I2C_CLIENT_OV9650; + i2c_camera_chipid = (chipid<<8) | ver; + + return 0; +} + +#ifdef CONFIG_I2C_OV9640 +int ov9640_read(u8 addr, u8 *pvalue) +{ + return i2c_ov9650_read(addr, pvalue); +} + +int ov9640_write(u8 addr, u8 value) +{ + return i2c_ov9650_write(addr, value); +} + +int i2c_ov9640_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} + +#define OV9640_CHIPID_M 0x96 +#define OV9640_CHIPID_L 0x49 +#define OV9640_CHIPID_L_V2 0x48 + +int i2c_ov9640_init(void) +{ + unsigned char chipid; + unsigned char ver; + // setup i2c address + a780_camera_client->addr = 0x30; //0x60; + + if( ov9640_read(OV_REG_PID, &chipid) < 0 ) + { + err_print("error: failed to read chipid"); + return -EIO; + } + if( chipid != OV9640_CHIPID_M ) + { + err_print("chip is not Omnivision"); + return -EIO; + } + + ov9640_read(OV_REG_VER, &ver); + dbg_print("ov chip id is 0x%x:0x%x", chipid, ver); + + if( ver != OV9640_CHIPID_L && ver != OV9640_CHIPID_L_V2 ) + { + err_print("chip is not OV9640"); + return -EIO; + } + i2c_camera_client_type = I2C_CLIENT_OV9640; + i2c_camera_chipid = (chipid<<8) | ver; + + return 0; +} +#endif // CONFIG_I2C_OV9640 + +#endif // CONFIG_I2C_OV9650 + +#ifdef CONFIG_I2C_ADCM3800 + +#define ADCM3800_I2C_ADDR 0x56 +#define ADCM3800_BLOCK_SWITCH_CMD 0xFE + +/* Calculating the Module Block Number */ +#define ADCM3800_BLOCK(a) ((u8)(((a) >> 7) & 0xFF)) /* register's module block address. */ +#define ADCM3800_OFFSET(a) ((u8)(((a) << 1) & 0xFF)) /* register's offset to this block. */ +#define ADCM3800_OFFSET_R(a) (ADCM3800_OFFSET(a)|1) /* register's offset ot this block to read*/ + +static int adcm3800_ChgBlock(unsigned char block) +{ + static unsigned char old_blk = 0xFF; + int res; + char tmp[2]={ADCM3800_BLOCK_SWITCH_CMD, block}; + + if(block == old_blk) + { + return 0; + } + + res = a780_camera_write(tmp, 2); + if(res < 0) + { + err_print("error code = %d", res); + return -EIO; + } + old_blk = block; + + return 0; +} + +int i2c_adcm3800_read_byte(unsigned short addr, unsigned char *pvalue) +{ + unsigned char blockaddr = ADCM3800_BLOCK(addr); + unsigned char offset = ADCM3800_OFFSET_R(addr); + int ret; + + if((ret = adcm3800_ChgBlock(blockaddr)) != 0) + { + err_print("Change block address failed. block = 0x%2x", blockaddr); + return -EIO; + } + if((ret = a780_camera_write(&offset, 1)) < 0) + { + err_print("i2c write error code =%d", ret); + return -EIO; + } + + ret = a780_camera_read((char *)pvalue, 1); + if(ret < 0) + { + err_print("i2c read error code = %d", ret); + return -EIO; + } + ddbg_print("read b: addr(0x%x) value(0x%x)", addr, *pvalue); + + return *pvalue; +} + +int i2c_adcm3800_read(unsigned short addr, unsigned short *pvalue) +{ + unsigned char blockaddr = ADCM3800_BLOCK(addr); + unsigned char offset = ADCM3800_OFFSET_R(addr); + int ret; + + if((ret = adcm3800_ChgBlock(blockaddr)) != 0) + { + err_print("Change block address failed. block = 0x%2x", blockaddr); + return -EIO; + } + if((ret = a780_camera_write(&offset, 1)) < 0) + { + err_print("i2c write error code =%d", ret); + return -EIO; + } + + ret = a780_camera_read((char *)pvalue, 2); + if(ret < 0) + { + err_print("i2c read error code = %d", ret); + return -EIO; + } + ddbg_print("read: addr(0x%x) value(0x%x)", addr, *pvalue); + + return *pvalue; +} + +int i2c_adcm3800_write_byte(unsigned short addr, unsigned char value) +{ + unsigned char blockaddr = ADCM3800_BLOCK(addr); + unsigned char offset = ADCM3800_OFFSET(addr);; + char tmp[3]={offset, value}; + int ret; + + ddbg_print("write b: addr(0x%x) value(0x%x)", addr, value); + if((ret = adcm3800_ChgBlock(blockaddr)) != 0) + { + err_print("Change block address failed. block = 0x%2x", blockaddr); + return -EIO; + } + ret = a780_camera_write(tmp, 2); + if(ret < 0) + { + err_print("i2c write error code = %d", ret); + return -EIO; + } + return 0; + +} +int i2c_adcm3800_write(unsigned short addr, unsigned short value) +{ + unsigned char blockaddr = ADCM3800_BLOCK(addr); + unsigned char offset = ADCM3800_OFFSET(addr);; + char tmp[3]={offset, (char)(value&0xFF), (char)(value>>8)}; + int ret; + + ddbg_print("write: addr(0x%x) value(0x%x)", addr, value); + if((ret = adcm3800_ChgBlock(blockaddr)) != 0) + { + err_print("Change block address failed. block = 0x%2x", blockaddr); + return -EIO; + } + ret = a780_camera_write(tmp, 3); + if(ret < 0) + { + err_print("i2c write error code = %d", ret); + return -EIO; + } + return 0; +} + +int i2c_adcm3800_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} + +#define ADCM_SREG_PID 0x0000 +#define ADCM_EREG_PID 0x0800 + +#define ADCM3800_PIPE_REV 0x0068 +#define ADCM3800_SENSOR_REV 0x68 + +int i2c_adcm3800_init(void) +{ + unsigned short pid_pipe; + unsigned char pid_sensor; + a780_camera_client->addr = ADCM3800_I2C_ADDR; + + if(i2c_adcm3800_read(ADCM_SREG_PID, &pid_pipe) < 0) + { + return -EIO; + } + if(i2c_adcm3800_read_byte(ADCM_EREG_PID, &pid_sensor) < 0) + { + return -EIO; + } + + dbg_print("pipe id is 0x%x, sensor id is 0x%x", pid_pipe, pid_sensor); + if(pid_pipe != ADCM3800_PIPE_REV && pid_sensor != ADCM3800_SENSOR_REV) + { + err_print("sensor is not Agilent ADCM3800"); + return -EIO; + } + i2c_camera_client_type = I2C_CLIENT_ADCM3800; + i2c_camera_chipid = (pid_pipe<<8) | pid_sensor; + + return 0; +} +#endif // CONFIG_I2C_ADCM3800 + +static int i2c_camera_readw(unsigned short addr, unsigned short *pvalue) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { +#ifdef CONFIG_I2C_MT9M111 + case I2C_CLIENT_MT9M111: + ret = mt9m111_read(addr, pvalue); + break; +#endif +#ifdef CONFIG_I2C_ADCM3800 + case I2C_CLIENT_ADCM3800: + ret = i2c_adcm3800_read(addr, pvalue); + break; +#endif + default: + break; + } + return ret; +} + +static int i2c_camera_readb(unsigned short addr, unsigned char *pvalue) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { +#ifdef CONFIG_I2C_ADCM3800 + case I2C_CLIENT_ADCM3800: + ret = i2c_adcm3800_read_byte(addr, pvalue); + break; +#endif +#ifdef CONFIG_I2C_OV9640 + case I2C_CLIENT_OV9640: + ret = ov9640_read(addr, pvalue); + break; +#endif +#ifdef CONFIG_I2C_OV9650 + case I2C_CLIENT_OV9650: + ret = i2c_ov9650_read(addr, pvalue); + break; +#endif + default: + break; + } + return ret; +} + +static int i2c_camera_writew(unsigned short addr, unsigned short value) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { +#ifdef CONFIG_I2C_MT9M111 + case I2C_CLIENT_MT9M111: + ret = mt9m111_write(addr, value); + break; +#endif +#ifdef CONFIG_I2C_ADCM3800 + case I2C_CLIENT_ADCM3800: + ret = i2c_adcm3800_write(addr, value); + break; +#endif + default: + break; + } + return ret; +} + +static int i2c_camera_writeb(unsigned short addr, unsigned char value) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { +#ifdef CONFIG_I2C_ADCM3800 + case I2C_CLIENT_ADCM3800: + ret = i2c_adcm3800_write_byte(addr, value); + break; +#endif +#ifdef CONFIG_I2C_OV9640 + case I2C_CLIENT_OV9640: + ret = ov9640_write(addr, value); + break; +#endif +#ifdef CONFIG_I2C_OV9650 + case I2C_CLIENT_OV9650: + ret = i2c_ov9650_write(addr, value); + break; +#endif + default: + break; + } + return ret; +} + +#ifdef CONFIG_I2C_MT9M111 +EXPORT_SYMBOL(i2c_mt9m111_init); +EXPORT_SYMBOL(mt9m111_write); +EXPORT_SYMBOL(mt9m111_read); +EXPORT_SYMBOL(i2c_mt9m111_cleanup); +#endif + +#ifdef CONFIG_I2C_OV9650 +EXPORT_SYMBOL(i2c_ov9650_init); +EXPORT_SYMBOL(i2c_ov9650_write); +EXPORT_SYMBOL(i2c_ov9650_read); +EXPORT_SYMBOL(i2c_ov9650_cleanup); +#endif + +#ifdef CONFIG_I2C_OV9640 +EXPORT_SYMBOL(i2c_ov9640_init); +EXPORT_SYMBOL(ov9640_write); +EXPORT_SYMBOL(ov9640_read); +EXPORT_SYMBOL(i2c_ov9640_cleanup); +#endif + +#ifdef CONFIG_I2C_ADCM3800 +EXPORT_SYMBOL(i2c_adcm3800_init); +EXPORT_SYMBOL(i2c_adcm3800_write); +EXPORT_SYMBOL(i2c_adcm3800_read); +EXPORT_SYMBOL(i2c_adcm3800_write_byte); +EXPORT_SYMBOL(i2c_adcm3800_read_byte); +EXPORT_SYMBOL(i2c_adcm3800_cleanup); +#endif + +module_init(a780_camera_init_module); +module_exit(a780_camera_cleanup_module); +MODULE_AUTHOR("Jay Jia"); +MODULE_LICENSE("GPL"); diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/boomer.c linux-2.6.16.5-exz/drivers/i2c/chips/boomer.c --- linux-2.6.16.5/drivers/i2c/chips/boomer.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/boomer.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,175 @@ +/* + * linux/drivers/i2c/boomer.c + * + * Support for the Motorola Ezx A780 Development Platform. + * + * Author: Jay Jia + * Created: Nov 25, 2003 + * Copyright: Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Jin Lihong(w20076),Motorola Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#define TESTCODE +#undef TESTCODE +#define I2C_MIXER 0x80 + +static int mixer_adapter_attach(struct i2c_adapter *adap); +static int mixer_detach(struct i2c_client *client); +static int mixer_client_register(struct i2c_client *client); +static int mixer_client_unregister(struct i2c_client *client); +extern struct i2c_client *fmradio_client; +/* ----------------------------------------------------------------------- */ +static struct i2c_driver driver = { + .name = "mixer driver", + .id = I2C_MIXER, + //.flags = I2C_DF_DUMMY, + .attach_adapter = mixer_adapter_attach, + .detach_client = mixer_detach, + .owner = THIS_MODULE, +}; + +static struct i2c_adapter mixer_adapter = { + name: "Mixer adapter", + id: I2C_MIXER, + client_register: mixer_client_register, + client_unregister: mixer_client_unregister, +}; + +static struct i2c_client client_template = +{ + name: "(unset)", + adapter:&mixer_adapter, +}; + +struct i2c_client *mixer_client; +unsigned int mixer_minor; + +int mixer_write(const char *buf, size_t count); +int mixer_open(void) +{ + //MOD_INC_USE_COUNT; + + +#ifdef TESTCODE + char data[4]={0x18,0x7d,0xbd,0xcd}; + char freq[5]={0x2e,0x56,0x41,0x11,0x40}; + unsigned char s[5]={0, 0, 0, 0, 0}; + + mixer_write(data,4); +// i2c_master_send(fmradio_client,freq,5); +// printk("fmradio test code\n"); +// mdelay(300); +// i2c_master_recv(fmradio_client, s, 5); +// printk("s0=%02x s1=%02x s2=%02x s3=%02x s4=%02x \n",s[0],s[1],s[2],s[3],s[4]); +#endif + + + return 0; +} + +int mixer_release(void) +{ + //MOD_DEC_USE_COUNT; + return 0; +} + +int mixer_write(const char *buf, size_t count) +{ + int ret; + unsigned long flags; + + mixer_open(); + local_irq_save(flags); + enable_irq(IRQ_I2C); + ret = i2c_master_send(mixer_client, buf, count); + local_irq_restore(flags); +// printk("i2c-%d writing %d bytes.\n", mixer_minor, ret); + mixer_release(); + return ret; +} + +static int mixer_client_register(struct i2c_client *client) +{ + return 0; +} + +static int mixer_client_unregister(struct i2c_client *client) +{ + + return 0; +} +/* ----------------------------------------------------------------------- */ + +static int mixer_adapter_attach(struct i2c_adapter *adap) +{ + if(! (mixer_client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + memcpy(mixer_client,&client_template,sizeof(struct i2c_client)); + mixer_client->adapter = adap; + + mixer_client->addr = 0x7c; + + printk("adapter %s\n",adap->name); + i2c_attach_client(mixer_client); +#ifdef TESTCODE + mixer_open(); +#endif + return 0; +} + +static int mixer_detach(struct i2c_client *client) +{ + i2c_detach_client(mixer_client); + return 0; +} +/* ----------------------------------------------------------------------- */ + +static int mixer_init_module(void) +{ + int res; + + res = i2c_add_driver(&driver); + if( res < 0 ) + { + printk("error in add i2c driver\n"); + return res; + } + return 0; +} + +static void mixer_cleanup_module(void) +{ + i2c_del_driver(&driver); +} + +module_init(mixer_init_module); +module_exit(mixer_cleanup_module); +MODULE_AUTHOR("Jay Jia"); +MODULE_LICENSE("GPL"); diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/e680_camera.c linux-2.6.16.5-exz/drivers/i2c/chips/e680_camera.c --- linux-2.6.16.5/drivers/i2c/chips/e680_camera.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/e680_camera.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,668 @@ +/* + * linux/drivers/i2c/e680_camera.c + * + * Support for the Motorola Ezx A780 Development Platform. + * + * Author: Jay Jia + * Created: Nov 25, 2003 + * Copyright: Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Jin Lihong(w20076),Motorola Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include "i2c-adcm2700.h" + +/* Major 10, Minor 244, /dev/camerai2c */ +#define CAM_NAME "cami2c" +#define CAM_MINOR 244 + +#define TESTCODE +#undef TESTCODE +#define I2C_E680_CAMERA 0x86 + +#define I2C_CLIENT_NONE 0 +#define I2C_CLIENT_ADCM2700 1 +#define I2C_CLIENT_MT9V111 2 +static int i2c_camera_client_type = I2C_CLIENT_NONE; +static unsigned long i2c_camera_chipid = 0; +#define REG_ADDRSELECT (0x01) +#undef BLOCK(a) +#define BLOCK(a) ((u8)(((a)>>7)&0xFF)) + +static int e680_camera_adapter_attach(struct i2c_adapter *adap); +static int e680_camera_detach(struct i2c_client *client); +static int e680_camera_client_register(struct i2c_client *client); +static int e680_camera_client_unregister(struct i2c_client *client); + +typedef struct +{ + u16 addr; + union {u16 word; u8 byte;}value; +}i2c_camera_reg; +/* ----------------------------------------------------------------------- */ +static struct i2c_driver driver = { + .name = "e680 camera driver", + .id = I2C_E680_CAMERA, + //.flags = I2C_DF_DUMMY, + .attach_adapter = e680_camera_adapter_attach, + .detach_client = e680_camera_detach, + .owner = THIS_MODULE, +}; + +static struct i2c_adapter e680_camera_adapter = { + .name = "e680 camera adapter", + .id = I2C_E680_CAMERA, + .client_register = e680_camera_client_register, + .client_unregister = e680_camera_client_unregister, + .owner = THIS_MODULE, +}; + +static struct i2c_client client_template = +{ + name: "(unset)", + adapter:&e680_camera_adapter, +}; + +struct i2c_client *e680_camera_client; +unsigned int e680_camera_minor; + +static int e680_camera_open(void) +{ + //MOD_INC_USE_COUNT; + + return 0; +} + +static int e680_camera_release(void) +{ + //MOD_DEC_USE_COUNT; + return 0; +} + + +int e680_camera_read(char *buf, size_t count) +{ + int ret; + unsigned int flags; + + e680_camera_open(); + local_irq_save(flags); + enable_irq(IRQ_I2C); + ret = i2c_master_recv(e680_camera_client, buf, count); + local_irq_restore(flags); + e680_camera_release(); + return ret; + +} + +int e680_camera_write(const char *buf, size_t count) +{ + int ret; + unsigned int flags; + + e680_camera_open(); + local_irq_save(flags); + enable_irq(IRQ_I2C); + ret = i2c_master_send(e680_camera_client, buf, count); + local_irq_restore(flags); + e680_camera_release(); + return ret; +} + +static int e680_camera_client_register(struct i2c_client *client) +{ + + return 0; +} + +static int e680_camera_client_unregister(struct i2c_client *client) +{ + + return 0; +} +/* ----------------------------------------------------------------------- */ + +static int e680_camera_adapter_attach(struct i2c_adapter *adap) +{ + if(! (e680_camera_client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + + memcpy(e680_camera_client,&client_template,sizeof(struct i2c_client)); + e680_camera_client->adapter = adap; + + /*adcm2700 i2c client address*/ + e680_camera_client->addr = 0x53; + i2c_attach_client(e680_camera_client); + return 0; +} + +static int e680_camera_detach(struct i2c_client *client) +{ + i2c_detach_client(e680_camera_client); + return 0; +} + +/* ----------------------------------------------------------------------- */ +static int cam_open(struct inode *inode, struct file *file) +{ + if(i2c_camera_client_type == I2C_CLIENT_NONE) + return -EINVAL; + + //MOD_INC_USE_COUNT; + return 0; +} + +static int i2c_camera_readw(unsigned short addr, unsigned short *pvalue); +static int i2c_camera_readb(unsigned short addr, unsigned char *pvalue); +static int i2c_camera_writew(unsigned short addr, unsigned short value); +static int i2c_camera_writeb(unsigned short addr, unsigned char value); + +static int cam_close(struct inode * inode, struct file *file) +{ + //MOD_DEC_USE_COUNT; + return 0; +} + +#define DETECT_BUFLEN 256 +static int cam_ioctl_detectid (void * arg) +{ + int buflen, idlen; + char* id; + struct camera_i2c_detectid * param = arg; + if(copy_from_user(&buflen, &(param->buflen), sizeof(buflen))) + { + return -EFAULT; + } + if(buflen > DETECT_BUFLEN) + { + return -ENOMEM; + } + id = kmalloc(DETECT_BUFLEN, GFP_KERNEL); + if(id == NULL) + { + return -ENOMEM; + } + + idlen = 0; + switch(i2c_camera_client_type) + { + case I2C_CLIENT_MT9V111: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "MICRON", "MT9V111", i2c_camera_chipid); + break; + case I2C_CLIENT_ADCM2700: + idlen = snprintf(id, DETECT_BUFLEN-1, "%s %s %lx", + "AGILENT", "ADCM2700", i2c_camera_chipid); + break; + default: + break; + } + id[DETECT_BUFLEN-1] = 0; + idlen = strlen(id)+1; + if(buflen < idlen) + { + kfree(id); + return -ENOMEM; + } + if(copy_to_user(param->data, id, idlen)) + { + kfree(id); + return -EFAULT; + } + kfree(id); + return 0; +} + +static int cam_ioctl_register_rw (unsigned int cmd, void * arg) +{ + int ret = -ENOTSUPP; + struct camera_i2c_register reg; + if(copy_from_user(®, arg, sizeof(reg))) + { + return -EFAULT; + } + switch(cmd) + { + case CAMERA_I2C_WRITEW: + ret=i2c_camera_writew(reg.addr, reg.value.w); + break; + case CAMERA_I2C_WRITEB: + ret=i2c_camera_writeb(reg.addr, reg.value.b); + break; + case CAMERA_I2C_READW: + if((ret=i2c_camera_readw(reg.addr, &(reg.value.w)))>=0) + { + if(copy_to_user(arg, ®, sizeof(reg))) + ret = -EFAULT; + } + break; + case CAMERA_I2C_READB: + if((ret=i2c_camera_readb(reg.addr, &(reg.value.b)))>=0) + { + if(copy_to_user(arg, ®, sizeof(reg))) + ret = -EFAULT; + } + break; + default: + break; + } + return ret; +} + +static int cam_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOTSUPP; + switch (cmd) + { + case CAMERA_I2C_WRITEW: + case CAMERA_I2C_WRITEB: + case CAMERA_I2C_READW: + case CAMERA_I2C_READB: + ret = cam_ioctl_register_rw(cmd, (void *)arg); + break; + case CAMERA_I2C_DETECTID: + ret = cam_ioctl_detectid((void *)arg); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static struct file_operations cam_fops = { + ioctl: cam_ioctl, + open: cam_open, + release: cam_close, +}; + +static struct miscdevice cam_misc_device = { + CAM_MINOR, + CAM_NAME, + &cam_fops, +}; + +/* ----------------------------------------------------------------------- */ +static int e680_camera_init_module(void) +{ + int res; + + res = i2c_add_driver(&driver); + if( res < 0 ) + { + printk("error in add i2c driver\n"); + return res; + } + if (misc_register (&cam_misc_device)) + { + printk(KERN_ERR "Couldn't register cam driver\n"); + return -EIO; + } + + return 0; +} + +static void e680_camera_cleanup_module(void) +{ + i2c_del_driver(&driver); + misc_deregister(&cam_misc_device); +} +/*-----------------------------------------------------------*/ +static int ChgBlockAddr(unsigned char block) +{ + static unsigned char old_blk = 0xFF; + int res; + char tmp[2]={BLOCK_SWITCH_CMD, block}; + + if(block == old_blk) + { + return 0; + } + + res = e680_camera_write(tmp, 2); + if(res < 0) + { + dbg_print("error code = %d", res); + return -1; + } + old_blk = block; + + return 0; +} + +int adcm2700_read(unsigned short addr, unsigned short *pvalue) +{ + unsigned char blockaddr = BLOCK(addr); + unsigned char offset = OFFSET_R(addr); + int ret; + + if((ret = ChgBlockAddr(blockaddr)) != 0) + { + dbg_print("Change block address failed. block = 0x%2x", blockaddr); + return -1; + } + if((ret = e680_camera_write(&offset, 1)) < 0) + { + dbg_print("i2c write error code =%d", ret); + return -1; + } + + ret = e680_camera_read((char *)pvalue, 2); + if(ret < 0) + { + dbg_print("i2c read error oce = %d", ret); + return -1; + } + + return *pvalue; +} +int adcm2700_write_byte(unsigned short addr, unsigned char value) +{ + unsigned char blockaddr = BLOCK(addr); + unsigned char offset = OFFSET(addr);; + char tmp[3]={offset, value}; + int ret; + + if((ret = ChgBlockAddr(blockaddr)) != 0) + { + dbg_print("Change block address failed. block = 0x%2x", blockaddr); + return -1; + } + ret = e680_camera_write(tmp, 2); + if(ret < 0) + { + dbg_print("i2c write error code = %d", ret); + return -1; + } + return 0; + +} +int adcm2700_read_byte(unsigned short addr, unsigned char * pvalue) +{ + unsigned char blockaddr = BLOCK(addr); + unsigned char offset = OFFSET_R(addr);; + int ret; + + if((ret = ChgBlockAddr(blockaddr)) != 0) + { + dbg_print("Change block address failed. block = 0x%2x", blockaddr); + return -1; + } + if((ret = e680_camera_write(&offset, 1)) < 0) + { + dbg_print("i2c write error code =%d", ret); + return -1; + } + + ret = e680_camera_read((char *)pvalue, 1); + if(ret < 0) + { + dbg_print("i2c read error oce = %d", ret); + return -1; + } + return 0; + +} +int adcm2700_write(unsigned short addr, unsigned short value) +{ + unsigned char blockaddr = BLOCK(addr); + unsigned char offset = OFFSET(addr);; + char tmp[3]={offset, (char)(value&0xFF), (char)(value>>8)}; + int ret; + + if((ret = ChgBlockAddr(blockaddr)) != 0) + { + dbg_print("Change block address failed. block = 0x%2x", blockaddr); + return -1; + } + ret = e680_camera_write(tmp, 3); + if(ret < 0) + { + dbg_print("i2c write error code = %d", ret); + return -1; + } + return 0; +} + +int i2c_adcm2700_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} +int i2c_adcm2700_init(void) +{ + unsigned short chipid; + unsigned short adcm_chipids[] = {ADCM2700_CHIP_ID, ADCM2700_CHIP_ID_NEW, 0x62}; + int i; + e680_camera_client->addr = 0x53; + + if(adcm2700_read(0, &chipid) < 0) + { + return -1; + } + + dbg_print("CHIP ID IS %x", chipid); + + for(i = 0; i < sizeof(adcm_chipids)/sizeof(adcm_chipids[0]); i++) + { + if(chipid == adcm_chipids[i]) + break; + } + + if(i >= sizeof(adcm_chipids)/sizeof(adcm_chipids[0])) + { + return -1; + } + + i2c_camera_client_type = I2C_CLIENT_ADCM2700; + i2c_camera_chipid = chipid; + + return 0; +} +//======================================================================= +static int mt9v111_addr_select(unsigned char addrSpace) +{ + int ret; + static u8 curSpace = 0; + char buf[3] = {REG_ADDRSELECT, 0, addrSpace}; + + if(curSpace != addrSpace) + { + if((ret = e680_camera_write(buf, 3)) < 0) + { + dbg_print("i2c write error code = %d", ret); + return ret; + } + curSpace = addrSpace; + } + return 0; +} + +int mt9v111_read(unsigned char addrSpace, unsigned short addr) +{ + unsigned short value; + unsigned char reg_addr = (unsigned char)addr; + + if(addr != REG_ADDRSELECT) + { + if(mt9v111_addr_select(addrSpace) != 0) + { + dbg_print("Address space select failed. addrSpace = 0x%2x", addrSpace); + return -1; + } + } + if(e680_camera_write(®_addr, 1) < 0) + { + return -1; + } + + if(e680_camera_read((char *)&value, 2) < 0) + { + return -1; + } + + value = (value << 8 | value >> 8); + return value; +} + +int mt9v111_write(unsigned char addrSpace, unsigned short addr, unsigned short value) +{ + int ret; + char buf[3] = {(char)addr, (char)(value>>8), (char)value}; + + if(addr != REG_ADDRSELECT) + { + if(mt9v111_addr_select(addrSpace) != 0) + { + dbg_print("Address space select failed. addrSpace = 0x%2x", addrSpace); + return -1; + } + } + + if((ret = e680_camera_write(buf, 3)) < 0) + { + dbg_print("write error code = %d", ret); + } + + return ret; +} +int i2c_mt9v111_cleanup(void) +{ + i2c_camera_client_type = I2C_CLIENT_NONE; + return 0; +} +int i2c_mt9v111_init(void) +{ + int chipid; + e680_camera_client->addr = 0x5C; + + if((chipid = mt9v111_read(0x04, 0x36)) < 0) + { + return -1; + } + + if((chipid & 0xFF00) != 0x8200) + { + return -1; + } + + i2c_camera_client_type = I2C_CLIENT_MT9V111; + i2c_camera_chipid = chipid; + + return 0; + +} + +static int i2c_camera_readw(unsigned short addr, unsigned short *pvalue) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { + case I2C_CLIENT_MT9V111: + ret = mt9v111_read((addr>>8), (addr&0xFF)); + if(ret > 0) + { + *pvalue = (u16)ret; + } + break; + case I2C_CLIENT_ADCM2700: + ret = adcm2700_read(addr, pvalue); + break; + default: + break; + } + return ret; +} + +static int i2c_camera_readb(unsigned short addr, unsigned char *pvalue) +{ + int ret = -ENOTSUPP; + unsigned short value; + switch(i2c_camera_client_type) + { + case I2C_CLIENT_ADCM2700: + ret = adcm2700_read(addr, &value); + *pvalue = (value>>8); + break; + default: + break; + } + return ret; +} + +static int i2c_camera_writew(unsigned short addr, unsigned short value) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { + case I2C_CLIENT_MT9V111: + ret = mt9v111_write((addr>>8), (addr&0xFF), value); + break; + case I2C_CLIENT_ADCM2700: + ret = adcm2700_write(addr, value); + break; + default: + break; + } + return ret; +} + +static int i2c_camera_writeb(unsigned short addr, unsigned char value) +{ + int ret = -ENOTSUPP; + switch(i2c_camera_client_type) + { + case I2C_CLIENT_ADCM2700: + ret = adcm2700_write_byte(addr, value); + break; + default: + break; + } + return ret; +} + + +EXPORT_SYMBOL(i2c_adcm2700_init); +EXPORT_SYMBOL(adcm2700_write); +EXPORT_SYMBOL(adcm2700_write_byte); +EXPORT_SYMBOL(adcm2700_read_byte); +EXPORT_SYMBOL(adcm2700_read); +EXPORT_SYMBOL(i2c_adcm2700_cleanup); + +EXPORT_SYMBOL(i2c_mt9v111_init); +EXPORT_SYMBOL(mt9v111_write); +EXPORT_SYMBOL(mt9v111_read); +EXPORT_SYMBOL(i2c_mt9v111_cleanup); + +module_init(e680_camera_init_module); +module_exit(e680_camera_cleanup_module); +MODULE_AUTHOR("Jay Jia"); +MODULE_LICENSE("GPL"); diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/i2c-adcm2700.h linux-2.6.16.5-exz/drivers/i2c/chips/i2c-adcm2700.h --- linux-2.6.16.5/drivers/i2c/chips/i2c-adcm2700.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/i2c-adcm2700.h 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,65 @@ + +/*================================================================================ + + Header Name: i2c-adcm2700.h + +General Description: Camera module adcm2700 I2C interface head file + +================================================================================== + Motorola Confidential Proprietary + Advanced Technology and Software Operations + (c) Copyright Motorola 1999, All Rights Reserved + +Revision History: + Modification Tracking +Author Date Number Description of Changes +---------------- ------------ ---------- ------------------------- +wangfei(w20239) 12/15/2003 LIBdd35749 Created +wangfei(w20239) 02/26/2004 LIBdd81055 New chip id support + +================================================================================== + INCLUDE FILES +==================================================================================*/ + +#ifndef __I2C_ADCM2700_H__ +#define __I2C_ADCM2700_H__ + +#define DEBUG + +/* Calculating the Module Block Number */ +#define BLOCK(a) ((u8)(((a) >> 7) & 0x7F)) /* register's module block address. */ +#define OFFSET(a) ((u8)(((a) << 1) & 0xFF)) /* register's offset to this block. */ +#define OFFSET_R(a) (OFFSET(a)|1) /* register's offset ot this block to read*/ + +#define BLOCK_SWITCH_CMD 0xFE +#define ADCM2700_I2C_ADDR 0x53 +#define I2C_DRIVERID_ADCM2700 I2C_DRIVERID_EXP1 +#define ADCM2700_CHIP_ID 0x0060 +#define ADCM2700_CHIP_ID_NEW 0x0061 +#define REV_ID 0x0 /* Register definitions in ADCM2700's chip. */ + + +struct adcm2700_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 */ +}; + +#ifdef DEBUG +#define dbg_print(fmt, args...) printk(KERN_INFO "I2C-ADCM2700 in fun:%s "fmt"\n", __FUNCTION__, ##args) +#else +#define dbg_print(fmt, args...) ; +#endif + +#endif /* __I2C_ADCM2700_H__ */ + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/i2c-ov9640.c linux-2.6.16.5-exz/drivers/i2c/chips/i2c-ov9640.c --- linux-2.6.16.5/drivers/i2c/chips/i2c-ov9640.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/i2c-ov9640.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/i2c/chips/i2c-ov9640.h linux-2.6.16.5-exz/drivers/i2c/chips/i2c-ov9640.h --- linux-2.6.16.5/drivers/i2c/chips/i2c-ov9640.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/i2c/chips/i2c-ov9640.h 2006-04-16 18:49:29.000000000 +0200 @@ -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 + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/Kconfig linux-2.6.16.5-exz/drivers/media/video/Kconfig --- linux-2.6.16.5/drivers/media/video/Kconfig 2006-04-12 22:27:57.000000000 +0200 +++ linux-2.6.16.5-exz/drivers/media/video/Kconfig 2006-04-16 18:49:29.000000000 +0200 @@ -354,4 +354,35 @@ Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 video decoders. +config PXA_CAMERA + depends on VIDEO_DEV + tristate "Camera Interface for PXA27x" + +choice + prompt "PXA27x Camera Type" + depends on PXA_CAMERA + +config CAMERA_ADCM2700 + select I2C_ADCM2700 + bool "ADCM2700" + +config CAMERA_MT9M111 + select I2C_A780_CAMERA + bool "Mt9m111" + +config CAMERA_OV9640 + select I2C_A780_CAMERA + bool "Omnivision 9640" + +config CAMERA_OV9650 + select I2C_A780_CAMERA + bool "Omnivision 9650" + +config CAMERA_ADCM3800 + select I2C_A780_CAMERA + bool "ADCM3900" + +endchoice + + endmenu diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/Makefile linux-2.6.16.5-exz/drivers/media/video/Makefile --- linux-2.6.16.5/drivers/media/video/Makefile 2006-04-12 22:27:57.000000000 +0200 +++ linux-2.6.16.5-exz/drivers/media/video/Makefile 2006-04-16 18:49:29.000000000 +0200 @@ -19,6 +19,14 @@ tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o +obj-$(CONFIG_PXA_CAMERA) += pxa_camera.o + +obj-$(CONFIG_CAMERA_ADCM2700) += adcm2700.o adcm2700_hw.o +obj-$(CONFIG_CAMERA_OV9640) += ov9640.o ov9640_hw.o +obj-$(CONFIG_CAMERA_OV9650) += ov9650.o ov9650_hw.o +obj-$(CONFIG_CAMERA_MT9M111) += mt9m111.o mt9m111_hw.o +obj-$(CONFIG_CAMERA_ADCM3800) += adcm3800.o adcm3800_hw.o + obj-$(CONFIG_VIDEO_ZR36120) += zoran.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/adcm2700.c linux-2.6.16.5-exz/drivers/media/video/adcm2700.c --- linux-2.6.16.5/drivers/media/video/adcm2700.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/media/video/adcm2700.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,644 @@ + +/*================================================================================ + + Header Name: adcm2700.c + +General Description: Camera module adcm2700 interface source file + +================================================================================== + Motorola Confidential Proprietary + Advanced Technology and Software Operations + (c) Copyright Motorola 1999, All Rights Reserved + +Revision History: + Modification Tracking +Author Date Number Description of Changes +---------------- ------------ ---------- ------------------------- +wangfei(w20239) 12/15/2003 LIBdd35749 Created +wangfei(w20239) 02/05/2004 LIBdd74309 Set frame rate in video mode +wangfei(w20239) 02/26/2004 LIBdd81055 New chip id support + Update algorithm for DMA transfer + Update strategy for memory management + Fix still picture capture failed sometime + New Agilent sensor chip ID support + Make output height in an even multiple of 8 + +================================================================================== + INCLUDE FILES +==================================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "camera.h" +#include "adcm2700.h" +#include "adcm2700_hw.h" + + +/*********************************************************************** + * + * ADCM2700 and MT9v111 common functions + * + ***********************************************************************/ +#define MAX_WIDTH 640 +#define MAX_HEIGHT 480 +#define MIN_WIDTH 64 +#define MIN_HEIGHT 64 +#define WIDTH_DEFT 240 +#define HEIGHT_DEFT 320 +#define FRAMERATE_DEFT 15 +#define MCLK_DEFT 6 /* Default Master clock*/ +#define BUF_SIZE_DEFT ((PAGE_ALIGN(MAX_WIDTH * MAX_HEIGHT) + (PAGE_ALIGN(MAX_WIDTH*MAX_HEIGHT/2)*2))) + +extern int i2c_adcm2700_init(void); +extern int i2c_mt9v111_init(void); + +////////////////////////////////////////////////////////////////////////////////////// +//adcm2700 functions +// +int camera_func_adcm2700_init(p_camera_context_t); +int camera_func_adcm2700_deinit(p_camera_context_t); +int camera_func_adcm2700_docommand(p_camera_context_t cam_ctx, unsigned int cmd, void *param); +int camera_func_adcm2700_set_capture_format(p_camera_context_t); +int camera_func_adcm2700_start_capture(p_camera_context_t, unsigned int frames); +int camera_func_adcm2700_stop_capture(p_camera_context_t); + +int camera_func_adcm2700_pm_management(p_camera_context_t, int); + +////////////////////////////////////////////////////////////////////////////////////// +//mt9v111 functions +// +int camera_func_mt9v111_init(p_camera_context_t); +int camera_func_mt9v111_deinit(p_camera_context_t); +int camera_func_mt9v111_docommand(p_camera_context_t cam_ctx, unsigned int cmd, void *param); +int camera_func_mt9v111_set_capture_format(p_camera_context_t); +int camera_func_mt9v111_start_capture(p_camera_context_t, unsigned int frames); +int camera_func_mt9v111_stop_capture(p_camera_context_t); + +int camera_func_mt9v111_pm_management(p_camera_context_t, int); + +int camera_func_init(p_camera_context_t cam_ctx); + + +camera_function_t e680_camera_func = +{ + init: camera_func_init, +}; + +int camera_func_init(p_camera_context_t cam_ctx) +{ + int ret = 0; + // init context status + cam_ctx->dma_channels[0] = 0xFF; + cam_ctx->dma_channels[1] = 0xFF; + cam_ctx->dma_channels[2] = 0xFF; + + cam_ctx->capture_width = WIDTH_DEFT; + cam_ctx->capture_height = HEIGHT_DEFT; + + cam_ctx->capture_input_format = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR; + cam_ctx->capture_output_format = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR; + + cam_ctx->frame_rate = cam_ctx->fps = FRAMERATE_DEFT; + + cam_ctx->mini_fps = FRAMERATE_DEFT-5; + + cam_ctx->mclk = MCLK_DEFT; + cam_ctx->flicker_freq = 50; + + cam_ctx->buf_size = BUF_SIZE_DEFT; + cam_ctx->dma_descriptors_size = (cam_ctx->buf_size/PAGE_SIZE + 10); + cam_ctx->vc.maxwidth = MAX_WIDTH; + cam_ctx->vc.maxheight = MAX_HEIGHT; + cam_ctx->vc.minwidth = MIN_WIDTH; + cam_ctx->vc.minheight = MIN_HEIGHT; + + camera_gpio_init(); + ci_init(); + + // Configure CI according to hardware + // master parallel with 8 data pins + ci_set_mode(CI_MODE_MP, CI_DATA_WIDTH8); + + // enable pixel clock(sensor will provide pclock) + ci_set_clock(cam_ctx->clk_reg_base, 1, 1, cam_ctx->mclk); + + // data sample on rising and h,vsync active high + ci_set_polarity(0, 0, 0); + + // fifo control + ci_set_fifo(0, CI_FIFO_THL_32, 1, 1); // quality + + // Turn on M_CLK using xx MHz and wait for 150 ms. + ci_enable(1); + + mdelay(150); + + if(i2c_adcm2700_init() == 0) + { + cam_ctx->sensor_type = CAMERA_TYPE_ADCM_2700; + e680_camera_func.deinit = camera_func_adcm2700_deinit; + e680_camera_func.command = camera_func_adcm2700_docommand; + e680_camera_func.set_capture_format = camera_func_adcm2700_set_capture_format; + e680_camera_func.start_capture = camera_func_adcm2700_start_capture; + e680_camera_func.stop_capture = camera_func_adcm2700_stop_capture; + e680_camera_func.pm_management = camera_func_adcm2700_pm_management; + + if((ret = camera_func_adcm2700_init(cam_ctx)) < 0) + { + dbg_print("adcm2700 init error! capture format!"); + return -1; + } + ddbg_print("Agilent ADCM2700 camera module detected!"); + } + else if(i2c_mt9v111_init() == 0) + { + cam_ctx->sensor_type = CAMERA_TYPE_MT9V111; + + e680_camera_func.deinit = camera_func_mt9v111_deinit; + e680_camera_func.command = camera_func_mt9v111_docommand; + e680_camera_func.set_capture_format = camera_func_mt9v111_set_capture_format; + e680_camera_func.start_capture = camera_func_mt9v111_start_capture; + e680_camera_func.stop_capture = camera_func_mt9v111_stop_capture; + e680_camera_func.pm_management = camera_func_mt9v111_pm_management; + if((ret = camera_func_mt9v111_init(cam_ctx)) < 0) + { + dbg_print("mt9v111 init error! capture format!"); + return -1; + } + ddbg_print("Micro MT9V111 camera module detected!"); + } + else + { + dbg_print("no camera sensor detected!!!\n"); + return -1; + } + + return 0; +} + +/*********************************************************************** + * + * ADCM2700 Functions + * + ***********************************************************************/ +int camera_func_adcm2700_init( p_camera_context_t camera_context ) +{ + u16 sensor_rev, cm_rev; + int i; + adcm2700_power_on(camera_context->mclk); + //read out version + //adcm2700_version_revision(&cm_rev, &sensor_rev); + return 0; +} + +int camera_func_adcm2700_deinit( p_camera_context_t camera_context ) +{ + /* power off the external module */ + camera_func_adcm2700_stop_capture(camera_context); + /* disable CI */ + ci_disable(1); + + i2c_adcm2700_cleanup(); + camera_gpio_deinit(); + return 0; +} + +int camera_func_adcm2700_set_capture_format(p_camera_context_t camera_context) +{ + u16 adcm_format; + adcm_window_size size; + + //set sensor format + switch(camera_context->capture_input_format) + { + case CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR: + case CAMERA_IMAGE_FORMAT_YCBCR422_PACKED: + adcm_format = O_FORMAT_422_B_YCbYCr; + break; + case CAMERA_IMAGE_FORMAT_RGB565: + adcm_format = O_FORMAT_565_RGB; + break; + case CAMERA_IMAGE_FORMAT_RGB888_PACKED: + case CAMERA_IMAGE_FORMAT_RGB888_PLANAR: + adcm_format = O_FORMAT_888RGB; + break; + default: + adcm_format = O_FORMAT_422_B_YCbYCr; + break; + } + size.width = camera_context->capture_width; + size.height = camera_context->capture_height; + //adcm2700_output_size(&size); + //adcm2700_viewfinder_cfg_output(adcm_format); + return 0; +} + +int camera_func_adcm2700_start_capture(p_camera_context_t cam_ctx, unsigned int frames) +{ + int cisr; + int wait_count; + int error_count = 0; + static int error_times = 0; + +start: + + // frames=0 means video mode capture + if(frames == 0) + { + // ddbg_print("video capture!"); + wait_count = 1; + adcm2700_restore_property(cam_ctx, frames); + adcm2700_viewfinder_on(); + ci_disable(1); + ci_enable(1); + + } + else + { + // ddbg_print("still capture"); + + wait_count = 1; + adcm2700_restore_property(cam_ctx, frames); + adcm2700_snapshot_trigger(); + ci_disable(1); + ci_enable(1); + + } + + dbg_print("wait for EOF %d time", wait_count); + unsigned int start_time = 0xFFFFF * 20 * wait_count; + unsigned int flags; + + // local_irq_save(flags); + CISR |= CI_CISR_EOF; + CISR |= CI_CISR_SOF; + cisr=CISR; + while(wait_count) + { + if(cisr & CI_CISR_EOF) + { + //wait_count -- ; + CISR |= CI_CISR_EOF; + } + + if(cisr & CI_CISR_SOF) + { + wait_count -- ; + CISR |= CI_CISR_SOF; + } + + cisr=CISR; + if(!(--start_time)) + { + goto wait_EOF_error; + } + + } + ci_disable(1); + ci_enable(1); + ci_reset_fifo(); + ci_clear_int_status(0xFFFFFFFF); + mdelay(1); + start_dma_transfer(cam_ctx, cam_ctx->block_header); +// local_irq_restore(flags); + dbg_print("wait ok..%d", start_time); + return 0; + +wait_EOF_error: + // local_irq_restore(flags); + error_times++; + if(error_count++ >= 3) + { + return -1; + } + dbg_print("wait EOF error! error_count = %d", error_count); + dbg_print("wait EOF error! error_times = %d", error_times); + dbg_print("Reset CIF and camera..."); + ci_disable(1); + // master parallel with 8 data pins + ci_set_mode(CI_MODE_MP, CI_DATA_WIDTH8); + // enable pixel clock(sensor will provide pclock) + ci_set_clock(cam_ctx->clk_reg_base, 1, 1, cam_ctx->mclk); + // data sample on rising and h,vsync active high + ci_set_polarity(0, 0, 0); + // fifo control + ci_set_fifo(0, CI_FIFO_THL_32, 1, 1); // quality + // Turn on M_CLK using xx MHz and wait for 150 ms. + ci_enable(1); + mdelay(10); + adcm2700_power_on(cam_ctx->mclk); + goto start; +} + +int camera_func_adcm2700_stop_capture(p_camera_context_t cam_ctx) +{ + adcm2700_viewfinder_off(); + stop_dma_transfer(cam_ctx); + return 0; +} + +int camera_func_adcm2700_pm_management(p_camera_context_t cam_ctx, int suspend) +{ + static int resume_dma = 0; + if(suspend) + { + if(cam_ctx != NULL ) + { + if(cam_ctx->dma_started) + { + ddbg_print("camera running, suspended"); + stop_dma_transfer(cam_ctx); + resume_dma = 1; + } + } + + disable_irq(IRQ_CAMERA); + pxa_set_cken(CKEN24_CAMERA, 0); + } + else + { + pxa_set_cken(CKEN24_CAMERA, 1); + enable_irq(IRQ_CAMERA); + + if(cam_ctx != NULL) + { + ddbg_print("camera running, resumed"); + camera_init(cam_ctx); + if(resume_dma == 1) + { + camera_start_video_capture(cam_ctx, 0); + resume_dma = 0; + } + } + } + return 0; +} + +/*set picture brightness*/ +static int pxa_cam_WCAM_VIDIOCSBRIGHT(p_camera_context_t cam_ctx, void * param) +{ + ddbg_print("WCAM_VIDIOCSBRIGHT"); + int ret = 0; + if(cam_ctx->capture_bright != (int)param) + { + cam_ctx->capture_bright = (int)param; + ret = adcm2700_set_bright(cam_ctx->capture_bright); + } + return ret; +} + +/*set picture style*/ +static int pxa_cam_WCAM_VIDIOCSSTYLE(p_camera_context_t cam_ctx, void * param) +{ + ddbg_print("WCAM_VIDIOCSSTYLE"); + int ret = 0; + if(cam_ctx->capture_style != (V4l_PIC_STYLE)param) + { + cam_ctx->capture_style = (V4l_PIC_STYLE)param; + if(cam_ctx->dma_started == 1) + { + camera_func_adcm2700_stop_capture(cam_ctx); + ret = camera_func_adcm2700_start_capture(cam_ctx, 0); + } + + } + + return ret; +} + + +/*set picture light*/ +static int pxa_cam_WCAM_VIDIOCSLIGHT(p_camera_context_t cam_ctx, void * param) +{ + + dbg_print("WCAM_VIDIOCSLIGHT"); + int ret = 0; + if(cam_ctx->capture_light != (V4l_PIC_WB)param) + { + cam_ctx->capture_light = (V4l_PIC_WB)param; + if(cam_ctx->dma_started == 1) + { + camera_func_adcm2700_stop_capture(cam_ctx); + ret = camera_func_adcm2700_start_capture(cam_ctx, 0); + } + + } + return ret; +} + + +//set output size +static int pxa_cam_WCAM_VIDIOCSOSIZE(p_camera_context_t cam_ctx, void * param) +{ + + //ddbg_print("WCAM_VIDIOCSOSIZE"); + + adcm_window_size size; + CI_MP_TIMING timing; + int ret = 0; + + if(copy_from_user(&size, param, sizeof(adcm_window_size))) + { + return -EFAULT; + } + if(cam_ctx->dma_started == 1) + { + return -EFAULT; + } + //make it in an even of multiple of 8 + size.width = (size.width +7)/8 * 8; + size.height = (size.height+7)/8 * 8; + dbg_print("w=%d h=%d", size.width, size.height); + if(cam_ctx->capture_width != size.width || cam_ctx->capture_height != size.height) + { + cam_ctx->capture_width = size.width; + cam_ctx->capture_height = size.height; + ret = adcm2700_output_size(&size); + + timing.BFW = timing.BLW = 0; + + ci_configure_mp(cam_ctx->capture_width-1, cam_ctx->capture_height-1, &timing); + camera_ring_buf_init(cam_ctx); + } + + return ret; +} + +/*Set sensor size*/ +static int pxa_cam_WCAM_VIDIOCSSSIZE(p_camera_context_t cam_ctx, void * param) +{ + //ddbg_print("WCAM_VIDIOCSSSIZE"); + adcm_window_size size; + int ret = 0; + + if(copy_from_user(&size, param, sizeof(adcm_window_size))) + { + return -EFAULT; + } + if(cam_ctx->dma_started == 1) + { + return -EFAULT; + } + //make it in an even of multiple of 8 + size.width = (size.width +7)/8 * 8; + size.height = (size.height+7)/8 * 8; + + if(cam_ctx->sensor_width != size.width || cam_ctx->sensor_height != size.height) + { + cam_ctx->sensor_width = size.width; + cam_ctx->sensor_height = size.height; + ret = adcm2700_input_size(&size); + dbg_print("w = %d h = %d", size.width, size.height); + } + return ret; +} + +static int pxa_cam_WCAM_VIDIOCSFPS(p_camera_context_t cam_ctx, void * param) +{ + //ddbg_print("WCAM_VIDIOCSFPS"); + + struct {int fps, minfps;} cam_fps; + int ret = 0; + + if(copy_from_user(&cam_fps, param, sizeof(int) * 2)) + { + return -EFAULT; + } + if(cam_fps.fps < 12) + { + cam_fps.fps = 12; + } + + if(cam_ctx->fps != cam_fps.fps || cam_ctx->mini_fps != cam_fps.minfps) + { + cam_ctx->fps = cam_fps.fps; + cam_ctx->mini_fps = cam_fps.minfps; + if(cam_ctx->dma_started == 1) + { + camera_func_adcm2700_stop_capture(cam_ctx); + ret = camera_func_adcm2700_start_capture(cam_ctx, 0); + } + } + return ret; +} + +static int pxa_camera_WCAM_VIDIOCGCAMREG(p_camera_context_t cam_ctx, void * param) +{ + int reg_value, offset; + //ddbg_print("WCAM_VIDIOCGCAMREG"); + if(copy_from_user(&offset, param, sizeof(int))) + { + return -EFAULT; + } + reg_value = (int)adcm2700_reg_read((u16)offset); + + if(copy_to_user(param, ®_value, sizeof(int))) + { + return -EFAULT; + } + + return 0; +} +/*set flicker frequency*/ +static int pxa_cam_WCAM_VIDIOCSFLICKER(p_camera_context_t cam_ctx, void * param) +{ + dbg_print("WCAM_VIDIOCSFLICKER"); + cam_ctx->flicker_freq = (int)param; + + return adcm2700_set_flicker(cam_ctx->flicker_freq); +} + + +static int pxa_camera_WCAM_VIDIOCSCAMREG(p_camera_context_t cam_ctx, void * param) +{ + struct reg_set_s{int val1, val2} reg_s; + //ddbg_print("WCAM_VIDIOCSCAMREG"); + + if(copy_from_user(®_s, param, sizeof(int) * 2)) + { + return -EFAULT; + } + adcm2700_write((u16)reg_s.val1, (u16)reg_s.val2); + return 0; +} + +int camera_func_adcm2700_docommand(p_camera_context_t cam_ctx, unsigned int cmd, void *param) +{ + switch(cmd) + { + /*read adcm2700 registers*/ + case WCAM_VIDIOCGCAMREG: + return pxa_camera_WCAM_VIDIOCGCAMREG(cam_ctx, param); + + /*write adcm2700 registers*/ + case WCAM_VIDIOCSCAMREG: + return pxa_camera_WCAM_VIDIOCSCAMREG(cam_ctx, param); + + /*set sensor size */ + case WCAM_VIDIOCSSSIZE: + return pxa_cam_WCAM_VIDIOCSSSIZE(cam_ctx, param); + + /*set output size*/ + case WCAM_VIDIOCSOSIZE: + return pxa_cam_WCAM_VIDIOCSOSIZE(cam_ctx, param); + + + /*set video mode fps*/ + case WCAM_VIDIOCSFPS: + return pxa_cam_WCAM_VIDIOCSFPS(cam_ctx, param); + + /*set picture style*/ + case WCAM_VIDIOCSSTYLE: + return pxa_cam_WCAM_VIDIOCSSTYLE(cam_ctx, param); + + /*set picture light*/ + case WCAM_VIDIOCSLIGHT: + return pxa_cam_WCAM_VIDIOCSLIGHT(cam_ctx, param); + + /*set picture brightness*/ + case WCAM_VIDIOCSBRIGHT: + return pxa_cam_WCAM_VIDIOCSBRIGHT(cam_ctx, param); + + /*set flicker frequency*/ + case WCAM_VIDIOCSFLICKER: + return pxa_cam_WCAM_VIDIOCSFLICKER(cam_ctx, param); + + default: + { + dbg_print("Error cmd=0x%x", cmd); + return -1; + } + } + return 0; + + } + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/adcm2700.h linux-2.6.16.5-exz/drivers/media/video/adcm2700.h --- linux-2.6.16.5/drivers/media/video/adcm2700.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/media/video/adcm2700.h 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,42 @@ + +/*================================================================================ + + Header Name: adcm2700.h + +General Description: Camera module adcm2700 interface head file + +================================================================================== + Motorola Confidential Proprietary + Advanced Technology and Software Operations + (c) Copyright Motorola 1999, All Rights Reserved + +Revision History: + Modification Tracking +Author Date Number Description of Changes +---------------- ------------ ---------- ------------------------- +wangfei(w20239) 12/15/2003 LIBdd35749 Created + +================================================================================== + INCLUDE FILES +==================================================================================*/ + +#ifndef _ADCM2700_H_ +#define _ADCM2700_H_ + +#include "camera.h" + +////////////////////////////////////////////////////////////////////////////////////// +// +// Prototypes +// +////////////////////////////////////////////////////////////////////////////////////// + +int camera_func_adcm2700_init(p_camera_context_t); +int camera_func_adcm2700_deinit(p_camera_context_t); +int camera_func_adcm2700_set_capture_format(p_camera_context_t); +int camera_func_adcm2700_start_capture(p_camera_context_t, unsigned int frames); +int camera_func_adcm2700_stop_capture(p_camera_context_t); + +#endif /* _ADCM2700_H_ */ + + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/adcm2700_hw.c linux-2.6.16.5-exz/drivers/media/video/adcm2700_hw.c --- linux-2.6.16.5/drivers/media/video/adcm2700_hw.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/media/video/adcm2700_hw.c 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,936 @@ +/*================================================================================ + + Header Name: adcm2700_hw.c + +General Description: Camera module adcm2700 interface source file + +================================================================================== + Motorola Confidential Proprietary + Advanced Technology and Software Operations + (c) Copyright Motorola 1999, All Rights Reserved + +Revision History: + Modification Tracking +Author Date Number Description of Changes +---------------- ------------ ---------- ------------------------- +wangfei(w20239) 12/15/2003 LIBdd35749 Created + +wangfei(w20239) 02/05/2004 LIBdd74309 Set frame rate in video mode + +wangfei(w20239) 02/26/2004 LIBdd81055 New chip id support + Update algorithm for DMA transfer + Update strategy for memory management + Fix still picture capture failed sometime + New Agilent sensor chip ID support + Make output height in an even multiple of 8 + +wangfei(w20239) 03/08/2004 LIBdd84578 Photo effects setting + +================================================================================== + INCLUDE FILES +==================================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define MAX_FPS 20 + +#include "adcm2700_hw.h" +#include "camera.h" + + +extern int adcm2700_read(u16 addr, u16 *pvalue); +extern int adcm2700_write(u16 addr, u16 value); +extern int adcm2700_read_byte(unsigned short addr, unsigned char * value); + + + +#define wait_sreg_update() { int retry = adcm2700__TIMEOUT<<2; \ + dbg_print("wait for sensor update simple registers"); \ + adcm2700_write(SREG_CONTROL, 0x05); \ + while(--retry) \ + { \ + u16 v = adcm2700_reg_read(SREG_CONTROL); \ + mdelay(1); \ + if(v == 0xFF) break; \ + if(!(v & 0x04)) break; \ + } \ + dbg_print("retry = %d", retry); \ + } + +void adcm2700_wait(u32 ms) +{ + if(ms > 10) + { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ms/10); + } +} + +/**************************************************************************** +* * +* I2C Management * +* * +*****************************************************************************/ +u16 adcm2700_reg_read(u16 reg_addr) +{ + u16 value; + int ret = adcm2700_read(reg_addr, &value); + if(ret < 0) + { + return 0xFF; + } + return value; +} + +void adcm2700_reg_write(u16 reg_addr, u16 reg_value) +{ + + /*experts registers or SREG_CONTROL write directly*/ + if(reg_addr > 0x26 || reg_addr == SREG_CONTROL) + { + adcm2700_write(reg_addr, reg_value); + return; + } + + /* write sample control register step: + 1 Stop the camera ¨C write 0x0000 to the CONTROL register. + 2 Change the relevant register. + 3 Set the CONFIG bit in the CONTROL register, write 0x0004. + 4 Wait for the CONFIG bit in CONTROL to clear. */ + adcm2700_write(SREG_CONTROL, 0); + adcm2700_write(reg_addr, reg_value); + wait_sreg_update(); + adcm2700_write(SREG_CONTROL, 0x01); + +} + +/*restore capture property*/ +int adcm2700_restore_property(p_camera_context_t cam_ctx, int frames) +{ + u16 awb_gain_grn1, awb_gain_grn2, awb_gain_red, awb_gain_blue; + u8 ae_gain1, ae_gain2, ae_gain3, ae_gain4; + u8 r813, r814, r815, r80e; + u16 r80, r84, rp; + u16 clk_div, sen_clk_div; + u32 texp; + + dbg_print("sensor width %d", cam_ctx->sensor_width); + dbg_print("sensor height %d", cam_ctx->sensor_height); + dbg_print("capture_width %d", cam_ctx->capture_width); + dbg_print("capture_height %d", cam_ctx->capture_height); + ddbg_print("fps %d mini fps %d", cam_ctx->fps, cam_ctx->mini_fps); + ddbg_print("light %d", cam_ctx->capture_light); + ddbg_print("capture_bright %d", cam_ctx->capture_bright); + ddbg_print("capture_style %d", cam_ctx->capture_style); + + + awb_gain_grn1 = adcm2700_reg_read(EREG_APS_COEF_GRN1); + awb_gain_grn2 = adcm2700_reg_read(EREG_APS_COEF_GRN2); + awb_gain_red = adcm2700_reg_read(EREG_APS_COEF_RED); + awb_gain_blue = adcm2700_reg_read(EREG_APS_COEF_BLUE); + + adcm2700_read_byte(0x080F, &ae_gain1); + adcm2700_read_byte(0x0810, &ae_gain2); + adcm2700_read_byte(0x0811, &ae_gain3); + adcm2700_read_byte(0x0812, &ae_gain4); + + adcm2700_read_byte(0x813, &r813); + adcm2700_read_byte(0x814, &r814); + adcm2700_read_byte(0x815, &r815); + adcm2700_read_byte(0x80e, &r80e); + dbg_print("r813= %x, r814=%x r815 = %x", r813, r814, r815); + + adcm2700_read(0x80, &r80); + adcm2700_read(0x84, &r84); + adcm2700_read(0x114, &rp); + + clk_div = r80+1; + sen_clk_div = (r84 == 0) ? 1 : (r84<<1); + texp = ((((u32)r814)<<8) + r813) * rp + 4 * r815; + texp *= clk_div * sen_clk_div * r80e; + dbg_print("before rp = 0x%x r80 = 0x%x r84 = 0x%x", rp, r80, r84); + dbg_print("before clk_div = 0x%x sen_clk_div = 0x%x r80e = 0x%x", clk_div, sen_clk_div, r80e); + //update simple registers + adcm2700_write(SREG_CONTROL, 0); + //sensor width and sensor height + adcm2700_write(SREG_SIZE, 0x707); + adcm2700_write(SREG_SENSOR_WID_V, (u16)(cam_ctx->sensor_width)); + adcm2700_write(SREG_SENSOR_HGT_V, (u16)(cam_ctx->sensor_height)); + + //output width and output height + adcm2700_write(SREG_OUTPUT_WID_V, (u16)(cam_ctx->capture_width)); + adcm2700_write(SREG_OUTPUT_HGT_V, (u16)(cam_ctx->capture_height)); + + //default fps + adcm2700_write(SREG_FRAME_RATE, cam_ctx->fps*10); + wait_sreg_update(); + adcm2700_set_light(cam_ctx->capture_light); + adcm2700_write(EREG_AE_ETIME_MAX, 100000/(cam_ctx->mini_fps)); + + //still mode and not night mode + if(frames == 1) + { + adcm2700_write(EREG_AF_CTRL1, 0x10); + adcm2700_read_byte(0x80e, &r80e); + adcm2700_read(0x80, &r80); + adcm2700_read(0x84, &r84); + adcm2700_read(0x114, &rp); + clk_div = r80+1; + sen_clk_div = (r84 == 0) ? 1 : (r84<<1); + texp /= (clk_div * sen_clk_div * r80e); + u16 ttexp = (texp/rp); + r815 = (u8)((texp - ttexp * rp)>>2); + r813 = (u8)(ttexp & 0xFF); + r814 = (u8)(ttexp >> 8); + dbg_print("after r813= %x, r814=%x r815 = %x", r813, r814, r815); + adcm2700_write_byte(0x813, r813); + adcm2700_write_byte(0x814, r814); + adcm2700_write_byte(0x815, r815); + dbg_print("after rp = 0x%x r80 = 0x%x r84 = 0x%x", rp, r80, r84); + dbg_print("after clk_div = 0x%x sen_clk_div = 0x%x r80e = 0x%x", clk_div, sen_clk_div, r80e); + + + adcm2700_write_byte(0x080F, ae_gain1); + adcm2700_write_byte(0x0810, ae_gain2); + adcm2700_write_byte(0x0811, ae_gain3); + adcm2700_write_byte(0x0812, ae_gain4); + + adcm2700_write(EREG_APS_COEF_GRN1, awb_gain_grn1); + adcm2700_write(EREG_APS_COEF_GRN2, awb_gain_grn2); + adcm2700_write(EREG_APS_COEF_RED, awb_gain_red); + adcm2700_write(EREG_APS_COEF_BLUE, awb_gain_blue); + + } + else + { + + } + + + //expert registers + adcm2700_set_bright(cam_ctx->capture_bright); + + if(cam_ctx->capture_style == V4l_STYLE_NORMAL && frames == 1) + { + adcm2700_set_gamma(3); + } + else + { + adcm2700_set_style(cam_ctx->capture_style); + } + + adcm2700_write(SREG_CONTROL, 0x01); + return ADCM_ERR_NONE; + +} + + +/////////////////////////////////////////////////////////////// +// +// Programming Guide Chapter 1: Basic Programming +// +/////////////////////////////////////////////////////////////// + +void adcm2700_color_init(void); + +int adcm2700_power_on( u8 clk ) +{ + /*Follow these steps to correctly power on the ADCM-2700: + 1 Turn on VCC voltage (2.8 volts) and wait 20 milliseconds. + 2 Turn on MCLK (13 MHz is the default value) and wait 150 milliseconds. + 3 Read register 0x0004; if the return value equals 0x0001, power-up is complete. */ + int retry = adcm2700__TIMEOUT<<2; + while(--retry) + { + if(adcm2700_reg_read(SREG_STATUS) == 0x0001) + { + dbg_print("adcm2700 Power-up complete!!"); + break; + } + adcm2700_wait(2); + } + + + + /* Program the mafster clock */ + adcm2700_master_clock(clk); + + /* Configure anti-vignetting */ + adcm2700_color_init(); + + return ADCM_ERR_NONE; +} + + +int adcm2700_power_off() +{ + /*stop camera*/ + adcm2700_write(SREG_CONTROL, 0); + return ADCM_ERR_NONE; +} + + +///////////////////////////////////////////////////////////////////////////////////// +// +// Programming Guide Chapter 2: Configuration Methods +// +///////////////////////////////////////////////////////////////////////////////////// + + +int adcm2700_version_revision(u16 * cm_revision, u16 *sensor_revision) +{ + //Camera module version is 0x060 + *cm_revision = adcm2700_reg_read(SREG_ID); + dbg_print("adcm2700 SREG_ID is 0x%x", *cm_revision); + + //Image sensor version is 0x60 + *sensor_revision = adcm2700_reg_read(EREG_IDENT); + dbg_print("adcm2700 EREG_IDENT is 0x%x", *sensor_revision); + return ADCM_ERR_NONE; +} + +int adcm2700_viewfinder_on() +{ + //adcm2700_write(SREG_CONTROL, 0x01); + ddbg_print("camera video mode start!"); + return ADCM_ERR_NONE; +} + + + +int adcm2700_viewfinder_off() +{ + //adcm2700_write(SREG_CONTROL, 0); + ddbg_print("camera video mode stop!"); + // adcm2700_store_af_regs(); + return ADCM_ERR_NONE; +} + + +int adcm2700_snapshot_trigger() +{ + /* + u16 status = adcm2700_reg_read(EREG_AF_STATUS); + int retry = adcm2700__TIMEOUT<<1; + while(--retry) + { + if(status & 0x08) + break; + status = adcm2700_reg_read(EREG_AF_STATUS); + } + dbg_print("retry = %d", retry); + + */ + return ADCM_ERR_NONE; +} + +int adcm2700_master_clock(u8 clk) +{ + + //0x2712 2X + //0x1D09 3X //default + //0x2709 4X + //0xFC53 + u16 div = 0x1D09; + + clk *= (((div>>8) + 1)/((div&0xFF) + 1)); + + + //adcm2700_reg_write(EREG_SEN_CLK_DIV, 1); + + /*enable pll*/ + adcm2700_write(SREG_CONTROL, 0); + + adcm2700_write(SREG_CLK_FREQ, (u16)clk * 1000); + adcm2700_write(EREG_PLL_DIV_L, div); + adcm2700_write(EREG_PLL_DIV_S, div); + adcm2700_write(EREG_PLL_CTRL, 0x0025); //0x002D + + wait_sreg_update(); + //adcm2700_reg_write(EREG_I_CLK_DIV, 0); + adcm2700_write(SREG_CONTROL, 1); + + return ADCM_ERR_NONE; +} + + +int adcm2700_input_size(adcm_window_size * window) +{ + + /* write sample control register step: + 1 Stop the camera ¨C write 0x0000 to the CONTROL register. + 2 Change the relevant register. + 3 Set the CONFIG bit in the CONTROL register, write 0x0004. + 4 Wait for the CONFIG bit in CONTROL to clear. */ + /* + adcm2700_write(SREG_CONTROL, 0); + + adcm2700_write(SREG_SIZE, 0x707); + adcm2700_write(SREG_SENSOR_WID_V, window->width); + adcm2700_write(SREG_SENSOR_HGT_V, window->height); + + //adcm2700_write(SREG_SENSOR_WID_S, window->width); + //adcm2700_write(SREG_SENSOR_HGT_S, window->height); + + wait_sreg_update(); + */ + return ADCM_ERR_NONE; + } +int adcm2700_output_size(adcm_window_size * window) +{ + + /* write sample control register step: + 1 Stop the camera ¨C write 0x0000 to the CONTROL register. + 2 Change the relevant register. + 3 Set the CONFIG bit in the CONTROL register, write 0x0004. + 4 Wait for the CONFIG bit in CONTROL to clear. */ +/* + adcm2700_write(SREG_CONTROL, 0); + + adcm2700_write(SREG_SIZE, 0x707); + adcm2700_write(SREG_OUTPUT_WID_V, window->width); + adcm2700_write(SREG_OUTPUT_HGT_V, window->height); +// adcm2700_write(SREG_OUTPUT_WID_S, window->width); +// adcm2700_write(SREG_OUTPUT_HGT_S, window->height); + + wait_sreg_update(); + */ + return ADCM_ERR_NONE; +} + + +int adcm2700_set_fps(u16 fps, u16 minfps) +{ + if(fps > MAX_FPS || minfps > fps) + { + return ADCM_ERR_PARAMETER; + } + + adcm2700_reg_write(SREG_FRAME_RATE, fps*10); + adcm2700_reg_write(EREG_AE_ETIME_MAX, 100000/(minfps)); + + return ADCM_ERR_NONE; +} + + +int adcm2700_stillframe_cfg_output(u16 format) +{ + + u16 oldcfg = adcm2700_reg_read(SREG_OUTPUT_FORMAT); + + oldcfg = (oldcfg & 0xF0FF) | ((format & 0x000F) << 8); + adcm2700_reg_write( SREG_OUTPUT_FORMAT, oldcfg); + + return ADCM_ERR_NONE; +} + +int adcm2700_viewfinder_cfg_output(u16 format) +{ + + u16 oldcfg = adcm2700_reg_read( SREG_OUTPUT_FORMAT); + + oldcfg = (oldcfg & 0xFFF0) | (format & 0x000F); + adcm2700_reg_write( SREG_OUTPUT_FORMAT, oldcfg ); + return ADCM_ERR_NONE; +} + + + +void adcm2700_dump_register(u16 startRegAddr, u16 endRegAddr, u16* buffer) +{ + u16 addr; + + for(addr = startRegAddr; addr <= endRegAddr; addr+=2) + { + adcm2700_read(addr, buffer++); + } +} + +int adcm2700_set_gamma(int table) +{ + const u16 regs[] = + { + 0x1400, 0x1402, 0x1404, 0x1406, 0x1408, 0x140a, 0x140c, 0x140e, 0x1410, 0x1412, 0x1414, + 0x1416, 0x1418, 0x141a, 0x141c, 0x141e, 0x1420, 0x1422, 0x1424, 0x1426, 0x1428, 0x142a, + 0x142c, 0x142e, 0x1430, 0x1432, 0x1434, 0x1436, 0x1438, 0x143a, 0x143c, 0x143e, 0x1440 + }; + + + const u16 regsv[] = + { + EREG_TM_COEF_00_V, EREG_TM_COEF_01_V, EREG_TM_COEF_02_V, EREG_TM_COEF_03_V, + EREG_TM_COEF_04_V, EREG_TM_COEF_05_V, EREG_TM_COEF_06_V, EREG_TM_COEF_07_V, + EREG_TM_COEF_08_V, EREG_TM_COEF_09_V, EREG_TM_COEF_10_V, EREG_TM_COEF_11_V, + EREG_TM_COEF_12_V, EREG_TM_COEF_13_V, EREG_TM_COEF_14_V, EREG_TM_COEF_15_V, + EREG_TM_COEF_16_V, EREG_TM_COEF_17_V, EREG_TM_COEF_18_V, EREG_TM_COEF_19_V, + EREG_TM_COEF_20_V, EREG_TM_COEF_21_V, EREG_TM_COEF_22_V, EREG_TM_COEF_23_V, + EREG_TM_COEF_24_V, EREG_TM_COEF_25_V, EREG_TM_COEF_26_V, EREG_TM_COEF_27_V, + EREG_TM_COEF_28_V, EREG_TM_COEF_29_V, EREG_TM_COEF_30_V, EREG_TM_COEF_31_V, + EREG_TM_COEF_32_V + }; + const u16 regss[] = + { + EREG_TM_COEF_00_S, EREG_TM_COEF_01_S, EREG_TM_COEF_02_S, EREG_TM_COEF_03_S, + EREG_TM_COEF_04_S, EREG_TM_COEF_05_S, EREG_TM_COEF_06_S, EREG_TM_COEF_07_S, + EREG_TM_COEF_08_S, EREG_TM_COEF_09_S, EREG_TM_COEF_10_S, EREG_TM_COEF_11_S, + EREG_TM_COEF_12_S, EREG_TM_COEF_13_S, EREG_TM_COEF_14_S, EREG_TM_COEF_15_S, + EREG_TM_COEF_16_S, EREG_TM_COEF_17_S, EREG_TM_COEF_18_S, EREG_TM_COEF_19_S, + EREG_TM_COEF_20_S, EREG_TM_COEF_21_S, EREG_TM_COEF_22_S, EREG_TM_COEF_23_S, + EREG_TM_COEF_24_S, EREG_TM_COEF_25_S, EREG_TM_COEF_26_S, EREG_TM_COEF_27_S, + EREG_TM_COEF_28_S, EREG_TM_COEF_29_S, EREG_TM_COEF_30_S, EREG_TM_COEF_31_S, + EREG_TM_COEF_32_S + }; + + const u16 value[][33] = + { + //default + 0x0000, 0x003c, 0x0052, 0x0063, 0x0070, 0x007c, 0x0087, 0x0091, 0x0094, 0x00ab, 0x00b9, + 0x00c7, 0x00d3, 0x00ea, 0x00fe, 0x0111, 0x0122, 0x0141, 0x015d, 0x0176, 0x018d, 0x01b8, + 0x01de, 0x0201, 0x0221, 0x025b, 0x028f, 0x02bf, 0x02eb, 0x033b, 0x0382, 0x03c3, 0x0400, + /* + 0x0000, 0x004C, 0x0065, 0x0078, 0x0087, 0x0094, 0x00A0, 0x00ab, 0x00b5, 0x00c6, 0x00d6, + 0x00e4, 0x00f1, 0x0109, 0x011E, 0x0131, 0x0142, 0x0161, 0x017D, 0x0197, 0x01AE, 0x01d8, + 0x01fd, 0x021F, 0x023E, 0x0276, 0x02a8, 0x02d5, 0x02ff, 0x0349, 0x038C, 0x03C8, 0x0400, + */ + + + //solarize + 0x0400, 0x03e9, 0x03a9, 0x0344, 0x02c3, 0x0232, 0x019c, 0x010e, 0x0095, 0x003c, 0x0009, + 0x0002, 0x0026, 0x0074, 0x00e3, 0x016b, 0x01ff, 0x0294, 0x031c, 0x038b, 0x03d9, 0x03fd, + 0x03f6, 0x03c3, 0x036a, 0x02f1, 0x0263, 0x01cd, 0x013c, 0x00bb, 0x0056, 0x0016, 0x0000, + + //neg.art + 0x03ff, 0x03e8, 0x03cd, 0x03b9, 0x03a9, 0x039b, 0x038e, 0x0383, 0x0379, 0x0366, 0x0356, + 0x0347, 0x0339, 0x0320, 0x030a, 0x02f6, 0x02e4, 0x02c2, 0x02a5, 0x028a, 0x0272, 0x0245, + 0x021e, 0x01fa, 0x01da, 0x019e, 0x016a, 0x013a, 0x010e, 0x00c0, 0x007a, 0x003a, 0x0000, + + + /* + //2.6 + 0x0000, 0x005C, 0x0079, 0x008d, 0x009e, 0x00ac, 0x00b9, 0x00c4, 0x00ce, 0x00e1, 0x00f1, + 0x0100, 0x010e, 0x0126, 0x013b, 0x014e, 0x0160, 0x0180, 0x019c, 0x01b5, 0x01cc, 0x01f5, + 0x0219, 0x023a, 0x0258, 0x028e, 0x02be, 0x02e9, 0x0310, 0x0356, 0x0394, 0x03cc, 0x0400, + + //2.4 + 0x0000, 0x004C, 0x0065, 0x0078, 0x0087, 0x0094, 0x00A0, 0x00ab, 0x00b5, 0x00c6, 0x00d6, + 0x00e4, 0x00f1, 0x0109, 0x011E, 0x0131, 0x0142, 0x0161, 0x017D, 0x0197, 0x01AE, 0x01d8, + 0x01fd, 0x021F, 0x023E, 0x0276, 0x02a8, 0x02d5, 0x02ff, 0x0349, 0x038C, 0x03C8, 0x0400, + + //2.3 + 0x0000, 0x0043, 0x005b, 0x006d, 0x007c, 0x0088, 0x0094, 0x009e, 0x00a7, 0x00b8, 0x00c8, + 0x00d6, 0x00e2, 0x00fa, 0x010e, 0x0121, 0x0132, 0x0151, 0x016d, 0x0187, 0x019e, 0x01c8, + 0x01ee, 0x0210, 0x0230, 0x0269, 0x029c, 0x02ca, 0x02f5, 0x0342, 0x0387, 0x03c6, 0x0400, + */ + //2.2 + 0x0000, 0x003c, 0x0052, 0x0063, 0x0070, 0x007c, 0x0087, 0x0091, 0x0094, 0x00ab, 0x00b9, + 0x00c7, 0x00d3, 0x00ea, 0x00fe, 0x0111, 0x0122, 0x0141, 0x015d, 0x0176, 0x018d, 0x01b8, + 0x01de, 0x0201, 0x0221, 0x025b, 0x028f, 0x02bf, 0x02eb, 0x033b, 0x0382, 0x03c3, 0x0400, + + //2.1 + 0x0000, 0x0034, 0x0049, 0x0058, 0x0065, 0x0070, 0x007b, 0x0084, 0x008d, 0x009d, 0x00ab, + 0x00b8, 0x00c4, 0x00da, 0x00ee, 0x0100, 0x0111, 0x0130, 0x014b, 0x0164, 0x017c, 0x01a7, + 0x01cd, 0x01f0, 0x0211, 0x024c, 0x0281, 0x02b2, 0x02e0, 0x0332, 0x037c, 0x03c0, 0x0400, + + //2.0 + 0x0000, 0x002d, 0x0040, 0x004e, 0x005a, 0x0065, 0x006e, 0x0077, 0x0080, 0x008f, 0x009c, + 0x00a9, 0x00b5, 0x00ca, 0x00dd, 0x00ef, 0x0100, 0x011e, 0x0139, 0x0152, 0x016a, 0x0194, + 0x01bb, 0x01de, 0x0200, 0x023c, 0x0273, 0x02a5, 0x02d4, 0x0329, 0x0376, 0x03bd, 0x0400, + + //1.9 + 0x0000, 0x0026, 0x0037, 0x0044, 0x004f, 0x0059, 0x0062, 0x006a, 0x0072, 0x0081, 0x008e, + 0x009a, 0x00a5, 0x00b9, 0x00cc, 0x00dd, 0x00ed, 0x010b, 0x0126, 0x013f, 0x0156, 0x0181, + 0x01a8, 0x01cc, 0x01ed, 0x022b, 0x0263, 0x0296, 0x02c6, 0x031f, 0x0370, 0x03ba, 0x0400, + + //1.8 ap30 + 0x0000, 0x0020, 0x002f, 0x003a, 0x0045, 0x004e, 0x0056, 0x005e, 0x0065, 0x0073, 0x007f, + 0x008a, 0x0095, 0x00a9, 0x00bb, 0x00cb, 0x00db, 0x00f8, 0x0112, 0x012b, 0x0142, 0x016d, + 0x0194, 0x01b8, 0x01da, 0x0218, 0x0251, 0x0286, 0x02b8, 0x0314, 0x0368, 0x03b6, 0x0400, + //default + + 0x0000, 0x0017, 0x0032, 0x0046, 0x0056, 0x0064, 0x0071, 0x007c, 0x0086, 0x0099, 0x00a9, + 0x00b8, 0x00c6, 0x00df, 0x00f5, 0x0109, 0x011b, 0x013d, 0x015a, 0x0175, 0x018d, 0x01ba, + 0x01e1, 0x0205, 0x0225, 0x0261, 0x0295, 0x02c5, 0x02f1, 0x033f, 0x0385, 0x03c5, 0x0400 + + }; + + int i, ret; + /* + for(i = 0; i < 33; i++) + { + ret = adcm2700_write(regss[i], value[table][i]); + if(ret < 0) + { + dbg_print("adcm2700 write error!"); + return -1; + } + } + */ + + for(i = 0; i < 33; i++) + { + ret = adcm2700_write(regsv[i], value[table][i]); + if(ret < 0) + { + dbg_print("adcm2700 write error!"); + return -1; + } + } + + for(i = 0; i < 33; i++) + { + ret = adcm2700_write(regs[i], value[table][i]); + if(ret < 0) + { + dbg_print("adcm2700 write error!"); + return -1; + } + } + return ADCM_ERR_NONE; +} +/*set picture style(normal/black white/sepia/solarize/neg.art)*/ +int adcm2700_set_style(V4l_PIC_STYLE style) +{ + const u16 regs1[] = {EREG_CC_COEF_00, EREG_CC_COEF_01, EREG_CC_COEF_02, + EREG_CC_COEF_10, EREG_CC_COEF_11, EREG_CC_COEF_12, + EREG_CC_COEF_20, EREG_CC_COEF_21, EREG_CC_COEF_22}; + + // 0 - normal 1 - black white 2 - sepia + const u16 value1[][9] = + { + //{0x02f9, 0x0f03, 0x0f02, 0x0f4f, 0x025c, 0x0f54, 0x0fe0, 0x0e4a, 0x02d5}, //normal settings + + {0x01f0, 0x0f88, 0x0f88, + 0x0f88, 0x01f0, 0x0f88, + 0x0f88, 0x0f88, 0x01f0}, + + {0x003b, 0x00c8, 0x0fcf, 0x003b, 0x00c8, 0x0fcf, 0x003b, 0x00c8, 0x0fcf}, //black white + {0x005c, 0x0131, 0x0fb6, 0x0030, 0x00a2, 0x0fd9, 0x001a, 0x0058, 0x0feb}, //sepia + }; + + + u16 * reg_value; + u16 reg_count; + int i; + + switch(style) + { + case V4l_STYLE_BLACK_WHITE: + adcm2700_set_gamma(0); + reg_value = value1[1]; + reg_count = 9; + break; + case V4l_STYLE_SEPIA: + adcm2700_set_gamma(0); + reg_value = value1[2]; + reg_count = 9; + break; + case V4l_STYLE_SOLARIZE: + adcm2700_set_gamma(1); + return ADCM_ERR_NONE; + case V4l_STYLE_NEG_ART: + adcm2700_set_gamma(2); + return ADCM_ERR_NONE; + default: + adcm2700_set_gamma(0); + // adcm2700_reg_write(SREG_ILLUM, illum); + return ADCM_ERR_NONE; + } + + for(i = 0; i < reg_count; i++) + { + adcm2700_write(regs1[i], reg_value[i]); + } + return ADCM_ERR_NONE; +} + +/*set picture light(auto/direct sun/incandescent/fluorescent)*/ +u16 adcm2700_get_light_v(V4l_PIC_WB light) +{ /* + const u16 regs1[] = {EREG_CC_COEF_00, EREG_CC_COEF_01, EREG_CC_COEF_02, + EREG_CC_COEF_10, EREG_CC_COEF_11, EREG_CC_COEF_12, + EREG_CC_COEF_20, EREG_CC_COEF_21, EREG_CC_COEF_22}; + + const u16 value1[][9] = + { + {0x02f9, 0x0f03, 0x0f02, 0x0f4f, 0x025c, 0x0f54, 0x0fe0, 0x0e4a, 0x02d5}, //default + {0x0235, 0x0f8f, 0x0f3b, 0x0f63, 0x01f0, 0x0fad, 0x000d, 0x0eb2, 0x0241}, //day + {0x0235, 0x0f46, 0x0f85, 0x0f64, 0x01fc, 0x0f9f, 0x0008, 0x0e8d, 0x026b}, //fluorescent + {0x023a, 0x0f34, 0x0f92, 0x0f5a, 0x0218, 0x0f8e, 0x0ffa, 0x0deb, 0x031b}, //tungsten + }; + int i, index; + switch(light) + { + case V4l_WB_DIRECT_SUN: + index = 1; + break; + case V4l_WB_INCANDESCENT: + index = 3; + break; + case V4l_WB_FLUORESCENT: + index = 2; + break; + default: + index = 0; + break; + } + for(i = 0; i< 9; i++) + { + adcm2700_write(regs1[i], value1[index][i]); + } + + */ + + u16 value = adcm2700_reg_read(SREG_ILLUM); + value &= ~0x0007; + switch(light) + { + case V4l_WB_DIRECT_SUN: + value |= 0x0002; + break; + case V4l_WB_INCANDESCENT: + value |= 0x0006; + break; + case V4l_WB_FLUORESCENT: + value |= 0x0004; + break; + default: + break; + } + return value; +} +/* Sunny - 5500K daylight */ +const u16 agilent_sunny_color[] = +{0x0214, 0x0F6E, 0x0F7C, + 0x0F58, 0x022D, 0x0F79, + 0x0FF4, 0x0EB3, 0x0257}; + +/* Cloudy - 7500K daylight */ +const u16 agilent_cloudy_color[] = +{0x021B, 0x0F8D, 0x0F56, + 0x0F5C, 0x0226, 0x0F7D, + 0x0FF5, 0x0EE7, 0x0223}; + +/* Indoor - home tungsten */ +const u16 agilent_home_tungsten_color[] = +{0x0243, 0x0EDD, 0x0FDF, + 0x0F3B, 0x0273, 0x0F50, + 0x0FA4, 0x0D9F, 0x03BB}; + +/* Indoor - office cool white fluorescent */ +const u16 agilent_office_cool_white_fluorescent_color[] = +{0x01CF, 0x0F6E, 0x0FC1, + 0x0F72, 0x020D, 0x0F7F, + 0x0FEF, 0x0E5A, 0x02B6}; + +/* Night tungsten */ +const u16 agilent_night_tungsten_color[] = +{0x0243, 0x0EDD, 0x0FDF, + 0x0F3B, 0x0273, 0x0F50, + 0x0FA4, 0x0D9F, 0x03BB}; + +/* Automatic (generic default setting) 6500K daylight */ +const u16 agilent_automatic_color[] = +{0x02F4, 0x0F27, 0x0F30, + 0x0F0C, 0x02F2, 0x0F4E, + 0x0FE8, 0x0E2E, 0x0335}; + +int adcm2700_set_light(V4l_PIC_WB light) +{ + // u16 value = adcm2700_get_light_v(light); + // adcm2700_reg_write(SREG_ILLUM, value); + + const u16 regs1[] = {EREG_CC_COEF_00, EREG_CC_COEF_01, EREG_CC_COEF_02, + EREG_CC_COEF_10, EREG_CC_COEF_11, EREG_CC_COEF_12, + EREG_CC_COEF_20, EREG_CC_COEF_21, EREG_CC_COEF_22}; + const u16 agilent_default[] = {0x02f9, 0x0f03, 0x0f02, 0x0f4f, 0x025c, 0x0f54, 0x0fe0, 0x0e4a, 0x02d5}; + /* + const u16 value1[][9] = + { + {0x02f9, 0x0f03, 0x0f02, 0x0f4f, 0x025c, 0x0f54, 0x0fe0, 0x0e4a, 0x02d5}, //default + {0x0235, 0x0f8f, 0x0f3b, 0x0f63, 0x01f0, 0x0fad, 0x000d, 0x0eb2, 0x0241}, //day + {0x0235, 0x0f46, 0x0f85, 0x0f64, 0x01fc, 0x0f9f, 0x0008, 0x0e8d, 0x026b}, //fluorescent + {0x023a, 0x0f34, 0x0f92, 0x0f5a, 0x0218, 0x0f8e, 0x0ffa, 0x0deb, 0x031b}, //tungsten + }; + */ + int i; + const u16 * values = NULL; + u16 v = adcm2700_reg_read(EREG_AF_CTRL1); + switch(light) + { + case V4l_WB_DIRECT_SUN: + values = agilent_sunny_color; + adcm2700_write(EREG_AF_CTRL1, v&(~0x0002)); + break; + case V4l_WB_INCANDESCENT: + values = agilent_night_tungsten_color; + adcm2700_write(EREG_AF_CTRL1, v&(~0x0002)); + break; + case V4l_WB_FLUORESCENT: + values = agilent_office_cool_white_fluorescent_color; + adcm2700_write(EREG_AF_CTRL1, v&(~0x0002)); + break; + default: + values = agilent_automatic_color; + adcm2700_write(EREG_AF_CTRL1, v|0x0002); + break; + } + if(values != agilent_automatic_color) + { + for(i = 0; i < 9; i++) + { + adcm2700_write(regs1[i], values[i]); + } + } + return 0; +} + +/*set picture brightness*/ +int adcm2700_set_bright(int bright) +{ + const u16 target[] = + { + 0x0010, // -2.0 EV + 0x0015, // -1.5 EV + 0x0020, // -1.0 EV + 0x0030, // -0.5 EV + 0x0040, // 0.0 EV + 0x0060, // +0.5 EV + 0x0080, // +1.0 EV + 0x00C0, // +1.5 EV + 0x00FF // +2.0 EV + }; + + if(bright < -4 || bright > 4) + { + return ADCM_ERR_PARAMETER; + } + adcm2700_write(EREG_AE_TARGET, target[bright+4]); + return ADCM_ERR_NONE; +} + +#define ADCM2700_PROC_CTRL_V_REG 0x0112 +#define ADCM2700_PROC_CTRL_S_REG 0x0132 + +#define ADCM2700_AV_CENTER_COL_REG 0x106e +#define ADCM2700_AV_CENTER_ROW_REG 0x1070 +#define ADCM2700_AV_OVAL_FACT_REG 0x1094 + + +#define ADCM2700_PROC_CTRL_V_REG 0x0112 +#define ADCM2700_PROC_CTRL_S_REG 0x0132 + +#define ADCM2700_AV_LEFT_TOP_REG 0x106a +#define ADCM2700_AV_RIGHT_BOT_REG 0x106c +#define ADCM2700_AV_CENTER_COL_REG 0x106e +#define ADCM2700_AV_CENTER_ROW_REG 0x1070 +#define ADCM2700_AV_OVAL_FACT_REG 0x1094 + +#define ADCM2700_AV_RED_RAM_REG 0x1800 +#define ADCM2700_AV_GREEN_RAM_REG 0x1840 +#define ADCM2700_AV_BLUE_RAM_REG 0x1880 + +unsigned short AV_BLUE_2700[32] = +{ + 0x47, 0x49, 0x4b, 0x4d, 0x50, 0x52, 0x55, 0x58, + 0x5a, 0x5d, 0x60, 0x63, 0x66, 0x69, 0x6d, 0x71, + 0x75, 0x79, 0x7d, 0x82, 0x87, 0x8d, 0x93, 0x9a, + 0xa1, 0xa9, 0xb2, 0xbd, 0xc8, 0xd6, 0xe5, 0xf7 +}; + +unsigned short AV_GREEN_2700[32] = +{ + 0x44, 0x48, 0x4b, 0x4f, 0x52, 0x56, 0x5a, 0x5e, + 0x63, 0x67, 0x6c, 0x70, 0x75, 0x7b, 0x80, 0x86, + 0x8c, 0x92, 0x98, 0x9f, 0xa6, 0xae, 0xb5, 0xbd, + 0xc6, 0xcf, 0xd8, 0xe2, 0xed, 0xf8, 0x103, 0x10f +}; + +unsigned short AV_RED_2700[32] = +{ + 0x43, 0x47, 0x4b, 0x50, 0x54, 0x59, 0x5e, 0x63, + 0x69, 0x6f, 0x75, 0x7b, 0x82, 0x89, 0x90, 0x97, + 0x9e, 0xa6, 0xae, 0xb6, 0xbe, 0xc6, 0xce, 0xd6, + 0xde, 0xe6, 0xee, 0xf6, 0xfe, 0x103, 0x104, 0x103 +}; + + +void adcm2700_color_init(void) +{ + u16 regdata; + int count; + + adcm2700_reg_write(ADCM2700_AV_CENTER_COL_REG, 0x0146); + adcm2700_reg_write(ADCM2700_AV_CENTER_ROW_REG, 0x00fc); + adcm2700_reg_write(ADCM2700_AV_OVAL_FACT_REG, 0x10e); + + for(count = 0; count < 32; count++) + { + adcm2700_reg_write(ADCM2700_AV_RED_RAM_REG+count*2, AV_RED_2700[count]); + } + + for(count = 0; count < 32; count++) + { + adcm2700_reg_write(ADCM2700_AV_GREEN_RAM_REG+count*2, AV_GREEN_2700[count]); + } + + for(count = 0; count < 32; count++) + { + adcm2700_reg_write(ADCM2700_AV_BLUE_RAM_REG+count*2, AV_BLUE_2700[count]); + } + + + /* video mode sharpening enable*/ + regdata = adcm2700_reg_read(ADCM2700_PROC_CTRL_V_REG); + adcm2700_reg_write(ADCM2700_PROC_CTRL_V_REG, regdata|0x4800); + + /* still mode sharpening enable*/ + regdata = adcm2700_reg_read(ADCM2700_PROC_CTRL_S_REG); + adcm2700_reg_write(ADCM2700_PROC_CTRL_S_REG, regdata|0x4800); + + + /* disable automatic dark*/ + regdata = 0x64; + adcm2700_reg_write(0x081C, regdata); +} + +int adcm2700_set_flicker(int flicker) +{ + + u16 old = adcm2700_reg_read(EREG_AF_CTRL2); + u16 old1 = adcm2700_reg_read(SREG_ILLUM); + old1 &= ~(0x18); + dbg_print("set flicker to %d", flicker); + if(flicker == 50) + { + adcm2700_reg_write(SREG_ILLUM, old1|0x08); + adcm2700_write(EREG_AF_CTRL2, old&(~0x02)); + //1000 = 100000/50/2 + adcm2700_write(EREG_AE_ETIME_DFLT, 1000); + } + else if(flicker == 60) + { + adcm2700_reg_write(SREG_ILLUM, old1|0x10); + adcm2700_write(EREG_AF_CTRL2, old|0x02); + // 833 = 100000/60/2 + adcm2700_write(EREG_AE_ETIME_DFLT, 833); + } + else + { + return ADCM_ERR_PARAMETER; + } + return 0; +} + diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/drivers/media/video/adcm2700_hw.h linux-2.6.16.5-exz/drivers/media/video/adcm2700_hw.h --- linux-2.6.16.5/drivers/media/video/adcm2700_hw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16.5-exz/drivers/media/video/adcm2700_hw.h 2006-04-16 18:49:29.000000000 +0200 @@ -0,0 +1,533 @@ +/*================================================================================ + + Header Name: adcm2700_hw.h + +General Description: Camera module adcm2700 interface header file + +================================================================================== + Motorola Confidential Proprietary + Advanced Technology and Software Operations + (c) Copyright Motorola 1999, All Rights Reserved + +Revision History: + Modification Tracking +Author Date Number Description of Changes +---------------- ------------ ---------- ------------------------- +wangfei(w20239) 12/15/2003 LIBdd35749 Created +wangfei(w20239) 02/05/2004 LIBdd74309 Set frame rate in video mode +wangfei(w20239) 02/26/2004 LIBdd81055 New chip id support +wangfei(w20239) 03/08/2004 LIBdd84578 Photo effects setting +================================================================================== + INCLUDE FILES +==================================================================================*/ + +#ifndef _PXA_ADCM_2700_HW_H__ +#define _PXA_ADCM_2700_HW_H__ + +#include "camera.h" +/*********************************************************************** + * + * Constants & Structures + * + ***********************************************************************/ + +/* ADCM_WINDOWSIZE */ +typedef struct { + u16 width; + u16 height; +} adcm_window_size; + + +// Revision constants +#define PIPE_REV 0x60 +#define PIPE_REV_NEW 0x61 +#define SENSOR_REV 0x60 + +// 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. + +// Return codes +#define ADCM_ERR_NONE 0x00 +#define ADCM_ERR_TIMEOUT -1 +#define ADCM_ERR_PARAMETER -2 + +// Auto Exposure Frequency +#define AEF_50HZ 0x20 +#define AEF_60HZ 0x40 + +// Non JEPG Output Format +#define O_FORMAT_888RGB 0 //0b0000 // 888 RGB (1 pixel in 3 bytes ) +#define O_FORMAT_666_A_RGB 1 //0b0001 // 666 A RGB (tight pack, 4 pixels in 9 bytes) +#define O_FORMAT_666_B_RGB 2 //0b0010 // 666 B RGB (loose pack, 1 pixel in 3 bytes,left or right justified) +#define O_FORMAT_565_RGB 3 //0b0011 // 565 RGB (1 pixel in 2 bytes) +#define O_FORMAT_444_A_RGB 4 //0b0100 // 444 A RGB (tight pack, 2 pixels per 3 bytes, RG BR GB) +#define O_FORMAT_444_B_RGB 5 //0b0101 // 444 B RGB (loose pack, 1 pixel per 2 bytes,RG B0 or 0R GB) +#define O_FORMAT_444_C_RGV 6 //0b0110 // 444 C RGB (sparse pack, 1 pixel per three bytes,R0 G0 B0 or 0R 0G 0B) +#define O_FORMAT_332_RGB 7 //0b0111 // 332 RGB (1 pixel in 1 byte) +#define O_FORMAT_422_A_YCbYCr 8 //0b1000 // 4:2:2 A YCbYCr (Y1 Cb12 Y2 CRL2 order) +#define O_FORMAT_422_B_YCbYCr 9 //0b1001 // 4:2:2 B YCbYCr (Cb12 Y1 CRL2 Y2 order) +#define O_FORMAT_422_C_YCbYCr 10 //0b1010 // 4:2:2 C YCbYCr (Y1 CRL2 Y2 Cb12 order) +#define O_FORMAT_422_D_YCbYCr 11 //0b1011 // 4:2:2 D YCbYCr (CRL2 Y1 Cb12 Y2 order) +#define O_FORMAT_444_YCbYCr 12 //0b1100 // 4:4:4 YCbCr (1 pixels per 3 bytes) +#define O_FORMAT_400_B_YCbYCr 13 //0b1101 // 4:0:0 YCbCr (Greyscale, 1 pixel per 1 byte) +#define O_FORMAT_RAWBPA 14 //0b1110 // RAWBPA (with AWB and BPA) +#define O_FORMAT_RAW 15 //0b1111 // RAW (without AWB and BPA) + +// Camera Mode +#define VIEWFINDER_MODE 0x10 +#define STILLFRAME_MODE 0x20 + +// Others +#define adcm2700__TIMEOUT 100 // ms to timeout. +#define BLOCK_SWITCH_CMD ((u8)0xFE) // Block Switch Code: 0x7F, CMD = Code << 1 +#define VOLTS_28 0x28 + + +/************************************************************************************* + * + * Simple Control Registers Address + * + *************************************************************************************/ +// name addr description default page +#define SREG_ID 0x0000 //Chip ID 0x0060 139 +#define SREG_CONTROL 0x0002 //Camera control 0x0001 140 +#define SREG_STATUS 0x0004 //Camera status 0x0004 142 +#define SREG_CLK_FREQ 0x0006 //Input clock frequency 0x32c8 144 +#define SREG_SIZE 0x0008 //Image size and orientation 0x0605 145 +#define SREG_OUTPUT_FORMAT 0x000a //Output format 0x0909 147 +#define SREG_EXPOSURE 0x000c //Exposure 0x03e8 149 +#define SREG_EXP_ADJ 0x000e //Exposure adjustment 0x0000 150 +#define SREG_ILLUM 0x0010 //Illumination 0x0000 151 +#define SREG_FRAME_RATE 0x0012 //Requested frame rate 0x0096 152 +#define SREG_A_FRAME_RATE 0x0016 //Actual frame rate 0x0096 154 +#define SREG_SENSOR_WID_V 0x0018 //Sensor window width, video mode 0x0000 155 +#define SREG_SENSOR_HGT_V 0x001a //Sensor window height, video mode 0x0000 156 +#define SREG_OUTPUT_WID_V 0x001c //Output window width, video mode 0x0000 157 +#define SREG_OUTPUT_HGT_V 0x001e //Output window height, video mode 0x0000 158 +#define SREG_SENSOR_WID_S 0x0020 //Sensor window width, still mode 0x0000 159 +#define SREG_SENSOR_HGT_S 0x0022 //Sensor window height, still mode 0x0000 160 +#define SREG_OUTPUT_WID_S 0x0024 //Output window width, still mode 0x0000 161 +#define SREG_OUTPUT_HGT_S 0x0026 //Output window height, still mode 0x0000 162 + +/************************************************************************************* + * + * Expert Hardware Registers + * + *************************************************************************************/ +// name addr description default page +#define EREG_I_CLK_DIV 0x0080 //Initial clock divider 0x0001 166 +#define EREG_CTL_CLK_DIV 0x0082 //Clock dividers for control + //and serial interfaces 0x4000 167 +#define EREG_SEN_CLK_DIV 0x0084 //Sensor clock dividers 0x0000 168 +#define EREG_IP_CLK_DIV 0x0086 //Clock dividers for image pipeline 0x0000 169 +#define EREG_TST_MODE 0x0088 //Latched test mode 0x0000 170 +#define EREG_SER_ADDR 0x008a //Serial interface device address 0x0053 171 +#define EREG_SER_PARM 0x008c //Serial Interface parameters 0x0000 172 +#define EREG_OUT_CTRL 0x008e //Output control 0x0000 173 +#define EREG_PLL_CTRL 0x0090 //PLL control 0x0024 174 +#define EREG_PLL_DIV_L 0x0092 //PLL divisors, large values 0x1d09 175 +#define EREG_PLL_DIV_S 0x0094 //PLL divisors, small values 0x0200 176 + +/************************************************************************************* + * + * Expert Control Registers + * + *************************************************************************************/ +// name addr description default page +#define EREG_SZR_IN_WID_V 0x0100 //Sizer input width, video mode 0x0280 184 +#define EREG_SZR_IN_HGT_V 0x0102 //Sizer input height, video mode 0x01e0 185 +#define EREG_SZR_OUT_WID_V 0x0104 //Sizer output width, video mode 0x0140 186 +#define EREG_SZR_OUT_HGT_V 0x0106 //Sizer output height, video mode 0x00f0 187 +#define EREG_CPP_V 0x0108 //Clocks per pixel, video mode 0x0002 188 +#define EREG_HBLANK_V 0x010a //Horizontal blanking period, video mode 0x0000 189 +#define EREG_VBLANK_V 0x010c //Vertical blanking period, video mode 0x0000 190 +#define EREG_MIN_MAX_F_V 0x010e //Frame convergence rates, video mode 0x0000 191 +#define EREG_OUTPUT_CTRL_V 0x0110 //Output control, video mode 0x9019 192 +#define EREG_PROC_CTRL_V 0x0112 //Processing control, video mode 0x0280 194 +#define EREG_RPT_V 0x0114 //Row processing time, video mode 0x0546 196 +#define EREG_HYSNC_PER_V 0x0116 //HSYNC period, video mode 0x0a8b 197 +#define EREG_CLK_DIV_V 0x0118 //Clock divisors, video mode 0x0000 198 +#define EREG_PARALLEL_CTRL_V 0x011a //Parallel output control, video mode 0x0003 199 +#define EREG_SEN_CTRL_V 0x011c //Sensor control, video mode 0x0000 200 + +#define EREG_SZR_IN_WID_S 0x0120 //Sizer input width, still mode 0x0280 202 +#define EREG_SZR_IN_HGT_S 0x0122 //Sizer input height, still mode 0x01e0 203 +#define EREG_SZR_OUT_WID_S 0x0124 //Sizer output width, still mode 0x0280 204 +#define EREG_SZR_OUT_HGT_S 0x0126 //Sizer output height, still mode 0x01e0 205 +#define EREG_CPP_S 0x0128 //Clocks per pixel, still mode 0x0002 206 +#define EREG_HBLANK_S 0x012a //Horizontal blanking period, still mode 0x0000 207 +#define EREG_VBLANK_S 0x012c //Vertical blanking period, still mode 0x0000 208 +#define EREG_MIN_MAX_F_S 0x012e //Frame convergence rates, still mode 0x0002 209 +#define EREG_OUTPUT_CTRL_S 0x0130 //Output control, still mode 0x8019 210 +#define EREG_PROC_CTRL_S 0x0132 //Processing control, still mode 0x0280 212 +#define EREG_RPT_S 0x0134 //Row processing time, still mode 0x0546 214 +#define EREG_HYSNC_PER_S 0x0136 //HSYNC period, still mode 0x0545 215 +#define EREG_CLK_DIV_S 0x0138 //Clock divisors, still mode 0x0000 216 +#define EREG_PARALLEL_CTRL_S 0x013a //Parallel output control, still mode 0x0000 217 +#define EREG_SEN_CTRL_S 0x013c //Sensor control, still mode 0x0000 218 + +#define EREG_AF_CTRL1 0x0140 //Auto functions control 1 0x0013 220 +#define EREG_AF_CTRL2 0x0142 //Auto functions control 2 0x0001 221 +#define EREG_AF_STATUS 0x0144 //Auto functions status 0x0000 222 +#define EREG_SOF_CODES 0x0146 //Start of frame codes 0xfeff 223 +#define EREG_EOF_CODES 0x0148 //End of frame codes 0x0100 224 +#define EREG_ABL_TARGET 0x014a //Auto black level target 0x0005 225 +#define EREG_ABL_MAX_BIN 0x014c //Auto black level maximum bin 0x0003 226 +#define EREG_ABL_MAX_BLACK 0x014e //Auto black level maximum black 0x0010 227 +#define EREG_AE_GAIN_MIN 0x0150 //Auto exposure gain minimum 0x01c0 228 +#define EREG_AE_GAIN_MIN_P 0x0152 //Auto exposure gain minimum, preferred 0x0200 229 +#define EREG_AE_GAIN_MAX 0x0154 //Auto exposure gain maximum 0x0500 230 +#define EREG_AE_GAIN_DFLT 0x0156 //Auto exposure gain default 0x0200 231 +#define EREG_AE_ETIME_MIN 0x0158 //Auto exposure time minimum 0x0005 232 +#define EREG_AE_ETIME_MAX 0x015a //Auto exposure time maximum 0x4e20 233 +#define EREG_AE_ETIME_DFLT 0x015c //Auto exposure time default 0x03e8 234 +#define EREG_AE_TARGET 0x015e //Auto exposure target 0x0040 235 +#define EREG_AE_TOL_ACQ 0x0160 //Auto exposure tolerance acquire 0x0118 236 +#define EREG_AE_TOL_MON 0x0162 //Auto exposure tolerance monitor 0x0118 237 +#define EREG_AE_MARGIN 0x0164 //Auto exposure margin 0x0120 238 +#define EREG_AE_DOE_FACTOR 0x0166 //AE deliberate overexposure factor 0x014e 239 +#define EREG_AE_DOE_MARGIN 0x0168 //AE deliberate overexposure margin 0x0140 240 + +#define EREG_AWB_RED_MIN 0x0170 //AWB minimum red/green ratio 0x00c0 242 +#define EREG_AWB_RED_MAX 0x0172 //AWB maximum red/green ratio 0x01a6 243 +#define EREG_AWB_RED_DFLT 0x0174 //AWB default red/green ratio 0x0134 244 +#define EREG_AWB_BLUE_MIN 0x0176 //AWB minimum blue/green ratio 0x00c0 245 +#define EREG_AWB_BLUE_MAX 0x0178 //AWB maximum blue/green ratio 0x02a4 246 +#define EREG_AWB_BLUE_DFLT 0x017a //AWB default blue/green ratio 0x01e4 247 +#define EREG_AWB_TOL_ACQ 0x017c //Auto white balance tolerance acquire 0x0110 248 +#define EREG_AWB_TOL_MON 0x017e //Auto white balance tolerance monitor 0x0120 249 +#define EREG_FIRMWARE_REV 0x0180 //Current firmware revision 0x0152 250 +#define EREG_FLICK_CFG_1 0x0182 //Flicker configuration 1 0x2aeb 251 +#define EREG_FLICK_CFG_2 0x0184 //Flicker configuration 2 0x0005 252 + +#define EREG_MAX_SCLK 0x018a //Maximum sensor clock 0x1964 254 + +#define EREG_CSC_00_V 0x0190 //Color conversion coefficient 00, video 0x0026 256 +#define EREG_CSC_01_V 0x0192 //Color conversion coefficient 01, video 0x004b 256 +#define EREG_CSC_02_V 0x0194 //Color conversion coefficient 02, video 0x000f 256 +#define EREG_CSC_10_V 0x0196 //Color conversion coefficient 10, video 0x01ed 256 +#define EREG_CSC_11_V 0x0198 //Color conversion coefficient 11, video 0x01db 256 +#define EREG_CSC_12_V 0x019a //Color conversion coefficient 12, video 0x0038 256 +#define EREG_CSC_20_V 0x019c //Color conversion coefficient 20, video 0x004f 256 +#define EREG_CSC_21_V 0x019e //Color conversion coefficient 21, video 0x01be 256 +#define EREG_CSC_22_V 0x01a0 //Color conversion coefficient 22, video 0x01f3 256 + +#define EREG_CSC_OS0_V 0x01a2 //Color space conversion offset 0, video 0x0000 257 +#define EREG_CSC_OS1_V 0x01a4 //Color space conversion offset 1, video 0x0080 257 +#define EREG_CSC_OS2_V 0x01a6 //Color space conversion offset 2, video 0x0080 257 + +#define EREG_CSC_00_S 0x01a8 //Color conversion coefficient 00, still 0x0026 258 +#define EREG_CSC_01_S 0x01aa //Color conversion coefficient 01, still 0x004b 258 +#define EREG_CSC_02_S 0x01ac //Color conversion coefficient 02, still 0x000f 258 +#define EREG_CSC_10_S 0x01ae //Color conversion coefficient 10, still 0x01ed 258 +#define EREG_CSC_11_S 0x01b0 //Color conversion coefficient 11, still 0x01db 258 +#define EREG_CSC_12_S 0x01b2 //Color conversion coefficient 12, still 0x0038 258 +#define EREG_CSC_20_S 0x01b4 //Color conversion coefficient 20, still 0x004f 258 +#define EREG_CSC_21_S 0x01b6 //Color conversion coefficient 21, still 0x01be 258 +#define EREG_CSC_22_S 0x01b8 //Color conversion coefficient 22,