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

📄 pxa_camera.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  pxa_camera.c * *  Bulverde Processor Camera Interface driver. * *  Copyright (C) 2003, Intel Corporation *  Copyright (C) 2003, Montavista Software Inc. * *  Author: Intel Corporation Inc. *          MontaVista Software, Inc. *           source@mvista.com *  *  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. * */#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/wrapper.h>#include <linux/videodev.h>#include <linux/pci.h>#include <linux/pm.h>#include <linux/poll.h>#include <linux/wait.h>#ifdef CONFIG_DPM#include <linux/device.h>#include <asm/arch/ldm.h>#endif#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 "pxa_camera.h"#include "adcm2650.h"#include "adcm2650_hw.h"#define PREFIX "PXA camera: "#define CIBR0_PHY	(0x50000000 + 0x28)#define CIBR1_PHY	(0x50000000 + 0x30)#define CIBR2_PHY	(0x50000000 + 0x38)#define MAX_BPP		32#define MAX_WIDTH	1200 //yul 480 640 #define MAX_HEIGHT	1600#define MIN_WIDTH	72#define MIN_HEIGHT	72#define WIDTH_DEFT	240//800 176 yul #define HEIGHT_DEFT	320//600 144 #define FRAMERATE_DEFT	0x0 //0x0  yul(0x7)#define BUF_SIZE_DEFT	0x400000// 0xE1000 0x400000 800*600*4 yul 6 frame#define SINGLE_DESC_TRANS_MAX  	8000#define MAX_DESC_NUM	0x400#define MAX_BLOCK_NUM	0x400static camera_context_t  *g_camera_context = NULL;static camera_function_t  adcm2650_func;wait_queue_head_t  camera_wait_q;	/* /dev/videoX registration number */static int 	minor = 0;static int	ci_dma_y = -1;static int	ci_dma_cb = -1;static int	ci_dma_cr = -1;static 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 */#define CICR0		        CI_REG((u32)(ci_regs_base) + 0x00)#define CICR1           	CI_REG((u32)(ci_regs_base) + 0x04)#define CICR2 		        CI_REG((u32)(ci_regs_base) + 0x08)#define CICR3           	CI_REG((u32)(ci_regs_base) + 0x0c)#define CICR4             	CI_REG((u32)(ci_regs_base) + 0x10)#define CISR 	        	CI_REG((u32)(ci_regs_base) + 0x14)#define CIFR              	CI_REG((u32)(ci_regs_base) + 0x18)#define CITOR             	CI_REG((u32)(ci_regs_base) + 0x1c)#define CIBR0             	CI_REG((u32)(ci_regs_base) + 0x28)#define CIBR1             	CI_REG((u32)(ci_regs_base) + 0x30)#define CIBR2             	CI_REG((u32)(ci_regs_base) + 0x38)/*********************************************************************** * * 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,        CI_YCBCR420_PLANAR,        CI_YCBCR420,               added by yul @2006-1-12 10:04 */        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 );static void pxa_dma_repeat(camera_context_t  *cam_ctx);static void pxa_dma_continue(camera_context_t *cam_ctx);/*************** * * DPM functions * ***************/#ifdef CONFIG_DPMstatic int last_buffer_id;static int pxa_camera_dpm_suspend(struct device *dev, u32 state, u32 level){	printk(KERN_DEBUG PREFIX "DPM suspend (state %d, level %d)\n", state, level);	switch (level) {        case SUSPEND_POWER_DOWN:		if (g_camera_context->dma_started) {			printk(KERN_DEBUG PREFIX "DMA running, suspended\n");			last_buffer_id = camera_get_last_frame_buffer_id(g_camera_context);			stop_dma_transfer(g_camera_context);		}		disable_irq(IRQ_CAMERA);		CKEN &= ~CKEN24_CAMERA;                break;	}        return 0;}static int pxa_camera_dpm_resume(struct device *dev, u32 level){        printk(KERN_DEBUG PREFIX "DPM resume (level %d)\n", level);        switch (level) {        case RESUME_POWER_ON:		CKEN |= CKEN24_CAMERA;		enable_irq(IRQ_CAMERA);		if (g_camera_context->dma_started) {			printk(KERN_DEBUG PREFIX "resume DMA\n");			start_dma_transfer(g_camera_context, last_buffer_id);		}                break;	}	return 0;}static int pxa_camera_dpm_scale(struct bus_op_point *op, u32 level){        printk(KERN_DEBUG PREFIX "DPM scale (level %d)\n", level);	/* CCCR is changed - adjust clock */	ci_set_clock(g_camera_context->clk_reg_base, 1, 1, 7 /* MCLK_DEFT in adcm2650.c */);        return 0;}static struct device_driver pxa_camera_driver_ldm = {        name:           "camera",        devclass:       NULL,        probe:          NULL,        suspend:        pxa_camera_dpm_suspend,        resume:         pxa_camera_dpm_resume,        scale:          pxa_camera_dpm_scale,        remove:         NULL,};static struct device pxa_camera_device_ldm = {        name:           "PXA camera",        bus_id:         "video",        driver:         NULL,        power_state:    DPM_POWER_ON};static void pxa_camera_ldm_register(void){        pxaebc_driver_register(&pxa_camera_driver_ldm);        pxaebc_device_register(&pxa_camera_device_ldm);}static void pxa_camera_ldm_unregister(void){        pxaebc_driver_unregister(&pxa_camera_driver_ldm);        pxaebc_device_unregister(&pxa_camera_device_ldm);}#endif /* CONFIG_DPM *//*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;	// 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;//yulu #if 0	printk("\n camera_context->fifo0_descriptors_virtual = 0x%x",camera_context->fifo0_descriptors_virtual);	printk("\n camera_context->fifo0_descriptors_physical = 0x%x",camera_context->fifo0_descriptors_physical);	printk("\n camera_context->buffer_physical = 0x%x",camera_context->buffer_physical);	printk("\n camera_context->buffer_virtual = 0x%x",camera_context->buffer_virtual);//0xc8862000//0xa0d64000//0xa0400000//0xc8867000#endif		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;		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;		}        		// 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;#if 0	printk("\n camera_context->fifo1_descriptors_virtual = 0x%x",camera_context->fifo1_descriptors_virtual);	printk("\n camera_context->fifo1_descriptors_physical = 0x%x",camera_context->fifo1_descriptors_physical);	printk("\n camera_context->buffer_physical = 0x%x",camera_context->buffer_physical);	printk("\n camera_context->buffer_virtual = 0x%x",camera_context->buffer_virtual);#endif			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;        		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;       			}        		// 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;#if 0	printk("\n camera_context->fifo2_descriptors_virtual = 0x%x",camera_context->fifo2_descriptors_virtual);	printk("\n camera_context->fifo2_descriptors_physical = 0x%x",camera_context->fifo2_descriptors_physical);#endif			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]) = 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]) = des_physical;                DCSR(camera_context->dma_channels[1]) |= DCSR_RUN;

⌨️ 快捷键说明

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