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

📄 csi.c

📁 This program is free software you can redistribute it and/or modify * it under the terms of the GN
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MX21 CSI 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. * *//***@defgroup CSI CSI driver*//**@{*//** *@file csi.c *@brief CSI driver source file * *  linux/drivers/csi/csi.c */#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/pm.h>#include <asm/arch/apmc.h>#include "csi.h"/********************************************************************************---------------------------- HARDWARE SPECIFIC -------------------------------*///tapeout 2 specific#ifndef _reg_CSI_CSICR3#define _reg_CSI_CSICR3	(*((volatile unsigned long *)(CSI_IO_ADDRESS(CSI_BASE_ADDR+0x1C))))#endif//globalstatic int g_csi_ver = 2;	//version check	//-- should be done by s/w, however in current csi design, there is no way to distinguish	//   TO1 & 2 by softwarestatic int g_csi_busy = 0;static CSI_CFG g_csi_cfg;static CSI_STATUS g_csi_status;	//cache copy of csi status register//localstatic void csihw_read_config(CSI_CFG * _cfg);static void csihw_config(CSI_CFG * _cfg);static int csihw_poll(unsigned int * _buf, int byte_size);static void csihw_reset_frame_count(void);static int csihw_get_frame_count(void);static int csihw_pol_eof(int rxcnt);	//blockstatic int csihw_pol_sof(void);		//blockstatic void csihw_clock_enable(void);static void csihw_clock_disable(void);static void csihw_reset(void);//reset values#define CSICR1_RESET_VAL	0x40000800#define CSICR2_RESET_VAL	0x0#define CSICR3_RESET_VAL	0x0//csi control reg 1#define BIT_SWAP16_EN		(0x1 << 31)#define BIT_EXT_VSYNC		(0x1 << 30)#define BIT_EOF_INT_EN		(0x1 << 29)#define BIT_PRP_IF_EN		(0x1 << 28)#define BIT_CCIR_MODE		(0x1 << 27)#define BIT_COF_INT_EN		(0x1 << 26)#define BIT_SF_OR_INTEN		(0x1 << 25)#define BIT_RF_OR_INTEN		(0x1 << 24)#define BIT_STATFF_LEVEL	(0x3 << 22)#define BIT_STATFF_INTEN	(0x1 << 21)#define BIT_RXFF_LEVEL		(0x3 << 19)#define BIT_RXFF_INTEN		(0x1 << 18)#define BIT_SOF_POL		(0x1 << 17)#define BIT_SOF_INTEN		(0x1 << 16)#define BIT_MCLKDIV		(0xF << 12)#define BIT_HSYNC_POL		(0x1 << 11)#define BIT_CCIR_EN		(0x1 << 10)#define BIT_MCLKEN		(0x1 << 9)#define BIT_FCC			(0x1 << 8)#define BIT_PACK_DIR		(0x1 << 7)#define BIT_CLR_STATFIFO	(0x1 << 6)#define BIT_CLR_RXFIFO		(0x1 << 5)#define BIT_GCLK_MODE		(0x1 << 4)#define BIT_INV_DATA		(0x1 << 3)#define BIT_INV_PCLK		(0x1 << 2)#define BIT_REDGE		(0x1 << 1)#define SHIFT_STATFF_LEVEL	22#define SHIFT_RXFF_LEVEL	19#define SHIFT_MCLKDIV		12//control reg 3#define BIT_FRMCNT		(0xFFFF << 16)#define BIT_FRMCNT_RST		(0x1 << 15)#define BIT_CSI_SUP		(0x1 << 3)#define BIT_ZERO_PACK_EN	(0x1 << 2)#define BIT_ECC_INT_EN		(0x1 << 1)#define BIT_ECC_AUTO_EN		(0x1)#define SHIFT_FRMCNT		16//csi status reg#define BIT_SFF_OR_INT	(0x1 << 25)#define BIT_RFF_OR_INT	(0x1 << 24)#define BIT_STATFF_INT	(0x1 << 21)#define BIT_RXFF_INT	(0x1 << 18)#define BIT_EOF_INT	(0x1 << 17)#define BIT_SOF_INT	(0x1 << 16)#define BIT_F2_INT	(0x1 << 15)#define BIT_F1_INT	(0x1 << 14)#define BIT_COF_INT	(0x1 << 13)#define BIT_ECC_INT	(0x1 << 1)#define BIT_DRDY	(0x1 << 0)static void csihw_read_status(CSI_STATUS * _status){	_status->sff_or_int = (_reg_CSI_CSISR & BIT_SFF_OR_INT) ? 1 : 0;	_status->rff_or_int = (_reg_CSI_CSISR & BIT_RFF_OR_INT) ? 1 : 0;	_status->statff_int = (_reg_CSI_CSISR & BIT_STATFF_INT) ? 1 : 0;	_status->rxff_int = (_reg_CSI_CSISR & BIT_RXFF_INT) ? 1 : 0;	_status->eof_int = (_reg_CSI_CSISR & BIT_EOF_INT) ? 1 : 0;	_status->sof_int = (_reg_CSI_CSISR & BIT_SOF_INT) ? 1 : 0;	_status->f2_int = (_reg_CSI_CSISR & BIT_F2_INT) ? 1 : 0;	_status->f1_int = (_reg_CSI_CSISR & BIT_F1_INT) ? 1 : 0;	_status->cof_int = (_reg_CSI_CSISR & BIT_COF_INT) ? 1 : 0;	_status->ecc_int = (_reg_CSI_CSISR & BIT_ECC_INT) ? 1 : 0;	_status->drdy = (_reg_CSI_CSISR & BIT_DRDY) ? 1 : 0;		return;}static void csi_irq_handler(int irq, void * data, struct pt_regs * pt){	csihw_read_status(&g_csi_status);//go to individual handlers//leave it untouched if user has not enabled the interrupt	if(g_csi_cfg.rf_or_inten)	{		if(g_csi_status.rff_or_int)		{			g_csi_status.rff_or_int = 0;						printk("csi error: rxff overflow\n");					//flush fifo			_reg_CSI_CSICR1 &= ~BIT_FCC;			_reg_CSI_CSICR1 |= BIT_CLR_RXFIFO;			if(g_csi_cfg.fcc)				_reg_CSI_CSICR1 |= BIT_FCC;						_reg_CSI_CSISR = BIT_RFF_OR_INT;		}	}	if(g_csi_cfg.sof_inten)	{		if(g_csi_status.sof_int)		{			_reg_CSI_CSISR = BIT_SOF_INT;			g_csi_status.sof_int = 0;		}	}		return;}static void csihw_read_config(CSI_CFG * _cfg){	unsigned int tmp;	unsigned val;//1. read from register	//control reg 1	val = _reg_CSI_CSICR1;	_cfg->swap16_en = (val & BIT_SWAP16_EN)? 1 : 0;	_cfg->ext_vsync = (val & BIT_EXT_VSYNC)? 1 : 0;	_cfg->eof_int_en = (val & BIT_EOF_INT_EN)? 1 : 0;	_cfg->prp_if_en = (val & BIT_PRP_IF_EN)? 1 : 0;	_cfg->ccir_mode = (val & BIT_CCIR_MODE)? 1 : 0;	_cfg->cof_int_en = (val & BIT_COF_INT_EN)? 1 : 0;	_cfg->sf_or_inten = (val & BIT_SF_OR_INTEN)? 1 : 0;	_cfg->rf_or_inten = (val & BIT_RF_OR_INTEN)? 1 : 0;		tmp = (val & BIT_STATFF_LEVEL) >> SHIFT_STATFF_LEVEL;	if(tmp == 0x3)		_cfg->statff_level = 16;	else if(tmp == 0x2)		_cfg->statff_level = 12;	else if(tmp == 0x1)		_cfg->statff_level = 8;	else		_cfg->statff_level = 4;			_cfg->staff_inten = (val & BIT_STATFF_INTEN)? 1 : 0;		tmp = (val & BIT_RXFF_LEVEL) >> SHIFT_RXFF_LEVEL;	if(tmp == 0x3)		_cfg->rxff_level = 24;	else if(tmp == 0x2)		_cfg->rxff_level = 16;	else if(tmp == 0x1)		_cfg->rxff_level = 8;	else		_cfg->rxff_level = 4;			_cfg->rxff_inten = (val & BIT_RXFF_INTEN)? 1 : 0;	_cfg->sof_pol = (val & BIT_SOF_POL)? 1 : 0;	_cfg->sof_inten = (val & BIT_SOF_INTEN)? 1 : 0;	tmp = (val & BIT_MCLKDIV) >> SHIFT_MCLKDIV;	_cfg->mclkdiv = (tmp + 1) * 2;		_cfg->hsync_pol = (val & BIT_HSYNC_POL)? 1 : 0;	_cfg->ccir_en = (val & BIT_CCIR_EN)? 1 : 0;	_cfg->mclken = (val & BIT_MCLKEN)? 1 : 0;	_cfg->fcc = (val & BIT_FCC)? 1 : 0;	_cfg->pack_dir = (val & BIT_PACK_DIR)? 1 : 0;		_cfg->gclk_mode = (val & BIT_GCLK_MODE)? 1 : 0;	_cfg->inv_data = (val & BIT_INV_DATA)? 1 : 0;	_cfg->inv_pclk = (val & BIT_INV_PCLK)? 1 : 0;	_cfg->redge = (val & BIT_REDGE)? 1 : 0;	//control reg 3	val = _reg_CSI_CSICR3;	_cfg->csi_sup = (val & BIT_CSI_SUP)? 1 : 0;	_cfg->zero_pack_en = (val & BIT_ZERO_PACK_EN)? 1 : 0;	_cfg->ecc_int_en = (val & BIT_ECC_INT_EN)? 1 : 0;	_cfg->ecc_auto_en = (val & BIT_ECC_AUTO_EN)? 1 : 0;		//rxfifo reg	val = _reg_CSI_CSIRXCNT;	//keep system settings	_cfg->module_irq_enable = g_csi_cfg.module_irq_enable;//2. update global config	memcpy(&g_csi_cfg, _cfg, sizeof(CSI_CFG));	return;}static void csihw_config(CSI_CFG * _cfg){	unsigned int tmp;	unsigned val = 0x0;	int rt;//1. write to registers	//control reg 1	if(_cfg->swap16_en)		val |= BIT_SWAP16_EN;	if(_cfg->ext_vsync)		val |= BIT_EXT_VSYNC;	if(_cfg->eof_int_en)		val |= BIT_EOF_INT_EN;	if(_cfg->prp_if_en)		val |= BIT_PRP_IF_EN;	if(_cfg->ccir_mode)		val |= BIT_CCIR_MODE;	if(_cfg->cof_int_en)		val |= BIT_COF_INT_EN;	if(_cfg->sf_or_inten)		val |= BIT_SF_OR_INTEN;	if(_cfg->rf_or_inten)		val |= BIT_RF_OR_INTEN;	if(_cfg->statff_level == 16)		tmp = 0x3;	else if(_cfg->statff_level == 12)		tmp = 0x2;	else if(_cfg->statff_level == 8)		tmp = 0x1;	else		tmp = 0x0;	val |= (tmp << SHIFT_STATFF_LEVEL);	if(_cfg->staff_inten)		val|= BIT_STATFF_INTEN;		if(_cfg->rxff_level == 24)		tmp = 0x3;	else if(_cfg->rxff_level == 16)		tmp = 0x2;	else if(_cfg->rxff_level == 8)		tmp = 0x1;	else		tmp = 0x0;	val |= (tmp << SHIFT_RXFF_LEVEL);			if(_cfg->rxff_inten)		val |= BIT_RXFF_INTEN;	if(_cfg->sof_pol)		val |= BIT_SOF_POL;	if(_cfg->sof_inten)		val |= BIT_SOF_INTEN;	tmp = (_cfg->mclkdiv / 2) - 1;	val |= (tmp << SHIFT_MCLKDIV);		if(_cfg->hsync_pol)		val |= BIT_HSYNC_POL;	if(_cfg->ccir_en)		val |= BIT_CCIR_EN;	if(_cfg->mclken)		val |= BIT_MCLKEN;	if(_cfg->fcc)		val |= BIT_FCC;	if(_cfg->pack_dir)		val |= BIT_PACK_DIR;		if(_cfg->gclk_mode)		val |= BIT_GCLK_MODE;	if(_cfg->inv_data)		val |= BIT_INV_DATA;	if(_cfg->inv_pclk)		val |= BIT_INV_PCLK;	if(_cfg->redge)		val |= BIT_REDGE;		_reg_CSI_CSICR1 = val;	//control reg 3	val = 0x0;	if(_cfg->csi_sup)		val |= BIT_CSI_SUP;	if(_cfg->zero_pack_en)		val |= BIT_ZERO_PACK_EN;	if(_cfg->ecc_int_en)		val |= BIT_ECC_INT_EN;	if(_cfg->ecc_auto_en)		val |= BIT_ECC_AUTO_EN;			_reg_CSI_CSICR3 = val;	//rxfifo counter	_reg_CSI_CSIRXCNT = _cfg->rxcnt;//2. update global config	memcpy(&g_csi_cfg, _cfg, sizeof(CSI_CFG));//3. interrupt enable	if(_cfg->module_irq_enable)	{		rt = request_irq(INT_CSI, 			  	 csi_irq_handler,			  	 SA_INTERRUPT,				 "csi",				 "csi");		if(rt)			printk("csi error: irq request fail\n");	}	//4. init status flags	memset(&g_csi_status, 0, sizeof(CSI_CFG));	return;}//nothing special, simply set gpiostatic void csihw_init(void){//disable GPIO PB[21..10]	_reg_GPIO_GIUS(GPIOB) &= ~0x3FFC00;//note -- csi version check should be here...	return;}static void csihw_cleanup(void){//resume GPIO PB[21..10]	_reg_GPIO_GIUS(GPIOB) |= 0x3FFC00;	csihw_clock_disable();	csihw_reset();	return;}//generate default mclk to drive sensorstatic void csihw_open(void){	unsigned int val;	unsigned int perclk4div = 3;	//default set to fclk/3 => 88MHz	unsigned int mclkdiv = 4;	//default set to perclk4/4 => 22MHz	csihw_clock_enable();//set default perclk4 for mclk	if(g_csi_ver == 2)	{		val = _reg_CRM_PCDR1;		val &= ~(0x3F << 24);		val |= (perclk4div - 1) << 24;		_reg_CRM_PCDR1 = val;	}	csihw_reset();	//enable default mclk clock	val = CSICR1_RESET_VAL;	val |= ((mclkdiv / 2) - 1) << SHIFT_MCLKDIV;	val |= BIT_MCLKEN;	_reg_CSI_CSICR1 = val;	return;}static void csihw_release(void){	//nothing to do	//as a result, the csi state will not unchange unless the module is unloaded		return;}//Read a frame by pollingstatic int csihw_poll(unsigned int * _buf, int byte_size){	int i, j;	int word_size = byte_size >> 2;	unsigned int *_kbuf = NULL;

⌨️ 快捷键说明

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