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

📄 ov9650.c

📁 嵌入式Linux系统下,ov965摄像头驱动.
💻 C
字号:
/*
*
*	MX21 OV9650 Driver
*
*	cliff.wong@motorola.com
*	16 Jun, 04
*/

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/hfs_sysdep.h>
#include <linux/compatmac.h>
#include <linux/hdreg.h>
#include <linux/vmalloc.h>
#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/blkpg.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-id.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mm.h>
#include <linux/wrapper.h>
#include <asm/dma.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>

#include "asm/arch/mx2.h"
#include "asm/arch/platform.h"

#include "linux/i2c.h"
#include "linux/i2c-dev.h"
#include "khead.h"
#include "csi.h"
#include "ov9650.h"

/*************************************************************************************************
	i2c related
*************************************************************************************************/
static unsigned int error_status = 0;
static unsigned int i2c_init = 0;

void I2C_init()
{
	_reg_GPIO_GIUS(GPIOD) &= ~((1<<17)|(1<<18));
	_reg_GPIO_GPR(GPIOD) &= ~((1<<17)|(1<<18));
	_reg_GPIO_GIUS(GPIOD) |= 0x00100000;
	_reg_GPIO_DDIR(GPIOD) |= 0x00100000;
	_reg_GPIO_OCR2(GPIOD) |= 0x00000300;
	_reg_GPIO_DR(GPIOD) |= 0x00100000;
	_reg_GPIO_DR(GPIOD) &= ~0x00100000;
}

static int i2c_write(unsigned char reg, unsigned char data)
{
		I2C_init();
       //module reset
        _reg_I2C_I2CR = 0x0;

        //I2C init
        _reg_I2C_IFDR = 0x19;   //clock select
        _reg_I2C_I2CR |= 0x80;        //I2C enable
        _reg_I2C_I2CR |= 0x08;        //ack disable
        //grant bus master
        _reg_I2C_I2CR |= 0x20;        //gen START signal
        while (!(_reg_I2C_I2SR & 0x20));      //poll until bus is grant (IBB bit)

        //enter transmit mode
        _reg_I2C_I2CR |= 0x10;        //transmit mode

        //transmit device slave calling addr
       	_reg_I2C_I2DR = 0x60;       //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack4\n");

        //transmit register addr
        _reg_I2C_I2DR = reg;        //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack5\n");

        //transmit data LSB
        _reg_I2C_I2DR = data;        //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack6\n");

        //generate STOP signal
        _reg_I2C_I2CR &= ~0x20;      //enter slave mode
        while (_reg_I2C_I2SR & 0x20); //poll until bus is release (IBB = 0)

        //disable I2C
        _reg_I2C_I2CR = 0x0;

        return 0;

//	return ret;
}


static int i2c_read(unsigned char reg, unsigned char *_data)
{
		I2C_init();
        //module reset
        _reg_I2C_I2CR = 0x0;

        //I2C init
        _reg_I2C_IFDR = 0x19;   //clock select
        _reg_I2C_I2CR |= 0x80;        //I2C enable

        //grant bus master
        _reg_I2C_I2CR |= 0x20;        //gen START signal
        while (!(_reg_I2C_I2SR & 0x20));      //poll until bus is grant (IBB bit)

        //enter transmit mode
        _reg_I2C_I2CR |= 0x10;

        //transmit device addr for WRITE
        _reg_I2C_I2DR = 0x60;       //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack1\n");

        //transmit register addr
        _reg_I2C_I2DR = reg;        //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack2\n");
        _reg_I2C_I2CR &= ~0x20;      //enter slave mode
        while (_reg_I2C_I2SR & 0x20); //poll until bus is release (IBB = 0)
        _reg_I2C_I2CR |= 0x20;        //gen START signal
        while (!(_reg_I2C_I2SR & 0x20));      //poll until bus is grant (IBB bit
        //generate repeated START signal
//        _reg_I2C_I2CR |= 0x4;
        _reg_I2C_I2CR |= 0x10;

        //transmit device calling addr for READ
        _reg_I2C_I2DR = 0x61;       //initiate transfer
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit

        //check for ACK bit
        if (_reg_I2C_I2SR & 0x1)
                printk("not Ack3\n");

        //change to recieve mode
        _reg_I2C_I2CR &= ~0x10;

        //dummy read to excite clock generation
        _reg_I2C_I2CR &= ~0x08;     //ack enable
        *_data = _reg_I2C_I2DR;
//        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
//        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit
        //get MSB, and gen clock for reading LSB
        _reg_I2C_I2CR |= 0x08;      //ack disable
        while (!(_reg_I2C_I2SR & 0x02));    //poll IIF bit
        _reg_I2C_I2SR &= ~0x02;     //must clear IIF bit
//        msb = *(U32 *) I2C_I2DR;
//        while (!(*(U32 *) I2C_I2SR & 0x02));    //poll IIF bit
//        *(U32 *) I2C_I2SR &= ~0x02;     //must clear IIF bit
//	printk("data = %x\n",_reg_I2C_I2DR);
        //generate STOP signal
        _reg_I2C_I2CR &= ~0x20;      //enter slave mode
        while (_reg_I2C_I2SR & 0x20); //poll until bus is release (IBB = 0)
        //get LSB
        *_data = _reg_I2C_I2DR;
//		printk("data = %x\n",*_data);
		udelay(100);
        //disable I2C
        _reg_I2C_I2CR = 0x0;

        //concantenate 2 bytes into 16-bit

        return 0;

//	return ret;
}
/*************************************************************************************************
	sensor api
*************************************************************************************************/

#define CSI_CTL0		0x0040
#define CSI_CTL1		0x0020
#define CSI_CTL2		0x0010

static OV9650_CFG 		g_ov9650_cfg;

void ov9650_config_SENSOR(OV9650_CFG * _cfg)
{
	i2c_write(0x12, 0x80);	// reset sensor
	udelay(50000);
	i2c_write(0x09, 0x11);
	i2c_write(0x6b, 0x0a);
	i2c_write(0x3b, 0x09);
	i2c_write(0x13, 0xe0);
	i2c_write(0x01, 0x80);
	i2c_write(0x02, 0x80);
	i2c_write(0x00, 0x00);
	i2c_write(0x10, 0x00);
	i2c_write(0x13, 0xe5);
	i2c_write(0x39, 0x43);
	i2c_write(0x38, 0x12);
	i2c_write(0x37, 0x00);
	i2c_write(0x35, 0x91);
	i2c_write(0x1e, 0x04);
	i2c_write(0xA8, 0x80);
	i2c_write(0x3f, 0xa6);
	i2c_write(0x14, 0x2e);
	i2c_write(0x15, 0x02);
	i2c_write(0x41, 0x02);
	i2c_write(0x42, 0x08);
	i2c_write(0x1b, 0x00);
	i2c_write(0x16, 0x06);
	i2c_write(0x33, 0xe2);
	i2c_write(0x34, 0xbf);
	i2c_write(0x96, 0x04);
	i2c_write(0x3a, 0x00);
	i2c_write(0x8e, 0x00);
	i2c_write(0x3c, 0x77);
	i2c_write(0x8B, 0x06);
	i2c_write(0x94, 0x88);
	i2c_write(0x95, 0x88);
	i2c_write(0x40, 0xc1);
	i2c_write(0x29, 0x3f);
	i2c_write(0x0f, 0x42);
	i2c_write(0x3d, 0x92);
	i2c_write(0x69, 0x40);
	i2c_write(0x5C, 0xb9);
	i2c_write(0x5D, 0x96);
	i2c_write(0x5E, 0x10);
	i2c_write(0x59, 0xc0);
	i2c_write(0x5A, 0xaf);
	i2c_write(0x5B, 0x55);
	i2c_write(0x43, 0xf0);
	i2c_write(0x44, 0x10);
	i2c_write(0x45, 0x68);
	i2c_write(0x46, 0x96);
	i2c_write(0x47, 0x60);
	i2c_write(0x48, 0x80);
	i2c_write(0x5F, 0xe0);
	i2c_write(0x60, 0x8c);
	i2c_write(0x61, 0x20);
	i2c_write(0xa5, 0xd9);
	i2c_write(0xa4, 0x74);
	i2c_write(0x8d, 0x02);
	i2c_write(0x13, 0xe7);
	i2c_write(0x4f, 0x3a);
	i2c_write(0x50, 0x3d);
	i2c_write(0x51, 0x03);
	i2c_write(0x52, 0x12);
	i2c_write(0x53, 0x26);
	i2c_write(0x54, 0x38);
	i2c_write(0x55, 0x40);
	i2c_write(0x56, 0x40);
	i2c_write(0x57, 0x40);
	i2c_write(0x58, 0x0d);
	i2c_write(0x8C, 0x23);
	i2c_write(0x3E, 0x02);
	i2c_write(0xa9, 0xb8);
	i2c_write(0xaa, 0x92);
	i2c_write(0xab, 0x0a);
	i2c_write(0x8f, 0xdf);
	i2c_write(0x90, 0x00);
	i2c_write(0x91, 0x00);
	i2c_write(0x9f, 0x00);
	i2c_write(0xa0, 0x00);
	i2c_write(0x3A, 0x02);
	i2c_write(0x24, 0x70);
	i2c_write(0x25, 0x64);
	i2c_write(0x26, 0xc3);
	i2c_write(0x2a, 0x00);
	i2c_write(0x2b, 0x00);
	i2c_write(0x6c, 0x40);
	i2c_write(0x6d, 0x30);
	i2c_write(0x6e, 0x4b);
	i2c_write(0x6f, 0x60);
	i2c_write(0x70, 0x70);
	i2c_write(0x71, 0x70);
	i2c_write(0x72, 0x70);
	i2c_write(0x73, 0x70);
	i2c_write(0x74, 0x60);
	i2c_write(0x75, 0x60);
	i2c_write(0x76, 0x50);
	i2c_write(0x77, 0x48);
	i2c_write(0x78, 0x3a);
	i2c_write(0x79, 0x2e);
	i2c_write(0x7a, 0x28);
	i2c_write(0x7b, 0x22);
	i2c_write(0x7c, 0x04);
	i2c_write(0x7d, 0x07);
	i2c_write(0x7e, 0x10);
	i2c_write(0x7f, 0x28);
	i2c_write(0x80, 0x36);
	i2c_write(0x81, 0x44);
	i2c_write(0x82, 0x52);
	i2c_write(0x83, 0x60);
	i2c_write(0x84, 0x6c);
	i2c_write(0x85, 0x78);
	i2c_write(0x86, 0x8c);
	i2c_write(0x87, 0x9e);
	i2c_write(0x88, 0xbb);
	i2c_write(0x89, 0xd2);
	i2c_write(0x8a, 0xe6);
	
	i2c_write(0x15, 0x10);
	i2c_write(0x3a, 0x08);

	return;
}

void ov9650_config_SXGA(OV9650_CFG * _cfg)
{
	i2c_write(0x6a, 0x27);
	i2c_write(0x0e, 0xa0);

	i2c_write(0x04, 0x00);
	i2c_write(0x0c, 0x00);
	i2c_write(0x0d, 0x00);
	i2c_write(0x11, 0x80);
	i2c_write(0x12, 0x00);
	i2c_write(0x40, 0xc1);
	i2c_write(0x2a, 0x10);
	i2c_write(0x2b, 0x34);

	i2c_write(0x18, 0xbd);
	i2c_write(0x17, 0x1d);
	i2c_write(0x32, 0xa4);
	i2c_write(0x03, 0x12);
	i2c_write(0x1a, 0x81);
	i2c_write(0x19, 0x01);

	i2c_write(0x09, 0x01);
	return;
}

void ov9650_config_VGA(OV9650_CFG * _cfg)
{
	i2c_write(0x6a, 0x13);
	i2c_write(0x0e, 0x20);

	i2c_write(0x04, 0x00);
	i2c_write(0x0c, 0x04);
	i2c_write(0x0d, 0x80);
	i2c_write(0x11, 0x81);
	i2c_write(0x12, 0x40);
	i2c_write(0x40, 0xc1);
	i2c_write(0x2a, 0x10);
	i2c_write(0x2b, 0x40);

	i2c_write(0x18, 0xc6);
	i2c_write(0x17, 0x26);
	i2c_write(0x32, 0xad);
	i2c_write(0x03, 0x36);
	i2c_write(0x1a, 0x3c);
	i2c_write(0x19, 0x00);

	i2c_write(0x09, 0x01);
        return;
}

void ov9650_config_QVGA(OV9650_CFG * _cfg)
{
	i2c_write(0x6a, 0x25);
	i2c_write(0x0e, 0xa0);

	i2c_write(0x04, 0x00);
	i2c_write(0x0c, 0x04);
	i2c_write(0x0d, 0x80);
	i2c_write(0x11, 0x83);
	i2c_write(0x12, 0x10);
	i2c_write(0x40, 0xc1);
	i2c_write(0x2a, 0x00);
	i2c_write(0x2b, 0x00);

	i2c_write(0x18, 0xc6);
	i2c_write(0x17, 0x26);
	i2c_write(0x32, 0xa4);
	i2c_write(0x03, 0x36);
	i2c_write(0x1a, 0x1e);
	i2c_write(0x19, 0x00);

	i2c_write(0x09, 0x01);
	return;
}

void ov9650_config_V_Q(OV9650_CFG * _cfg)
{
	i2c_write(0x6a, 0x13);
	i2c_write(0x0e, 0x20);

	i2c_write(0x04, 0x00);
	i2c_write(0x0c, 0x04);
	i2c_write(0x0d, 0x80);
	i2c_write(0x11, 0x81);
	i2c_write(0x12, 0x40);

	i2c_write(0x18, 0x9e);//c6
	i2c_write(0x17, 0x4e);//26
	i2c_write(0x32, 0xad);//ad
	i2c_write(0x03, 0x36);//36
	i2c_write(0x1a, 0x2d);//3c
	i2c_write(0x19, 0x0f);//00

	i2c_write(0x40, 0xc1);
	i2c_write(0x2a, 0x00);
	i2c_write(0x2b, 0x00);

	i2c_write(0x09, 0x01);
	return;
}

void ov9650_config_S_Q(OV9650_CFG * _cfg)
{
	i2c_write(0x6a, 0x27);//41
	i2c_write(0x0e, 0xa0);//20

	i2c_write(0x04, 0x00);
	i2c_write(0x0c, 0x00);
	i2c_write(0x0d, 0x00);
	i2c_write(0x11, 0x80);
	i2c_write(0x12, 0x00);

	i2c_write(0x18, 0x82);//bd
	i2c_write(0x17, 0x5a);//1d
	i2c_write(0x32, 0xa4);//bf
	i2c_write(0x03, 0x12);
	i2c_write(0x1a, 0x50);
	i2c_write(0x19, 0x32);

	i2c_write(0x40, 0xc1);
	i2c_write(0x2a, 0x00);//10
	i2c_write(0x2b, 0x00);//34

	i2c_write(0x09, 0x01);
	return;
}

void ov9650_cleanup(void)
{
	return;	
}

void sensor_reset(void)
{
	// set powerdown signal low , and give a pluse for reset signal
#if 0
	setgpio(RESET, 0);
	setgpio(POWERDOWN, 0);
	udelay(1000);
	setgpio(RESET, 1);
	udelay(1000);
	setgpio(RESET, 0);
	udelay(1000);
#endif
}

void i2c_test(void)
{
	U8 pid,ver;
	i2c_read(0x0a,&pid);
	i2c_read(0x0b,&ver);
	printk("Sensor PID 0x%x VER 0x%x\n",pid,ver);
								        return;
}

/*************************************************************************************************
	sensor driver
*************************************************************************************************/

//global static
static devfs_handle_t devfs_handle;
static int gMajor = 0;

//functions and interface
static int 		ov9650_open(struct inode *inode, struct file *filp);
static int 		ov9650_release(struct inode *inode, struct file *filp);
static ssize_t 	ov9650_read(struct file *filp, char *buf, size_t size, loff_t *l);
static ssize_t 	ov9650_write(struct file *filp, const char *buf, size_t size, loff_t *l);
static int 		ov9650_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);


struct file_operations ov9650_fops = 
{
	open:		ov9650_open,
	release:	ov9650_release,
	read:		ov9650_read,
	write:		ov9650_write,
	ioctl:		ov9650_ioctl,
};

static int ov9650_open(struct inode *inode, struct file *filp)
{
        MOD_INC_USE_COUNT;
 	return 0;
}


static int ov9650_release(struct inode *inode, struct file *filp)
{
        MOD_DEC_USE_COUNT;
	return 0;	
}


static ssize_t ov9650_read(struct file *filp, char *buf, size_t size, loff_t *l)
{
	printk("ov9650: read ioctl not implemented\n");
	return -1;
}


static ssize_t ov9650_write(struct file *filp, const char *buf, size_t size, loff_t *l)
{
	printk("ov9650: write ioctl not implemented\n");
	return -1;
}


static int ov9650_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	switch(cmd)
	{
		case OV9650_IOC_CONFIG:
		{
			if(copy_from_user((void *)&g_ov9650_cfg, (void *)arg, sizeof(OV9650_CFG)))
				return -EFAULT;

			break;
		}
		case OV9650_IOC_I2C_TEST:
		{
			break;
		}
	}
	return 0;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -