📄 pxa_ov_camera.c
字号:
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 + -