⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qci.c

📁 windows ce 6.0 camera driver
💻 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 OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
    
#include <windows.h>
#include <ceddk.h>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include <nkintr.h>

#include "monahans.h"
#include "qci.h"
#include "qci_private.h"

#include "BSP_CommonDefs.h"
#include "clkmgr.h"
#include "camera_SOC.h"
#include "CI.h"
#include "Args.h"
#include "ioctl_cfg.h"
#include "GPX_API.h" 
#include "MFP_DRV.h"

static PXA_CLKREF_HANDLE g_hClock = NULL;




// to call back camera driver
typedef struct qci_callback_item_s
{
    capture_callback_t callback;
    ULONG user;
    frame_t** frame;
} qci_callback_item_t;

static qci_callback_item_t callbacks[MAX_CALLBACK_NUM];
DWORD qci_sys_intr;
HANDLE qci_intr_event;
BOOL cgu_enable = 0;

dma_buf_t histogram_lut_buf;
UINT32 *histogram_lut_desc;
UINT32 histogram_lut_desc_phy;
UCHAR *lut = NULL;

#ifdef DEBUG
void QciDumpRegs();
#endif

static BOOL InitPins()
{

    if (PXA_STATUS_SUCCESS != MFP_SetActiveMode(PXA_COMPONENT_CIF_ID))
    {          
        RETAILMSG(1, (TEXT("CAM: Error Init MFP!\r\n")));
    }
    GPX_SetDirection(GPX_GPIO_UTMI_TEST_EN, PXA_GPIO_DIRECTION_OUT);
    GPX_SetDirection(GPX_GPIO_UTMI_SWITCH, PXA_GPIO_DIRECTION_OUT);
    GPX_SetDirection(GPX_GPIO_CAMERA_LIGHT_EN, PXA_GPIO_DIRECTION_OUT);
    GPX_SetOutputLevel(GPX_GPIO_UTMI_TEST_EN, PXA_HI);
    GPX_SetOutputLevel(GPX_GPIO_UTMI_SWITCH, PXA_LO);
    
    /* Call_GPX */
    GPX_SetDirection(GPX_GPIO_CAMERA_HI_PWDN, PXA_GPIO_DIRECTION_OUT);
    GPX_SetDirection(GPX_GPIO_CAMERA_LO_PWDN, PXA_GPIO_DIRECTION_OUT);
    GPX_SetOutputLevel(GPX_GPIO_CAMERA_HI_PWDN, PXA_HI);
    GPX_SetOutputLevel(GPX_GPIO_CAMERA_LO_PWDN, PXA_HI);

    return TRUE;
}


static void HistogramLutInit()
{
    UINT32 size;
    dma_buf_t *buf = &histogram_lut_buf;

    size = HISTOGRAM_LUT_BUF_SIZE + sizeof(PXA_CI_DMAC_DESCRIPTOR_T);
    
    DMABufAlloc(buf, size, 0);
    histogram_lut_desc = (UINT32*)(buf->buf + HISTOGRAM_LUT_BUF_SIZE);
    histogram_lut_desc_phy = buf->phy_addr + HISTOGRAM_LUT_BUF_SIZE;
}

static BOOL InitResources(void)
{
    DWORD qci_irq = IRQ_QCI;
    int status;
    HANDLE thread;

    g_pCIRegs = (PXA_CI_REGS*)PXA_CTX_GetRegAddr(PXA_PERIPHERAL_REGIDX_QCI);
    g_pGPIORegs = (PXA_GPIOREG_T *)PXA_CTX_GetRegAddr(PXA_PERIPHERAL_REGIDX_GPIO);
    
    g_hClock = PXA_CreateClockReferenceObject3(PXA_CKEN_CAMERA, PXA_CLKREF_ACCESS_EXCLUSIVE, FALSE);

    status = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &qci_irq, sizeof(UINT32), 
                             &qci_sys_intr, sizeof(UINT32), NULL);
    if (status != TRUE)
    {
        RETAILMSG(1, (TEXT("CAM: Error obtaining camera SYSINTR value %d!\r\n"), status));
        return FALSE;
    }

    qci_intr_event = CreateEvent(NULL, FALSE, FALSE,NULL);
    if (!InterruptInitialize(qci_sys_intr, qci_intr_event, NULL, 0)) 
    {
        RETAILMSG(1, (TEXT("CAM: Error initializing camera interrupt event!\r\n")));
        return FALSE;
    }

    HistogramLutInit();

    // Launch the Camera ISR
    thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)QciIntrThread, 0, 0, NULL);
    CloseHandle(thread);
    return TRUE;
}

static BOOL LutLoad()
{
    PXA_STATUS_T status;
    if (lut)
    {
        status = PXA_CICGULoadLutRam(g_pCIRegs, 
                                   (UINT32*)histogram_lut_buf.buf,
                                   histogram_lut_buf.phy_addr,
                                   histogram_lut_desc,
                                   histogram_lut_desc_phy,
                                   lut);
        return status == PXA_STATUS_SUCCESS;
    }

    return FALSE;
}

static PXA_CI_IMAGE_FORMAT GetCIFormat(int format)
{
    switch (format)
    {
    case PXA_CAMERA_IMAGE_FORMAT_RAW10:
        return PXA_CI_RAW10;
    case PXA_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR:
        return PXA_CI_YCBCR422_PLANAR;
    default:
        return PXA_CI_RAW10;
    }
}


void QCIPowerOn()
{
    UCHAR buffer[2];
    
    InitPins();    
    QCIClockEnable(0);
    // camera setup arava

    //power on sensor
    buffer[0] = 0x14;
    buffer[1] = 0x2a;
        
    I2C_WriteData(0x49, buffer, 2, TRUE, PXA_I2C_NORMAL_LEVEL);
}


void QCIClockEnable(BOOL is_on)
{        
    if((NULL != g_hClock)&& (is_on)) 
    {
        PXA_TurnOnClock(g_hClock);
        PXA_CIInit(g_pCIRegs);
    }    
    else
        PXA_TurnOffClock(g_hClock);
}


BOOL QCIInitAll()
{
    memset(callbacks, 0, sizeof(callbacks));

    if (InitResources() != TRUE)
        return FALSE;

    //power_on();
    QCIPowerOn();
    return TRUE;
}


void QCISetInterface(qci_interface_t *intf)
{
    // Configure CI according to OV2620's hardware        
    // master parallel with 8 data pins
    PXA_CISetMode(g_pCIRegs, intf->mode, intf->data_width);
    
    // enable pixel clock(sensor will provide pclock) and master clock = 26MHZ
    PXA_CISetClock(g_pCIRegs,TRUE, TRUE, intf->clock);

    // data sample on rising and h,vsync active high
    PXA_CISetPolarity(g_pCIRegs, 
                      intf->pclk_polarity, 
                      intf->hsync_polarity, 
                      intf->vsync_polarity);
}


void QCIEnable()
{
    PXA_CISetFIFO(g_pCIRegs, 0, PXA_CI_FIFO_THL_32, TRUE, TRUE);
    PXA_CIEnable(g_pCIRegs);
}


void QCISetMasterTiming(qci_master_timing_t* timing)
{
    PXA_CIConfigureMP(g_pCIRegs, timing->width, timing->height, &timing->timing);
}


// set qci input output format
void QCISetImageFormat(int in_format, 
                          int out_format)
{
    PXA_CI_CMU_USAGE cmu_usage = PXA_CI_CICMR_DMODE_DISABLE;
    PXA_CI_IMAGE_FORMAT ci_in_format = GetCIFormat(in_format);
    PXA_CI_IMAGE_FORMAT ci_out_format = GetCIFormat(out_format);

    cgu_enable = 0;
    PXA_CISetImageFormat(g_pCIRegs, ci_in_format, ci_out_format);

    if (in_format == PXA_CAMERA_IMAGE_FORMAT_RAW10)
    {
        PXA_CICGUSetAddrMuxSelect(g_pCIRegs, PXA_CI_CGU_MUX_2_TO_9);
        if (out_format == PXA_CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR)//Use CGU to change format from RGB to YUV
        {
            cgu_enable = 1;
            cmu_usage = PXA_CI_CMU_OUTPUT_YUV;
        }
    }
    PXA_CICMUEnable(g_pCIRegs, cmu_usage);
}

/////////////////////////////////////////////////////
// Wait for Vsync Blank time
// Config the Vsync to GPIO, then read it's level
/////////////////////////////////////////////////////
static void WaitVsyncBlank(PXA_LEVEL_T waitLevel)
{
    PXA_LEVEL_T level;

    //Config VSYNC to GPIO function 0, and Input
    MFP_SetPinAfDs(PXA_MFP_GPIO_CIF_FV_VSYNC_ID, PXA_MFP_ALT_FN_3, PXA_MFP_DS_04X);
    PXA_GPIOSetDirection(g_pGPIORegs, PXA_MFP_GPIO_CIF_FV_VSYNC_ID, PXA_GPIO_DIRECTION_IN);

    //Wait for VSYNC low
    while(TRUE){
        PXA_GPIOGetLevel(g_pGPIORegs, PXA_MFP_GPIO_CIF_FV_VSYNC_ID, &level);
        if(level == waitLevel){
            //VSYNC is blank
            RETAILMSG(1,(L"[QCI]: VSYNC is bank now!!\r\n"));
            break;
        }
    }

    //Config the VSYNC back to QCI pin functioin
    MFP_SetPinAfDs(PXA_MFP_GPIO_CIF_FV_VSYNC_ID, PXA_MFP_ALT_FN_0, PXA_MFP_DS_04X);
}


void QCICaptureStart(int in_still_skips)
{
    //Wait for vsync blank time(assume its low), then disable/enable CI.
    WaitVsyncBlank(PXA_LO);
    
    PXA_CIDisable(g_pCIRegs, TRUE, TRUE);
    PXA_CIResetFIFO(g_pCIRegs);

    PXA_CIClearInterruptStatus(g_pCIRegs, 0xFFFFFFFF);

    PXA_CIDisableComplete(g_pCIRegs);

    if (cgu_enable)
        if (LutLoad()) 
            PXA_CICGUEnable(g_pCIRegs, TRUE);

    DMALoad();

    //QCI Enable
    PXA_CISetFIFO(g_pCIRegs, 0, PXA_CI_FIFO_THL_32, TRUE, TRUE);
    PXA_CIEnable(g_pCIRegs);
    
    PXA_CISetInterruptMask(g_pCIRegs, PXA_CI_CICR0_INTERRUPT_MASK & (~PXA_CI_INT_EOF));
    PXA_CISetFrameRate(g_pCIRegs, in_still_skips);    
    
}


void QCICaptureStop()

{
    PXA_CISetInterruptMask(g_pCIRegs, PXA_CI_CICR0_INTERRUPT_MASK);
    PXA_CIDisable(g_pCIRegs, TRUE, TRUE);
    PXA_CIResetFIFO(g_pCIRegs);
}


BOOL QCIAddCallBack(callback_data_t* callback_data)
{
    ULONG index = callback_data->mode;

    if (index >= MAX_CALLBACK_NUM)
        return FALSE;

    callbacks[index].callback = callback_data->callback;
    callbacks[index].user = callback_data->user;
    callbacks[index].frame = callback_data->frame;
    return TRUE;
}

void QciCallBack(frame_t* frame)
{
    int i;

    for (i = 0; i < MAX_CALLBACK_NUM; i++)
    {
        if (callbacks[i].callback == NULL)
            continue;

        __try
        {
            *(callbacks[i].frame) = frame;
            callbacks[i].callback(callbacks[i].user, i);
        }
        __except( EXCEPTION_EXECUTE_HANDLER )
        {
            ERRORMSG(1, (TEXT("CAM: Qcibus.DLL : frame %x callback exception\r\n"), frame));
        }
    }
}


#ifdef DEBUG
void QciDumpRegs()
{
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICR0 0x%08x\r\n",g_pCIRegs->PXA_CICR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICR1 0x%08x\r\n",g_pCIRegs->PXA_CICR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICR2 0x%08x\r\n",g_pCIRegs->PXA_CICR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICR3 0x%08x\r\n",g_pCIRegs->PXA_CICR3));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICR4 0x%08x\r\n",g_pCIRegs->PXA_CICR4));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CISR 0x%08x\r\n",g_pCIRegs->PXA_CISR));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CITOR 0x%08x\r\n",g_pCIRegs->PXA_CITOR));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIBR0 0x%08x\r\n",g_pCIRegs->PXA_CIBR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIBR1 0x%08x\r\n",g_pCIRegs->PXA_CIBR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIBR2 0x%08x\r\n",g_pCIRegs->PXA_CIBR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIBR3 0x%08x\r\n",g_pCIRegs->PXA_CIBR3));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIFR0 0x%08x\r\n",g_pCIRegs->PXA_CIFR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIFR1 0x%08x\r\n",g_pCIRegs->PXA_CIFR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIFSR 0x%08x\r\n",g_pCIRegs->PXA_CIFSR));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDCSR0 0x%08x\r\n",g_pCIRegs->PXA_CIDCSR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDCSR1 0x%08x\r\n",g_pCIRegs->PXA_CIDCSR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDCSR2 0x%08x\r\n",g_pCIRegs->PXA_CIDCSR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDCSR3 0x%08x\r\n",g_pCIRegs->PXA_CIDCSR3));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDBR0 0x%08x\r\n",g_pCIRegs->PXA_CIDBR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDBR1 0x%08x\r\n",g_pCIRegs->PXA_CIDBR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDBR2 0x%08x\r\n",g_pCIRegs->PXA_CIDBR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDBR3 0x%08x\r\n",g_pCIRegs->PXA_CIDBR3));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDADR0 0x%08x\r\n",g_pCIRegs->PXA_CIDADR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CITADR0 0x%08x\r\n",g_pCIRegs->PXA_CITADR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CISADR0 0x%08x\r\n",g_pCIRegs->PXA_CISADR0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMD0 0x%08x\r\n",g_pCIRegs->PXA_CICMD0));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDADR1 0x%08x\r\n",g_pCIRegs->PXA_CIDADR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CITADR1 0x%08x\r\n",g_pCIRegs->PXA_CITADR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CISADR1 0x%08x\r\n",g_pCIRegs->PXA_CISADR1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMD1 0x%08x\r\n",g_pCIRegs->PXA_CICMD1));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDADR2 0x%08x\r\n",g_pCIRegs->PXA_CIDADR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CITADR2 0x%08x\r\n",g_pCIRegs->PXA_CITADR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CISADR2 0x%08x\r\n",g_pCIRegs->PXA_CISADR2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMD2 0x%08x\r\n",g_pCIRegs->PXA_CICMD2));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CIDADR3 0x%08x\r\n",g_pCIRegs->PXA_CIDADR3));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CITADR3 0x%08x\r\n",g_pCIRegs->PXA_CITADR3));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CISADR3 0x%08x\r\n",g_pCIRegs->PXA_CISADR3));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMD3 0x%08x\r\n",g_pCIRegs->PXA_CICMD3));
    
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMR 0x%08x\r\n",g_pCIRegs->PXA_CICMR));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMC0 0x%08x\r\n",g_pCIRegs->PXA_CICMC0));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMC1 0x%08x\r\n",g_pCIRegs->PXA_CICMC1));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICMC2 0x%08x\r\n",g_pCIRegs->PXA_CICMC2));
    DEBUGMSG(ZONE_IOCTL,(L"PXA_CICCR 0x%08x\r\n",g_pCIRegs->PXA_CICCR));

}
#endif

static UCHAR default_lut[] = {
    // RED LUT
    0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
    0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
    0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
    0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
    0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
    0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
    0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
    0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,

    // BLUE LUT
    0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
    0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
    0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
    0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
    0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
    0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
    0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
    0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,

    // GREEN LUT
    0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
    0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
    0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c,
    0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,
    0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c,
    0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,
    0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc,
    0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,
};

PXA_CI_CMU_COE_MATRIX default_coe = 
{
    YUV_FLOAT_TO_INT(0.299), YUV_FLOAT_TO_INT(0.587), YUV_FLOAT_TO_INT(0.114),
    YUV_FLOAT_TO_INT(0.5), YUV_FLOAT_TO_INT(-0.41869), YUV_FLOAT_TO_INT(-0.08131),
    YUV_FLOAT_TO_INT(-0.16874), YUV_FLOAT_TO_INT(-0.33126), YUV_FLOAT_TO_INT(0.5)
};

// set the black level, color correction and gama correction
// if no configuration specified, default values will be used


void QCIImageProcCfg(qci_image_proc_cfg_t* cfg)
{
    UINT32 black_level = 0;
    PXA_CI_CMU_COE_MATRIX* coe = &default_coe;
    lut = default_lut;

    if (cfg)
    {
        cgu_enable = 1;

        black_level = cfg->black_level;
        coe = &cfg->coe;
        if (cfg->lut)
            lut = cfg->lut;
    }

    PXA_CICGUSetBlackLevel(g_pCIRegs, black_level);
    PXA_CICMUSetColorCorrectionCoe(g_pCIRegs, coe);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -