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

📄 im8012.c

📁 MX21 IM8012 driver This program is free software you can redistribute it and/or modify it under t
💻 C
📖 第 1 页 / 共 2 页
字号:
	for(i = 0; i < 10; i ++)	{		Y[i] = (unsigned int)(224 * pow(X[i] / 896, nGamma));	}	ifp_select();	 	for(ii = 0; ii < 5; ii ++)	{   		//Write 0x53~0x57 gamma value y1~y10		i2c_write(0x53 + ii, Y[ii * 2]|((Y[ii * 2] + 1) << 8)); 	}*/	return;}//set analog color gain//floating point is not supported in kernel mode??static void im8012_color_gain(int gain_green1, int gain_blue, int gain_red, int gain_green2, int gain_global){/*	//Formula read DataSheet Page 17	unsigned short nValue = 0x20;	double step = 0;	int add = 0;	double nGain[5];	int i;	nGain[0] = (double)gain_green1 / SCALEFAC;	nGain[1] = (double)gain_blue / SCALEFAC;	nGain[2] = (double)gain_red / SCALEFAC;	nGain[3] = (double)gain_green2 / SCALEFAC;	nGain[4] = (double)gain_global / SCALEFAC;	for(i = 0; i < 5; i ++)	{		if((nGain[i]>=1.0) && (nGain[i]<=1.969))		{ 			step = (1.969-1.0)/0.03125;			add= (int)((0x3F-0x20)/step);			step = (nGain[i]-1.0)/0.03125;			nValue = 0x20+(unsigned short)(step*add);		}		if((nGain[i]>=2.0) && (nGain[i]<=7.938))		{ 			step = (7.938-2.0)/0.0625;			add= (int)((0xFF-0xA0)/step);			step = (nGain[i]-2.0)/0.0625;			nValue = 0xA0+(unsigned short)(step*add);		}		if((nGain[i]>=8.0) && (nGain[i]<=15.875))		{ 			step = (15.875-8.0)/0.0125;			add= (int)((0x1FF-0x1C0)/step);			step = (nGain[i]-8.0)/0.0125;			nValue = 0x1C0+(unsigned short)(step*add);		}		if(i == 4)		{			//global gain			ic_select();			i2c_write(0x35, nValue);		}		else		{		//color gain			ic_select();			i2c_write(0x2B+i, nValue); 		}	}*/	return;}//frame rate control//0 = disable, i.e. variable frame ratestatic void im8012_frame_rate_control(int fps){	//not implemented	//using auto mode by default	return;}//color saturation, AWB, defect correctionstatic void im8012_color_processing(int colorsat){	unsigned short nValue;	ifp_select();		i2c_read(0x06, &nValue);//color correction	i2c_write(0x06, nValue &= 0xFF0F); //turn on 	//Auto White Balance(AWB)	i2c_write(0x06, nValue |= 0x0002); //turn on AWB	i2c_write(0x22, 0xD960);           //Red channel limit by AWB	i2c_write(0x23, 0xD960);           //Blue channel limit by AWB//AWB color saturation control	i2c_write(0x25, nValue |= 0x4000);  //turn on color saturation		switch(colorsat)	{		case 100:			i2c_write(0x25, 0x4514);	//100% color saturation=>Default			break;		case 150:			i2c_write(0x25, 0x6D14);	//150% color saturation			break;		case 75:			i2c_write(0x25, 0x4D14);	//75% color saturation			break;		case 50:			i2c_write(0x25, 0x5514);	//50% color saturation			break;		case 37:			i2c_write(0x25, 0x5D14);	//37.5% color saturation 			break;		case 25:			i2c_write(0x25, 0x6514);	//25% color saturation 			break;		case -1:			i2c_write(0x25, 0x7514);	//black and white			break;		case 0:			i2c_write(0x25, nValue & ~0x4000); 	//turn off color saturation			break;		default:			i2c_write(0x25, 0x4514);	//100% color saturation=>Default			break;	}//Defect Correction	i2c_write(0x06, nValue |= 0x2000);	//turn on defect correction	return;}static void im8012_sharpening(int sharpening){	ifp_select();		i2c_write(0x05, 0x0008);	//turn on , no sharpening		switch(sharpening)	{		case 0:			i2c_write(0x05, 0x0008);	//turn on , no sharpening			break;		case 25:			i2c_write(0x05, 0x0009);	//25% sharpening			break;		case 50:			i2c_write(0x05, 0x000A);	//50% sharpening    			break;		case 75:			i2c_write(0x05, 0x000B);	//75% sharpening=>Default			break;		case 100:			i2c_write(0x05, 0x000C);	//100% sharpening  				break;		case 125:			i2c_write(0x05, 0x000D);	//125% sharpening  			break;		case 150:			i2c_write(0x05, 0x000E);	//150% sharpening  			break;		case 200:			i2c_write(0x05, 0x000F);        //200% sharpening  			break;		default:			i2c_write(0x05, 0x000B);        //75% sharpening=>Default			break;	}		return;}//select awb areastatic void im8012_cal_awb_bound(int nLeft, int nRight, int nTop, int nBottom){	unsigned short val;//horizontal direction is divided by 64	nLeft /= 64;	nRight /= 64;//vertical direction is divided by 32	nTop /= 32;	nBottom /= 32;	val = (unsigned short)((nBottom & 0xF) << 12) | ((nTop & 0xF) << 8) | ((nRight & 0xF) << 4) | ((nLeft & 0xF));	ifp_select();	i2c_write(0x2D, val);}//test pattern generation//input -- pattern: 0=turn off, 1=color bar, 2=black, 3=white, 4=graystatic void im8012_test_pattern_enable(int pattern){ 	ifp_select();	switch(pattern)	{		case 0:			i2c_write(0x48, 0x00); //turn off			break;		case 1:			i2c_write(0x48, 0x07); //Color bar			break;		case 2:			i2c_write(0x48, 0x02); //Black			break;		case 3:			i2c_write(0x48, 0x06); //White			break;		case 4:			i2c_write(0x48, 0x04); //Gray			break;		default:			i2c_write(0x48, 0x07); //Color bar			break;	}	return;}//auto flicker cancellation//note -- still got little flickering//input -- freq: -1=off, 0=auto, 50=50Hz, 60=60Hzstatic void im8012_flicker_cancellation(int freq){	unsigned short data;		ifp_select();	switch(freq)	{		case -1:			//disable flicker cancellation			i2c_read(0x08, &data);			i2c_write(0x08, data & ~0x0800);			break;		case 0:			i2c_read(0x08, &data);			i2c_write(0x08, data | 0x0800);	//enable flicker cancellation			i2c_write(0x5B, 0x00);		//auto detect flicker freq			break;		case 50:			i2c_read(0x08, &data);			i2c_write(0x08, data | 0x0800);	//enable flicker cancellation			i2c_write(0x5B, 0x01);		//set flicker freq = 50			break;		case 60:			i2c_read(0x08, &data);			i2c_write(0x08, data | 0x0800);	//enable flicker cancellation			i2c_write(0x5B, 0x03);		//set flicker freq = 60			break;	}	return;}static void im8012_config(IM8012_CFG * _cfg){	im8012_hard_reset();	im8012_hard_standby_control(0);	im8012_soft_reset();	//dummy, just for testing	im8012_read_mode_ctrl(_cfg->vert_mirror, _cfg->hori_mirror);	im8012_blanking_ctrl();	im8012_lens_correction();	im8012_black_threshold();	im8012_cal_awb_bound(_cfg->awb_left, _cfg->awb_right, _cfg->awb_top, _cfg->awb_bottom);//	im8012_color_gain(_cfg->gain_green1, _cfg->gain_blue, _cfg->gain_red, _cfg->gain_green2, _cfg->gain_global);//	im8012_gamma_correction(_cfg->gamma);	im8012_sharpening(_cfg->sharpening);	im8012_color_processing(_cfg->colorsat);	im8012_decimation_ctrl(_cfg->out_width, _cfg->out_height);	im8012_color_fmt_ctrl(_cfg->color_format);	if(_cfg->test_pattern_enable)		im8012_test_pattern_enable(_cfg->test_pattern_enable);//	im8012_frame_rate_control(_cfg->fps);	im8012_flicker_cancellation(_cfg->afc_freq);		return;}void im8012_cleanup(void){//let sensor enter power saving mode	im8012_hard_reset();	im8012_hard_standby_control(1);		return;	}/*************************************************************************************************	sensor driver*************************************************************************************************///global staticstatic devfs_handle_t devfs_handle = NULL;static int gMajor = 0;static int g_im8012_busy = 0;static struct pm_dev *pmdev;static struct apmc_user *g_im8012_apmc;//functions and interfacestatic int im8012_open(struct inode *inode, struct file *filp);static int im8012_release(struct inode *inode, struct file *filp);static ssize_t im8012_read(struct file *filp, char *buf, size_t size, loff_t *l);static ssize_t im8012_write(struct file *filp, const char *buf, size_t size, loff_t *l);static int im8012_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int im8012_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data);struct file_operations im8012_fops = {	open:		im8012_open,	release:	im8012_release,	read:		im8012_read,	write:		im8012_write,	ioctl:		im8012_ioctl,};int __init init_module(){	int result;		printk("iMagic IM8012 Linux driver ver 0.1\n"		" - Copyright (C) 2004 Motorola Inc\n\n");	i2c_init();//register character device 	result = devfs_register_chrdev(0, "im8012", &im8012_fops); 	if ( result < 0 ) 	{		printk("im8012 error: Unable to register driver\n");		return -ENODEV;	}	devfs_handle = devfs_register(NULL, "im8012", DEVFS_FL_DEFAULT,				      result, 0,				      S_IFCHR | S_IRUSR | S_IWUSR,				      &im8012_fops, NULL);	if(devfs_handle == NULL)	{		printk("im8012 error: unable to register driver\n");		return -ENODEV;	}	gMajor = result;	g_im8012_busy = 0;//power management	if ((pmdev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, im8012_pm_handler)) == NULL)	{		printk("im8012 error: failed to register PM... continuing with driver init\n");	}	g_im8012_apmc = apmc_register(APMC_LEVEL_HIGHEST);   	return 0;}void __exit cleanup_module(){    	im8012_cleanup();	i2c_cleanup();	apmc_unregister(g_im8012_apmc);	pm_unregister(pmdev);   	if(gMajor > 0)   	{		if(devfs_unregister_chrdev(gMajor, "im8012") < 0)		{			printk("im8012 error: failed to unregister from devfs\n");			return;		}	}	if(devfs_handle != NULL)		devfs_unregister(devfs_handle);	else	{		printk("im8012 error: failed to unregister from devfs, devfs_handle = 0x%08X\n", (int)devfs_handle);		return;	}	printk("IM8012 driver unloaded sucessfully\n");		return;}static int im8012_open(struct inode *inode, struct file *filp){        MOD_INC_USE_COUNT; 	return 0;}static int im8012_release(struct inode *inode, struct file *filp){        MOD_DEC_USE_COUNT;	return 0;	}static ssize_t im8012_read(struct file *filp, char *buf, size_t size, loff_t *l){	printk("im8012: read ioctl not implemented\n");	return -1;}static ssize_t im8012_write(struct file *filp, const char *buf, size_t size, loff_t *l){	printk("im8012: write ioctl not implemented\n");	return -1;}static int im8012_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	switch(cmd)	{		case IM8012_IOC_CONFIG:		{			g_im8012_busy = 1;			if(copy_from_user((void *)&g_im8012_cfg, (void *)arg, sizeof(IM8012_CFG)))				return -EFAULT;		 	im8012_config(&g_im8012_cfg);		 	g_im8012_busy = 0;			break;		}		case IM8012_IOC_I2C_TEST:		{			g_im8012_busy = 1;			im8012_i2c_test();			g_im8012_busy = 0;						break;		}		case IM8012_IOC_READ_CONFIG:		{			if(copy_to_user((void *)arg, (void *)&g_im8012_cfg, sizeof(IM8012_CFG)))				return -EFAULT;							break;		}		case IM8012_IOC_SET_CAPTURE_MODE:		{			//if user does not specify the capture size,			//then use the config during im8012_config()			if(arg)			{				if(copy_from_user((void *)&g_im8012_cfg, (void *)arg, sizeof(IM8012_CFG)))					return -EFAULT;			}						//major thing is to change size			im8012_decimation_ctrl(g_im8012_cfg.capture_width, g_im8012_cfg.capture_height);			break;		}		case IM8012_IOC_SET_PREVIEW_MODE:		{			//if user does not specify the preview size,			//then use the config during im8012_config()			if(arg)			{				if(copy_from_user((void *)&g_im8012_cfg, (void *)arg, sizeof(IM8012_CFG)))					return -EFAULT;			}						//major thing is to change size			im8012_decimation_ctrl(g_im8012_cfg.out_width, g_im8012_cfg.out_height);			break;		}		case IM8012_IOC_STANDBY:		{			im8012_hard_standby_control(arg);						break;		}	}	return 0;}static int im8012_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data){	switch (rqst)	{		case PM_SUSPEND:		{			if(g_im8012_busy)			{				//does not allow suspend when i2c bus is running and configuring the sensor				return 1;			}			else			{				//put sensor into standby mode by gpio				im8012_hard_standby_control(1);				printk("im8012 suspend\n");			}			break;		}		case PM_RESUME:		{			im8012_hard_standby_control(0);			printk("im8012 resume\n");			break;		}	}		return 0;}

⌨️ 快捷键说明

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