📄 pxa27x_camera.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
/**************************************************************************
** Copyright 2000-2004 Intel Corporation. All Rights Reserved.
**
** Portions of the source code contained or described herein and all documents
** related to such source code (Material) are owned by Intel Corporation
** or its suppliers or licensors and is licensed by Microsoft Corporation for distribution.
** Title to the Material remains with Intel Corporation or its suppliers and licensors.
** Use of the Materials is subject to the terms of the Microsoft license agreement which accompanied the Materials.
** No other license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise
** Some portion of the Materials may be copyrighted by Microsoft Corporation.
Module Name:
CAMERA.c
**************************************************************************/
#include <windows.h>
#include <ceddk.h>
#include <types.h>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include <nkintr.h>
#include <giisr.h>
#include <bulverde.h>
#include "xllp_ci.h"
#include "xllp_i2c.h"
#include "xllp_serialization.h"
#include "pxa27x_camera.h"
#define ZONE_ERROR 1
#define ZONE_INIT 1
#define ZONE_VERBOSE 1
#define DMA_INTERRUPT_REGISTER (BULVERDE_BASE_REG_PA_DMAC + (DWORD)&(((P_XLLP_DMAC_T)0)->DINT))
// Global variables
// Pointer to camera driver instance which we will send back with callback functions
DWORD dwCameraDriverContext;
// Signals the application that the video or still image frame is available
PFNCAMHANDLEFRAME pfnCameraHandleVideoFrame = NULL;
PFNCAMHANDLEFRAME pfnCameraHandleStillFrame = NULL;
volatile XLLP_DMAC_T * v_pDMARegs = NULL;
volatile XLLP_GPIO_T * v_pGPIORegs = NULL;
volatile XLLP_CLKMGR_T * v_pClkRegs = NULL;
volatile unsigned int * v_pOSTRegs = NULL;
volatile unsigned int * v_pCIRegs = NULL;
volatile unsigned int * v_pI2C = NULL;
// Local variables
//
static const LPCWSTR g_wszDmaIsrDll = L"giisr.dll";
static const LPCWSTR g_wszDmaIsrHandler = L"ISRHandler";
// The camera hardware context
static HW_CONTEXT_T g_HwContext;
// The MasterBufferList contains pointers to a DESCRIPTOR_INFO_T structure for each buffer in the list.
// This is currently statically allocated.
static DESCRIPTOR_INFO_T *MasterBufferList[MAX_CAMERA_DMA_BUFFERS];
// Describes the current number of buffers that are contained in the Master Buffer List.
static DWORD NumBuffers = 0;
// Address of the last phantom descriptor
static XLLP_VUINT32_T VirtAddr_Last_Pn_CH0 = 0x0;
static XLLP_VUINT32_T VirtAddr_Last_Pn_CH1 = 0x0;
static XLLP_VUINT32_T VirtAddr_Last_Pn_CH2 = 0x0;
// Address of the last real descriptor
static XLLP_VUINT32_T VirtAddr_Last_n_CH0 = 0x0;
static XLLP_VUINT32_T VirtAddr_Last_n_CH1 = 0x0;
static XLLP_VUINT32_T VirtAddr_Last_n_CH2 = 0x0;
// Virtual address of the phantom buffer
static XLLP_VUINT32_T VirtAddr_Phantom_Buffer = 0x0;
static XLLP_VUINT32_T VirtAddr_Phantom_Buffer_Base_Address = 0x0;
// Physical address of the phantom buffer
static XLLP_VUINT32_T PhysAddr_Phantom_Buffer = 0x0;
// Physical address of the start of the video capture descriptor chain
static XLLP_VUINT32_T VideoCaptureDescriptorPhysicalStartAddress_CH0 = 0x0;
static XLLP_VUINT32_T VideoCaptureDescriptorPhysicalStartAddress_CH1 = 0x0;
static XLLP_VUINT32_T VideoCaptureDescriptorPhysicalStartAddress_CH2 = 0x0;
// Physical address of the start of the still capture descriptor chain
static XLLP_VUINT32_T StillCaptureDescriptorPhysicalStartAddress_CH0 = 0x0;
static XLLP_VUINT32_T StillCaptureDescriptorPhysicalStartAddress_CH1 = 0x0;
static XLLP_VUINT32_T StillCaptureDescriptorPhysicalStartAddress_CH2 = 0x0;
// Set to true when the first video capture buffer has been submitted.
static BOOL bFirstVideoCaptureBufferSubmitted = FALSE;
// Set to true when the first stll image buffer has been submitted
static BOOL bFirstStillBufferSubmitted = FALSE;
// Used to provide synchronized access to certain camera functions
static CRITICAL_SECTION CameraMutex;
// Use to inform the interrupt service thread that a still capture event is occuring.
static unsigned int bDoStillCapture = FALSE;
static unsigned int bDoVideoCapture = FALSE;
// Used to discard a certain number of still image frames before signalling the application
// that the frame is available. Some sensors output bad frames for the first few captured frames
// and they need to be "discarded."
static int discardframes = 0;
// Signals the application that a frame of motion video is available
static HANDLE hCameraFrameReady;
// Signals the application that the still image frame is available
static HANDLE hStillImageReady;
// Signals the application that the shutdown of the camera driver is complete.
static HANDLE hCameraShutdownComplete;
static HANDLE hShutDown;
static const XLLP_DMAC_DEVICE_T CAMERA_DMA_DEVICE[3] =
{
XLLP_DMAC_QCI_RX1,
XLLP_DMAC_QCI_RX2,
XLLP_DMAC_QCI_RX3
};
static XLLP_STATUS_T PrvCameraDmacInit(HW_CONTEXT_T *pHwContext);
static XLLP_STATUS_T PrvCameraDmacDeinit(HW_CONTEXT_T *pHwContext);
static void PrvStartDMATransfer(P_HW_CONTEXT_T pHwContext, unsigned block_id);
static void PrvStopDMATransfer(P_HW_CONTEXT_T pHwContext);
static XLLP_STATUS_T PrvStartCapture(P_HW_CONTEXT_T pHwContext, unsigned int block_id, unsigned int frames);
static XLLP_STATUS_T PrvCameraSetCaptureFormat(P_HW_CONTEXT_T pHwContext);
static DWORD WINAPI CAMIntrThread(HW_CONTEXT_T *pHwContext);
VOID CameraInterfaceInterruptHandler(HW_CONTEXT_T *pHwContext)
{
DWORD dwDCSR;
DWORD dwDINT;
int i;
dwDINT = v_pDMARegs->DINT;
DEBUGMSG(ZONE_VERBOSE, (TEXT( "CameraInterfaceInterruptHandler: DINT=0x%x\r\n" ), dwDINT));
for(i=0; i<3; i++)
if(dwDINT & (1<<pHwContext->XllpDMA.dma_channels[i]))
{
dwDCSR = v_pDMARegs->DCSR[pHwContext->XllpDMA.dma_channels[i]];
DEBUGMSG(ZONE_VERBOSE, (TEXT( "CameraInterfaceInterruptHandler: CH[%d] DCSR: 0x%x\r\n" ),pHwContext->XllpDMA.dma_channels[i], dwDCSR));
// Provide waiting Object the current value of DCSR
// SetEventData(pHwContext->hDMAEvent[i], dwDCSR);
//did we get an error?
if (dwDCSR & XLLP_DMAC_DCSR_BUS_ERR_INTR)
{
DEBUGMSG(ZONE_ERROR, (TEXT( "DCSR_BUSERRINTR ERROR\r\n" )) );
DEBUGCHK(0); // an unplanned dma interrupt occured
}
//did we get an start interrupt?
if (dwDCSR & XLLP_DMAC_DCSR_START_INTR)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STARTINTR\n" )) );
DEBUGCHK(0); // an unplanned dma interrupt occured
}
//did we get an end interrupt?
if (dwDCSR & XLLP_DMAC_DCSR_END_INTR) //if the channel stopped at the end of a buffer xfer
{
DEBUGMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTR\r\n" )) );
}
//did we get an stop interrupt?
if (dwDCSR & XLLP_DMAC_DCSR_STOP_INTR)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STOPINTR\r\n" )) );
dwDCSR &= ~XLLP_DMAC_DCSR_STOP_IRQ_EN;
DEBUGCHK(0); // an unplanned dma interrupt occured
}
// Clear the status
v_pDMARegs->DCSR[pHwContext->XllpDMA.dma_channels[i]] = dwDCSR;
SetEvent(pHwContext->hDMAEvent[i]);
}
return;
}
DWORD DMAInterruptThread(HW_CONTEXT_T *pHwContext)
{
DEBUGMSG(1, (TEXT("DMAInterruptThread\r\n")));
while (TRUE)
{
WaitForSingleObject(pHwContext->hDmaIntrEvent, INFINITE);
// Grab the lock
//Lock();
CameraInterfaceInterruptHandler(pHwContext);
//Unlock();
InterruptDone(pHwContext->dwSysIntrDMA);
} // while(TRUE)
return 0;
}
XLLP_STATUS_T PrvCameraDmacInit(HW_CONTEXT_T *pHwContext)
{
int i;
_TCHAR EventName[20];
DWORD dwDMAIrq = pHwContext->dwDmaIrq;
for(i=0; i<3; i++)
{
// Get DMA channel event handler
// Compose the name of the channel event for use with CreateEvent(...) below.
wsprintf(EventName, TEXT("DMA_CHANNEL_%d"), pHwContext->XllpDMA.dma_channels[i]);
pHwContext->hDMAEvent[i] = CreateEvent(NULL,FALSE,FALSE, EventName);
if (pHwContext->hDMAEvent[i] == NULL)
{
DEBUGMSG(ZONE_ERROR,(TEXT("hDMAEvent (Named) is Zero...\r\n")));
return (FALSE);
}
}
// Convert the hardwre DMA controller interrupt IRQ into a logical SYSINTR value
if(!pHwContext->dwSysIntrDMA || pHwContext->dwSysIntrDMA == SYSINTR_UNDEFINED)
{
if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,
&dwDMAIrq, sizeof(DWORD),
&pHwContext->dwSysIntrDMA, sizeof(DWORD), NULL))
{
DEBUGMSG(ZONE_ERROR, (TEXT("Error obtaining DMA interrupt SYSINTR value!\n")));
return (FALSE);
}
}
// Install the DMA ISR handler
if(pHwContext->hDMAIsrHandler == NULL)
{
GIISR_INFO Info;
HANDLE hBusAccessHandle;
PVOID PhysAddr;
DWORD inIoSpace = 0; // io space
PHYSICAL_ADDRESS DmaRegisterAddress = {DMA_INTERRUPT_REGISTER, 0};
pHwContext->hDMAIsrHandler = LoadIntChainHandler(g_wszDmaIsrDll,
g_wszDmaIsrHandler,
(BYTE)dwDMAIrq);
if(pHwContext->hDMAIsrHandler == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("LoadIntChainHandler (%s, %s, %d) failed!\r\n"),
g_wszDmaIsrDll,
g_wszDmaIsrHandler,
dwDMAIrq));
return FALSE;
}
hBusAccessHandle = CreateBusAccessHandle((LPCTSTR)pHwContext->hDriverIndex);
if(!BusTransBusAddrToStatic(hBusAccessHandle,
Internal, 0,
DmaRegisterAddress, sizeof(DWORD),
&inIoSpace, &PhysAddr))
{
DEBUGMSG(ZONE_ERROR, (L"pxa27x_camera: Failed TransBusAddrToStatic\r\n"));
return FALSE;
}
DEBUGMSG(ZONE_INIT, (L"Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n",
g_wszDmaIsrDll, g_wszDmaIsrHandler, dwDMAIrq, PhysAddr));
// Set up ISR handler
Info.SysIntr = pHwContext->dwSysIntrDMA;
Info.CheckPort = TRUE;
Info.PortIsIO = FALSE;
Info.UseMaskReg = FALSE;
Info.PortAddr = (DWORD)PhysAddr;
Info.PortSize = sizeof(DWORD);
Info.Mask = (1 << pHwContext->XllpDMA.dma_channels[0]) |
(1 << pHwContext->XllpDMA.dma_channels[1]) |
(1 << pHwContext->XllpDMA.dma_channels[2]) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -