📄 pxa27x_camera.c
字号:
int GenerateDMAChain(
DESCRIPTOR_INFO_T *pDescriptorInfo,
int fifo0_transfer_size,
int fifo1_transfer_size,
int fifo2_transfer_size
)
{
XLLP_DMAC_DESCRIPTOR_T *cur_des_virtual;
int des_transfer_size, remain_size;
unsigned int i,j,k,l;
unsigned int fifo0_num_descriptors = 0;
unsigned int fifo1_num_descriptors = 0;
unsigned int fifo2_num_descriptors = 0;
// calculate how many descriptors are needed per frame
fifo0_num_descriptors = (( fifo0_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
/ SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;
fifo1_num_descriptors = (( fifo1_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
/ SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;
fifo2_num_descriptors = (( fifo2_transfer_size + SINGLE_DESCRIPTOR_TRANSFER_MAX -1 )
/ SINGLE_DESCRIPTOR_TRANSFER_MAX) * 2;
cur_des_virtual = (XLLP_DMAC_DESCRIPTOR_T*)pDescriptorInfo->pDescriptorBufferVirtAddress;
// First iteration, build the real chain.
// Second iteration, build the phantom chain.
k = 0;
l = 0;
for(i=0; i < 2; i++) {
remain_size = fifo0_transfer_size;
for(j=0; j < fifo0_num_descriptors >> 1; j++) {
// set descriptor
if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX)
des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
else
des_transfer_size = remain_size;
// Build the primary DMA chain
if (i == 0)
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR0; // FIFO0 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_16 << 16);
if (j == 0)
{
pDescriptorInfo->pPhysAddr_X1_CH0 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
}
// Special case for the last non-phantom descriptor in the chain
// Enable an end of frame interrupt for this descriptor only.
// Save a pointer to this descriptor and reset the remaining size for the phantom descriptor chain
if (j == ((fifo0_num_descriptors >> 1) - 1))
{
cur_des_virtual->DCMD |= XLLP_DMAC_DCMD_END_IRQ_EN;
pDescriptorInfo->pVirtAddr_Xn_CH0 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
// Reset the DMA transfer size for the phantom descriptor
remain_size = fifo0_transfer_size;
}
} else
// Build the phantom DMA chain
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR0; // FIFO0 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_16 << 16);
if (j == 0)
{
pDescriptorInfo->pPhysAddr_XP1_CH0 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1]; // Physical address of the first phantom descriptor
}
if (j == ((fifo0_num_descriptors >> 1) - 1))
{
pDescriptorInfo->pVirtAddr_XPn_CH0 = (XLLP_UINT32_T)cur_des_virtual; // Virtual address of the last phantom descriptor
}
}
// advance pointers
remain_size -= des_transfer_size;
cur_des_virtual++;
}
}
// generate fifo1 dma chains
if (fifo1_transfer_size) {
for(i=0; i < 2; i++) {
// in each iteration, generate one dma chain for one frame
remain_size = fifo1_transfer_size;
for(j=0; j < fifo1_num_descriptors >> 1; j++) {
// set descriptor
if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX)
des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
else
des_transfer_size = remain_size;
if (i == 0)
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR1; // FIFO1 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
if (j == 0)
pDescriptorInfo->pPhysAddr_X1_CH1 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
if (j == ((fifo1_num_descriptors >> 1) - 1))
{
pDescriptorInfo->pVirtAddr_Xn_CH1 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
// Reset the DMA transfer size for the phantom descriptor
remain_size = fifo1_transfer_size;
}
}
else
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR1; // FIFO1 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
if (j == 0)
pDescriptorInfo->pPhysAddr_XP1_CH1 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1]; // Physical address of the first phantom descriptor
if (j == ((fifo1_num_descriptors >> 1) - 1))
pDescriptorInfo->pVirtAddr_XPn_CH1 = (XLLP_UINT32_T)cur_des_virtual; // Virtual address of the last phantom descriptor
}
// advance pointers
remain_size -= des_transfer_size;
cur_des_virtual++;
}
}
}
// generate fifo2 dma chains
if (fifo2_transfer_size) {
for(i=0; i < 2; i++) {
// in each iteration, generate one dma chain for one frame
remain_size = fifo2_transfer_size;
for(j=0; j < fifo2_num_descriptors >> 1; j++) {
// set descriptor
if (remain_size > SINGLE_DESCRIPTOR_TRANSFER_MAX)
des_transfer_size = SINGLE_DESCRIPTOR_TRANSFER_MAX;
else
des_transfer_size = remain_size;
if (i == 0)
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR2; // FIFO2 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pBufferPhyAddress[k++];
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
if (j == 0)
pDescriptorInfo->pPhysAddr_X1_CH2 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1];// Physical address of the first real descriptor
if (j == ((fifo2_num_descriptors >> 1) - 1))
{
pDescriptorInfo->pVirtAddr_Xn_CH2 = (XLLP_UINT32_T)cur_des_virtual;// Virtual address of the last real descriptor
// Reset the DMA transfer size for the phantom descriptor
remain_size = fifo2_transfer_size;
}
}
else
{
cur_des_virtual->DDADR = (unsigned)pDescriptorInfo->pDescriptorBufferPhyAddress[++l];
cur_des_virtual->DSADR = XLLP_CI_REGBASE_PHY + XLLP_CIBR2; // FIFO2 physical address
cur_des_virtual->DTADR = (unsigned)pDescriptorInfo->pPhysAddr_Phantom;
cur_des_virtual->DCMD = des_transfer_size | XLLP_DMAC_DCMD_FLOW_SRC | XLLP_DMAC_DCMD_INC_TRG_ADDR | (XLLP_DMAC_BURSTSIZE_8 << 16);
if (j == 0)
pDescriptorInfo->pPhysAddr_XP1_CH2 = (XLLP_UINT32_T)pDescriptorInfo->pDescriptorBufferPhyAddress[l-1]; // Physical address of the first phantom descriptor
if (j == ((fifo2_num_descriptors >> 1) - 1))
pDescriptorInfo->pVirtAddr_XPn_CH2 = (XLLP_UINT32_T)cur_des_virtual; // Virtual address of the last phantom descriptor
}
// advance pointers
remain_size -= des_transfer_size;
cur_des_virtual++;
}
}
}
return TRUE;
}
/***********************************************************************
*
* Private functions
*
***********************************************************************/
void PrvStartDMATransfer(P_HW_CONTEXT_T pHwContext, unsigned block_id)
{
XLLP_DMAC_DESCRIPTOR_T *des_virtual, *des_physical;
des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo0_descriptors_physical;
XllpDmacCfgChannelDescTransfer( //des_virtual,
des_physical,
pHwContext->XllpDMA.dma_channels[0],
CAMERA_DMA_DEVICE[0],
XLLP_DMAC_ALIGNMENT_OFF
);
if ( pHwContext->XllpDMA.fifo1_transfer_size ) {
des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo1_descriptors_physical;
XllpDmacCfgChannelDescTransfer( //des_virtual,
des_physical,
pHwContext->XllpDMA.dma_channels[1],
CAMERA_DMA_DEVICE[1],
XLLP_DMAC_ALIGNMENT_OFF
);
}
if ( pHwContext->XllpDMA.fifo2_transfer_size ) {
des_virtual = (P_XLLP_DMAC_DESCRIPTOR_T)NULL;
des_physical = (P_XLLP_DMAC_DESCRIPTOR_T)pHwContext->XllpDMA.fifo2_descriptors_physical;
XllpDmacCfgChannelDescTransfer( //des_virtual,
des_physical,
pHwContext->XllpDMA.dma_channels[2],
CAMERA_DMA_DEVICE[2],
XLLP_DMAC_ALIGNMENT_OFF
);
}
if ( pHwContext->XllpDMA.fifo0_transfer_size &&
pHwContext->XllpDMA.fifo1_transfer_size &&
pHwContext->XllpDMA.fifo2_transfer_size )
{
XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[0] );
XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[1] );
XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[2] );
} else
{
XllpDmacStartTransfer( pHwContext->XllpDMA.dma_channels[0] );
}
}
void PrvStopDMATransfer(P_HW_CONTEXT_T pHwContext)
{
unsigned int capture_output_format = pHwContext->XllpCAMERA.Video_capture_output_format;
if (pHwContext->XllpCAMERA.capture_mode == XLLP_CAMERA_MODE_STILL)
{
capture_output_format = pHwContext->XllpCAMERA.Still_capture_output_format;
}
// stop channel 0
XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[0] );
// stop channel 1 and 2
if ( capture_output_format == XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR )
{
XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[1] );
XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[2] );
}
}
XLLP_STATUS_T PrvStartCapture(P_HW_CONTEXT_T pHwContext, unsigned int block_id, unsigned int frames)
{
XLLP_STATUS_T status;
// clear ci fifo
XllpCIResetFIFO(pHwContext->XllpCAMERA.ci_reg_base);
XllpCIClearInterruptStatus(pHwContext->XllpCAMERA.ci_reg_base, 0xFFFFFFFF);
// start dma
PrvStartDMATransfer(pHwContext, block_id);
// start capture
status = pHwContext->XllpCAMERA.camera_functions->start_capture(&pHwContext->XllpCAMERA, frames);
return status;
}
// Set the image format
XLLP_STATUS_T PrvSetDMARingBuffer(P_HW_CONTEXT_T pHwContext)
{
unsigned int frame_size;
unsigned int capture_output_format = pHwContext->XllpCAMERA.Video_capture_output_format;
if (pHwContext->XllpCAMERA.capture_mode == XLLP_CAMERA_MODE_STILL)
{
capture_output_format = pHwContext->XllpCAMERA.Still_capture_output_format;
}
// ring buffer init
switch(capture_output_format) {
case XLLP_CAMERA_IMAGE_FORMAT_RGB555:
case XLLP_CAMERA_IMAGE_FORMAT_RGB565:
frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
pHwContext->XllpDMA.fifo0_transfer_size = frame_size;
pHwContext->XllpDMA.fifo1_transfer_size = 0;
pHwContext->XllpDMA.fifo2_transfer_size = 0;
break;
case XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PACKED:
frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
pHwContext->XllpDMA.fifo0_transfer_size = frame_size;
pHwContext->XllpDMA.fifo1_transfer_size = 0;
pHwContext->XllpDMA.fifo2_transfer_size = 0;
break;
case XLLP_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR:
frame_size = pHwContext->XllpCAMERA.capture_width * pHwContext->XllpCAMERA.capture_height * 2;
pHwContext->XllpDMA.fifo0_transfer_size = frame_size / 2;
pHwContext->XllpDMA.fifo1_transfer_size = frame_size / 4;
pHwContext->Xl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -