📄 pxa27x_camera.c
字号:
{
*bufP = 0;
if(g_HwContext.XllpCAMERA.camera_functions->ReadRegister)
{
XllpLock(I2C);
g_HwContext.XllpCAMERA.camera_functions->ReadRegister(&g_HwContext.XllpCAMERA, subAddress, bufP);
XllpUnlock(I2C);
}
//RETAILMSG(1,(TEXT("Reading register %x with %x\r\n"), subAddress, *bufP));
}
// Start the video capture process initiated by the application
void CameraStartVideoCapture()
{
XLLP_STATUS_T status;
EnterCriticalSection(&CameraMutex);
bDoStillCapture = FALSE;
XllpLock(I2C);
// Configure the capture format. Set the width, height, mode, and the physical addresses of the
// start of the descriptor chain.
g_HwContext.XllpCAMERA.capture_width = g_HwContext.XllpCAMERA.Video_capture_width;
g_HwContext.XllpCAMERA.capture_height = g_HwContext.XllpCAMERA.Video_capture_height;
g_HwContext.XllpCAMERA.capture_mode = XLLP_CAMERA_MODE_RECORD;
g_HwContext.XllpDMA.fifo0_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH0;
g_HwContext.XllpDMA.fifo1_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH1;
g_HwContext.XllpDMA.fifo2_descriptors_physical = VideoCaptureDescriptorPhysicalStartAddress_CH2;
// set capture format
status = PrvCameraSetCaptureFormat(&g_HwContext);
if (status)
{
RETAILMSG(1,(TEXT("Camera init failure inside CameraSetCaptureFormat().\r\n")));
}
XllpCameraSetInterruptMask(&g_HwContext.XllpCAMERA,
XLLP_CI_CICR0_FOM |
XLLP_CI_CICR0_EOFM |
XLLP_CI_CICR0_SOFM |
XLLP_CI_CICR0_CDM |
XLLP_CI_CICR0_QDM |
XLLP_CI_CICR0_PERRM |
XLLP_CI_CICR0_EOLM |
XLLP_CI_CICR0_FEM);
PrvStartCapture(&g_HwContext, 0, 0);
XllpUnlock(I2C);
LeaveCriticalSection(&CameraMutex);
}
void CameraStopVideoCapture()
{
EnterCriticalSection(&CameraMutex);
XllpLock(I2C);
// stop capture
g_HwContext.XllpCAMERA.camera_functions->stop_capture(&g_HwContext.XllpCAMERA);
// stop dma
PrvStopDMATransfer(&g_HwContext);
XllpUnlock(I2C);
LeaveCriticalSection(&CameraMutex);
}
void CameraCaptureStillImage()
{
XLLP_STATUS_T status;
// stop capture
g_HwContext.XllpCAMERA.camera_functions->stop_capture(&g_HwContext.XllpCAMERA);
// stop dma
PrvStopDMATransfer(&g_HwContext);
EnterCriticalSection(&CameraMutex);
XllpLock(I2C);
discardframes = 0;
// Configure the capture format. Set the width, height, mode, and the physical addresses of the
// start of the descriptor chain.
g_HwContext.XllpCAMERA.capture_width = g_HwContext.XllpCAMERA.Still_capture_width;
g_HwContext.XllpCAMERA.capture_height = g_HwContext.XllpCAMERA.Still_capture_height;
g_HwContext.XllpCAMERA.capture_mode = XLLP_CAMERA_MODE_STILL;
g_HwContext.XllpDMA.fifo0_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH0;
g_HwContext.XllpDMA.fifo1_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH1;
g_HwContext.XllpDMA.fifo2_descriptors_physical = StillCaptureDescriptorPhysicalStartAddress_CH2;
// Reset the buffer chain. The application must now resubmit all capture buffers.
bFirstVideoCaptureBufferSubmitted = FALSE;
VirtAddr_Last_Pn_CH0 = 0x0;
// set capture format
status = PrvCameraSetCaptureFormat(&g_HwContext);
if (status)
{
RETAILMSG(1,(TEXT("Camera init failure inside CameraSetCaptureFormat().\r\n")));
// return 1;
}
XllpCameraSetInterruptMask(&g_HwContext.XllpCAMERA,
XLLP_CI_CICR0_FOM |
XLLP_CI_CICR0_EOFM |
XLLP_CI_CICR0_SOFM |
XLLP_CI_CICR0_CDM |
XLLP_CI_CICR0_QDM |
XLLP_CI_CICR0_PERRM |
XLLP_CI_CICR0_EOLM |
XLLP_CI_CICR0_FEM);
bDoStillCapture = TRUE;
// Enable the still image capture sequence.
// Calling this routine once results in capture sequence that sometimes fails to interrupt
// on the end of frame.
// Calling this routine twice works around this problem - but it needs to be looked into
// to root cause the failure.
PrvStartCapture(&g_HwContext, 0, 1);
PrvStartCapture(&g_HwContext, 0, 1);
XllpUnlock(I2C);
LeaveCriticalSection(&CameraMutex);
}
// Shut down this session of the camera driver and free all of the relevent resources allocated within.
int CameraShutdown(void)
{
DWORD i;
DESCRIPTOR_INFO_T *pDescriptorInfo;
XllpLock(I2C);
XllpCameraDeInit(&g_HwContext.XllpCAMERA);
for (i = 0; i < NumBuffers; i++)
{
pDescriptorInfo = MasterBufferList[i];
free(pDescriptorInfo->pDescriptorBufferPhyAddress);
free(pDescriptorInfo->pDescriptorBufferVirtAddress);
free(pDescriptorInfo->pBufferPhyAddress);
free(pDescriptorInfo);
}
free((void *)VirtAddr_Phantom_Buffer_Base_Address);
NumBuffers = 0;
// Signal the ISR thread to shutdown
SetEvent(hShutDown);
XllpUnlock(I2C);
return TRUE;
}
// A helper function that is called to configure the parameters that are later used
// to configure the capture format.
int CameraChangeCaptureFormat(void)
{
// TBD: call some real function
return TRUE;
}
// Provides a physical address for a given user mode virtual address.
BOOL getPhyAddress (DWORD * pdwVirtual, DWORD * pdwPhysical)
{
BOOL bReturnVal = TRUE;
DWORD dwPageSize = UserKInfo[KINX_PAGESIZE];
DWORD dwPageTableEntry;
DWORD dwPageTablePart;
DWORD dwOffsetInPage;
/* query the page tables */
if (LockPages (pdwVirtual, sizeof (DWORD), &dwPageTableEntry, LOCKFLAG_QUERY_ONLY) != TRUE)
{
bReturnVal = FALSE;
goto cleanAndReturn;
}
/* shift left to make into a real address */
dwPageTablePart = dwPageTableEntry << UserKInfo[KINX_PFN_SHIFT];
/* figure out the offset in the page */
dwOffsetInPage = ((DWORD) pdwVirtual) & (~UserKInfo[KINX_PFN_MASK]);
/* combine the page table part and offset to create the address */
*pdwPhysical = dwPageTablePart | dwOffsetInPage;
cleanAndReturn:
return (bReturnVal);
}
//
// Submit a buffer to be filled by the camera DMA.
// A buffer is submitted by chaining the last buffer to this new buffer.
//
// Requires a valid FrameID, which is obtained from a successful call to PrepareBuffer().
//
void CameraSubmitBuffer(P_CAMERA_DMA_BUFFER_INFO pBufInfo, int BufferType)
{
DESCRIPTOR_INFO_T *pDescriptorInfo;
XLLP_DMAC_DESCRIPTOR_T *pXPn_CH0;
XLLP_DMAC_DESCRIPTOR_T *pXPn_CH1;
XLLP_DMAC_DESCRIPTOR_T *pXPn_CH2;
XLLP_DMAC_DESCRIPTOR_T *pXn_CH0;
XLLP_DMAC_DESCRIPTOR_T *pXn_CH1;
XLLP_DMAC_DESCRIPTOR_T *pXn_CH2;
XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH0;
XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH1;
XLLP_DMAC_DESCRIPTOR_T *pLast_Pn_CH2;
XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH0;
XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH1;
XLLP_DMAC_DESCRIPTOR_T *pLast_n_CH2;
BOOL isYUV_PLANAR;
pDescriptorInfo = NULL;
if (pBufInfo)
{
if (pBufInfo->BufferID < MAX_CAMERA_DMA_BUFFERS)
{
pDescriptorInfo = MasterBufferList[pBufInfo->BufferID];
}
}
if (pDescriptorInfo)
{
isYUV_PLANAR = (3 == pDescriptorInfo->dwPlanesNumber ? TRUE : FALSE);
// If this is the first buffer being submitted, then we want to store the physical address of the descriptor chain
// so that when we start DMA's later on, we start with _this_ buffer. All buffers submitted after this first buffer
// are chained behind this one. Therefore, this buffer is the logical choice to start with.
if (BufferType == VIDEO_CAPTURE_BUFFER)
{
if (bFirstVideoCaptureBufferSubmitted == FALSE)
{
VideoCaptureDescriptorPhysicalStartAddress_CH0 = pDescriptorInfo->pPhysAddr_X1_CH0;
VideoCaptureDescriptorPhysicalStartAddress_CH1 = pDescriptorInfo->pPhysAddr_X1_CH1;
VideoCaptureDescriptorPhysicalStartAddress_CH2 = pDescriptorInfo->pPhysAddr_X1_CH2;
bFirstVideoCaptureBufferSubmitted = TRUE;
}
pXPn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH0;
pXPn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH1;
pXPn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_XPn_CH2;
pXn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH0;
pXn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH1;
pXn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)pDescriptorInfo->pVirtAddr_Xn_CH2;
pLast_Pn_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH0;
pLast_Pn_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH1;
pLast_Pn_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_Pn_CH2;
pLast_n_CH0 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH0;
pLast_n_CH1 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH1;
pLast_n_CH2 = (XLLP_DMAC_DESCRIPTOR_T *)VirtAddr_Last_n_CH2;
// Chain last phantom descriptor XPn to the first phantom descriptor XP1.
// This loops the phantom descriptor back to itself.
pXPn_CH0->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH0;
if (isYUV_PLANAR) pXPn_CH1->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH1;
if (isYUV_PLANAR) pXPn_CH2->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH2;
// Chain the last real descriptor to the start of the phantom descriptor chain
pXn_CH0->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH0;
if (isYUV_PLANAR) pXn_CH1->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH1;
if (isYUV_PLANAR) pXn_CH2->DDADR = pDescriptorInfo->pPhysAddr_XP1_CH2;
// Chain the last descriptor to this new descriptor by adding this new descriptor to the end of the chain.
// We either are already looping on the phantom descriptor by the time this frame buffer is submitted, or
// we have yet to begin looping on the phantom descriptor. Therefore, we must program the end of the phantom descriptor
// to branch to the beginning of the new descriptor. And, if we were not already looping on the phantom descriptor,
// then we want to program the last real descriptor so that it branches to the beginning of the new descriptor.
if (VirtAddr_Last_Pn_CH0)
{
pLast_Pn_CH0->DDADR = pDescriptorInfo->pPhysAddr_X1_CH0;
if (isYUV_PLANAR) pLast_Pn_CH1->DDADR = pDescriptorInfo->pPhysAddr_X1_CH1;
if (isYUV_PLANAR) pLast_Pn_CH2->DDADR = pDescriptorInfo->pPhysAddr_X1_CH2;
pLast_n_CH0->DDADR = pDescriptorInfo->pPhysAddr_X1_CH0;
if (isYUV_PLANAR) pLast_n_CH1->DDADR = pDescriptorInfo->pPhysAddr_X1_CH1;
if (isYUV_PLANAR) pLast_n_CH2->DDADR = pDescriptorInfo->pPhysAddr_X1_CH2;
}
// Update pVirtAddr_Last_Pn and pVirtAddr_Last_n so they point to this new buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -