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

📄 pxa_camera.c

📁 基于intel xscale下的linux系统camera驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*     pxa_camera - main file for camera driver	Copyright (C) 2003, Intel Corporation.    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., 675 Mass Ave, Cambridge, MA 02139, USA.    Code Status:    2004/10/19: Yan Yin <yan.yin@intel.com>        - Ported to 2.6 kernel		- Made camera driver a loadable module*/ #include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include <linux/interrupt.h>#include <linux/videodev.h>#include <linux/pci.h>#include <linux/pm.h>#include <linux/poll.h>#include <linux/wait.h>#include <linux/cpufreq.h>#include <linux/types.h>#include <asm/mach-types.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/hardware.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/arch/irqs.h>#include <asm/arch/pxa-regs.h>#include "camera.h"#include "ci.h"#if defined (CONFIG_MACH_MAINSTONE) && !defined(CONFIG_ARCH_FS_PXA27X)	//hzh#define   ADCM2650#elif defined(CONFIG_ARCH_FS_PXA27X)	//hzh#define   OV9650#else#define   OV9640#endif#ifdef ADCM2650#include "adcm2650.h"#include "adcm2650_hw.h"#endif#ifdef OV9640#include "ov9640.h"#include "ov9640_hw.h"#endif#ifdef OV9650	//hzh#include "ov9650.h"//#include "ov9650_hw.h"#endif#define CIBR0_PHY	(0x50000000 + 0x28)#define CIBR1_PHY	(0x50000000 + 0x30)#define CIBR2_PHY	(0x50000000 + 0x38)#ifdef ADCM2650#define MAX_WIDTH	480#define MAX_HEIGHT	640#define MIN_WIDTH	72#define MIN_HEIGHT	72#endif#ifdef OV9640#define MAX_WIDTH	640#define MAX_HEIGHT	480#define MIN_WIDTH	88#define MIN_HEIGHT	72#endif#ifdef OV9650	//hzh#define MAX_WIDTH	1280#define MAX_HEIGHT	1024#define MIN_WIDTH	88#define MIN_HEIGHT	72#endif#define WIDTH_DEFT	176#define HEIGHT_DEFT	144#define FRAMERATE_DEFT	0x0#define BUF_SIZE_DEFT	0xEA600//0xE1000	//hzh#define SINGLE_DESC_TRANS_MAX  	8000#define MAX_DESC_NUM	0x400#define MAX_BLOCK_NUM	20/* * Buffer Size Calculate Formula * Buffer_Size = Page_Align (Max(window_size(VGA), window_size(CIF)*3) * Max(BPP)) * Buffer_Size = Page_Align (Max ((640 * 480), (352 * 288 *3)) * 3) = 0xE1000 */static camera_context_t  *g_camera_context = NULL;struct device *g_camera_device;#ifdef ADCM2650static camera_function_t  adcm2650_func;#endif#ifdef OV9640static camera_function_t  ov9640_func;#endif#ifdef OV9650	//hzhstatic camera_function_t  ov9650_func;#endifwait_queue_head_t  camera_wait_q;	/* /dev/videoX registration number */static int 	minor = 0;int		ci_dma_y;int		ci_dma_cb;int		ci_dma_cr;volatile int 	task_waiting = 0;static int 	still_image_mode = 0;static int	still_image_rdy	= 0;static int 	first_video_frame = 0;void pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs);void pxa_ci_dma_irq_cb(int channel, void *data, struct pt_regs *regs);void pxa_ci_dma_irq_cr(int channel, void *data, struct pt_regs *regs);static unsigned long ci_regs_base = 0;   /* for CI registers IOMEM mapping */#define CI_REG(x)             (* (volatile u32*)(x) )#define CI_REG_SIZE             0x40 /* 0x5000_0000 --- 0x5000_0038 * 64K */#define CI_REGS_PHYS            0x50000000  /* Start phyical address of CI registers *//*********************************************************************** * * Declarations * ***********************************************************************/// map of camera image format (camera.h) ==> capture interface format (ci.h)static const CI_IMAGE_FORMAT FORMAT_MAPPINGS[] = {        CI_RAW8,                   //RAW        CI_RAW9,        CI_RAW10,        CI_RGB444,                 //RGB        CI_RGB555,        CI_RGB565,        CI_RGB666_PACKED,          //RGB Packed         CI_RGB666,        CI_RGB888_PACKED,        CI_RGB888,        CI_RGBT555_0,              //RGB+Transparent bit 0        CI_RGBT888_0,        CI_RGBT555_1,              //RGB+Transparent bit 1          CI_RGBT888_1,            CI_INVALID_FORMAT,        CI_YCBCR422,               //YCBCR        CI_YCBCR422_PLANAR,        //YCBCR Planaried        CI_INVALID_FORMAT,        CI_INVALID_FORMAT};static int update_dma_chain( p_camera_context_t camera_context );static void start_dma_transfer( p_camera_context_t camera_context, unsigned block_id );static void stop_dma_transfer( p_camera_context_t camera_context );static int start_capture( p_camera_context_t camera_context, unsigned int block_id, unsigned int frames );void pxa_dma_repeat(camera_context_t  *cam_ctx);void pxa_dma_continue(camera_context_t *cam_ctx);/*********************************************************************** * * Private functions * ***********************************************************************//*Generate dma descriptorsPre-condition: these variables must be set properly                block_number, fifox_transfer_size                 dma_descriptors_virtual, dma_descriptors_physical, dma_descirptors_sizePost-condition: these variables will be set                fifox_descriptors_virtual, fifox_descriptors_physical                              fifox_num_descriptors */int update_dma_chain( p_camera_context_t camera_context ){	pxa_dma_desc *cur_des_virtual, *cur_des_physical, *last_des_virtual = NULL;	int des_transfer_size, remain_size;	unsigned int i,j;	int target_physical;	int target_virtual;	// clear descriptor pointers	camera_context->fifo0_descriptors_virtual = camera_context->fifo0_descriptors_physical = 0;	camera_context->fifo1_descriptors_virtual = camera_context->fifo1_descriptors_physical = 0;	camera_context->fifo2_descriptors_virtual = camera_context->fifo2_descriptors_physical = 0;	// calculate how many descriptors are needed per frame	camera_context->fifo0_num_descriptors = ( camera_context->fifo0_transfer_size + SINGLE_DESC_TRANS_MAX -1 )		 / SINGLE_DESC_TRANS_MAX;	camera_context->fifo1_num_descriptors = ( camera_context->fifo1_transfer_size + SINGLE_DESC_TRANS_MAX -1 )		 / SINGLE_DESC_TRANS_MAX;	camera_context->fifo2_num_descriptors = ( camera_context->fifo2_transfer_size + SINGLE_DESC_TRANS_MAX -1 )		 / SINGLE_DESC_TRANS_MAX;	// check if enough memory to generate descriptors	if ( (camera_context->fifo0_num_descriptors + camera_context->fifo1_num_descriptors +  			camera_context->fifo2_num_descriptors) * camera_context->block_number 			> camera_context->dma_descriptors_size)		return -1;	// generate fifo0 dma chains	camera_context->fifo0_descriptors_virtual = (unsigned)camera_context->dma_descriptors_virtual;	camera_context->fifo0_descriptors_physical = (unsigned)camera_context->dma_descriptors_physical;	cur_des_virtual = (pxa_dma_desc *)camera_context->fifo0_descriptors_virtual;	cur_des_physical = (pxa_dma_desc *)camera_context->fifo0_descriptors_physical;	for(i=0; i<camera_context->block_number; i++) {		// in each iteration, generate one dma chain for one frame		remain_size = camera_context->fifo0_transfer_size;		// assume the blocks are stored consecutively		target_physical = (unsigned)camera_context->buffer_physical + camera_context->block_size * i;		target_virtual = (unsigned)camera_context->buffer_virtual + camera_context->block_size * i;				for(j=0; j<camera_context->fifo0_num_descriptors; j++) {			 // set descriptor		        if (remain_size > SINGLE_DESC_TRANS_MAX)         			des_transfer_size = SINGLE_DESC_TRANS_MAX;        		else		       		des_transfer_size = remain_size;		        cur_des_virtual->ddadr = (unsigned)cur_des_physical + sizeof(pxa_dma_desc);        		cur_des_virtual->dsadr = CIBR0_PHY;       // FIFO0 physical address        		cur_des_virtual->dtadr = target_physical;        		cur_des_virtual->dcmd = des_transfer_size | DCMD_FLOWSRC | DCMD_INCTRGADDR | DCMD_BURST32;		        // advance pointers        		remain_size -= des_transfer_size;        		cur_des_virtual++;		        cur_des_physical++;        		target_physical += des_transfer_size;		        target_virtual += des_transfer_size;		}        		// stop the dma transfer on one frame captured		last_des_virtual = cur_des_virtual - 1;		//last_des_virtual->ddadr |= 0x1;	}	last_des_virtual->ddadr = ((unsigned)camera_context->fifo0_descriptors_physical);    	// generate fifo1 dma chains	if (camera_context->fifo1_transfer_size) {		// record fifo1 descriptors' start address		camera_context->fifo1_descriptors_virtual = (unsigned)cur_des_virtual;		camera_context->fifo1_descriptors_physical = (unsigned)cur_des_physical;		for(i=0; i<camera_context->block_number; i++) {			// in each iteration, generate one dma chain for one frame			remain_size = camera_context->fifo1_transfer_size;        		// assume the blocks are stored consecutively        		target_physical = (unsigned)camera_context->buffer_physical + camera_context->block_size * i         	                    + camera_context->fifo0_transfer_size;        		target_virtual = (unsigned)camera_context->buffer_virtual + camera_context->block_size * i         	                    + camera_context->fifo0_transfer_size;            		for(j=0; j<camera_context->fifo1_num_descriptors; j++) {        		        // set descriptor        			if (remain_size > SINGLE_DESC_TRANS_MAX)         		            des_transfer_size = SINGLE_DESC_TRANS_MAX;        		        else        		            des_transfer_size = remain_size;        		        cur_des_virtual->ddadr = (unsigned)cur_des_physical + sizeof(pxa_dma_desc);        		        cur_des_virtual->dsadr = CIBR1_PHY;      // FIFO1 physical address        		        cur_des_virtual->dtadr = target_physical;        		        cur_des_virtual->dcmd = des_transfer_size | DCMD_FLOWSRC | DCMD_INCTRGADDR | DCMD_BURST32;            		        // advance pointers        		        remain_size -= des_transfer_size;        		        cur_des_virtual++;        		        cur_des_physical++;        		        target_physical += des_transfer_size;        		        target_virtual += des_transfer_size;        			}        		// stop the dma transfer on one frame captured        		last_des_virtual = cur_des_virtual - 1;			//last_des_virtual->ddadr |= 0x1;        	}		last_des_virtual->ddadr = ((unsigned)camera_context->fifo1_descriptors_physical);	}    	// generate fifo2 dma chains	if (camera_context->fifo2_transfer_size) {		// record fifo1 descriptors' start address		camera_context->fifo2_descriptors_virtual = (unsigned)cur_des_virtual;		camera_context->fifo2_descriptors_physical = (unsigned)cur_des_physical;		for(i=0; i<camera_context->block_number; i++) {			// in each iteration, generate one dma chain for one frame			remain_size = camera_context->fifo2_transfer_size;			// assume the blocks are stored consecutively			target_physical = (unsigned)camera_context->buffer_physical + camera_context->block_size * i                             + camera_context->fifo0_transfer_size + camera_context->fifo1_transfer_size;    		        for(j=0; j<camera_context->fifo2_num_descriptors; j++) {                		// set descriptor                		if (remain_size > SINGLE_DESC_TRANS_MAX)                 			des_transfer_size = SINGLE_DESC_TRANS_MAX;                		else                			des_transfer_size = remain_size;                		cur_des_virtual->ddadr = (unsigned)cur_des_physical + sizeof(pxa_dma_desc);                		cur_des_virtual->dsadr = CIBR2_PHY;      // FIFO2 physical address                		cur_des_virtual->dtadr = target_physical;                		cur_des_virtual->dcmd = des_transfer_size | DCMD_FLOWSRC | DCMD_INCTRGADDR | DCMD_BURST32;                    		// advance pointers                		remain_size -= des_transfer_size;                		cur_des_virtual++;                		cur_des_physical++;                		target_physical += des_transfer_size;		        }		        // stop the dma transfer on one frame captured        		last_des_virtual = cur_des_virtual - 1;			//last_des_virtual->ddadr |= 0x1;        	}		last_des_virtual->ddadr = ((unsigned)camera_context->fifo2_descriptors_physical);	}	return 0;   }void start_dma_transfer( p_camera_context_t camera_context, unsigned block_id ){	pxa_dma_desc *des_virtual, *des_physical;    	if (block_id >= camera_context->block_number)        	return;        	// start channel 0	des_virtual = (pxa_dma_desc *)camera_context->fifo0_descriptors_virtual 		+ block_id * camera_context->fifo0_num_descriptors;	des_physical = (pxa_dma_desc *)camera_context->fifo0_descriptors_physical 		+ block_id * camera_context->fifo0_num_descriptors;        DDADR(camera_context->dma_channels[0]) = (int) des_physical;        DCSR(camera_context->dma_channels[0]) |= DCSR_RUN;	// start channel 1	if ( camera_context->fifo1_descriptors_virtual ) {		des_virtual = (pxa_dma_desc *)camera_context->fifo1_descriptors_virtual + 			block_id * camera_context->fifo1_num_descriptors;		des_physical = (pxa_dma_desc *)camera_context->fifo1_descriptors_physical + 			block_id * camera_context->fifo1_num_descriptors;                DDADR(camera_context->dma_channels[1]) = (int) des_physical;                DCSR(camera_context->dma_channels[1]) |= DCSR_RUN;	}	// start channel 2	if ( camera_context->fifo2_descriptors_virtual ) {		des_virtual = (pxa_dma_desc *)camera_context->fifo2_descriptors_virtual + 			block_id * camera_context->fifo2_num_descriptors;		des_physical = (pxa_dma_desc *)camera_context->fifo2_descriptors_physical + 			block_id * camera_context->fifo2_num_descriptors;                DDADR(camera_context->dma_channels[2]) = (int) des_physical;                DCSR(camera_context->dma_channels[2]) |= DCSR_RUN;	}}void stop_dma_transfer( p_camera_context_t camera_context ){	        int ch0, ch1, ch2;        ch0 = camera_context->dma_channels[0];        ch1 = camera_context->dma_channels[1];        ch2 = camera_context->dma_channels[2];        DCSR(ch0) &= ~DCSR_RUN;        DCSR(ch1) &= ~DCSR_RUN;        DCSR(ch2) &= ~DCSR_RUN;	return;}int start_capture( p_camera_context_t camera_context, unsigned int block_id, unsigned int frames ){	int   status;	// clear ci fifo	ci_reset_fifo();	ci_clear_int_status(0xFFFFFFFF);	// start dma	start_dma_transfer(camera_context, block_id);		// start capture	status = camera_context->camera_functions->start_capture(camera_context, frames);	return status;}/*********************************************************************** * * Init/Deinit APIs * ***********************************************************************/int camera_init( p_camera_context_t camera_context ){	int   ret = 0;

⌨️ 快捷键说明

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