📄 pxa27x_camera.c
字号:
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)
{
// stop channel 0
XllpDmacStopTransfer( pHwContext->XllpDMA.dma_channels[0] );
// stop channel 1 and 2
if ( pHwContext->XllpCAMERA.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 frame_size;
// ring buffer init
switch(pHwContext->XllpCAMERA.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->XllpDMA.fifo2_transfer_size = frame_size / 4;
break;
default:
return XLLP_STATUS_WRONG_PARAMETER;
break;
}
pHwContext->XllpDMA.block_size = frame_size;
pHwContext->XllpDMA.block_number = pHwContext->XllpDMA.buf_size / frame_size;
pHwContext->XllpDMA.block_header = pHwContext->XllpDMA.block_tail = 0;
return XLLP_STATUS_SUCCESS;
}
// Set the image format
XLLP_STATUS_T PrvCameraSetCaptureFormat(P_HW_CONTEXT_T pHwContext)
{
XLLP_STATUS_T status;
status = XllpCameraSetCaptureFormat(&pHwContext->XllpCAMERA);
if(status == XLLP_STATUS_SUCCESS)
{
status = PrvSetDMARingBuffer(pHwContext);
}
return status;
}
int CameraSleep(void)
{
RETAILMSG(1, (TEXT("CameraSleep\r\n")));
return 0;
}
int CameraResume(void)
{
RETAILMSG(1, (TEXT("CameraResume\r\n")));
XllpI2cInit((P_XLLP_I2C_T)(v_pI2C), (P_XLLP_GPIO_T) v_pGPIORegs, (P_XLLP_CLKMGR_T) v_pClkRegs, (XLLP_UINT32_T) 0);
CameraInitSensor();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -