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

📄 pxa_ov_camera.c

📁 ov2640驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		dmaend_irq_enable = 1;
	}
	else
	{
		dmaend_irq_enable = 0;
	}

	// set fifo0 dma chains' flag
	end_des_virtual = (pxa_dma_desc*)ovcam_ctx->fifo0_descriptors_virtual 
		+ ovcam_ctx->fifo0_num_descriptors - 1;
	for(i=0; i<ovcam_ctx->block_number; i++) 
	{
		if (dmaend_irq_enable)
		{
		    end_des_virtual->dcmd |= DCMD_ENDIRQEN;
		}
		else
		{
			end_des_virtual->dcmd &= ~DCMD_ENDIRQEN;
		}
		end_des_virtual += ovcam_ctx->fifo0_num_descriptors;
	}
	
	return;
}

void ovcamerachip_gpio_init ( void )
{
	set_GPIO_mode(  81 | GPIO_ALT_FN_2_IN); /* CIF_DD[0] */
	set_GPIO_mode(  55 | GPIO_ALT_FN_1_IN); /* CIF_DD[1] */
	set_GPIO_mode(  51 | GPIO_ALT_FN_1_IN); /* CIF_DD[2] */
	set_GPIO_mode(  50 | GPIO_ALT_FN_1_IN); /* CIF_DD[3] */
	set_GPIO_mode(  52 | GPIO_ALT_FN_1_IN); /* CIF_DD[4] */
	set_GPIO_mode(  48 | GPIO_ALT_FN_1_IN); /* CIF_DD[5] */
	set_GPIO_mode(  93 | GPIO_ALT_FN_2_IN); /* CIF_DD[6] */
	set_GPIO_mode(  108 | GPIO_ALT_FN_1_IN); /* CIF_DD[7] */
	set_GPIO_mode(  53 | GPIO_ALT_FN_2_OUT); /* CIF_MCLK */
	set_GPIO_mode(  54 | GPIO_ALT_FN_3_IN);  /* CIF_PCLK */
	set_GPIO_mode(  85 | GPIO_ALT_FN_3_IN);  /* CIF_LV */
	set_GPIO_mode(  84 | GPIO_ALT_FN_3_IN);  /* CIF_FV */
	
		
	return;
}

void ovcamerachip_clock_set ( unsigned int clk_regs_base, int pclk_enable, int mclk_enable, unsigned int mclk_khz)
{
	unsigned int ciclk=0,value,div,cccr_l;
	
	cccr_l = ( CCCR & 0x0000001F ); 
	
	if ( cccr_l < 8 ) 
	{
		ciclk = ( 13 * cccr_l ) * 100;
	}
	else if ( cccr_l < 17 ) 
	{
		ciclk = (( 13 * cccr_l ) * 100 ) >> 1;
	}
	else if ( cccr_l < 32 )
	{
		ciclk = (( 13 * cccr_l ) * 100 ) >> 2;
	}

	ovcamprint("the mclk = %d \n", mclk_khz);
	

	div = ( ciclk + mclk_khz ) / (2 * mclk_khz ) -1; /* zhudavid: ciclk > mclk_khz ?*/
	
	value = CICR4;
	value &= ~( CI_CICR4_PCLK_EN | CI_CICR4_MCLK_EN | CI_CICR4_DIV_SMASK << CI_CICR4_DIV_SHIFT);
	value |= (mclk_enable) ? CI_CICR4_MCLK_EN : 0;
	value |= (pclk_enable) ? CI_CICR4_PCLK_EN : 0;
	value |= div << CI_CICR4_DIV_SHIFT;
	
	CICR4 = value;
}

int ci_init()
{
	int cken_val;
	(unsigned long*)ci_regs_base = (unsigned long*)ioremap(CI_REGS_PHYS, CI_REG_SIZE);
	if(!ci_regs_base) 
	{
		ovcamprint("Remap Quick Capture Interface I/O registers 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()
{
	CKEN &= ~CKEN24_CAMERA;
}

void ci_enable ( int dma_en )
{
	unsigned int value;
	
	value = CICR0;
	value |= CI_CICR0_ENB;
	
	if ( dma_en )
	{
		value |= CI_CICR0_DMA_EN;
	}

	CICR0 = value;
}

int ci_disable ( int quick )
{
	volatile unsigned int value, mask;
	int retry;
	
	value = CICR0;
	if ( quick )
	{
		value &= ~CI_CICR0_ENB;
		mask = CI_CISR_CQD;
	}
	else
	{
		value |= CI_CICR0_DIS;
		mask = CI_CISR_CDD;
	}
	CICR0 = value;
	
	retry = 50;
	while ( 0 < retry-- )
	{
		value = CISR;
		if (value & mask) 
		{
			CISR = mask;
			return 0;
		}
		mdelay(10);
	}
	
	return -1;
}

/*
Generate dma descriptors
Pre-condition: these variables must be set properly
                block_number, fifox_transfer_size 
                dma_descriptors_virtual, dma_descriptors_physical, dma_descirptors_size
Post-condition: these variables will be set
                fifox_descriptors_virtual, fifox_descriptors_physical              
                fifox_num_descriptors 
*/
int update_dma_chain( p_ovcamera_context_t p_ovcam_ctx )
{
	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;
	
	ovcamprint("update_dma_chain( + ) \n");		
 
	// clear descriptor pointers
	p_ovcam_ctx->fifo0_descriptors_virtual = p_ovcam_ctx->fifo0_descriptors_physical = 0;
	p_ovcam_ctx->fifo1_descriptors_virtual = p_ovcam_ctx->fifo1_descriptors_physical = 0;
	p_ovcam_ctx->fifo2_descriptors_virtual = p_ovcam_ctx->fifo2_descriptors_physical = 0;

	// calculate how many descriptors are needed per frame
	p_ovcam_ctx->fifo0_num_descriptors = ( p_ovcam_ctx->fifo0_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 )
		 / SINGLE_DESCRIPTORS_TRANSFER_MAX;
	p_ovcam_ctx->fifo1_num_descriptors = ( p_ovcam_ctx->fifo1_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 )
		 / SINGLE_DESCRIPTORS_TRANSFER_MAX;
	p_ovcam_ctx->fifo2_num_descriptors = ( p_ovcam_ctx->fifo2_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 )
		 / SINGLE_DESCRIPTORS_TRANSFER_MAX;
	// check if enough memory to generate descriptors
	if ( (p_ovcam_ctx->fifo0_num_descriptors + p_ovcam_ctx->fifo1_num_descriptors + 
 			p_ovcam_ctx->fifo2_num_descriptors) * p_ovcam_ctx->block_number 
			> p_ovcam_ctx->ui_dmadest_size)
	{
		ovcamprint("update_dma_chain( -0 ) \n");		
		return -1;
	}

	// generate fifo0 dma chains
	p_ovcam_ctx->fifo0_descriptors_virtual = (unsigned)p_ovcam_ctx->p_dmadest_virtual;
	p_ovcam_ctx->fifo0_descriptors_physical = (unsigned)p_ovcam_ctx->p_dmadest_physical;
	cur_des_virtual = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_virtual;
	cur_des_physical = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_physical;

	for(i=0; i<p_ovcam_ctx->block_number; i++) 
	{
		// in each iteration, generate one dma chain for one frame
		remain_size = p_ovcam_ctx->fifo0_transfer_size;

		// assume the blocks are stored consecutively
		target_physical = (unsigned)p_ovcam_ctx->p_buffer_physical + p_ovcam_ctx->block_size * i;
		target_virtual = (unsigned)p_ovcam_ctx->p_buffer_virtual + p_ovcam_ctx->block_size * i;
		
		for(j=0; j<p_ovcam_ctx->fifo0_num_descriptors; j++) 
		{
			 // set descriptor
		        if (remain_size > SINGLE_DESCRIPTORS_TRANSFER_MAX) 
        			des_transfer_size = SINGLE_DESCRIPTORS_TRANSFER_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)p_ovcam_ctx->fifo0_descriptors_physical);//LOOP
    
	// generate fifo1 dma chains
	if (p_ovcam_ctx->fifo1_transfer_size) 
	{
		// record fifo1 descriptors' start address
		p_ovcam_ctx->fifo1_descriptors_virtual = (unsigned)cur_des_virtual;
		p_ovcam_ctx->fifo1_descriptors_physical = (unsigned)cur_des_physical;

		for(i=0; i<p_ovcam_ctx->block_number; i++) 
		{
			// in each iteration, generate one dma chain for one frame
			remain_size = p_ovcam_ctx->fifo1_transfer_size;

    		// assume the blocks are stored consecutively
    		target_physical = (unsigned)p_ovcam_ctx->p_buffer_physical + p_ovcam_ctx->block_size * i 
    	                    + p_ovcam_ctx->fifo0_transfer_size;
    		target_virtual = (unsigned)p_ovcam_ctx->p_buffer_virtual + p_ovcam_ctx->block_size * i 
    	                    + p_ovcam_ctx->fifo0_transfer_size;
    
    		for(j=0; j<p_ovcam_ctx->fifo1_num_descriptors; j++) 
    		{
    		        // set descriptor
				if (remain_size > SINGLE_DESCRIPTORS_TRANSFER_MAX)
				{ 
					des_transfer_size = SINGLE_DESCRIPTORS_TRANSFER_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)p_ovcam_ctx->fifo1_descriptors_physical);
	}
    
	// generate fifo2 dma chains
	if (p_ovcam_ctx->fifo2_transfer_size) 
	{
		// record fifo1 descriptors' start address
		p_ovcam_ctx->fifo2_descriptors_virtual = (unsigned)cur_des_virtual;
		p_ovcam_ctx->fifo2_descriptors_physical = (unsigned)cur_des_physical;

		for(i=0; i<p_ovcam_ctx->block_number; i++) 
		{
			// in each iteration, generate one dma chain for one frame
			remain_size = p_ovcam_ctx->fifo2_transfer_size;

			// assume the blocks are stored consecutively
			target_physical = (unsigned)p_ovcam_ctx->p_buffer_physical + p_ovcam_ctx->block_size * i 
                            + p_ovcam_ctx->fifo0_transfer_size + p_ovcam_ctx->fifo1_transfer_size;
    
	        for(j=0; j<p_ovcam_ctx->fifo2_num_descriptors; j++) 
	        {
            		// set descriptor
            		if (remain_size > SINGLE_DESCRIPTORS_TRANSFER_MAX)
            		{ 
            			des_transfer_size = SINGLE_DESCRIPTORS_TRANSFER_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)p_ovcam_ctx->fifo2_descriptors_physical);
	}

	ovcamprint("update_dma_chain( - ) \n");		

	return 0;   
}

////////////////////////////////////////////////////////////////////////////////////
//Manual Set the DDADR and Start DMA transfer
////////////////////////////////////////////////////////////////////////////////////
void dma_transfer_start ( p_ovcamera_context_t p_ovcam_ctx, unsigned int block_id )
{
	pxa_dma_desc *des_virtual, *des_physical;
	
 	ovcamprint("dma_transfer_start( + ) \n");		
   
	if ( block_id >= p_ovcam_ctx->block_number)
	{
   		return;
    	}
        
	// start channel 0
	des_virtual = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_virtual
		+ block_id * p_ovcam_ctx->fifo0_num_descriptors;
	des_physical = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_physical 
		+ block_id * p_ovcam_ctx->fifo0_num_descriptors;

	DDADR(p_ovcam_ctx->dma_channels[0]) = des_physical;
	DCSR(p_ovcam_ctx->dma_channels[0]) |= DCSR_RUN;

	// start channel 1
	if ( p_ovcam_ctx->fifo1_descriptors_virtual ) 
	{
		des_virtual = (pxa_dma_desc *)p_ovcam_ctx->fifo1_descriptors_virtual + 
			block_id * p_ovcam_ctx->fifo1_num_descriptors;
		des_physical = (pxa_dma_desc *)p_ovcam_ctx->fifo1_descriptors_physical + 
			block_id * p_ovcam_ctx->fifo1_num_descriptors;
        	DDADR(p_ovcam_ctx->dma_channels[1]) = des_physical;
        	DCSR(p_ovcam_ctx->dma_channels[1]) |= DCSR_RUN;
	}

	// start channel 2
	if ( p_ovcam_ctx->fifo2_descriptors_virtual ) 
	{
		des_virtual = (pxa_dma_desc *)p_ovcam_ctx->fifo2_descriptors_virtual + 
			block_id * p_ovcam_ctx->fifo2_num_descriptors;
		des_physical = (pxa_dma_desc *)p_ovcam_ctx->fifo2_descriptors_physical + 
			block_id * p_ovcam_ctx->fifo2_num_descriptors;
        	DDADR(p_ovcam_ctx->dma_channels[2]) = des_physical;
        	DCSR(p_ovcam_ctx->dma_channels[2]) |= DCSR_RUN;
	}
	
 	ovcamprint("dma_transfer_start( - ) \n");		

}

void dma_transfer_stop ( p_ovcamera_context_t p_ovcam_ctx )
{	
        int ch0, ch1, ch2;

	ovcamprint("dma_transfer_stop( + ) \n");		

        ch0 = p_ovcam_ctx->dma_channels[0];
        ch1 = p_ovcam_ctx->dma_channels[1];
        ch2 = p_ovcam_ctx->dma_channels[2];
        DCSR(ch0) &= ~DCSR_RUN;
        DCSR(ch1) &= ~DCSR_RUN;
        DCSR(ch2) &= ~DCSR_RUN;
        
	ovcamprint("dma_transfer_stop( - ) \n");		
	return;
}

static int capture_start ( p_ovcamera_context_t p_ovcam_ctx, unsigned int block_id, unsigned int frames )
{
	int ret;
	
	ovcamprint("capture_start( + ) \n");	
		
	ci_reset_fifo ();
	
	ci_clear_int_status ( 0xFFFFFFFF );
	
	dma_transfer_start ( p_ovcam_ctx, block_id );

	ret = p_ovcam_ctx->camera_functions->capture_start ( p_ovcam_ctx, frames );
	
	ovcamprint("capture_start( - ) \n");		
	return ret;
}

static int ovcamera_init ( p_ovcamera_context_t p_ovcam_ctx )
{
	int ret = 0;
	int i;

	ovcamprint("ovcamera_init ( + ) \n");		
	// parameter check
	if (p_ovcam_ctx->p_buffer_virtual == NULL || p_ovcam_ctx->p_buffer_physical == NULL || p_ovcam_ctx->ui_buffer_size == 0)
	{
		ovcamprint("ovcamera_init ( -1 ) \n");		
		return STATUS_WRONG_PARAMETER; 
	}
	
	if (p_ovcam_ctx->p_dmadest_virtual == NULL || p_ovcam_ctx->p_dmadest_physical == NULL || 
		p_ovcam_ctx->ui_dmadest_size == 0)
	{
		ovcamprint("ovcamera_init ( -2 ) \n");		
		return STATUS_WRONG_PARAMETER; 
	}
		
	if (p_ovcam_ctx->cf.in > CAMERA_IMAGE_FORMAT_MAX ||
		p_ovcam_ctx->cf.out > CAMERA_IMAGE_FORMAT_MAX)
	{
		ovcamprint("ovcamera_init ( -4 ) \n");		
		return STATUS_WRONG_PARAMETER; 
	}
	
	// check the function dispatch table according to the sensor type
	if ( !p_ovcam_ctx->camera_functions )
	{
		ovcamprint("ovcamera_init ( -5 ) \n");		
		return STATUS_WRONG_PARAMETER;
	}
	
	if ( !p_ovcam_ctx->camera_functions->init || 	
		 !p_ovcam_ctx->camera_functions->deinit ||
		 !p_ovcam_ctx->camera_functions->capture_set_format ||
		 !p_ovcam_ctx->camera_functions->capture_start ||
		 !p_ovcam_ctx->camera_functions->capture_stop )
	{     	
		ovcamprint("ovcamera_init ( -6 ) \n");		
		return STATUS_WRONG_PARAMETER;
	}

	// init context status
	for(i=0; i<3; i++)
	{
		p_ovcam_ctx->dma_channels[i] = 0xFF;
	}
	
	(int)p_ovcam_ctx->fifo0_descriptors_virtual = NULL;
	(int)p_ovcam_ctx->fifo1_descriptors_virtual = NULL;
	(int)p_ovcam_ctx->fifo2_descriptors_virtual = NULL;
	(int)p_ovcam_ctx->fifo0_descriptors_physical = NULL;
	(int)p_ovcam_ctx->fifo1_descriptors_physical = NULL;
	(int)p_ovcam_ctx->fifo2_descriptors_physical = NULL;
	
	p_ovcam_ctx->fifo0_num_descriptors = 0;
	p_ovcam_ctx->fifo1_num_descriptors = 0;
	p_ovcam_ctx->fifo2_num_descriptors = 0;

	p_ovcam_ctx->fifo0_transfer_size = 0;
	p_ovcam_ctx->fifo1_transfer_size = 0;
	p_ovcam_ctx->fifo2_transfer_size = 0;
	
	p_ovcam_ctx->block_number = 0;
	p_ovcam_ctx->block_size = 0;
	p_ovcam_ctx->block_header = 0;
	p_ovcam_ctx->block_tail = 0;

	// Enable hardware
	ovcamerachip_gpio_init();
	    
	// capture interface init
	ci_init();

	// sensor init
	ret = p_ovcam_ctx->camera_functions->init(p_ovcam_ctx);    
	if (ret)
	{
		ovcamprint("ovcamera_init ( -7 ) \n");		
		goto camera_init_err;
	}

	//dma channels
	p_ovcam_ctx->dma_channels[0] = ci_dma_y;
	p_ovcam_ctx->dma_channels[1] = ci_dma_u;
	p_ovcam_ctx->dma_channels[2] = ci_dma_v;
	

⌨️ 快捷键说明

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