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

📄 chg-pxa_ov_camera.c

📁 ov2640驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* pxa_ov_camera - main file for OmniVision camera driver *	 * Copyrith (c) 2006, OmniVision * 	 * 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. NO WARRANTY OF ANY KIND is expressed or implied. * * OmniVision is a trademark of OmniVision Technologies, Inc.  * *  Version 1.00   July.04.2006   david zhu *					      david@ovt.com.cn */ #include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/list.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/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 <asm/arch/apap.h>/*capture interface*/#include "ci_ov.h"#include "pxaovcamera.h"#ifdef CONFIG_ARCH_MAINSTONE/*camerachip control interface*/#include "ovcamerachip.h"#endif#include "ovcamerachip.h"//#define DEBUG#undef DEBUG#ifdef DEBUG#define ovcamprint(fmt,args...) printk(KERN_WARNING "pax ovcamera:" fmt, ## args)#else#define ovcamprint(fmt,args...) #endif//ov2640 support UXVGA(1600*1200), SVGA(800*600), CIF(400*300)/* macro define *///#define BUFFER_SIZE_DEFAULT	0x1D4C00#define BUFFER_SIZE_DEFAULT	0xea600 //jhy#define SINGLE_DESCRIPTORS_TRANSFER_MAX	8000#define MAX_DESCRIPTORS_NUM	(BUFFER_SIZE_DEFAULT/SINGLE_DESCRIPTORS_TRANSFER_MAX)//For YUV422  //jhy#define FIFO_0_SINGLE_DESC_TRANS_MAX		8000//7680#define FIFO_1_SINGLE_DESC_TRANS_MAX		8000//3840#define FIFO_2_SINGLE_DESC_TRANS_MAX		8000//3840#define MAX_DESC_NUM		0x400#define MAX_BLOCK_NUM	20#define CAPTURE_STILL_IMAGE	1  //jhy#define CAPTURE_VIDEO_DATA	0#define WIDTH_DEFAULT		176#define HEIGHT_DEFAULT		144#define FRAMERATE_DEFAULT	0x0#define CIBR0_PHY	(0x50000000 + 0x28)#define CIBR1_PHY	(0x50000000 + 0x30)#define CIBR2_PHY	(0x50000000 + 0x38)typedef struct camera_control_s {	/* /dev/videoX registration number */	int 	minor;	int	ci_dma_y;	int	ci_dma_cb;	int	ci_dma_cr;	int	first_video_frame;	volatile unsigned int frames_captured;	volatile unsigned char	capture_status; 	volatile unsigned char	still_image_rdy;	int	refcount;	struct	semaphore 	mutex;#ifdef CONFIG_CPU_FREQ        struct notifier_block   clockchg;#endif} camera_control_t,*p_camera_control_t;static camera_control_t g_camera_control;extern ovcamera_function_t camerachip_func;static ovcamera_context_t	*g_ovcamera_context;//static int minor = 0;wait_queue_head_t ovcamera_wait_q;volatile int	task_waiting = 0;static int 	still_image_mode = 0;static int	still_image_ready = 0;static int 	first_video_frame = 0;//jhystruct reg_set_s {	int  val1;	int  val2;};/*DMA*/int	ci_dma_y,ci_dma_u,ci_dma_v;void	pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs);void 	pxa_ci_dma_irq_u(int channel, void *data, struct pt_regs *regs);void	pxa_ci_dma_irq_v(int channel, void *data, struct pt_regs *regs);static unsigned long ci_regs_base = 0; /* CI registers IOMEM mapping */// map of camera image format (pxaovcamera.h) ==> capture interface format (ci_ov.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_JPEG,};static int ovcamera_set_capture_format(p_ovcamera_context_t p_ovcam_ctx);static int ovcamera_deinit ( p_ovcamera_context_t p_ovcam_ctx );static int dma_buf_setup(int width, int height);   //jhystatic DECLARE_WAIT_QUEUE_HEAD(dma_wait);static DECLARE_WAIT_QUEUE_HEAD(dma_read_wait);//jhystruct dma_buf_struct{	unsigned int	vaddr;	unsigned int 	paddr;	unsigned int	size;	struct list_head queue;};//jhystruct dma_buf_struct *get_list_entry(struct list_head *head){	struct list_head *next;	if (!head){		printk("%s: %d NULL Pointer!\n", __FUNCTION__, __LINE__);		return NULL;	}	next = head->next;	if (!next || next == head){		return NULL;	}	return (container_of(next, struct dma_buf_struct, queue));}/* #############################################################/#/# Intel Quick Capture Interface Configuration Interface/#/############################################################# */void ci_set_frame_rate(CI_FRAME_CAPTURE_RATE frate){	unsigned int value;	// write cicr4	value = CICR4;	value &= ~(CI_CICR4_FR_RATE_SMASK << CI_CICR4_FR_RATE_SHIFT);	value |= (unsigned)frate << CI_CICR4_FR_RATE_SHIFT;	CICR4 = value;}CI_FRAME_CAPTURE_RATE ci_get_frame_rate(void){	unsigned int value;	value = CICR4;	return (CI_FRAME_CAPTURE_RATE)((value >> CI_CICR4_FR_RATE_SHIFT) & CI_CICR4_FR_RATE_SMASK);}void ci_set_image_format(CI_IMAGE_FORMAT input_format, CI_IMAGE_FORMAT output_format){	unsigned int value, tbit, rgbt_conv, rgb_conv, rgb_f, ycbcr_f, rgb_bpp, raw_bpp, cspace;	// write cicr1: preserve ppl value and data width value	value = CICR1;	value &= ( (CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT) | ((CI_CICR1_DW_SMASK) << CI_CICR1_DW_SHIFT));	tbit = rgbt_conv = rgb_conv = rgb_f = ycbcr_f = rgb_bpp = raw_bpp = cspace = 0;	switch(input_format) {	case CI_RAW8:		cspace = 0;		raw_bpp = 0;		break;	case CI_RAW9:		cspace = 0;		raw_bpp = 1;		break;	case CI_RAW10:		cspace = 0;		raw_bpp = 2;		break;	case CI_YCBCR422:	case CI_YCBCR422_PLANAR:		cspace = 2;		if (output_format == CI_YCBCR422_PLANAR) {			ycbcr_f = 1;		}		break;	case CI_RGB444:		cspace = 1;		rgb_bpp = 0;		break;  	case CI_RGB555:		cspace = 1;		rgb_bpp = 1;		if (output_format == CI_RGBT555_0) {			rgbt_conv = 2;			tbit = 0;		} 		else if (output_format == CI_RGBT555_1) {			rgbt_conv = 2;			tbit = 1;		}		break;  	case CI_RGB565:		cspace = 1;		rgb_bpp = 2;		rgb_f = 1;		break;  	case CI_RGB666:		cspace = 1;		rgb_bpp = 3;		if (output_format == CI_RGB666_PACKED) {			rgb_f = 1;		}		break;  	case CI_RGB888:	case CI_RGB888_PACKED:		cspace = 1;		rgb_bpp = 4;		switch(output_format) {		case CI_RGB888_PACKED:			rgb_f = 1;			break;		case CI_RGBT888_0:			rgbt_conv = 1;			tbit = 0;			break;		case CI_RGBT888_1:			rgbt_conv = 1;			tbit = 1;			break;		case CI_RGB666:			rgb_conv = 1;			break;		case CI_RGB666_PACKED:			rgb_conv = 1;			rgb_f = 1;			break;		case CI_RGB565:			rgb_conv = 2;			break;		case CI_RGB555:			rgb_conv = 3;			break;		case CI_RGB444:			rgb_conv = 4;			break;		default:			break;		}		break;  	case CI_JPEG:		cspace = 0;		raw_bpp = 0;		break;	default:		break;	}	value |= (tbit==1) ? CI_CICR1_TBIT : 0;	value |= rgbt_conv << CI_CICR1_RGBT_CONV_SHIFT;	value |= rgb_conv << CI_CICR1_RGB_CONV_SHIFT;	value |= (rgb_f==1) ? CI_CICR1_RBG_F : 0;	value |= (ycbcr_f==1) ? CI_CICR1_YCBCR_F : 0;	value |= rgb_bpp << CI_CICR1_RGB_BPP_SHIFT;	value |= raw_bpp << CI_CICR1_RAW_BPP_SHIFT;	value |= cspace << CI_CICR1_COLOR_SP_SHIFT;	CICR1 = value;   		return; }void ci_set_mode(CI_MODE mode, CI_DATA_WIDTH data_width){	unsigned int value;		// write mode field in cicr0	value = CICR0;	value &= ~(CI_CICR0_SIM_SMASK << CI_CICR0_SIM_SHIFT);//clear CIR0[26:24] 	value |= (unsigned int)mode << CI_CICR0_SIM_SHIFT;//set CIR0[26:24]	CICR0 = value;   		// write data width cicr1	value = CICR1;	value &= ~(CI_CICR1_DW_SMASK << CI_CICR1_DW_SHIFT);//claer CIR1[2:0]	value |= ((unsigned)data_width) << CI_CICR1_DW_SHIFT;//set CIR1[2:0]	CICR1 = value;   	return; }/////////////////////////////////////////////////////////////////////////////////Configure Quick Capture Interface to Master-Parallel mode///////////////////////////////////////////////////////////////////////////////void ci_configure_mp(unsigned int ppl, unsigned int lpf, CI_MP_TIMING* timing){	unsigned int value;	// write ppl field in cicr1	value = CICR1;	value &= ~(CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT);	value |= (ppl & CI_CICR1_PPL_SMASK) << CI_CICR1_PPL_SHIFT;	CICR1 = value;   		// write BLW, ELW in cicr2  	value = CICR2;	value &= ~(CI_CICR2_BLW_SMASK << CI_CICR2_BLW_SHIFT | CI_CICR2_ELW_SMASK << CI_CICR2_ELW_SHIFT );	value |= (timing->BLW & CI_CICR2_BLW_SMASK) << CI_CICR2_BLW_SHIFT;	CICR2 = value;   		// write BFW, LPF in cicr3	value = CICR3;	value &= ~(CI_CICR3_BFW_SMASK << CI_CICR3_BFW_SHIFT | CI_CICR3_LPF_SMASK << CI_CICR3_LPF_SHIFT );	value |= (timing->BFW & CI_CICR3_BFW_SMASK) << CI_CICR3_BFW_SHIFT;	value |= (lpf & CI_CICR3_LPF_SMASK) << CI_CICR3_LPF_SHIFT;	CICR3 = value;   	return;}void ci_configure_sp(unsigned int ppl, unsigned int lpf, CI_SP_TIMING* timing){	unsigned int value;	// write ppl field in cicr1	value = CICR1;	value &= ~(CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT);	value |= (ppl & CI_CICR1_PPL_SMASK) << CI_CICR1_PPL_SHIFT;	CICR1 = value;   		// write cicr2	value = CICR2;	value |= (timing->BLW & CI_CICR2_BLW_SMASK) << CI_CICR2_BLW_SHIFT;	value |= (timing->ELW & CI_CICR2_ELW_SMASK) << CI_CICR2_ELW_SHIFT;	value |= (timing->HSW & CI_CICR2_HSW_SMASK) << CI_CICR2_HSW_SHIFT;	value |= (timing->BFPW & CI_CICR2_BFPW_SMASK) << CI_CICR2_BFPW_SHIFT;	value |= (timing->FSW & CI_CICR2_FSW_SMASK) << CI_CICR2_FSW_SHIFT;	CICR2 = value;   	// write cicr3	value = CICR3;	value |= (timing->BFW & CI_CICR3_BFW_SMASK) << CI_CICR3_BFW_SHIFT;	value |= (timing->EFW & CI_CICR3_EFW_SMASK) << CI_CICR3_EFW_SHIFT;	value |= (timing->VSW & CI_CICR3_VSW_SMASK) << CI_CICR3_VSW_SHIFT;	value |= (lpf & CI_CICR3_LPF_SMASK) << CI_CICR3_LPF_SHIFT;	CICR3 = value;   	return;}void ci_configure_ms(unsigned int ppl, unsigned int lpf, CI_MS_TIMING* timing){	// the operation is same as Master-Parallel	ci_configure_mp(ppl, lpf, (CI_MP_TIMING*)timing);}void ci_configure_ep(int parity_check){	unsigned int value;	// write parity_enable field in cicr0   	value = CICR0;	if (parity_check) {		value |= CI_CICR0_PAR_EN;	}	else {		value &= ~CI_CICR0_PAR_EN;	}	CICR0 = value;   	return; }void ci_configure_es(int parity_check){	// the operationi is same as Embedded-Parallel	ci_configure_ep(parity_check);}void ci_set_clock(unsigned int clk_regs_base, int pclk_enable, int mclk_enable, unsigned int mclk_khz){	unsigned int ciclk = 0,  value, div, cccr_l;	ovcamprint("ci_set_clock( + ) \n");			ovcamprint("CCCR =%16x\n",CCCR);		// determine the LCLK frequency programmed into the CCCR.	cccr_l = (CCCR & 0x0000001F); 	       if (cccr_l < 8) // L = [2 - 7]                ciclk = (13 * cccr_l) * 100;        else if (cccr_l < 17) // L = [8 - 16]               ciclk = ((13 * cccr_l) * 100) >> 1;        else if (cccr_l < 32) // L = [17 - 31]               ciclk = ((13 * cccr_l) * 100) >> 2;

⌨️ 快捷键说明

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