//
// 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.
//
//
// Copyright (c) Samsung Electronics. Co. LTD.  All rights reserved.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:    camera_hal.cpp

Abstract:       Handle Camera device in Low level abstract

Functions:


Notes:


--*/

#include <bsp.h>
#include <pm.h>
#include <pmplatform.h>
#include <drvlib_mem.h>
#include <drvlib_wait.h>
#include <drvmsg.h>
#include <camera_hal.h>
#include "csi_s.h"

//#define ChcekUsedCamera
#define MODULE_NAME      _T("CAMIF")
CAM_CALLBACK_ARGS pfnCallbacks;

#define USE_LASTIRQ_STILLCAPTURE    (TRUE)
#define USE_CAPTURE_FRAME_CONTROL   (TRUE)
#define USE_STEPBYSTEP_CONTROL      (TRUE)

#define CAPTURE_TIMEOUT             (5000)          // 1 second/frame

static int m_bSensorInit=0;//=FALSE;
const UINT32 ImageSizeTbl[][2] =
{
    {176,144},{176,176},{320,240},{352,288},{400,240},
    {640,480},{720,480},{800,480},{800,600},{1280,720},
    {1280,960},{1280,1024},{1600,1200},{2048,1536},{2560,1536},
    {2560,1920},{2592,1944},{3264,1960},{3264,2448},
    {0xffffffff,0xffffffff}
};

#define AlignSize(x, alignbyte) (alignbyte * (( x / alignbyte) + 1))

static void DumpCamReg(volatile CAMIF_REG *DumpReg)
{

    static int callcount =0;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s(DumpReg=0x%x), callcount=%d\r\n"), _T(__FUNCTION__), DumpReg, callcount));
    for(int i =0;i<sizeof(CAMIF_REG)/sizeof(DWORD);i++)
    {
        DBGMSG(CIF_FUNC && CIF_USR3,(_T("0x%08x,"), *((DWORD *)DumpReg + i)));
    }
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("\r\n")));
    callcount++;

}

CameraHal::CameraHal() :
        m_regIOP(NULL),
        m_regCAM(NULL),
        m_regCLKCON(NULL),
        m_CaptureOn(0),
        m_hPwrControl(NULL),
        m_dwCurrentCAMIFID(NULL),   // Use HW IP PHYSICAL ADDRESS as CAMIFID
        m_CamIrq(IRQ_FIMC0),        // IRQ_FIMC0, IRQ_FIMC1, IRQ_FIMC2
        m_CamSysIntr(SYSINTR_UNDEFINED),
        m_InputPort(CAM_DMA_PORT),
        m_CamOperationMode(ABNORMAL_MODE),
        CMiniThread (0, TRUE),
        m_dwISTTimeout(INFINITE),
        m_oCSI_S(NULL),
        m_isPowerOn(0),
        m_dwSkipFrameCnt(0),
        hVideoCaptureEvent(NULL),
        hPreviewCaptureEvent(NULL)

{
    memset(&m_moduleDesc, 0, sizeof(MODULE_DESCRIPTOR));
}

DWORD CameraHal::ThreadRun()
{
    CeSetPriority(100);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()=0x%x\r\n"), _T(__FUNCTION__), &CameraHal::ThreadRun));
    while ( m_hCaptureEvent!=NULL && !IsTerminated() )
    {
        DWORD dwCause;
        DBGMSG(CIF_INFO && CIF_USR3,(_T("%s() Waitfor Event: 0x%x\r\n"), _T(__FUNCTION__), m_hCaptureEvent));
        dwCause = WaitForSingleObject( m_hCaptureEvent, m_dwISTTimeout);
        if (  dwCause == WAIT_OBJECT_0)
        {
            DBGMSG(CIF_INFO && CIF_USR3,(_T("Event Catched from:0x%x(%d)\r\n"), m_hCaptureEvent, m_CamOperationMode));

            if(m_CamOperationMode == VIDEO_CAPTURE)
            {
                if(m_bWeaveMode == TRUE)
                {
                    if(((m_regCAM->BFS_CISTATUS.FrameCnt + 2) % 2) == 1)
                    {
                        DBGMSG(CIF_INFO && CIF_USR3,(TEXT("\n\nWEAVE OUT INT SKIP!!!! \r\n")));
                        // Clear Interrupt Pending
                        SET_BIT(m_regCAM->CIGCTRL, BP_CAM_IRQ_CLR);
                        //SET_BIT(m_regCAM->CIOCTRL, BP_CAM_FRAME_END);
                        if(m_oCSI_S)
                            m_oCSI_S->ClearInterrupt(ALLINT);
                        InterruptDone(m_CamSysIntr);
                        continue;
                    }
                }

                if(m_dwSkipFrameCnt >= 1)
                {
                    m_dwSkipFrameCnt = 2;
                    if(pfnCallbacks.dwCameraDriverContext != 0)
                    {
                        pfnCallbacks.pfnCameraHandleVideoFrame(pfnCallbacks.dwCameraDriverContext);
                    }
                    else
                    {
                        DBGMSG(CIF_INFO && CIF_USR3,(TEXT("Video Capture Event Called...\r\n")));
                        SetVideoCaptureCallbackEvent();
                    }
                }
                else
                {
                    m_dwSkipFrameCnt++;
                }
            }
            else if(m_CamOperationMode == STILL_CAPTURE)
            {
                // This will be taken on LAST IRQ
                if(m_dwSkipFrameCnt >= 1)
                {
                    m_dwSkipFrameCnt = 2;
                    // Stop Capture

                    if(m_oCSI_S)
                    {
                        DBGMSG(CIF_INFO && CIF_USR3,(TEXT("MIPI Status ECC:%d, CRC:%d\r\n"),
                            m_oCSI_S->CheckPacketHeaderECC(),
                            m_oCSI_S->CheckPacketDataCRC()));
                    }

                    m_dwSkipFrameCnt = 0;

                    SetEvent(m_hCaptureFinishEvent);
                    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("C%d\r\n"), m_dwSkipFrameCnt));
                }
                else
                {
#if USE_LASTIRQ_STILLCAPTURE
                    m_regCAM->CIOCTRL |= (1<<BP_LASTIRQEN);                 // This will generate IRQ after capturing last frame
                    // In this case, Camera Capture is disabled, so Preview also will be stopped even when use different camera IP.
                    m_regCAM->CIIMGCPT &= ~(CAM_GLOBAL_CAPTURE_ENABLE_BIT); // This will book stopping camera capture
                    m_regCAM->CIOCTRL &= ~(1<<BP_LASTIRQEN);
#endif
                    m_dwSkipFrameCnt++;

                    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("L%d\r\n"), m_dwSkipFrameCnt));
                }
            }
            else if(m_CamOperationMode == PREVIEW_CAPTURE)
            {
                if(m_dwSkipFrameCnt >= 1)
                {
                    m_dwSkipFrameCnt = 2;
                    if(pfnCallbacks.dwCameraDriverContext != 0)
                    {
                        pfnCallbacks.pfnCameraHandlePreviewFrame(pfnCallbacks.dwCameraDriverContext);
                    }
                    else
                    {
                        DBGMSG(CIF_INFO && CIF_USR3,(TEXT("Preview Capture Event Called...\r\n")));
                        SetPreviewCaptureCallbackEvent();
                    }

                }
                else
                {
                    m_dwSkipFrameCnt ++;
                }
            }
            else if(m_CamOperationMode == POST_PROCESSOR)
            {
#if 1
                if(m_regCAM->CISTATUS & (0x1<<17))
                {
            		// [17]_bit is NOT auto clear, so we need to make [17]_bit be clear
                    m_regCAM->CISTATUS = m_regCAM->CISTATUS & (~(0x1<<17));

                    m_dwIDMABusy = 0;
                    SetEvent(m_hPostDoneEvent);
                    //DBGMSG(1,(TEXT("<<17\n")));
                }
                if(((m_regCAM->CISTATUS&0x10000)==0x10000) // [16]: Last capture end
				&& ((m_regCAM->CISTATUS&0x80000000)==0x0) // [31]: Overflow state of FIFO Y
				&& ((m_regCAM->CISTATUS&0x40000000)==0x0) // [30]: Overflow state of FIFO Cb
				&& ((m_regCAM->CISTATUS&0x20000000)==0x0) // [29]: Overflow state of FIFO Cr
				&& ((m_regCAM->CISTATUS&0x40000)==0x0)) // [18]: Overflow status of line buffer for rotation
				{
            		// [16]_bit is NOT auto clear, so we need to make [17]_bit be clear
                    m_regCAM->CISTATUS = m_regCAM->CISTATUS & (~(0x1<<16));
                    //DBGMSG(1,(TEXT("<<16\n")));

                m_dwIDMABusy = 0;
                SetEvent(m_hPostDoneEvent);
				}

#else
                if(m_dwSkipFrameCnt >= 1)
                {
                    m_dwSkipFrameCnt = 2;

                    // Stop Scaler
                    m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_SCALERSTART)) | SCALER_STOP;
                    // Disable scaler for capture
                    m_regCAM->CIIMGCPT = (m_regCAM->CIIMGCPT & ~(BM_IMGCPTEN_SC)) | SCALER_DISABLE;

                    {
                        UINT32 uiStatus;

                        do
                        {
                            uiStatus = m_regCAM->CISTATUS;
                        } while( (uiStatus & (BM_CAM_IMAGECAPTURE_ENABLE|BM_CAM_IMAGECAPTURE_SCALER_ENABLE)) != 0);
                    }

                    SetEvent(m_hPostDoneEvent);
                }
                else
                {
#if USE_LASTIRQ_STILLCAPTURE
                    m_regCAM->CIOCTRL |= (1<<BP_LASTIRQEN);                 // This will generate IRQ after capturing last frame
                    m_regCAM->CIIMGCPT &= ~(CAM_GLOBAL_CAPTURE_ENABLE_BIT);
                    m_regCAM->CIOCTRL &= ~(1<<BP_LASTIRQEN);
#endif
                    m_dwSkipFrameCnt ++;
                }
#endif
            }

            // Clear Interrupt Pending
            SET_BIT(m_regCAM->CIGCTRL, BP_CAM_IRQ_CLR);
            //SET_BIT(m_regCAM->CIOCTRL, BP_CAM_FRAME_END);
            if(m_moduleDesc.MIPI == TRUE)
            {
            if(m_oCSI_S)
                m_oCSI_S->ClearInterrupt(ALLINT);
            }
            InterruptDone(m_CamSysIntr);
//            if(CamOperationMode == POST_PROCESSOR) PulseEvent(pCtxt->hPostCmdDone);

        }
        else
        {
            ERRMSG((_T("[CAMIF:ERR] ++%s() : Exit %d, Cause %d\r\n"), _T(__FUNCTION__), GetLastError(), dwCause));
            // ASSERT(FALSE);
        }
    }
    m_dwIDMABusy = 0;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("%s(): Thread Finished"), _T(__FUNCTION__)));
    return 1;
}

// Initialize globals
// Run on Loading time
CAMERA_POST_ERROR CameraHal::Initialize(DWORD dwCAMIFPhyAddr, DWORD dwVirIRQ)
{
    PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};
    BOOL    bSuccess;

    m_dwCurrentCAMIFID = dwCAMIFPhyAddr;
    m_CamIrq = dwVirIRQ;

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    // GPIO Virtual alloc
    m_regIOP = (GPIO_REG *)DrvLib_MapIoSpace(BASE_REG_PA_GPIO, sizeof(GPIO_REG), FALSE);
    if (m_regIOP == NULL)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): m_regIOP DrvLib_MapIoSpace failed!\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTENOUGHMEMORY;
    }

    // Camera Virtual alloc
    m_regCAM = (CAMIF_REG *)DrvLib_MapIoSpace(m_dwCurrentCAMIFID, sizeof(CAMIF_REG), FALSE);
    if (m_regCAM == NULL)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): m_regCAM DrvLib_MapIoSpace failed!\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTENOUGHMEMORY;
    }
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] ++%s(): m_regCAM DrvLib_MapIoSpace succeeded:0x%x!\r\n"), _T(__FUNCTION__), m_regCAM));

    // Clock Control Virtual alloc
    m_regCLKCON = (CMU_CLK_REG *)DrvLib_MapIoSpace(BASE_REG_PA_CMU_CLK, sizeof(CMU_CLK_REG), FALSE);
    if (m_regCLKCON == NULL)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): m_regCLKCON DrvLib_MapIoSpace failed!\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTENOUGHMEMORY;
    }

    m_hPwrControl = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
    if (INVALID_HANDLE_VALUE == m_hPwrControl )
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): PWC0 Open Device Failed!\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTENOUGHMEMORY;
    }

    InitializeCriticalSection( &m_csHWregister );

    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_CamIrq, sizeof(UINT32), &m_CamSysIntr, sizeof(UINT32), NULL))
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Failed to request sysintr value for Camera interrupt.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    m_hCaptureEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (!m_hCaptureEvent)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to create camera interrupt event.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    hVideoCaptureEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR)(L"VideoCaptureEvent"));
    if (!hVideoCaptureEvent)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to create Video Capture Named event.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    hPreviewCaptureEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR)(L"PreviewCaptureEvent"));
    if (!hPreviewCaptureEvent)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to create Preview Capture Named event.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }


    bSuccess = InterruptInitialize(m_CamSysIntr, m_hCaptureEvent, NULL, 0);
    if (!bSuccess)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to initialize camera interrupt event.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    m_hCaptureFinishEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (!m_hCaptureFinishEvent)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to create camera capture finish event.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));

    // Create MIPI Control object
    m_oCSI_S = new CSI_S(BASE_REG_PA_MIPI_CSI_BASE);
    if(!m_oCSI_S)
    {
        ERRMSG((_T("[CAMIF:ERR] ++%s(): Fail to create MIPI Control object.\r\n"), _T(__FUNCTION__)));
        return ERROR_CAMIF_NOTDEFINED;
    }

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));

    return ERROR_CAMIF_SUCCESS;
}

// Deinitialize
void CameraHal::Deinitialize()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    if(m_regIOP != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_regIOP);
        m_regIOP = NULL;
    }
    if(m_regCAM != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_regCAM);
        m_regCAM = NULL;
    }
    if(m_regCLKCON != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_regCLKCON);
        m_regCLKCON = NULL;
    }

    if(m_hPwrControl != NULL)
    {
        CloseHandle(m_hPwrControl);
        m_hPwrControl = NULL;
    }

    if (m_hCaptureEvent)
    {
        m_bTerminated=TRUE;
        ThreadStart();
        SetEvent(m_hCaptureEvent);
        ThreadTerminated(1000);
        InterruptDisable( m_CamSysIntr );
        CloseHandle(m_hCaptureEvent);
        m_hCaptureEvent = NULL;
    };

    if(m_oCSI_S)
    {
        delete m_oCSI_S;
        m_oCSI_S = NULL;
    }
    DeleteCriticalSection( &m_csHWregister );

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
}

/**
 *  Initialize GPIO setting for Camera Interface
 *  Set GPIO Output, Pull/Up Down setting
 *
 */
void CameraHal::InitGPIO()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
    // Use m_InputPort
    switch(m_InputPort)
    {
        case CAM_A_PORT:

            RETAILMSG(1,(_T("[CAMIF] CAM_A_PORT\r\n")));
#ifndef TVP5150
            // camera power  GPH2_2     added by terry 20120426  //FOR x210
            Set_PinFunction(m_regIOP, GPH22_Output);
            Set_PinPullUD(m_regIOP, GPH22_Output, sgip_PULL_DISABLE);
            Set_PinData(m_regIOP, GPH22_Output, 1);
            RETAILMSG(1, (TEXT("\r\nOV2655::GPH22 INIT  POWER OFF--------------------\r\n")));
#else

            // camera power  GPF3_4     added by terry 20120705  //FOR x210-ii
            Set_PinFunction(m_regIOP, GPF34_Output);
            Set_PinPullUD(m_regIOP, GPF34_Output, sgip_PULL_DISABLE);
            Set_PinData(m_regIOP, GPF34_Output, 0);
            RETAILMSG(1, (TEXT("\r\nTVP5150::GPH34 0  POWER ON-----x210-ii---------------\r\n")));
#endif



            Set_PinFunction(m_regIOP, CAM_A_PCLK);
            Set_PinFunction(m_regIOP, CAM_A_VSYNC);
            Set_PinFunction(m_regIOP, CAM_A_HREF);
            Set_PinFunction(m_regIOP, CAM_A_DATA0);
            Set_PinFunction(m_regIOP, CAM_A_DATA1);
            Set_PinFunction(m_regIOP, CAM_A_DATA2);
            Set_PinFunction(m_regIOP, CAM_A_DATA3);
            Set_PinFunction(m_regIOP, CAM_A_DATA4);

            Set_PinFunction(m_regIOP, CAM_A_DATA5);
            Set_PinFunction(m_regIOP, CAM_A_DATA6);
            Set_PinFunction(m_regIOP, CAM_A_DATA7);
            Set_PinFunction(m_regIOP, CAM_A_CLKOUT);
            Set_PinFunction(m_regIOP, CAM_A_FIELD);

            Set_PinPullUD(m_regIOP, CAM_A_PCLK, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_VSYNC, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_HREF, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA0, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA1, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA2, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA3, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA4, sgip_PULL_DISABLE);

            Set_PinPullUD(m_regIOP, CAM_A_DATA5, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA6, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA7, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_CLKOUT, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_FIELD, sgip_PULL_DISABLE);

            Set_PinFunction(m_regIOP, CAM_A_RESET);
            Set_PinPullUD(m_regIOP, CAM_A_RESET, sgip_PULL_DISABLE);

	        Set_PinDrv(m_regIOP, CAM_A_CLKOUT, sgip_DRV_4x);

            break;

        case CAM_B_PORT:
            RETAILMSG(1,(_T("[CAMIF] CAM_B_PORT\r\n")));

            Set_PinFunction(m_regIOP, CAM_B_DATA_0);
            Set_PinFunction(m_regIOP, CAM_B_DATA_1);
            Set_PinFunction(m_regIOP, CAM_B_DATA_2);
            Set_PinFunction(m_regIOP, CAM_B_DATA_3);
            Set_PinFunction(m_regIOP, CAM_B_DATA_4);
            Set_PinFunction(m_regIOP, CAM_B_DATA_5);
            Set_PinFunction(m_regIOP, CAM_B_DATA_6);
            Set_PinFunction(m_regIOP, CAM_B_DATA_7);

            Set_PinFunction(m_regIOP, CAM_B_PCLK);
            Set_PinFunction(m_regIOP, CAM_B_VSYNC);
            Set_PinFunction(m_regIOP, CAM_B_HREF);
            Set_PinFunction(m_regIOP, CAM_B_FIELD);
            Set_PinFunction(m_regIOP, CAM_B_CLKOUT);


            Set_PinPullUD(m_regIOP, CAM_B_DATA_0, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_1, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_2, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_3, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_4, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_5, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_6, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_DATA_7, sgip_PULL_DISABLE);

            Set_PinPullUD(m_regIOP, CAM_B_PCLK, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_VSYNC, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_HREF, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_FIELD, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_B_CLKOUT, sgip_PULL_DISABLE);

            Set_PinFunction(m_regIOP, CAM_B_RESET);
            Set_PinPullUD(m_regIOP, CAM_B_RESET, sgip_PULL_DISABLE);

            break;

    case CAM_C_MIPI_PORT:
                RETAILMSG(1,(_T("[CAMIF] CAM_C_MIPI_PORT\r\n")));
            Set_PinFunction(m_regIOP, CAM_A_PCLK);
            Set_PinFunction(m_regIOP, CAM_A_VSYNC);
            Set_PinFunction(m_regIOP, CAM_A_HREF);
            Set_PinFunction(m_regIOP, CAM_A_DATA0);
            Set_PinFunction(m_regIOP, CAM_A_DATA1);
            Set_PinFunction(m_regIOP, CAM_A_DATA2);
            Set_PinFunction(m_regIOP, CAM_A_DATA3);
            Set_PinFunction(m_regIOP, CAM_A_DATA4);

            Set_PinFunction(m_regIOP, CAM_A_DATA5);
            Set_PinFunction(m_regIOP, CAM_A_DATA6);
            Set_PinFunction(m_regIOP, CAM_A_DATA7);
            Set_PinFunction(m_regIOP, CAM_A_CLKOUT);
            Set_PinFunction(m_regIOP, CAM_A_FIELD);

            Set_PinPullUD(m_regIOP, CAM_A_PCLK, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_VSYNC, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_HREF, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA0, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA1, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA2, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA3, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA4, sgip_PULL_DISABLE);

            Set_PinPullUD(m_regIOP, CAM_A_DATA5, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA6, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_DATA7, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_CLKOUT, sgip_PULL_DISABLE);
            Set_PinPullUD(m_regIOP, CAM_A_FIELD, sgip_PULL_DISABLE);

	        Set_PinDrv(m_regIOP, CAM_A_CLKOUT, sgip_DRV_4x);

            Set_PinFunction(m_regIOP, CAM_B_RESET);
            Set_PinPullUD(m_regIOP, CAM_B_RESET, sgip_PULL_DISABLE);

            Set_PinFunction(m_regIOP, MIPI_CSI_EN);
            Set_PinPullUD(m_regIOP, MIPI_CSI_EN, sgip_PULL_DISABLE);

            Set_PinData(m_regIOP, MIPI_CSI_EN, 1);

    break;
    default:
// DMA does not need to set
    case CAM_DMA_PORT:
    break;
    };


    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

void CameraHal::InterfaceReset(BOOL isForCam)    // Reset Camera Inteface IP
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
    // This functin is used on power handler operation.
    // So, you should not use Kernel API functions as like as "Sleep()".

    //
    // Camera (FIMC2.0) I/F Reset
    //
    m_regCAM->CISRCFMT |= BM_SELECT_ITU_INTERFACE;        // User manual recommended method, ITU601 Format
    m_regCAM->CIGCTRL |= BM_CAM_SWRESET;
    m_regCAM->CIGCTRL &= ~BM_CAM_SWRESET;

    if(isForCam == TRUE)
    {
        if(m_moduleDesc.MIPI == TRUE)
        {
            m_regCAM->CIGCTRL |= BM_CAM_SELCAM_FIMC;
            m_regCAM->CIGCTRL |= BM_CAM_SELCAM_MIPI;
        }
        else if(m_moduleDesc.ITUXXX == CAM_ITU656)
        {
            DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s ITU656 Reset()\r\n"), _T(__FUNCTION__)));
			RETAILMSG(1,(_T("[CAMIF] --%s ITU656 Reset()---------------------------\r\n"), _T(__FUNCTION__)));
            m_regCAM->CISRCFMT &= ~BM_SELECT_ITU_INTERFACE;
        }

    }

    m_regCAM->CISTATUS &= ~(0x1<<16);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}


// Select Camera Module Reset Signal PIN

void CameraHal::ModuleReset()        // Reset Camera Module
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    EnterCriticalSection(&m_csHWregister);

    if(m_moduleDesc.HighRst)
    {
        m_regCAM->CIGCTRL |= BM_CAM_CAMRST_A;
        // Don't modify this delay time
        //DrvLib_WaitUsec(100);
        Sleep(5);
        m_regCAM->CIGCTRL &= ~BM_CAM_CAMRST_A;
        // Wait for Camera module initialization
        Sleep(5);
    }
    else
    {
        m_regCAM->CIGCTRL &= ~BM_CAM_CAMRST_A;
        // Wait for Camera module initialization
        //DrvLib_WaitUsec(100);
        Sleep(5);
        m_regCAM->CIGCTRL |= BM_CAM_CAMRST_A;
        // Don't modify this delay time
        Sleep(5);
    }


    if(CAM_A_PORT == m_InputPort)
    {
        Set_PinData(m_regIOP, CAM_A_RESET, 0);
        Sleep(10);
        Set_PinData(m_regIOP, CAM_A_RESET, 1);
        Sleep(10);
    }
    else if(CAM_B_PORT == m_InputPort)
    {
        Set_PinData(m_regIOP, CAM_B_RESET, 0);
        Sleep(10);
        Set_PinData(m_regIOP, CAM_B_RESET, 1);
        Sleep(10);
    }
    else if(CAM_C_MIPI_PORT == m_InputPort)
    {
        Set_PinData(m_regIOP, CAM_B_RESET, 0);
        Sleep(10);
        Set_PinData(m_regIOP, CAM_B_RESET, 1);
    }

    LeaveCriticalSection(&m_csHWregister);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

// This function set External CAMERA Clock Divier
// This clock comes from DoutMPLL2, and goes out to PAD
// we assume OM[0] is always FIN=12Mhz, and all PLL is on
void CameraHal::SetMainClockDiv()
{
    int    div;
    UINT32 SourceClock;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAM] m_regCLKCON:0x%x\r\n"),m_regCLKCON));

    //Camera Module Clock setting
    //CAM A
    if(CAM_A_PORT == m_InputPort)
        m_regCLKCON->CLK_SRC.CLK_SRC1 = m_regCLKCON->CLK_SRC.CLK_SRC1 & ~(BW_MUX_CAM0_SEL<<BP_MUX_CAM0_SEL) | (0x7<<BP_MUX_CAM0_SEL);
    //CAM B
    else if(CAM_B_PORT == m_InputPort)
        m_regCLKCON->CLK_SRC.CLK_SRC1 = m_regCLKCON->CLK_SRC.CLK_SRC1 & ~(BW_MUX_CAM1_SEL<<BP_MUX_CAM1_SEL) | (0x7<<BP_MUX_CAM1_SEL);
    else if(CAM_C_MIPI_PORT == m_InputPort)
    {
        m_regCLKCON->CLK_SRC.CLK_SRC1 = m_regCLKCON->CLK_SRC.CLK_SRC1 & ~(BW_MUX_CAM0_SEL<<BP_MUX_CAM0_SEL) | (0x7<<BP_MUX_CAM0_SEL);
        m_regCLKCON->CLK_SRC.CLK_SRC1 = m_regCLKCON->CLK_SRC.CLK_SRC1 & ~(BW_MUX_CSIS_SEL<<BP_MUX_CSIS_SEL) | (0x1<<BP_MUX_CSIS_SEL);
    }
#if (S5PV210_EVT==0)
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] APLL = %d\r\n"),GET_APLLCLK(m_regCLKCON->PLL_CON.APLL_CON)));
#else
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] APLL = %d\r\n"),GET_APLLCLK(m_regCLKCON->PLL_CON.APLL_CON0)));
#endif
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] MPLL = %d\r\n"),GET_MPLLCLK(m_regCLKCON->PLL_CON.MPLL_CON)));
#if (S5PV210_EVT==0)
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] EPLL = %d\r\n"),GET_EPLLCLK(m_regCLKCON->PLL_CON.EPLL_CON)));
#else
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] EPLL = %d\r\n"),GET_EPLLCLK(m_regCLKCON->PLL_CON.EPLL_CON0)));
#endif
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] VPLL = %d\r\n"),GET_VPLLCLK(m_regCLKCON->PLL_CON.VPLL_CON)));

#if (S5PV210_EVT==0)
    SourceClock = GET_EPLLCLK(m_regCLKCON->PLL_CON.EPLL_CON);
#else
    SourceClock = GET_EPLLCLK(m_regCLKCON->PLL_CON.EPLL_CON0);
#endif
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAM] m_moduleDesc.Clock:%d\r\n"),m_moduleDesc.Clock));
    div = (int)(SourceClock / (float)m_moduleDesc.Clock + 0.5) - 1;

    //CAM A
    if(CAM_A_PORT == m_InputPort)
        m_regCLKCON->CLK_DIV.CLK_DIV1 = (m_regCLKCON->CLK_DIV.CLK_DIV1 & ~(BW_DIV_CAM0_RATIO<<BP_DIV_CAM0_RATIO) | (div<<BP_DIV_CAM0_RATIO));
    //CAM B
    else if(CAM_B_PORT == m_InputPort)
        m_regCLKCON->CLK_DIV.CLK_DIV1 = (m_regCLKCON->CLK_DIV.CLK_DIV1 & ~(BW_DIV_CAM1_RATIO<<BP_DIV_CAM1_RATIO) | (div<<BP_DIV_CAM1_RATIO));
    else if(CAM_C_MIPI_PORT == m_InputPort)
    {
        m_regCLKCON->CLK_DIV.CLK_DIV1 = (m_regCLKCON->CLK_DIV.CLK_DIV1 & ~(BW_DIV_CAM0_RATIO<<BP_DIV_CAM0_RATIO) | (div <<BP_DIV_CAM0_RATIO));
        m_regCLKCON->CLK_DIV.CLK_DIV1 = (m_regCLKCON->CLK_DIV.CLK_DIV1 & ~(BW_DIV_CSIS_RATIO<<BP_DIV_CSIS_RATIO) | (0 <<BP_DIV_CSIS_RATIO));
    }
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() div=%d(regval), Real MClk = %d, m_regCLKCON->CLK_DIV1=0x%x\r\n"), _T(__FUNCTION__), div, SourceClock/(div+1), m_regCLKCON->CLK_DIV.CLK_DIV1));
        RETAILMSG(1,(_T("[CAMIF] --%s() div=%d(regval), Real MClk = %d, m_regCLKCON->CLK_DIV1=0x%x\r\n"), _T(__FUNCTION__), div, SourceClock/(div+1), m_regCLKCON->CLK_DIV.CLK_DIV1));
}

// Set Camera Interface IP Clock Source and Divider
// At default use maximum clock
void CameraHal::SetCamIFClock()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("++%s() m_CamIrq=%d, Select Clock Source for FIMC DoutMPLL\r\n"), _T(__FUNCTION__), m_CamIrq));
    EnterCriticalSection(&m_csHWregister);



    m_regCLKCON->CLK_DIV.CLK_DIV1 = m_regCLKCON->CLK_DIV.CLK_DIV1 & ~(BW_DIV_FIMC_RATIO<<BP_DIV_FIMC_RATIO) | (0x3<<BP_DIV_FIMC_RATIO);

    switch(m_CamIrq)
    {
        case IRQ_FIMC0:
            m_regCLKCON->CLK_SRC.CLK_SRC3 = m_regCLKCON->CLK_SRC.CLK_SRC3 & ~(BW_MUX_FIMC0_LCLK_SEL<<BP_MUX_FIMC0_LCLK_SEL) | (0x6<<BP_MUX_FIMC0_LCLK_SEL);
            m_regCLKCON->CLK_DIV.CLK_DIV3 = m_regCLKCON->CLK_DIV.CLK_DIV3 & ~(BW_DIV_FIMC0_LCLK_RATIO<<BP_DIV_FIMC0_LCLK_RATIO) | (0x3<<BP_DIV_FIMC0_LCLK_RATIO);

        break;
        case IRQ_FIMC1:
            m_regCLKCON->CLK_SRC.CLK_SRC3 = m_regCLKCON->CLK_SRC.CLK_SRC3 & ~(BW_MUX_FIMC1_LCLK_SEL<<BP_MUX_FIMC1_LCLK_SEL) | (0x6<<BP_MUX_FIMC1_LCLK_SEL);
            m_regCLKCON->CLK_DIV.CLK_DIV3 = m_regCLKCON->CLK_DIV.CLK_DIV3 & ~(BW_DIV_FIMC1_LCLK_RATIO<<BP_DIV_FIMC1_LCLK_RATIO) | (0x3<<BP_DIV_FIMC1_LCLK_RATIO);

        break;
        case IRQ_FIMC2:
            m_regCLKCON->CLK_SRC.CLK_SRC3 = m_regCLKCON->CLK_SRC.CLK_SRC3 & ~(BW_MUX_FIMC2_LCLK_SEL<<BP_MUX_FIMC2_LCLK_SEL) | (0x6<<BP_MUX_FIMC2_LCLK_SEL);
            m_regCLKCON->CLK_DIV.CLK_DIV3 = m_regCLKCON->CLK_DIV.CLK_DIV3 & ~(BW_DIV_FIMC2_LCLK_RATIO<<BP_DIV_FIMC2_LCLK_RATIO) | (0x3<<BP_DIV_FIMC2_LCLK_RATIO);

        break;
    }
    LeaveCriticalSection(&m_csHWregister);

}

// Control Camera Interface IP Clock gating
// Camera Interface uses two clock domain, and additional one for Camera Module
// Here, only set for Camera Interface itself.
void CameraHal::SetCamIFClockOn(BOOL bOnOff)
{
    DWORD dwIPIndex ;
    DWORD dwBytes;

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s(bOnOff=%d) m_CamIrq = %d\r\n"),_T(__FUNCTION__), bOnOff, m_CamIrq));
    RETAILMSG(1,(_T("[CAMIF SetCamIFClockOn] ++%s(bOnOff=%d) m_CamIrq = %d\r\n"),_T(__FUNCTION__), bOnOff, m_CamIrq));

    EnterCriticalSection(&m_csHWregister);
    // Camera clock
    if (bOnOff)
    {
        switch(m_CamIrq)
        {
            case IRQ_FIMC0://CLK_IP0_FIMC0

                    dwIPIndex = CLK_IP0_FIMC0;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }

                break;
            case IRQ_FIMC1://CLK_IP0_FIMC1
                    dwIPIndex = CLK_IP0_FIMC1;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                break;
            case IRQ_FIMC2://CLK_IP0_FIMC2
                    dwIPIndex = CLK_IP0_FIMC2;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                break;
        }

        if(m_moduleDesc.MIPI)
        {
            dwIPIndex = CLK_IP0_CSIS;
            if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
            {
                ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
            }

        }
    }
    else
    {
        switch(m_CamIrq)
        {
            case IRQ_FIMC0:

                    dwIPIndex = CLK_IP0_FIMC0;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                break;
            case IRQ_FIMC1:
                    dwIPIndex = CLK_IP0_FIMC1;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                break;
            case IRQ_FIMC2:
                    dwIPIndex = CLK_IP0_FIMC2;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                break;
        }

        if(m_moduleDesc.MIPI)
        {
            dwIPIndex = CLK_IP0_CSIS;
            if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
            {
                ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
            }

        }
    }
    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

// Set Camera Main Clock divider to adjust fps.
void CameraHal::SetPixelClock(DWORD dwFreq)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("++%s() Set Pixel Clock to %u Hz for CamIrq=%d\r\n"), _T(__FUNCTION__), dwFreq, m_CamIrq));

    // CameraInitialize(Init) -> SetPixelClock(SetSensorModeFormat) -> InitSensor(Resume)
    ModuleGetFormat(&m_moduleDesc);

    if(!m_moduleDesc.MIPI)
    {
        ;//m_moduleDesc.Clock = (UINT32)dwFreq;
        //SetMainClockDiv();
    }
}

// Control Camera Interface IP Power domain, Actually, Camera IP uses display power domain
// So, just request to power controller.
void CameraHal::SetPowerOn(BOOL bOnOff)
{
    DWORD dwIPIndex ;
    DWORD dwBytes;
    static int isPowerOn = 0;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s(bOnOff=%d)\r\n"),_T(__FUNCTION__), bOnOff));

    EnterCriticalSection(&m_csHWregister);

    if (!bOnOff)
    {
        if(m_isPowerOn == 1)
        {
            m_isPowerOn = 0;

            switch(m_CamIrq)
            {
                case IRQ_FIMC0://CLK_IP0_FIMC0
                    dwIPIndex = PWR_IP_CAMIF;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }

                    break;
                case IRQ_FIMC1://CLK_IP0_FIMC1
                    dwIPIndex = PWR_IP_CAMIF1;
            if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
            {
                ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
            }


                    break;
                case IRQ_FIMC2://CLK_IP0_FIMC2
                    dwIPIndex = PWR_IP_CAMIF2;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }


                    break;

            }

            if (m_moduleDesc.MIPI)
            {
                DBGMSG(CIF_FUNC && CIF_USR3,(_T("%s - Disable MIPI power block for Camera\r\n"), _T(__FUNCTION__)));
                dwIPIndex = PWR_IP_MIPI_CSI_DPHY;
                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                {
                    ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                }
                dwIPIndex = PWR_IP_MIPI_CSI;
                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                {
                    ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                }
            }
        }
    }
    else
    {
        if(m_isPowerOn == 0)
        {
            m_isPowerOn = 1;

            switch(m_CamIrq)
            {
                case IRQ_FIMC0://CLK_IP0_FIMC0
                    dwIPIndex = PWR_IP_CAMIF;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                    break;
                case IRQ_FIMC1://CLK_IP0_FIMC1
                    dwIPIndex = PWR_IP_CAMIF1;
            if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
            {
                ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
            }
                    break;
                case IRQ_FIMC2://CLK_IP0_FIMC2
                    dwIPIndex = PWR_IP_CAMIF2;
                    if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                    {
                        ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                    }
                    break;

            }

            if (m_moduleDesc.MIPI)
            {
                DBGMSG(CIF_FUNC && CIF_USR3,(_T("%s - Enable MIPI power block for Camera\r\n"), _T(__FUNCTION__)));
                dwIPIndex = PWR_IP_MIPI_CSI;
                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                {
                    ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                }
                dwIPIndex = PWR_IP_MIPI_CSI_DPHY;
                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_POWER_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                {
                    ERRMSG((_T("[CAMIF:ERR] ++%s(bOnOff=%d):  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), bOnOff, __LINE__));
                }
            }
            Sleep(10);
        }
    }
    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));

}


// This function is called on Driver Opening Time.
// So thie function does not power on the Camera Block and Clock
// Just prepare internal state variables
CAMERA_POST_ERROR CameraHal::CameraInitialize(CAMERA_MODULE_DESC CamModuleInfo)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s(%d)\r\n"), _T(__FUNCTION__), CamModuleInfo.CamPort));
    RETAILMSG(1,(_T("[CAMIF] ++%s(%d)\r\n"), _T(__FUNCTION__), CamModuleInfo.CamPort));


    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;

// To share with filter and test application
// This should be removed before release.

#ifdef ChcekUsedCamera
    if(m_currentContext.usefor != USE_FOR_NONE)
    {
        ERRMSG((_T("[CAMIF] ++%s(%d) Already used..\r\n"), _T(__FUNCTION__), CamModuleInfo.CamPort));

        retval = ERROR_CAMIF_ALREADYUSED;
        goto done;
    }
#endif

    m_InputPort = CamModuleInfo.CamPort;
    m_MuduleSensor = CamModuleInfo.ModuleName;

    InitGPIO();
    ModuleReset();

    SetCamIFClock();
    SetCamIFClockOn(FALSE);

    ModuleSelectSensor(CamModuleInfo.ModuleName);

//    ModuleSelectSensor(SYSLSI_S5K4EAGX);
//    ModuleSelectSensor(SYSLSI_S5K6AAFX);
    // In this time Module Descriptor will be initialized.
    ModuleInit();
    ModuleGetFormat(&m_moduleDesc);


/*
    // Start IST.
    if(!ThreadStart())
    {
        retval = ERROR_CAMIF_NOTDEFINED;
        ERRMSG((_T("[CAMIF] --%s() Cannot run Thread\r\n"),_T(__FUNCTION__)));
    }
*/
    if(retval == ERROR_CAMIF_SUCCESS)
    {
        // Context Setting
        m_currentContext.usefor = USE_FOR_CAMERA;
    }

done:
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() return %d\r\n"), _T(__FUNCTION__), retval));
    return retval;
}

void CameraHal::CameraDeinitialize()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    ModuleDeinit();
    m_currentContext.usefor = USE_FOR_NONE;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

void CameraHal::SetID(UINT32 uCamID)
{
    m_CamID = uCamID;
}



void CameraHal::SetCameraSensor(MODULE_SENSOR SensorID)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s - Sensor ID=%d\r\n"), MODULE_NAME, _T(__FUNCTION__), SensorID));

    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;

    if ( SensorID >= MODULE_ID_MAX || SensorID == UNKNOWN_MODULE )
    {
        ERRMSG((_T("[%s] Invalid sensor id - %d\r\n"), MODULE_NAME, SensorID));
    }

    ModuleSelectSensor(SensorID);
    ModuleGetFormat(&m_moduleDesc);

    return;
}

void CameraHal::GetModuleDesc( MODULE_DESCRIPTOR *pModDesc )
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s \r\n"), MODULE_NAME, _T(__FUNCTION__)));

    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;

    memcpy(pModDesc, &m_moduleDesc, sizeof(MODULE_DESCRIPTOR));

    return;
}

CAMERA_POST_ERROR CameraHal::InitSensor()
{
#ifdef BSP_USEDVFS
	DWORD dwBytes;
	PROFILE_LIST Profile;
#endif

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

	//RETAILMSG(1, (TEXT("InitSensor() 1\r\n")));
    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;
    //---
#ifdef BSP_USEDVFS
	Profile = HIGH_NORM_PERF;

	if(!DeviceIoControl(m_hPwrControl, IOCTL_DVFS_SET_PROFILE, &Profile, sizeof(DWORD),NULL,0,&dwBytes,NULL))
	{
        DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAM:ERR] ++%s: IOCTL_DVFS_SET_PROFILE Failed\r\n"),_T(__FUNCTION__)));

	}
#endif

	//RETAILMSG(1, (TEXT("InitSensor() 2\r\n")));

    SetPowerOn(TRUE);
	//RETAILMSG(1, (TEXT("InitSensor() 3\r\n")));
    // Run Interface Clock
    SetCamIFClockOn(TRUE);
	//RETAILMSG(1, (TEXT("InitSensor() 4\r\n")));
    // Set External Camera Clock
    SetMainClockDiv();
	//RETAILMSG(1, (TEXT("InitSensor() 5\r\n")));

    Sleep(10);

    if(retval == ERROR_CAMIF_SUCCESS)
    {
        // Context Setting
        m_currentContext.usefor = USE_FOR_CAMERA;
    }

    InterfaceReset(TRUE);

	//RETAILMSG(1, (TEXT("InitSensor() 6\r\n")));

    //CameraSourceSet();

    if(m_bSensorInit <= 0)//Jerry
    {
	//RETAILMSG(1, (TEXT("InitSensor() 7\r\n")));
        if(/*m_moduleDesc.MIPI*/1)// jerry
        {
        	//RETAILMSG(1, (TEXT("InitSensor() 8\r\n")));
            ModuleReset();

            if(!ModulePrepare())
            {
            	//RETAILMSG(1, (TEXT("InitSensor() 9\r\n")));
                retval = ERROR_CAMIF_MODULEERR;
                goto done;
            }

            m_oCSI_S->InitIp((CSI_S_DATA_LANE)m_moduleDesc.LANE,FMT_YUV422, BIT_ALIGN_32 ,PCLK_SRC, m_moduleDesc.eHSsettle,
                             m_moduleDesc.SourceHSize,m_moduleDesc.SourceVSize, 0, 0, 0);


            if(!ModuleStart())
            {
                retval = ERROR_CAMIF_MODULEERR;
                goto done;
            }

        }
        else
        {
            ModuleReset();
            // With MIPI S5K6AAFX module, Long wait time After module reset can cause black screen
            // CAMRST_A register is just same to external GPIO pin to control CAMERA power or reset

            if(!ModuleWriteBlock())
            {
                retval = ERROR_CAMIF_MODULEERR;
                goto done;
            }

        }
        m_bSensorInit = 0;

    }
    m_bSensorInit++;//=TRUE;
    RETAILMSG(1, (TEXT("InitSensor() 10\r\n")));

done:
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() return %d\r\n"), _T(__FUNCTION__), retval));
    return retval;
}

// This function is called on unbinding camera application
CAMERA_POST_ERROR CameraHal::DeInitSensor()
{
#ifdef BSP_USEDVFS
	PROFILE_LIST Profile;
#endif
    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));
	DWORD dwBytes;

    //m_bSensorInit=FALSE;
    m_bSensorInit--;
    if(!m_bSensorInit)
    {

    if( m_moduleDesc.MIPI )
    {
        DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s - Disable MIPI IP for Camera\r\n"), MODULE_NAME, _T(__FUNCTION__)));
        m_oCSI_S->StopIp();
    }
    m_bSensorInit=FALSE;
    SetCamIFClockOn(FALSE);

    SetPowerOn(FALSE);

//    m_dwESDInterval = INFINITE;

    CAMERA_POST_ERROR retval = ERROR_CAMIF_SUCCESS;

    Set_PinData(m_regIOP, CAM_B_RESET, 0);

	ResetEvent(hVideoCaptureEvent);
	ResetEvent(hPreviewCaptureEvent);
#ifdef BSP_USEDVFS
	Profile = HIGH_NORM_PERF;

	if(!DeviceIoControl(m_hPwrControl, IOCTL_DVFS_CLEAR_PROFILE, &Profile, sizeof(DWORD),NULL,0,&dwBytes,NULL))
	{
		DBGMSG(CIF_FUNC,(_T("[TVPWR:ERR] ++%s: IOCTL_DVFS_SET_LEVEL_FIX Failed\r\n"),_T(__FUNCTION__)));
	}
#endif
    }

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s]-- %s\r\n"), MODULE_NAME, _T(__FUNCTION__)));

    return retval;
}

void CameraHal::CameraSourceSet(CAM_IMG_FORMAT Format)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s() : CIGCTRL=0x%x\r\n"), _T(__FUNCTION__), m_regCAM->CIGCTRL));
    DWORD dwPortNum = CAM_PORT_NONE;
    EnterCriticalSection(&m_csHWregister);
    if(m_InputPort == CAM_A_PORT || m_InputPort == CAM_C_MIPI_PORT)
        dwPortNum = 1;
    else if( m_InputPort == CAM_B_PORT )
        dwPortNum = 0;

    if( CAM_PORT_NONE == dwPortNum)
    {
        ERRMSG((_T("[CAM ERR] %s() No port !! \r\n"), _T(__FUNCTION__)));
        return;
    }

    m_regCAM->CIGCTRL = ((m_moduleDesc.HighRst ? 0 : 1)<<BP_CAM_CAMRST_A) |
                        (dwPortNum<<BP_CAM_SELCAM_ITU) |  // Camera Select
                        (0<<BP_CAM_TESTPATTERN) |
                        (m_moduleDesc.InvPCLK<<BP_CAM_INVPOLPCLK) |
                        (m_moduleDesc.InvVSYNC<<BP_CAM_INVPOLVSYNC) |
                        (m_moduleDesc.InvHREF<<BP_CAM_INVPOLHREF) |
                        (0<<BP_CAM_IRQ_OVFEN) |
                        (1<<BP_CAM_HREF_MASK) |
                        (1<<BP_CAM_IRQ_LEVEL) |
                        (1<<BP_CAM_IRQ_ENABLE) |
                        (1<<BP_CAM_SELCAM_MIPI) |
                        ((m_moduleDesc.MIPI?1:0)<<BP_CAM_SELCAM_FIMC) |
                        (m_moduleDesc.ModuleInterlace << BP_CAM_INTERLACE);
    m_regCAM->CIWDOFST = (1<<BP_CLROVFIY)|(0x1<<BP_CLROVRLB)|(0x1<<BP_CLROVFICB)|(0x1<<BP_CLROVFICR); // clear overflow
    m_regCAM->CIWDOFST = 0;    // No Window Offset
/*
    m_regCAM->CIWDOFST = m_regCAM->CIWDOFST |(0x1<<30); // Clear the overflow indication flag of input FIFO Y
	m_regCAM->CIWDOFST = m_regCAM->CIWDOFST |(0x1<<29); // Clear the overflow indication flag of line buffer for rotation
	m_regCAM->CIWDOFST = m_regCAM->CIWDOFST |(0x1<<15); // Clear the overflow indication flag of input FIFO Cb
	m_regCAM->CIWDOFST = m_regCAM->CIWDOFST |(0x1<<14); // Clear the overflow indication flag of input FIFO Cr
*/

    if( m_moduleDesc.MIPI )
    {
        if(Format == CAM_FORMAT_IJPG)
            m_regCAM->CSIIMGFMT = (0x1 << BP_DATAB_PORT) | (0x30 << BP_IMGFORMOFCH0);
        else
        m_regCAM->CSIIMGFMT = (0x1 << BP_DATAB_PORT) | (0x1E << BP_IMGFORMOFCH0);
    }
    LeaveCriticalSection(&m_csHWregister);

    // This value can be changed in each Capture Start function in custom_camera.cpp
    SetOffsetRegister(m_moduleDesc.SourceHOffset, m_moduleDesc.SourceHOffset2, m_moduleDesc.SourceVOffset, m_moduleDesc.SourceVOffset2);
    SetSourceRegister(m_moduleDesc.ITUXXX, m_moduleDesc.UVOffset, m_moduleDesc.Order422, m_moduleDesc.SourceHSize, m_moduleDesc.SourceVSize);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() : CIGCTRL=0x%x\r\n"), _T(__FUNCTION__), m_regCAM->CIGCTRL));
}

// CIWDOFST can have Left offset in SourceHSize, and Top Offset in SourceVSize
// CIWDOFST2 can have Rigth offset in SourceHSize, and Bottom Offset in SourceVSize
// This cropped Hsize has limitation
// Crop HSize ( = SourceHsize-WinHorOfst-WinHorOfst2 = RealImageInputHSize) should be 16's multiple and 4's multiple of PreHorRatio
// Crop VSize also has similar limitation
// See the S5PV210 user manual about details.
void CameraHal::SetOffsetRegister(UINT32 horOffset, UINT32 horOffset2, UINT32 verOffset, UINT32 verOffset2)
{
    EnterCriticalSection(&m_csHWregister);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    UINT32 WinOfsEn=0;

    m_currentContext.offset.HorOffset = horOffset;
    m_currentContext.offset.HorOffset2 = horOffset2;
    m_currentContext.offset.VerOffset = verOffset;
    m_currentContext.offset.VerOffset2 = verOffset2;

    if((horOffset > 0) || (verOffset > 0) || (horOffset2) || (verOffset2))
    {
        WinOfsEn=1;
    }

    m_regCAM->CIWDOFST = (WinOfsEn<<BP_WINOFSEN)|(m_currentContext.offset.HorOffset<<BP_WINHOROFST)|(m_currentContext.offset.VerOffset<<BP_WINVEROFST);
    m_regCAM->CIWDOFST2 = (m_currentContext.offset.HorOffset2<<BP_WINHOROFST2)|(m_currentContext.offset.VerOffset2<<BP_WINVEROFST2);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    LeaveCriticalSection(&m_csHWregister);
}

void CameraHal::SetSourceRegister(int ituxxx, int uvoffset, int order422, UINT32 hSize, UINT32 vSize)        // Set source registers
{
    EnterCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    m_currentContext.SourceFormat = CAM_FORMAT_YCBYCR422_1PLANE;    // In Camera mode, this value can be YUV422 or IJPG
    m_currentContext.SourceOrder422 = order422;
    m_currentContext.SourceHSize = hSize;
    m_currentContext.SourceVSize = vSize;

    m_regCAM->CISRCFMT = (ituxxx<<BP_SELECT_ITU_INTERFACE) |
                         (uvoffset<<BP_UVOFFSET) |
                         (0<<BP_IN16BIT) |
                         (hSize<<BP_SRCHSIZE_CAM) |
                         (order422<<BP_ORDER422_CAM) |
                         (vSize<<BP_SRCVSIZE_CAM);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() : hSize = %d  vSize = %d  CISRCFMT=0x%X\r\n"), _T(__FUNCTION__), hSize, vSize, m_regCAM->CISRCFMT));
	RETAILMSG(1,(_T("[CAMIF] --%s() : hSize = %d  vSize = %d  CISRCFMT=0x%X\r\n"), _T(__FUNCTION__), hSize, vSize, m_regCAM->CISRCFMT));
    LeaveCriticalSection(&m_csHWregister);
}

// Get IMG Type (With, Height, Format, Order, Plane)
// Todo: Add more Image Format
void CameraHal::SetTargetRegister(UINT32 width, UINT32 height, CAM_IMG_FORMAT Format)        // set target register
{
    //EnterCriticalSection(&m_csHWregister);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s() Width=%d  Height=%d  Format=%d\r\n"), _T(__FUNCTION__), width, height, Format));

	RETAILMSG(1,(_T("[CAMIF] ++%s() Width=%d  Height=%d  Format=%d----------------------\r\n"), _T(__FUNCTION__), width, height, Format));


	
    DWORD DMAOutFormat = OUTFMT_YUV420_23PLANE;             // Default value = 0
    DWORD OutRGBFormat = OUTRGB_RGB565;                     // Default value = 0(Don't care)
    DWORD OutPlaneFormat = OUTDMA_YUV_3PLANE;               // Default value = 0(Don't care)
    DWORD OutOrderCbCr_2Plane = OUTDMA_YUV_2PLANE_CBCR_LITTLE;  // Default value = 0(Dont' care)
    DWORD OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_YCBYCR; // Default value = 0(Don't care)
    DWORD OutInterlace = SCAN_PROGRESSIVE;
    DWORD OutWeave = OUTDMA_NOTUSE_WEAVEOUT;
    DWORD InCamScanMode = 0;
    m_moduleDesc.JPEG = 0;
    m_bWeaveMode = FALSE;
    switch(Format)
    {
    case CAM_FORMAT_IJPG:
        // Just fake Camera IP. take all data from Camera Module, bypassing data to upper buffer
        m_moduleDesc.JpegSpoofWidth = width;
        m_moduleDesc.JpegSpoofHeight = height;

        //width = m_moduleDesc.JpegSpoofWidth;
        //height = m_moduleDesc.JpegSpoofHeight;

        DMAOutFormat = OUTFMT_YUV422_1PLANE;        //< This will determine writing method
        OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_CBYCRY;
        m_moduleDesc.JPEG = 1;
        break;
    case CAM_FORMAT_YCBYCR422_1PLANE: // YUV422 3/2/1 Plane
        DMAOutFormat = OUTFMT_YUV422_1PLANE;
        OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_YCBYCR;
        break;
    case CAM_FORMAT_CBYCRY422_1PLANE: // YUV422 3/2/1 Plane
        DMAOutFormat = OUTFMT_YUV422_1PLANE;
        OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_CBYCRY;
        break;
    case CAM_FORMAT_YCRYCB422_1PLANE: // YUV422 3/2/1 Plane
        DMAOutFormat = OUTFMT_YUV422_1PLANE;
        OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_YCRYCB;
        break;
    case CAM_FORMAT_CRYCBY422_1PLANE: // YUV422 3/2/1 Plane
        DMAOutFormat = OUTFMT_YUV422_1PLANE;
        OutOrder422_1Plane = OUTDMA_YUV422_1PLANE_CRYCBY;
        break;



    case CAM_FORMAT_YCBYCR422_2PLANE:
        DMAOutFormat = OUTFMT_YUV422_23PLANE;
        OutPlaneFormat = OUTDMA_YUV_2PLANE;
        OutOrderCbCr_2Plane = OUTDMA_YUV_2PLANE_CBCR_LITTLE;
        break;
    case CAM_FORMAT_YCBYCR422_3PLANE:
        DMAOutFormat = OUTFMT_YUV422_23PLANE;
        OutPlaneFormat = OUTDMA_YUV_3PLANE;
        break;

    case CAM_FORMAT_RGB16:
        DMAOutFormat = OUTFMT_RGB;
        OutRGBFormat = OUTRGB_RGB565;
        break;
    case CAM_FORMAT_RGB18:
        DMAOutFormat = OUTFMT_RGB;
        OutRGBFormat = OUTRGB_RGB666;
        break;
    case CAM_FORMAT_RGB24:
        DMAOutFormat = OUTFMT_RGB;
        OutRGBFormat = OUTRGB_RGB888;
        break;
    case CAM_FORMAT_YCBCR444:     // YUV444 2/3 Plane, Not yet implemented
        break;
    case CAM_FORMAT_NV12_WEAVE:
        DMAOutFormat = OUTFMT_YUV420_23PLANE;
        OutOrderCbCr_2Plane = OUTDMA_YUV_2PLANE_CBCR_LITTLE;
        OutPlaneFormat = OUTDMA_YUV_2PLANE;
        OutWeave = OUTDMA_USE_WEAVEOUT;
        OutInterlace = SCAN_INTERLACE;
        m_bWeaveMode = TRUE;
        break;

    case CAM_FORMAT_YCBCR420_3PLANE:
//    case CAM_FORMAT_YV12:
        DMAOutFormat = OUTFMT_YUV420_23PLANE;
        OutPlaneFormat = OUTDMA_YUV_3PLANE;
        break;
    //case CAM_FORMAT_YCBCR420_2PLANE:     // YUV420 2/3 Plane(YUV420 2Plane = NV12)
    case CAM_FORMAT_NV12:
        //SetDMARegister(CAM_DMA_64BY32);
    default:
        DMAOutFormat = OUTFMT_YUV420_23PLANE;
        OutOrderCbCr_2Plane = OUTDMA_YUV_2PLANE_CBCR_LITTLE;
        OutPlaneFormat = OUTDMA_YUV_2PLANE;
        break;
    }

    EnterCriticalSection(&m_csHWregister);
#ifndef TVP5150


	// Don't care about rotation and flip
    m_regCAM->CITRGFMT = (DMAOutFormat) |OUTFLIP_NONE |//OUTFLIP_XY |//outrot180    
                        (width<<BP_TARGETHSIZE) |
                        (height<<BP_TARGETVSIZE);



#else	//for tvp5150
    m_regCAM->CITRGFMT = (DMAOutFormat) | OUTFLIP_X| //outrot180  ????
                        (width<<BP_TARGETHSIZE) |
                        (height<<BP_TARGETVSIZE);


#endif	
    m_regCAM->CIOCTRL = (OutWeave)|
                        (OutOrderCbCr_2Plane) |
                        (OutPlaneFormat) |
                        (OutOrder422_1Plane);   // LASTIRQEn will be set later in CaptureControl on JPEG Still capturing
    m_regCAM->CISCCTRL = (CSC_R2Y_WIDE)|
                        (CSC_Y2R_WIDE)|
                        (0<<BP_LCDPATHEN)|
                        (OutInterlace) |
                        (3<<BP_INRGB_FMT) |      // Reserved
                        (OutRGBFormat)|
                        (0<<BP_EXT_RGB);

    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] ++%s() CITRGFMT=0x%x  CISCCTRL=0x%x  Format=%d\r\n"), _T(__FUNCTION__),
                    m_regCAM->CITRGFMT, m_regCAM->CISCCTRL));

    RETAILMSG(1,(_T("[CAMIF] ++%s() CITRGFMT=0x%x  CISCCTRL=0x%x  CITRGFMT=0x%x\r\n"), _T(__FUNCTION__),
                    m_regCAM->CITRGFMT, m_regCAM->CISCCTRL,m_regCAM->CITRGFMT));


    if( Format != CAM_FORMAT_IJPG )
    {
        SetScaler(width, height);
    }

    EnterCriticalSection(&m_csHWregister);
    // 3. Output DMA Setting
    m_regCAM->ORGOSIZE = DST_WIDTH(width) | DST_HEIGHT(height);   // For Ouput DMA

    if(m_CamOperationMode == STILL_CAPTURE)
    {
        m_regCAM->CICPTSEQ = 0xC0000000;    // Accept only two frame, but first frame will be discarded.
#if USE_CAPTURE_FRAME_CONTROL
        // If use 1 Camera IP for all Still&Video Capture and preview, there is no need to discard
#if USE_STEPBYSTEP_CONTROL
        m_regCAM->CIIMGCPT |= (1<<BP_CPT_FREN) | (0<<BP_CPT_FRMOD);    // Step-by-Step shot.
#else
        m_regCAM->CIIMGCPT |= (1<<BP_CPT_FREN) | (1<<BP_CPT_FRMOD) | (2<<BP_CPT_FRCNT);    // Frame Count Mode, 1 Frame capture
#endif
#endif
    }
    else
    {
        m_regCAM->CICPTSEQ = 0xFFFFFFFF;    // For some reason this value can changed??
        m_regCAM->CIIMGCPT &= ~(1<<BP_CPT_FREN); // Disable Capture Frame Control
    }
    m_regCAM->MSCTRL &= ~(BM_SEL_DMA_CAM);    // For transition from Post Processor mode
    m_regCAM->CIIYOFF = 0;
    m_regCAM->CIICBOFF = 0;
    m_regCAM->CIICROFF = 0;

    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    //LeaveCriticalSection(&m_csHWregister);
}

// From Camera Input
void CameraHal::SetScaler(UINT32 DstWidth, UINT32 DstHeight)
{
    UINT32 SrcWidth, SrcHeight;

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s() DstWidth=%d  DstHeight=%d\r\n"), _T(__FUNCTION__), DstWidth, DstHeight));

    if(DstWidth == 0 || DstHeight == 0) return;

    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] ++%s() HOffset=(%d,%d), VOffset=(%d,%d), SrcSize(%d,%d)\r\n"), _T(__FUNCTION__),
                m_currentContext.offset.HorOffset,
                m_currentContext.offset.HorOffset2,
                m_currentContext.offset.VerOffset,
                m_currentContext.offset.VerOffset2,
                m_currentContext.SourceHSize,
                m_currentContext.SourceVSize));

    SrcWidth = m_currentContext.SourceHSize - m_currentContext.offset.HorOffset - m_currentContext.offset.HorOffset2;
    SrcHeight = m_currentContext.SourceVSize - m_currentContext.offset.VerOffset - m_currentContext.offset.VerOffset2;

//    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s() SrcWidth=%d  SrcHeight=%d DstWidth=%d  DstHeight=%d\r\n"), _T(__FUNCTION__), SrcWidth, SrcHeight, DstWidth, DstHeight));
	RETAILMSG(1,(_T("[CAMIF] ++%s() SrcWidth=%d  SrcHeight=%d DstWidth=%d  DstHeight=%d\r\n"), _T(__FUNCTION__), SrcWidth, SrcHeight, DstWidth, DstHeight));

    SetScaler(SrcWidth, SrcHeight, DstWidth, DstHeight);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

// For Post Processor
void CameraHal::SetScaler(UINT32 dwCropInHSize, UINT32 dwCropInVSize, UINT32 dwResizedOutHSize, UINT32 dwResizedOutVSize)
{
    unsigned int PreHozRatio, PreVerRatio;
    unsigned int MainHozShift, MainVerShift;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] %s() : %d, %d, %d, %d\r\n"), _T(__FUNCTION__), dwCropInHSize, dwCropInVSize, dwResizedOutHSize, dwResizedOutVSize));


    EnterCriticalSection(&m_csHWregister);

    if(dwCropInHSize <= dwResizedOutHSize)
    {
        m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_SCALEUP_H)) | SCALE_UP_H;
    }
    else
    {
        m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_SCALEUP_H)) | SCALE_DOWN_H;
    }
    if(dwCropInVSize <= dwResizedOutVSize)
    {
        m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_SCALEUP_V)) | SCALE_UP_V;
    }
    else
    {
        m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_SCALEUP_V)) | SCALE_DOWN_V;
    }
    LeaveCriticalSection(&m_csHWregister);

    if (GetPrescalerShiftvalue(&MainHozShift, dwCropInHSize, dwResizedOutHSize))
    {
        PreHozRatio = (1<<MainHozShift);
    }
    else
    {
        // Out of Range, Todo: Set Safe Value
        PreHozRatio = (1<<MainHozShift);
    }
    if (GetPrescalerShiftvalue(&MainVerShift, dwCropInVSize, dwResizedOutVSize))
    {
        PreVerRatio = (1<<MainVerShift);
    }
    else
    {
        // Out of Range, Todo: Set Safe Value
        PreVerRatio = (1<<MainVerShift);
    }
    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] ++%s() Src(%d,%d), Dst(%d,%d), Pre(%d,%d) Main(%d,%d)\r\n"), _T(__FUNCTION__),
                            dwCropInHSize, dwCropInVSize, dwResizedOutHSize, dwResizedOutVSize,
                            PreHozRatio, PreVerRatio, MainHozShift, MainVerShift));

    EnterCriticalSection(&m_csHWregister);
    m_regCAM->CISCPRERATIO = PRESCALE_SHFACTOR(10-(MainHozShift+MainVerShift)) | PRESCALE_H_RATIO(PreHozRatio) | PRESCALE_V_RATIO(PreVerRatio);
    m_regCAM->CISCPREDST = PRESCALE_WIDTH(dwCropInHSize/PreHozRatio) | PRESCALE_HEIGHT(dwCropInVSize/PreVerRatio);;
    m_regCAM->CISCCTRL = (m_regCAM->CISCCTRL & ~(BM_MAINHORRATIO | BM_MAINVERRATIO)) |
                            MAINSCALE_H_RATIO((dwCropInHSize<<8)/(dwResizedOutHSize<<MainHozShift)) |
                            MAINSCALE_V_RATIO((dwCropInVSize<<8)/(dwResizedOutVSize<<MainVerShift));
    m_regCAM->CITAREA = dwResizedOutHSize * dwResizedOutVSize;
    LeaveCriticalSection(&m_csHWregister);
}
BOOL CameraHal::GetPrescalerShiftvalue(unsigned int *MainShift, unsigned int SrcValue, unsigned int DstValue )
{
    BOOL bRetVal = TRUE;

    if (SrcValue >= 64*DstValue)
    {
        ERRMSG((_T("[CAMIF:ERR] %s() : Out of Range\r\n"), _T(__FUNCTION__)));
        *MainShift = 5;
        bRetVal = FALSE;
    }
    else if (SrcValue >= 32*DstValue)
    {
        *MainShift = 5;
    }
    else if (SrcValue >= 16*DstValue)
    {
        *MainShift = 4;
    }
    else if (SrcValue >= 8*DstValue)
    {
        *MainShift = 3;
    }
    else if (SrcValue >= 4*DstValue)
    {
        *MainShift = 2;
    }
    else if (SrcValue >= 2*DstValue)
    {
        *MainShift = 1;
    }
    else
    {
        *MainShift = 0;
    }

    return bRetVal;
}


int CameraHal::GetCurrentFrameNum()
{
    int temp;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++CAMIF_GetCurrentFrameNum()\r\n")));
    // Get Current FrameNumber from Next FrameNumber
    temp = (m_regCAM->BFS_CISTATUS.FrameCnt + 2) % 4;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --CAMIF_GetCurrentFrameNum()\r\n")));
    return temp;
}

int CameraHal::SetOutputAddress(P_CAMERA_DMA_BUFFER_INFO CAM_BUFFER_INFO)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++SetOutputAddress()\r\n")));

    EnterCriticalSection(&m_csHWregister);

    m_regCAM->CIOYSA1 = (DWORD)CAM_BUFFER_INFO[0].pY;
    m_regCAM->CIOYSA2 = (DWORD)CAM_BUFFER_INFO[1].pY;
    m_regCAM->CIOYSA3 = (DWORD)CAM_BUFFER_INFO[2].pY;
    m_regCAM->CIOYSA4 = (DWORD)CAM_BUFFER_INFO[3].pY;

    m_regCAM->CIOCRSA1= (DWORD)CAM_BUFFER_INFO[0].pCr;
    m_regCAM->CIOCRSA2= (DWORD)CAM_BUFFER_INFO[1].pCr;
    m_regCAM->CIOCRSA3= (DWORD)CAM_BUFFER_INFO[2].pCr;
    m_regCAM->CIOCRSA4= (DWORD)CAM_BUFFER_INFO[3].pCr;

    m_regCAM->CIOCBSA1= (DWORD)CAM_BUFFER_INFO[0].pCb;
    m_regCAM->CIOCBSA2= (DWORD)CAM_BUFFER_INFO[1].pCb;
    m_regCAM->CIOCBSA3= (DWORD)CAM_BUFFER_INFO[2].pCb;
    m_regCAM->CIOCBSA4= (DWORD)CAM_BUFFER_INFO[3].pCb;

    DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("CIOYSA1=0x%x, CIOCBSA1=0x%x,CIOCRSA1=0x%x,\n"),m_regCAM->CIOYSA1, m_regCAM->CIOCBSA1, m_regCAM->CIOCRSA1));
    DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("CIOYSA2=0x%x, CIOCBSA2=0x%x,CIOCRSA2=0x%x,\n"),m_regCAM->CIOYSA2, m_regCAM->CIOCBSA2, m_regCAM->CIOCRSA2));
    DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("CIOYSA3=0x%x, CIOCBSA3=0x%x,CIOCRSA3=0x%x,\n"),m_regCAM->CIOYSA3, m_regCAM->CIOCBSA3, m_regCAM->CIOCRSA3));
    DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("CIOYSA4=0x%x, CIOCBSA4=0x%x,CIOCRSA4=0x%x,\n"),m_regCAM->CIOYSA4, m_regCAM->CIOCBSA4, m_regCAM->CIOCRSA4));

    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --SetOutputAddress()\r\n")));
    return TRUE;
}

int CameraHal::OpenCMM()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
	//CMM init
	m_hCMMOpen = CreateFile(L"CMM1:",
					   GENERIC_READ|GENERIC_WRITE,
					   0,
					   NULL,
					   OPEN_EXISTING,
					   FILE_ATTRIBUTE_NORMAL,
					   NULL);

	if (m_hCMMOpen == INVALID_HANDLE_VALUE)
	{
		DBGMSG(CIF_FUNC && CIF_USR2, (TEXT("CMM Open failure\n")));
		return FALSE;
	}
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    return TRUE;
}

void CameraHal::CloseCMM()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
    CloseHandle(m_hCMMOpen);
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}

void CameraHal::FreeOutputDMABuffer(int dwVir)
{
    DWORD ret = 0;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s() dwVir = 0x%x\r\n"), _T(__FUNCTION__),dwVir));

	ret = DeviceIoControl(m_hCMMOpen, IOCTL_CODEC_MEM_FREE, (PBYTE)dwVir,
                        sizeof(BYTE), NULL, 0,
                        NULL, NULL);
	//if(ret == FALSE)
    //    ERRMSG((TEXT("IOCTL_CODEC_MEM_FREE failed\n")));

    if(ret == TRUE)
        DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] %s() dwVir = 0x%x\r\n"), _T(__FUNCTION__),dwVir));
    CloseHandle(m_hCMMOpen);

}

int CameraHal::AllocOutputDMABuffer(int dwSize, CMM_DRAM_LOCATION Loc, DWORD* dwPhy, DWORD* dwVir)
{
	CMM_ALLOC_PRAM_T	CMMParam;
	int 				virBuf;
	int 				phyBuf;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

	CMMParam.size = (unsigned int)(dwSize);
	CMMParam.dramLocation = Loc;       // DRAM 0 or DRAM 1 = 0;

	BOOL r = DeviceIoControl(m_hCMMOpen, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam,
							sizeof(CMM_ALLOC_PRAM_T *), &virBuf, sizeof(virBuf),
							NULL, NULL);
	if(r == FALSE)
	{
		ERRMSG((TEXT("CMM IOCTL_CODEC_MEM_ALLOC failure\n")));
		return 0;
	}

	r = DeviceIoControl(m_hCMMOpen, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)virBuf,
							sizeof(virBuf), &phyBuf, sizeof(phyBuf),
							NULL, NULL);
	if(r == FALSE)
	{
		ERRMSG((TEXT("CMM IOCTL_CODEC_GET_PHY_ADDR failure\n")));
		return 0;
	}

    *dwPhy = (DWORD)phyBuf;
    *dwVir = (DWORD)virBuf;

    DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("VirtAddr = 0x%x, PhyAddr = 0x%x\n"), virBuf,phyBuf));
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));

    return TRUE;

}

// Set the Output Address with Offset
// yoffset means
int CameraHal::SetOutputAddress(BUFFER_ADDRESS *pingpong, int yoffset, int coffset)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s(0x%x, %d, %d)\r\n"), _T(__FUNCTION__), pingpong, yoffset, coffset));
    if(pingpong)
    {
        for(int i=0;i<MAX_PINGPONG_NUM;i++)
        {
            DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] pingpong[%d].physicalAddr = 0x%x)\r\n"), i, pingpong[i].physicalAddr));
        }
    }
    else
    {
        return FALSE;
    }

    EnterCriticalSection(&m_csHWregister);

    m_regCAM->CIOYSA1 = pingpong[0].physicalAddr;
    m_regCAM->CIOYSA2 = pingpong[1].physicalAddr;
    m_regCAM->CIOYSA3 = pingpong[2].physicalAddr;
    m_regCAM->CIOYSA4 = pingpong[3].physicalAddr;

    if(yoffset > 0)
    {
        m_regCAM->CIOCRSA1=m_regCAM->CIOYSA1+yoffset;
        m_regCAM->CIOCRSA2=m_regCAM->CIOYSA2+yoffset;
        m_regCAM->CIOCRSA3=m_regCAM->CIOYSA3+yoffset;
        m_regCAM->CIOCRSA4=m_regCAM->CIOYSA4+yoffset;

        if(coffset == 0)
        {
            m_regCAM->CIOCBSA1=m_regCAM->CIOCRSA1;
            m_regCAM->CIOCBSA2=m_regCAM->CIOCRSA2;
            m_regCAM->CIOCBSA3=m_regCAM->CIOCRSA3;
            m_regCAM->CIOCBSA4=m_regCAM->CIOCRSA4;
        }
        else if(coffset > 0)
        {
            m_regCAM->CIOCBSA1=m_regCAM->CIOCRSA1+coffset;
            m_regCAM->CIOCBSA2=m_regCAM->CIOCRSA2+coffset;
            m_regCAM->CIOCBSA3=m_regCAM->CIOCRSA3+coffset;
            m_regCAM->CIOCBSA4=m_regCAM->CIOCRSA4+coffset;
        }

    }

    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("\n\n\n\nCIOYSA1=0x%x, CIOCBSA1=0x%x,CIOCRSA1=0x%x,\n"),m_regCAM->CIOYSA1, m_regCAM->CIOCBSA1, m_regCAM->CIOCRSA1));
    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("CIOYSA2=0x%x, CIOCBSA2=0x%x,CIOCRSA2=0x%x,\n"),m_regCAM->CIOYSA2, m_regCAM->CIOCBSA2, m_regCAM->CIOCRSA2));
    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("CIOYSA3=0x%x, CIOCBSA3=0x%x,CIOCRSA3=0x%x,\n"),m_regCAM->CIOYSA3, m_regCAM->CIOCBSA3, m_regCAM->CIOCRSA3));
    DBGMSG(CIF_INFO && CIF_USR3,(TEXT("CIOYSA4=0x%x, CIOCBSA4=0x%x,CIOCRSA4=0x%x,\n"),m_regCAM->CIOYSA4, m_regCAM->CIOCBSA4, m_regCAM->CIOCRSA4));

    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    return TRUE;
}

BOOL CameraHal::SetDMARegister(CAM_DMA_MODE OutputDMA)
{
    BOOL bRet = TRUE;


    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    m_regCAM->CIDMAPARAM = (m_regCAM->CIDMAPARAM & ~((BW_MODE_R<<BP_MODE_R) | (BW_MODE_W<<BP_MODE_W)))
                                            | (0<<BP_MODE_R) | (OutputDMA<<BP_MODE_W);


    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    return bRet;

}

UINT32 CameraHal::CalculateBufferSize(UINT32 width, UINT32 height, int format)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));
    UINT32 size=0;
    //DWORD AlignedWidth,AlignedYHeight,AlignedCbHeight;
    switch(format)
    {
    case CAM_FORMAT_YCBYCR422_1PLANE:
    case CAM_FORMAT_CBYCRY422_1PLANE:
    case CAM_FORMAT_YCRYCB422_1PLANE:
    case CAM_FORMAT_CRYCBY422_1PLANE:
    case CAM_FORMAT_YCBYCR422_2PLANE:
    case CAM_FORMAT_YCBYCR422_3PLANE:
        m_Size_Capture_Data = width*height + width*height/2*2;
        break;
    //case CAM_FORMAT_YCBCR420_3PLANE:
    case CAM_FORMAT_YV12:
        m_Size_Capture_Data = width*height + width*height/4*2;
        break;
    //case CAM_FORMAT_YCBCR420_2PLANE:
    case CAM_FORMAT_NV12:
    case CAM_FORMAT_NV12_WEAVE:
        //size = width*height + width*height/4*2;
        m_Size_Capture_Data = AlignSize(width*height, 0x4000) + AlignSize(width*height/2, 0x4000);
        /*
        AlignedWidth = AlignSize(width, 128);
        AlignedYHeight = AlignSize(height, 32);
        AlignedCbHeight = AlignSize(height/2, 32);

        m_Size_Capture_Data = AlignSize(AlignedWidth*AlignedYHeight, 64*1024) + AlignSize(AlignedWidth*AlignedCbHeight, 64*1024);
        */
        break;
    case CAM_FORMAT_YCBCR444:
    case CAM_FORMAT_RGB24:
    case CAM_FORMAT_RGB18:
        m_Size_Capture_Data = width*height*4;
        break;
    case CAM_FORMAT_RGB16:
        m_Size_Capture_Data = width*height*2;
        break;
    case CAM_FORMAT_IJPG:
        m_Size_Capture_Data = m_moduleDesc.JpegSpoofWidth * m_moduleDesc.JpegSpoofHeight * 2;
        break;
    }

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    return m_Size_Capture_Data;
}

// Todo: Return FALSE or Error Code if Power Off
int CameraHal::CaptureControl(BOOL on)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    if(!m_isPowerOn)
    {
        DBGMSG(CIF_FUNC && CIF_USR3,(TEXT("[CAM] Camera is Power Off state\n")));
        return FALSE;
    }

    EnterCriticalSection(&m_csHWregister);

    m_regCAM->CIIMGCPT &= ~(CAM_GLOBAL_CAPTURE_ENABLE_BIT); // This should be cleared before scaler.

    if(on)
    {
        DBGMSG(CIF_INFO && CIF_USR3,(_T("[%s] %s() : CAMIF Capture ON, m_CamOperationMode(%d), JPEG(%d)\r\n"),
                    MODULE_NAME, _T(__FUNCTION__), m_CamOperationMode, m_moduleDesc.JPEG));
        m_CaptureOn = TRUE;
        m_regCAM->CIGCTRL |= (1<<BP_CAM_IRQ_LEVEL);

        if( m_CamOperationMode == STILL_CAPTURE && m_moduleDesc.JPEG)
        {

            if( m_moduleDesc.MIPI )
            {
                DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s - Disable MIPI IP for Camera\r\n"), MODULE_NAME, _T(__FUNCTION__)));
                m_oCSI_S->StopIp();

                ModuleReset();

                ModuleCapturePrepare();

                m_oCSI_S->InitIp((CSI_S_DATA_LANE)m_moduleDesc.LANE,FMT_USER_DEFINED_TYPE1, BIT_ALIGN_32 ,PCLK_SRC, m_moduleDesc.eHSsettle,
                                 m_moduleDesc.SourceHSize,m_moduleDesc.SourceVSize, 0, 0, 0);

                ModuleCaptureStart();

            }

            DBGMSG(CIF_INFO && CIF_USR3,(_T("[%s] %s() : SCALER BYPASSED : STILL_CAPTURE with JPEG\r\n"), MODULE_NAME, _T(__FUNCTION__)));
            // scaler bypass ON
            m_regCAM->CISCCTRL |= (BM_SCALERBYPASS);
            // ITU_R BT.601 YCbCr 8-bit mode enable
            m_regCAM->CISRCFMT |= (BM_SELECT_ITU_INTERFACE) ;

            RETAILMSG(1,(_T("[%s] %s() : SCALER BYPASSED : STILL_CAPTURE with JPEG  CISRCFMT=0x%X-------\r\n"), MODULE_NAME, _T(__FUNCTION__)),m_regCAM->CISRCFMT);
			
            // JPEG file input enable
            m_regCAM->CIGCTRL |= (BM_CAM_INPUT_CAM_JPEG);
            // Scaler bypass so scalser stop
            m_regCAM->CISCCTRL &= ~(BM_SCALERSTART);

            // Capture frame control dispble
            // Camera interface global cpature enable
            // Capture disable for scaler
            m_regCAM->CIIMGCPT &= ~(BM_CPT_FREN);
            m_regCAM->CIIMGCPT &= ~(BM_IMGCPTEN_SC);
            m_regCAM->CIIMGCPT |= (CAM_GLOBAL_CAPTURE_ENABLE_BIT);


        }
        else // Preview, Video Capture and non JPEG Still shot
        {
            DBGMSG(CIF_INFO && CIF_USR3,(_T("[%s] %s() : Normal Capture Enable CIIMGCPT:0x%x\r\n"), MODULE_NAME, _T(__FUNCTION__), m_regCAM->CIIMGCPT));

            m_regCAM->CIGCTRL &= ~(BM_CAM_INPUT_CAM_JPEG);
            m_regCAM->CISCCTRL &= ~(BM_SCALERBYPASS);
            m_regCAM->CISCCTRL |= (CAM_SCALER_START_BIT);
            m_regCAM->CIIMGCPT |= (CAM_GLOBAL_CAPTURE_ENABLE_BIT) | (CAM_SCALER_CAPTURE_ENABLE_BIT);
        }
    }
    else
    {
        DBGMSG(CIF_INFO && CIF_USR3,(_T("[CAMIF] %s() : CAMIF Capture Off\r\n"), _T(__FUNCTION__)));

        m_dwSkipFrameCnt = 0;

        m_CaptureOn = FALSE;
        m_regCAM->CISCCTRL &= ~(CAM_SCALER_START_BIT);
        m_regCAM->CIGCTRL &= ~(1<<BP_CAM_IRQ_LEVEL);

        m_regCAM->CIIMGCPT &= ~(CAM_SCALER_CAPTURE_ENABLE_BIT);


        while((m_regCAM->CISTATUS & BM_CAM_IMAGECAPTURE_SCALER_ENABLE) == 1) // check Codec path disable
        {
            if(m_dwSkipFrameCnt > 100000)
            {
                ERRMSG((_T("[CAMERR] %s() : CAMIF Capture timeout!!\r\n"), _T(__FUNCTION__)));
                break;
            }
            m_dwSkipFrameCnt++;
        }

    }
    LeaveCriticalSection(&m_csHWregister);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
    return TRUE;
}

void CameraHal::SetCameraSource(CAM_IMG_FORMAT Format)
{
    CameraSourceSet(Format);
    //SetSourceRegister(m_moduleDesc.ITUXXX, m_moduleDesc.UVOffset, m_moduleDesc.Order422, m_moduleDesc.SourceHSize, m_moduleDesc.SourceVSize);
}

void CameraHal::ImageEffectOn(DWORD dwImgEffect)
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    m_regCAM->CIIMGEFF = (BM_IE_ON)| (BM_IE_AFTER_SC) | (dwImgEffect << BP_FIN);

    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s() CIIMGEFF = 0x%x\r\n"), _T(__FUNCTION__), m_regCAM->CIIMGEFF));
}

void CameraHal::ImageEffectOff()
{
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] ++%s()\r\n"), _T(__FUNCTION__)));

    m_regCAM->CIIMGEFF = 0;
    DBGMSG(CIF_FUNC && CIF_USR3,(_T("[CAMIF] --%s()\r\n"), _T(__FUNCTION__)));
}


// Intentional Time Delay to capture bigsize image
void CameraHal::SkipFrame(int frameNum)
{
    DWORD    dwCause;
    int i;
    for(i=0;i<frameNum;i++)
    {
        dwCause = WaitForSingleObject(m_hCaptureEvent, INFINITE);
        DBGMSG(CIF_INFO && CIF_USR3,(TEXT("%d Consume Capture Interrupt:0x%x\r\n"), i, m_hCaptureEvent));
        InterruptDone(m_CamSysIntr);
    }
}

void CameraHal::WaitForCaptureFinish()
{
    DWORD dwCause;

    dwCause = WaitForSingleObject(m_hCaptureFinishEvent, CAPTURE_TIMEOUT);

    switch( dwCause )
    {
        case WAIT_OBJECT_0:

            if( m_moduleDesc.MIPI && m_moduleDesc.JPEG == 1)
            {
                DBGMSG(CIF_FUNC && CIF_USR3,(_T("[%s] %s - Disable MIPI IP for Camera\r\n"), MODULE_NAME, _T(__FUNCTION__)));
                m_oCSI_S->StopIp();

                ModuleReset();

                ModulePrepare();

                m_oCSI_S->InitIp((CSI_S_DATA_LANE)m_moduleDesc.LANE,FMT_YUV422, BIT_ALIGN_32 ,PCLK_SRC, m_moduleDesc.eHSsettle,
                                 m_moduleDesc.SourceHSize,m_moduleDesc.SourceVSize, 0, 0, 0);

                ModuleStart();

            }


            return;
        case WAIT_TIMEOUT:
            DBGMSG(CIF_INFO && CIF_USR3,(TEXT("[%s] Timeout is occured on frame capturing\r\n"), MODULE_NAME));
            return;
    }
}
void CameraHal::SetVideoCaptureCallbackEvent()
{
	SetEvent(hVideoCaptureEvent);
}
void CameraHal::SetPreviewCaptureCallbackEvent()
{
	SetEvent(hPreviewCaptureEvent);
}
