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

📄 pxa_camera-hzh.c

📁 基于intel xscale下的linux系统camera驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);}//设置mclk频率和mclk及pclk是否由CPU产生(ciclk=104M,mclk=24M由CPU产生,pclk由sensor产生)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;	// 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;        // want a divisor that gives us a clock rate as close to, but not more than the given mclk.        div = (ciclk / (2 * mclk_khz));	div = div - 1;	// write cicr4	value = CICR4;	value &= ~(CI_CICR4_PCLK_EN | CI_CICR4_MCLK_EN | CI_CICR4_DIV_SMASK<<CI_CICR4_DIV_SHIFT);	value |= (pclk_enable) ? CI_CICR4_PCLK_EN : 0;	value |= (mclk_enable) ? CI_CICR4_MCLK_EN : 0;	value |= div << CI_CICR4_DIV_SHIFT;	CICR4 = value;   	return; }//设置采样有效边缘和同步信号有效极性void ci_set_polarity(int pclk_sample_falling, int hsync_active_low, int vsync_active_low){	unsigned int value;		// write cicr4	value = CICR4;	value &= ~(CI_CICR4_PCP | CI_CICR4_HSP | CI_CICR4_VSP);	value |= (pclk_sample_falling)? CI_CICR4_PCP : 0;	value |= (hsync_active_low) ? CI_CICR4_HSP : 0;	value |= (vsync_active_low) ? CI_CICR4_VSP : 0;	CICR4 = value;   	return; }//设置超时参数和FIFO启动DMA的阀值和使能/禁止FIFO1,FIFO2(FIFO现已可自动使能)void ci_set_fifo(unsigned int timeout, CI_FIFO_THRESHOLD threshold, int fifo1_enable,               int fifo2_enable){	unsigned int value;	// write citor	CITOR = timeout; 		// write cifr: always enable fifo 0! also reset input fifo 	value = CIFR;	value &= ~(CI_CIFR_FEN0 | CI_CIFR_FEN1 | CI_CIFR_FEN2 | CI_CIFR_RESETF | 	CI_CIFR_THL_0_SMASK<<CI_CIFR_THL_0_SHIFT);	value |= (unsigned int)threshold << CI_CIFR_THL_0_SHIFT;	value |= (fifo1_enable) ? CI_CIFR_FEN1 : 0;	value |= (fifo2_enable) ? CI_CIFR_FEN2 : 0;	value |= CI_CIFR_RESETF | CI_CIFR_FEN0;	CIFR = value;	return; }void ci_reset_fifo(void){	unsigned int value;	value = CIFR;	value |= CI_CIFR_RESETF;	CIFR = value;}//设置中断掩码void ci_set_int_mask(unsigned int mask){	unsigned int value;	// write mask in cicr0  	value = CICR0;	value &= ~CI_CICR0_INTERRUPT_MASK;	value |= (mask & CI_CICR0_INTERRUPT_MASK);	CICR0 = value;   	return; }//获取中断掩码unsigned int ci_get_int_mask(void){	unsigned int value;	// write mask in cicr0  	value = CICR0;	return (value & CI_CICR0_INTERRUPT_MASK);}//清除中断void ci_clear_int_status(unsigned int status){	// write 1 to clear	CISR = status;}//读中断状态unsigned int ci_get_int_status(void){	int value;	value = CISR;	return  value;}//写和读camera控制寄存器void ci_set_reg_value(unsigned int reg_offset, unsigned int value){	CI_REG((u32)(ci_regs_base) + reg_offset) = value;}int ci_get_reg_value(unsigned int reg_offset){	int value;	value = CI_REG((u32)(ci_regs_base) + reg_offset);	return value;}//-------------------------------------------------------------------------------------------------------//  Control APIs//-------------------------------------------------------------------------------------------------------int ci_init(void){	int cken_val;	(unsigned long*)ci_regs_base = (unsigned long*)ioremap(CI_REGS_PHYS, CI_REG_SIZE);	if(!ci_regs_base) {		printk ("ci regs base apply failed \n");		return -1;	}	// clear all CI registers	CICR0 = 0x3FF;   // disable all interrupts	CICR1 = 0;	CICR2 = 0;	CICR3 = 0;	CICR4 = 0;	CISR  = ~0;	CIFR  = 0;	CITOR = 0;		// enable CI clock	cken_val = CKEN;	cken_val |= CKEN24_CAMERA;	CKEN = cken_val;	return 0;}void ci_deinit(){	// disable CI clock	CKEN &= ~CKEN24_CAMERA;}void ci_enable(int dma_en){	unsigned int value;	// write mask in cicr0  	value = CICR0;	value |= CI_CICR0_ENB;	if (dma_en) {		value |= CI_CICR0_DMA_EN;	}	CICR0 = value;   	return; }//关闭camera,有快速和等待当前祯采样完毕两种模式int ci_disable(int quick){	volatile unsigned int value, mask;	int retry;	// write control bit in cicr0   	value = CICR0;	if (quick) {		value &= ~CI_CICR0_ENB;		mask = CI_CISR_CQD;	}	else {		value |= CI_CICR0_DIS;		mask = CI_CISR_CDD;	}	CICR0 = value;   		// wait shutdown complete	retry = 50;	while ( retry-- > 0 ) {		value = CISR;		if ( value & mask ) {			CISR = mask;			return 0;		}		mdelay(10);	}	return -1; }void ci_slave_capture_enable(){	unsigned int value;	// write mask in cicr0  	value = CICR0;	value |= CI_CICR0_SL_CAP_EN;	CICR0 = value;   	return; }void ci_slave_capture_disable(){	unsigned int value;		// write mask in cicr0  	value = CICR0;	value &= ~CI_CICR0_SL_CAP_EN;	CICR0 = value;   	return; }//DMA中断处理程序,只在Y通道结束才做具体操作void pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs){	int dcsr;	static int dma_repeated=0;	camera_context_t  *cam_ctx = g_camera_context;	dcsr = DCSR(channel);	DCSR(channel) = dcsr & ~DCSR_STOPIRQEN;	if (still_image_mode == 1) {		if (task_waiting == 1) {			wake_up_interruptible (&camera_wait_q);			task_waiting = 0;		}		else {			still_image_rdy = 1;		}	} 	//当尾块索引(读取数据时修改)与头块索引(DMA结束时修改)只差1时,在尾块前一块重复DMA以防止覆盖数据	else 	if (dma_repeated == 0 		&& (cam_ctx->block_tail == ((cam_ctx->block_header + 2) % cam_ctx->block_number)))  {		dma_repeated = 1;		pxa_dma_repeat(cam_ctx);		cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number;	}	//如前面有重复一块DMA操作,在条件满足时(数据已被读出,尾块已变)恢复DMA循环操作	else if (dma_repeated == 1 && 			(cam_ctx->block_tail != ((cam_ctx->block_header + 1) % cam_ctx->block_number))			&& (cam_ctx->block_tail != ((cam_ctx->block_header + 2) % cam_ctx->block_number)))  {			pxa_dma_continue(cam_ctx);			dma_repeated = 0;	}	else if (dma_repeated == 0) {		cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number;	}	if (task_waiting == 1 && !(cam_ctx->block_header == cam_ctx->block_tail)) {			wake_up_interruptible (&camera_wait_q);		task_waiting = 0;	}	return;}void pxa_ci_dma_irq_cb(int channel, void *data, struct pt_regs *regs){	return;}void pxa_ci_dma_irq_cr(int channel, void *data, struct pt_regs *regs){	return;}                                                                                                                     inline static void pxa_ci_dma_stop(camera_context_t  *cam_ctx){        int ch0, ch1, ch2;                ch0 = cam_ctx->dma_channels[0];        ch1 = cam_ctx->dma_channels[1];        ch2 = cam_ctx->dma_channels[2];        DCSR(ch0) &= ~DCSR_RUN;        DCSR(ch1) &= ~DCSR_RUN;        DCSR(ch2) &= ~DCSR_RUN;}                                                                                                                             //填充DMA目的地址并启动DMA操作void pxa_dma_start(camera_context_t  *cam_ctx){        unsigned char cnt_blk;        pxa_dma_desc   *cnt_desc;	cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number;        cnt_blk = (unsigned char)cam_ctx->block_header;	        cnt_desc = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_physical + cnt_blk * cam_ctx->fifo0_num_descriptors;        DDADR(cam_ctx->dma_channels[0]) = (int) cnt_desc;        DCSR(cam_ctx->dma_channels[0]) |= DCSR_RUN;        if (cam_ctx->fifo1_num_descriptors) {                cnt_desc = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_physical + cnt_blk * cam_ctx->fifo1_num_descriptors;                 DDADR(cam_ctx->dma_channels[1]) = (int) cnt_desc;                DCSR(cam_ctx->dma_channels[1]) |= DCSR_RUN;        }        if (cam_ctx->fifo2_num_descriptors) {                cnt_desc = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_physical + cnt_blk * cam_ctx->fifo2_num_descriptors;                 DDADR(cam_ctx->dma_channels[2]) = (int) cnt_desc;                DCSR(cam_ctx->dma_channels[2]) |= DCSR_RUN;        }		return;}irqreturn_t pxa_camera_irq(int irq, void *dev_id, struct pt_regs *regs)	{        int cisr;        static int dma_started=0;	disable_irq(IRQ_CAMERA);        cisr = CISR;        if (cisr & CI_CISR_SOF) {		if (dma_started == 0) {			dma_started = 1;		}                CISR |= CI_CISR_SOF;        }        if (cisr & CI_CISR_EOF) {                CISR |= CI_CISR_EOF;        }	enable_irq(IRQ_CAMERA);	return IRQ_HANDLED;	}void pxa_dma_repeat(camera_context_t  *cam_ctx){	pxa_dma_desc *cnt_head, *cnt_tail; 	int cnt_block;	cnt_block = (cam_ctx->block_header + 1) % cam_ctx->block_number;// FIFO0	(pxa_dma_desc *)cnt_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + cnt_block * cam_ctx->fifo0_num_descriptors;	cnt_tail = cnt_head + cam_ctx->fifo0_num_descriptors - 1;	cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);// FIFO1	if (cam_ctx->fifo1_transfer_size) {		cnt_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + cnt_block * cam_ctx->fifo1_num_descriptors;		cnt_tail = cnt_head + cam_ctx->fifo1_num_descriptors - 1;		cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);	}// FIFO2	if (cam_ctx->fifo2_transfer_size) {		cnt_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + cnt_block * cam_ctx->fifo2_num_descriptors;		cnt_tail = cnt_head + cam_ctx->fifo2_num_descriptors - 1;		cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);	}	return;}void pxa_dma_continue(camera_context_t *cam_ctx){	pxa_dma_desc *cnt_head, *cnt_tail; 	pxa_dma_desc *next_head;	int cnt_block, next_block;		cnt_block = cam_ctx->block_header;	next_block = (cnt_block + 1) % cam_ctx->block_number;// FIFO0		cnt_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + cnt_block * cam_ctx->fifo0_num_descriptors;	cnt_tail = cnt_head + cam_ctx->fifo0_num_descriptors - 1;	next_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + next_block * cam_ctx->fifo0_num_descriptors;	cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);// FIFO1	if (cam_ctx->fifo1_transfer_size) {		cnt_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + cnt_block * cam_ctx->fifo1_num_descriptors;		cnt_tail = cnt_head + cam_ctx->fifo1_num_descriptors - 1;		next_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + next_block * cam_ctx->fifo1_num_descriptors;		cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);	}// FIFO2	if (cam_ctx->fifo2_transfer_size) {		cnt_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + cnt_block * cam_ctx->fifo2_num_descriptors;		cnt_tail = cnt_head + cam_ctx->fifo2_num_descriptors - 1;		next_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + next_block * cam_ctx->fifo2_num_descriptors;		cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);	}	return;}module_init(pxa_camera_init);module_exit(pxa_camera_exit);MODULE_DESCRIPTION("Bulverde Camera Interface driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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