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

📄 im8012.c

📁 linux下面im8012的驱动程序,im8012为工业上通常使用的cmos摄像头
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MX21 IM8012 driver * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright (C) 2004 Motorola Semiconductors Hong Kong. * */#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 <linux/pm.h>#include <asm/arch/apmc.h>#include "asm/arch/mx2.h"#include "asm/arch/platform.h"#include "linux/i2c.h"#include "linux/i2c-dev.h"#include "im8012.h"/*************************************************************************************************	i2c related*************************************************************************************************/#define I2C_DRIVERID_I2CCSI 0xF000#define EMBEDDED_REGISTER 0x01#define I2C_M_READ 0x02#define I2C_M_WT 0x04//im8012 i2c addr#define SENSOR_I2C_ADDR 0x90static int i2c_csi_attach_adapter (struct i2c_adapter * adap);static struct i2c_driver i2c_csi_driver ={	name:		"i2c-csi client driver",	id:		I2C_DRIVERID_I2CCSI,	flags:		I2C_DF_DUMMY | I2C_DF_NOTIFY,	attach_adapter:	i2c_csi_attach_adapter,	detach_client:	NULL,	/*i2c_csi_detach_client,*/	command:	NULL};static struct i2c_client i2c_csi2c_client ={	name:		"i2c-csi client",	id:		2,	flags:		0,	addr:		-1,	adapter:	NULL,	driver:		&i2c_csi_driver,	data:		NULL};static int i2c_csi_attach_adapter (struct i2c_adapter * adap){	if (memcmp(adap->name, "DBMX I2C Adapter", 16) != 0 )		return -ENODEV;	i2c_csi2c_client.adapter = adap;	return 0;}static void i2c_init(void){	/* 	 * set the address of the CMOS sensor to the client	 */	i2c_csi2c_client.addr = SENSOR_I2C_ADDR;	/* 	 * call the i2c_add_driver() to register the driver 	 * to the Linux I2C system	 */	if (i2c_add_driver( &i2c_csi_driver ) != 0)	{		printk("I2C addr driver failed\n");		return;	}		/* 	 * attach the client to the adapter by calling the i2c_attach_client() 	 * function of the Linux I2C system	 */	if (i2c_attach_client(&i2c_csi2c_client ) != 0)	{			printk("I2C attach client failed\n");		i2c_del_driver(&i2c_csi_driver);		return;	}	i2c_csi2c_client.adapter->inc_use( i2c_csi2c_client.adapter );}static void i2c_cleanup(void){	i2c_csi2c_client.adapter->dec_use(i2c_csi2c_client.adapter);	i2c_detach_client(&i2c_csi2c_client );	i2c_del_driver(&i2c_csi_driver);}static int i2c_write(unsigned int reg, unsigned short data){	struct i2c_msg msg;	char buf[3];	int ret;	/* 	 * store the register value to the first address of the buffer 	 * the adapter/algorithm driver will regard the first byte 	 * as the register value 	 */	buf[0] = (char)reg;	buf[1] = (char)((data&0xFF00) >> 8);	buf[2] = (char)(data&0xFF);		/* 	 * initialize the message structure	 */	msg.addr = i2c_csi2c_client.addr;	msg.flags = EMBEDDED_REGISTER | I2C_M_WT;	msg.len = 3;	msg.buf = buf;		ret = i2c_transfer( i2c_csi2c_client.adapter, &msg, 1 );	return ret;}static int i2c_read(unsigned int reg, unsigned short *_data){	struct i2c_msg msg;	char buf[3];	int ret;		/* 	 * store the register value to the first address of the buffer 	 * the adapter/algorithm driver will regard the first byte 	 * as the register value 	 */	buf[0] = (char)reg;	/* 	 * initialize the message structure	 */	msg.addr =  i2c_csi2c_client.addr;	msg.flags = EMBEDDED_REGISTER | I2C_M_READ;	msg.len = 2;	msg.buf = buf;		ret = i2c_transfer( i2c_csi2c_client.adapter, &msg, 1 );	*_data = ((unsigned short)buf[0] << 8) | (unsigned short)buf[1];			return ret;}/*************************************************************************************************	sensor api*************************************************************************************************/#define CSI_CTL0		0x0040#define CSI_CTL1		0x0020#define CSI_CTL2		0x0010//globalstatic IM8012_CFG g_im8012_cfg;//localstatic void ifp_select(void);static void ic_select(void);static void ifp_soft_reset(void);static void ic_soft_reset(void);static void im8012_soft_reset(void);static void im8012_hard_reset(void);static void im8012_hard_standby_control(int enable);static int im8012_i2c_test(void);static void im8012_color_fmt_ctrl(int color_space);static void im8012_decimation_ctrl(unsigned int out_width, unsigned int out_height);static void im8012_lens_correction(void);static void im8012_black_threshold(void);static void im8012_read_mode_ctrl(int vert_mirror, int hori_mirror);static void im8012_blanking_ctrl(void);static void im8012_gamma_correction(int gamma);static void im8012_color_gain(int gain_green1, int gain_blue, int gain_red, int gain_green2, int gain_global);static void im8012_color_processing(int colorsat);static void im8012_sharpening(int sharpening);static void im8012_cal_awb_bound(int nLeft, int nRight, int nTop, int nBottom);static void im8012_test_pattern_enable(int nPattern);static void im8012_frame_rate_control(int fps);static void im8012_flicker_cancellation(int freq);//select ifp register spacestatic void ifp_select(void){	i2c_write(0x01, 0x0001);		return;}static void ifp_soft_reset(void){	ifp_select();		i2c_write(0x07, 0x0001);	i2c_write(0x07, 0x0000);		return;}//select ic register spacestatic void ic_select(void){	i2c_write(0x01, 0x0004);		return;}static void ic_soft_reset(void){	ic_select();		i2c_write(0x0D, 0x0001);	i2c_write(0x0D, 0x0000);		return;}//soft register resetstatic void im8012_soft_reset(void){	ifp_soft_reset();	ic_soft_reset();	return;}//set reset pin levelstatic void im8012_hard_reset(void){	unsigned short data;//assert reset pulse	data = _reg_EXP_IO_0;	data &= ~CSI_CTL1;	_reg_EXP_IO_0 = data;	udelay(100);		data |= CSI_CTL1;	_reg_EXP_IO_0 = data;	udelay(300);	return;}//set standby pin levelstatic void im8012_hard_standby_control(int enable){	unsigned short data;		data =_reg_EXP_IO_0;	if(enable)		data |= CSI_CTL0;	else		data &= ~CSI_CTL0;	_reg_EXP_IO_0 = data;	return;}//i2c channel read/write teststatic int im8012_i2c_test(void){	unsigned int test_reg = 0x04;	//bit [8..0] r/w	unsigned short test_val;	unsigned short temp_val;	int error = 0;	im8012_hard_reset();	im8012_hard_standby_control(0);	i2c_write(0x01, 0x0004);	//select IC	for(test_val = 0x0; test_val < 0xFF; test_val ++)	{		i2c_write(test_reg, test_val);		i2c_read(test_reg, &temp_val);		if(test_val != temp_val)			error = 1;	}	if(error)		printk("im8012: i2c test failed\n");	else		printk("im8012: i2c test ok\n");		im8012_hard_reset();	return error;}//set output color spacevoid im8012_color_fmt_ctrl(int color_space){	ifp_select();	if(color_space == YUV)	{		i2c_write(0x08, 0xCD00);	}	else if(color_space == RGB)	{		i2c_write(0x08, 0xD800);	}		return;}/*//arbitrary resize controlvoid im8012_decimation_ctrl(unsigned int out_width, unsigned int out_height){	if(out_width > 640)		out_width = 640;	if(out_height > 480)		out_height = 480;		ifp_select();		i2c_write(0xA5, 0x8000);	//hori control				i2c_write(0xA6, 0x8000 + 640);	//take full window	i2c_write(0xA7, 0x8000 + out_width);	i2c_write(0xA8, 0x8000);	//vert control	i2c_write(0xA9, 0x8000 + 480);	//take full window	i2c_write(0xAA, 0x8000 + out_height);	i2c_write(0xA5, 0x0000);	//enable changesprintk("im8012: dec control\n");	return;}*///arbitrary resize controlvoid im8012_decimation_ctrl(unsigned int out_width, unsigned int out_height){	unsigned short a5_val, a6_val, a7_val, a8_val, a9_val, aa_val;		if(out_width > 640)		out_width = 640;	if(out_height > 480)		out_height = 480;		a5_val = 0;		//hori control	a6_val = 640;		//take full window	a7_val = out_width;	a8_val = 0;		//vert control	a9_val = 480;		//take full window	aa_val = out_height;	ifp_select();	//change & freeze	i2c_write(0xA5, 0x8000 | a5_val);	//hori control				i2c_write(0xA6, 0x8000 | a6_val);	//take full window	i2c_write(0xA7, 0x8000 | a7_val);	i2c_write(0xA8, 0x8000 | a8_val);	//vert control	i2c_write(0xA9, 0x8000 | a9_val);	//take full window	i2c_write(0xAA, 0x8000 | aa_val);//unfreeze & synchronize the changes	i2c_write(0xA5, a5_val & ~0x8000);//printk("im8012: dec control\n");	return;}//lens geometry correctionstatic void im8012_lens_correction(void){	unsigned short nValue;		ifp_select();	i2c_read(0x08, &nValue);	i2c_write(0x08, nValue |= 0x0100);  //turn on Lens Shading correction		//Vertical direction,split into 5 vertical segment	i2c_write(0x81, 0xDD0C);              //Red pixel in frist vertex	i2c_write(0x82, 0x04F4);              //Red pixel in second & third vertex	i2c_write(0x83, 0x3C11);              //Red pixel in fourth & fifth vertex	i2c_write(0x84, 0xE20C);              //Green pixel in frist vertex	i2c_write(0x85, 0x02F6);              //Green pixel in second & third vertex	i2c_write(0x86, 0x3211);              //Green pixel in fourth & fifth vertex	i2c_write(0x87, 0xDD0C);              //Blue pixel in frist vertex	i2c_write(0x88, 0x00F4);              //Blue pixel in second & third vertex	i2c_write(0x89, 0x3216);              //Blue pixel in fourth & fifth vertex	//Horizontal diretion, split into 6 horizontal segment	i2c_write(0x8A, 0x8832);              //Red pixel in frist vertex	i2c_write(0x8B, 0xF7DD);              //Red pixel in second & third vertex	i2c_write(0x8C, 0x3C0C);              //Red pixel in fourth & fifth vertex	i2c_write(0x8D, 0x007F);              //Red pixel in sixth vertex	i2c_write(0x8E, 0xBA1E);              //Green pixel in frist vertex	i2c_write(0x8F, 0xF7EC);              //Green pixel in second & third vertex	i2c_write(0x90, 0x3708);              //Green pixel in fourth & fifth vertex	i2c_write(0x91, 0x0064);              //Green pixel in sixth vertex	i2c_write(0x92, 0xBF1E);              //Blue pixel in frist vertex	i2c_write(0x93, 0xF7EE);              //Blue pixel in second & third vertex	i2c_write(0x94, 0x320F);              //Blue pixel in fourth & fifth vertex	i2c_write(0x95, 0x0064);              //Blue pixel in sixth vertex		return;}//photodiode black threshold calibrationstatic void im8012_black_threshold(void){    	unsigned short nValue;    		ic_select();	i2c_read(0x62, &nValue);    	i2c_write(0x62, nValue|=0x0001);     //Manual mode	i2c_write(0x5F, 0xA31D);             //Calibration(Calib) threshold	i2c_write(0x60, 0x001C);             //Calib Green1	i2c_write(0x61, 0x0024);             //Calib Green2	i2c_write(0x63, 0x0023);             //Calib Red	i2c_write(0x64, 0x0023);             //Calib Blue	i2c_write(0x62, nValue&=0xFFFE);     //Resume normal mode	return;}//pixel read mode control//(read pixel in reverse order)static void im8012_read_mode_ctrl(int vert_mirror, int hori_mirror){	//spec is not updated	unsigned short val;	ic_select();	i2c_read(0x20, &val);		if(vert_mirror)		val &= ~0x8080;	else		val |= 0x8080;	//reverse col order	if(hori_mirror)		val &= ~0x4020;	else		val |= 0x4020;	//reverse row order	i2c_write(0x20, val);		return;}//frame timing v-blank, h-blank controlstatic void im8012_blanking_ctrl(void){	ic_select();//set to minimum blanking time => max frame rate	i2c_write(0x05, 0x9);	i2c_write(0x06, 0x3);		return;}//set digital gamma correction//to be verifiedstatic void im8012_gamma_correction(int gamma){/*	//Formula read DataSheet Page 47	unsigned short Y[10] = {0};	double X[10] = {16, 32, 64, 128, 256, 384, 512, 640, 768, 896};	double nGamma;	int i, ii;	nGamma = (double)gamma / SCALEFAC;

⌨️ 快捷键说明

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