//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// 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:

    display_main.cpp

Abstract:

    This module implement the main class that derived from DDGPE of display driver to support DirectDraw
    The class SMDKDisp has many method and member variables, so implementation code is split to other module

Functions:

    Common Initalization, Deinitialization,
Notes:

--*/

#include "precomp.h"
#include "pmplatform.h"
#include <DrvLib_mem.h>
#include <nkintr.h>
#include <syspal.h>    // for 8Bpp we use the natural palette
#include <gxinfo.h>
//#define DISPPERF_DECLARE    //< This is defined in ddi_if.cpp in GPE component in CE6R2
#include "dispperf.h"
#ifdef USE_CMM_FOR_YUVSURFACE
#include "cmmapi.h"
#endif

#ifdef SUPPORT_APM_DISP

// 1. Message Queue Declaration

HANDLE PWCmsgQDisp = NULL;
MSG_DEV_STATE   txmqParamDisp;
MSGQUEUEOPTIONS msgOptionsDisp;

#endif

DDGPE * gGPE = (DDGPE *)NULL;
#if 0
#define DBG_MSG_HEADER      _T("[DISPDRV]")

#ifdef DEBUG
// NOTE:  One file should use INSTANTIATE_GPE_ZONES.  This allows it to be pre-compiled
// initialZones should typically be 0x0003 (refer to "gpe.h")
INSTANTIATE_GPE_ZONES(DISPDRV_DEBUGZONES, __MODULE__, "", "")
#else


DBGPARAM dpCurSettings =                                \
{                                                       \
    TEXT(__MODULE__),                                      \
    {                                                   \
        TEXT("Errors"),                 /* 0  */        \
        TEXT("Warnings"),               /* 1  */        \
        TEXT("Performance"),            /* 2  */        \
        TEXT("Temporary tests"),        /* 3  */        \
        TEXT("Enter,Exit"),             /* 4  */        \
        TEXT("Initialize"),             /* 5  */        \
        TEXT("Blt Calls"),              /* 6  */        \
        TEXT("Blt Verbose"),            /* 7  */        \
        TEXT("Surface Create"),         /* 8  */        \
        TEXT("Flip"),                   /* 9  */        \
        TEXT("Line"),                   /* 10 */        \
        TEXT("Post"),                   /* 11 */        \
        TEXT("Rotator"),                /* 12 */        \
        TEXT("TV Scaler"),              /* 13 */        \
        TEXT("TV Encoder"),             /* 14 */        \
        TEXT("2D"),                     /* 15 */        \
    },                                                  \
    (DISPDRV_RETAILZONES)                               \
};
#endif
#else
#ifdef DEBUG
// NOTE:  One file should use INSTANTIATE_GPE_ZONES.  This allows it to be pre-compiled
// initialZones should typically be 0x0003 (refer to "gpe.h")
INSTANTIATE_GPE_ZONES(DISPDRV_DEBUGZONES, __MODULE__, "", "")
#endif // DEBUG
#endif

// A backlight driver controls the backlight.
#define BACKLIGHT_ON(gpioreg)  //{  Set_PinData(gpioreg, BACKLIGHT, sgip_Output_1);      \
                               //   Set_PinFunction(gpioreg, BACKLIGHT); }

#define BACKLIGHT_OFF(gpioreg) // {  Set_PinData(gpioreg, BACKLIGHT, sgip_Output_0);      \
                               //    Set_PinFunction(gpioreg, BACKLIGHT); }



// This prototype avoids problems exporting from .lib
BOOL APIENTRY GPEEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA * data, PENGCALLBACKS engineCallbacks);

BOOL AdvertisePowerInterface(HMODULE hInst);
BOOL ConvertStringToGuid (LPCTSTR pszGuid, GUID *pGuid);
CEDEVICE_POWER_STATE VideoToPmPowerState(VIDEO_POWER_STATE vps);
VIDEO_POWER_STATE PmToVideoPowerState(CEDEVICE_POWER_STATE pmDx);

BOOL
APIENTRY
DrvEnableDriver(
    ULONG           engineVersion,
    ULONG           cj,
    DRVENABLEDATA * data,
    PENGCALLBACKS   engineCallbacks
    )
{
    return GPEEnableDriver(engineVersion, cj, data, engineCallbacks);
}

GPE *
GetGPE()
{
    if (!gGPE)
    {
        gGPE = new SMDKDisp();
    }

    return gGPE;
}

// This is Temporary Code. Must fix bug & delete.
// Do not use on Mobile
//#define TEMP_FIX_ROTATION_BUG

#ifdef TEMP_FIX_ROTATION_BUG
BOOL g_bTempFirstRotation=FALSE;
#endif

SMDKDisp::SMDKDisp()
{
    //DWORD dwSplashFrameBufferSize;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV] ++%s()\n\r"),_T(__FUNCTION__)));

    m_pDispConReg = NULL;
    m_pGPIOReg = NULL;
#ifdef USE_DSI
    m_pMIPIDSIReg = NULL;
#else
    m_pSPIReg = NULL;
#endif
    m_pBspArg = NULL;

    m_VideoMemoryPhysicalBase = NULL;
    m_VideoMemoryVirtualBase = NULL;
    m_VideoMemorySize = 0;
#ifdef USE_CMM_FOR_YUVSURFACE
    m_hCmmFB = NULL;
#endif
#ifdef OVERLAY_USE_MEM2MEM
    for(int i=0;i<OVERLAY_FB_NUM;i++)
    {
        m_pOverlayDMAOutputBuf[i] = NULL;
    }
    m_hPostReadyEvent = NULL;
    m_hPostBusyEvent = NULL;
    m_hPostTreadEnd = NULL;
    m_bPostThreadExit = FALSE;
    m_hPostIST = NULL;
    m_uiCurPostFB = 0;
#endif
    m_pVideoMemoryHeap = NULL;

    m_hVideoDrv = NULL;

    m_CursorVisible = FALSE;
    m_CursorDisabled = TRUE;
    m_CursorForcedOff = FALSE;
    memset (&m_CursorRect, 0x0, sizeof(m_CursorRect));

    m_InDDraw = FALSE;

    InitalizeOverlayContext();

//---------------------
// Setup Mode Information
//---------------------


    // Initialize Screen Dimensions
    m_dwDeviceScreenWidth = LCD_WIDTH;
    m_dwDeviceScreenHeight = LCD_HEIGHT;
    m_nScreenWidthSave = m_dwDeviceScreenWidth;
    m_nScreenHeightSave = m_dwDeviceScreenHeight;

    // Initialize Rotate Mode
#ifdef TEMP_FIX_ROTATION_BUG
    m_iRotate = 0;
    g_bTempFirstRotation = TRUE;
#else
    m_iRotate = GetRotateModeFromReg();
#endif
    SetRotateParams();

    //----------------------------------------
    // Initialize ModeInfoEX, modeInfo Data Structure
    //----------------------------------------

    InitializeDisplayMode();



    // Initialize Power State
    m_VideoPowerState = VideoPowerOn;

    InitAcceleration();
    // Mapping Virtual Address (SFR, VideoMemory)
    if (AllocResource() == FALSE)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] %s() : AllocResource() Fail\n\r"), _T(__FUNCTION__)));
        return;
    }
    // Clear Video Memory
    //dwSplashFrameBufferSize = m_dwDeviceScreenWidth*m_dwDeviceScreenHeight*m_pMode->Bpp/8;
    memset ((void *)m_VideoMemoryVirtualBase, 0x0, m_VideoMemorySize);

    if(m_G2DControlArgs.UseHWAccel)
    {
        m_oG2D = new FIMG2D;

        // Initialize Interrupt (Event, Interrupt)
        if (m_oG2D)
        {
            BOOL bResult;

            bResult = m_oG2D->InitializeInterrupt();

            if(bResult==FALSE)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] InitializeInterrupt() 2D Object is failed.\n\r")));
            }
        }
        else
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] %s() : 2D Accelerator Initialization Fail\n\r"), _T(__FUNCTION__)));
        }
    }

    // Initialize Critical Section
    InitializeCriticalSection(&m_csDevice);
    InitializeCriticalSection(&m_cs2D);

    // Initialize Display Controller
    if (DevInitialize() == FALSE)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] %s() : InitializeDevice() Fail\n\r"), _T(__FUNCTION__)));
        return;
    }

    //Allocate Primary Surface
    if (NULL == m_pPrimarySurface)
    {
        if (FAILED(AllocSurface((DDGPESurf **)&m_pPrimarySurface,
                            m_nScreenWidthSave, m_nScreenHeightSave,
                            m_pMode->format, m_pModeEx->ePixelFormat,
                            GPE_REQUIRE_VIDEO_MEMORY)))
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] %s() : m_pPrimarySurface AllocSurface() Fail\n\r"), _T(__FUNCTION__)));
         }
        else
        {
            m_pVisibleSurface = (SMDKSurf*)m_pPrimarySurface;
        }
    }

    if((m_G2DControlArgs.UseHWAccel) && (m_G2DControlArgs.UseCloneBuffer))
    {
        CreateCloneSurf();
    }

    RETAIL_DISP_MSG(DISP_ZONE_TEMP,(TEXT("m_nScreenWidth:%d, m_nScreenHeight:%d, m_nWS:%d, m_nHS:%d, m_iRotate:%d, PriRot:%d\r\n"),
        m_nScreenWidth, m_nScreenHeight, m_nScreenWidthSave, m_nScreenHeightSave, m_iRotate, m_pPrimarySurface->Rotate()));
    m_pPrimarySurface->SetRotation(m_nScreenWidth, m_nScreenHeight, m_iRotate);
    RETAIL_DISP_MSG(DISP_ZONE_TEMP,(TEXT("Primary ScreenWidth:%d, ScreenHeight:%d, m_iRotate:%d\r\n"),
        m_pPrimarySurface->ScreenWidth(), m_pPrimarySurface->ScreenHeight(), m_pPrimarySurface->Rotate()));

    AdvertisePowerInterface(g_hmodDisplayDll);

#ifdef SUPPORT_APM_DISP
    Disp_power_init_APM();
#endif

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));
}

SMDKDisp::~SMDKDisp()
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    if (m_oG2D)
    {
        if(m_G2DControlArgs.UseCloneBuffer)
        {
            ReleaseCloneSurf();
        }

        m_oG2D->DeinitInterrupt();
        delete m_oG2D;
    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] DeinitInterrupt() : 2D Object is not created.\n\r")));
    }

#ifdef SUPPORT_APM_DISP
    Disp_power_deinit_APM();
#endif

    ReleaseResource();

    RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));
}

void
SMDKDisp::InitAcceleration(void)
{
    // Determine AccelLevel, Currently not used strictly.
    m_G2DControlArgs.AccelLevel = 0x8;

    m_G2DControlArgs.UseHWAccel = G2D_ACCELERATE;
    m_G2DControlArgs.UseSWAccel = USE_SECEMUL_LIBRARY;
    m_G2DControlArgs.UseCloneBuffer = USE_CLONEBUFFER;
    m_G2DControlArgs.UsePACSurf = USE_PACSURF;
    m_G2DControlArgs.UseForceSetPallete = FORCE_SET_PALLETE;
    m_G2DControlArgs.UseCachedVideoMemory = USE_CACHED_VIDEOMEMORY;
    m_G2DControlArgs.UseCacheFlushForVideoMemory = USE_CACHEFLUSH_FORVIDEOMEMORY;
}

void
SMDKDisp::WaitForNotBusy(void)
{
    if(m_VideoPowerState != VideoPowerOff && m_oG2D)
    {
        m_oG2D->WaitForIdle();
    }
}

int
SMDKDisp::IsBusy(void)
{
    if(m_VideoPowerState != VideoPowerOff && m_oG2D)
    {
        return m_oG2D->IsRunning();
    }
    return    0;        //< 2D HW not yet start
}

void
SMDKDisp::GetPhysicalVideoMemory(unsigned long *physicalMemoryBase, unsigned long *videoMemorySize)
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] %s()\n\r"), _T(__FUNCTION__)));

    *physicalMemoryBase = m_VideoMemoryPhysicalBase;
    *videoMemorySize = m_VideoMemorySize;
}

void
SMDKDisp::GetVirtualVideoMemory(unsigned long *virtualMemoryBase, unsigned long *videoMemorySize)
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] %s()\n\r"), _T(__FUNCTION__)));

    *virtualMemoryBase = m_VideoMemoryVirtualBase;
    *videoMemorySize = m_VideoMemorySize;
}


int
SMDKDisp::InDisplay(void)
{
    DEBUG_DISP_MSG (GPE_ZONE_INIT, (TEXT("%s()\r\n"), _T(__FUNCTION__)));

    if (DevGetVerticalStatus() == DISP_V_ACTIVE)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int
SMDKDisp::InVBlank(void)
{
    DEBUG_DISP_MSG (GPE_ZONE_INIT, (TEXT("%s()\r\n"), _T(__FUNCTION__)));

    switch(DevGetVerticalStatus())
    {
        case DISP_V_VSYNC:
        case DISP_V_BACKPORCH:
            return TRUE;
            break;
        case DISP_V_ACTIVE:
        case DISP_V_FRONTPORCH:
        default:
            return FALSE;
            break;
    }
}

SCODE
SMDKDisp::SetPalette(const PALETTEENTRY *source, USHORT firstEntry, USHORT numEntries)
{
    DEBUG_DISP_MSG (GPE_ZONE_INIT, (TEXT("%s()\r\n"), _T(__FUNCTION__)));

    if (firstEntry + numEntries > 256 || source == NULL)
    {
        return  E_INVALIDARG;
    }

    return S_OK;
}

int
SMDKDisp::GetGameXInfo(ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
{
    int     RetVal = 0;     // Default not supported
    GXDeviceInfo * pgxoi;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    // GAPI only support P8, RGB444, RGB555, RGB565, and RGB888
    if ((cjOut >= sizeof(GXDeviceInfo)) && (pvOut != NULL)
        && (m_pMode->Bpp == 8 || m_pMode->Bpp == 16 || m_pMode->Bpp == 24 || m_pMode->Bpp == 32))
    {
        if (((GXDeviceInfo *) pvOut)->idVersion == kidVersion100)
        {
            pgxoi = (GXDeviceInfo *) pvOut;
            pgxoi->idVersion = kidVersion100;
            pgxoi->pvFrameBuffer = (void *)m_pPrimarySurface->Buffer();
            pgxoi->cbStride = m_pPrimarySurface->Stride();
            pgxoi->cxWidth = m_pPrimarySurface->Width();
            pgxoi->cyHeight = m_pPrimarySurface->Height();

            if (m_pMode->Bpp == 8)
            {
                pgxoi->cBPP = 8;
                pgxoi->ffFormat = kfPalette;
            }
            else if (m_pMode->Bpp == 16)
            {
                pgxoi->cBPP = 16;
                pgxoi->ffFormat= kfDirect | kfDirect565;
            }
            else if (m_pMode->Bpp == 24)
            {
                pgxoi->cBPP = 24;
                pgxoi->ffFormat = kfDirect | kfDirect888;
            }
            else
            {
                pgxoi->cBPP = 32;
                pgxoi->ffFormat = kfDirect | kfDirect888;
            }

       if (m_iRotate == DMDO_90 || m_iRotate == DMDO_270 )
        pgxoi->ffFormat |= kfLandscape;  // Rotated

            pgxoi->vkButtonUpPortrait = VK_UP;
            pgxoi->vkButtonUpLandscape = VK_LEFT;
            pgxoi->vkButtonDownPortrait = VK_DOWN;
            pgxoi->vkButtonDownLandscape = VK_RIGHT;
            pgxoi->vkButtonLeftPortrait = VK_LEFT;
            pgxoi->vkButtonLeftLandscape = VK_DOWN;
            pgxoi->vkButtonRightPortrait = VK_RIGHT;
            pgxoi->vkButtonRightLandscape = VK_UP;
            pgxoi->vkButtonAPortrait = 0xC3;            // far right button
            pgxoi->vkButtonALandscape = 0xC5;            // record button on side
            pgxoi->vkButtonBPortrait = 0xC4;            // second from right button
            pgxoi->vkButtonBLandscape = 0xC1;
            pgxoi->vkButtonCPortrait = 0xC5;            // far left button
            pgxoi->vkButtonCLandscape = 0xC2;            // far left button
            pgxoi->vkButtonStartPortrait = 134;            // action button
            pgxoi->vkButtonStartLandscape = 134;
            pgxoi->ptButtonUp.x = 120;
            pgxoi->ptButtonUp.y = 330;
            pgxoi->ptButtonDown.x = 120;
            pgxoi->ptButtonDown.y = 390;
            pgxoi->ptButtonLeft.x = 90;
            pgxoi->ptButtonLeft.y = 360;
            pgxoi->ptButtonRight.x = 150;
            pgxoi->ptButtonRight.y = 360;
            pgxoi->ptButtonA.x = 180;
            pgxoi->ptButtonA.y = 330;
            pgxoi->ptButtonB.x = 210;
            pgxoi->ptButtonB.y = 345;
            pgxoi->ptButtonC.x = -50;
            pgxoi->ptButtonC.y = 0;
            pgxoi->ptButtonStart.x = 120;
            pgxoi->ptButtonStart.y = 360;
            pgxoi->pvReserved1 = (void *) 0;
            pgxoi->pvReserved2 = (void *) 0;
            RetVal = ESC_SUCCESS;
        }
        else
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] GetGameXInfo() : Invalid Parameter\n\r")));
            SetLastError (ERROR_INVALID_PARAMETER);
            RetVal = ESC_FAILED;
        }

    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] GetGameXInfo() : Invalid Parameter\n\r")));
        SetLastError (ERROR_INVALID_PARAMETER);
        RetVal = ESC_FAILED;
    }

    RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return(RetVal);
}


int
SMDKDisp::GetRawFrameBuffer(ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
{
    int RetVal = ESC_SUCCESS;     // Default not supported
    RawFrameBufferInfo *pRawFB;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    if ((cjOut >= sizeof(RawFrameBufferInfo)) && (pvOut != NULL))
    {
        pRawFB = (RawFrameBufferInfo *)pvOut;

        pRawFB->wBPP = m_pMode->Bpp;

        if (pRawFB->wBPP == gpe32Bpp)
        {
            pRawFB->wFormat= RAW_FORMAT_OTHER;
//            pRawFB->cxStride = m_pPrimarySurface->Stride();
 //           pRawFB->cyStride = sizeof(DWORD);
        }
        else
        {
            pRawFB->wFormat= RAW_FORMAT_565;
        }

#if (LCD_TYPE == LCD_TYPE_LANDSCAPE)
        // Application knows DMDO_0 means portrait internally DMDO_270:
        // Now we return parameters for RAWFRAMEBUFFER,
        // Logical       Physical
        // DMDO_0                    DMDO_270
        // DMDO_90                DMDO_0
        // DMDO_180                DMDO_90
        // DMDO_270                DMDO_180
        // Set (Logical -> Physical)   m_iRotate has Physical Values.
        // Get (Physical -> Logical)
        //    case DMDO_0:        // Logically Portrait DMDO_0, Physically Landscape DMDO_270
        if (pRawFB->wBPP == gpe32Bpp)
        {
            pRawFB->cyStride = -(int) sizeof(DWORD);
        }
        else
        {
            pRawFB->cyStride = -(int) sizeof(WORD);
        }
        pRawFB->cxStride = m_pPrimarySurface->Stride();
        pRawFB->pFramePointer = (void *)((DWORD)m_pPrimarySurface->Buffer() + m_pPrimarySurface->Width() * ABS(pRawFB->cyStride));

        pRawFB->cxPixels = m_nScreenHeightSave;
        pRawFB->cyPixels = m_nScreenWidthSave;

#elif (LCD_TYPE == LCD_TYPE_PORTRAIT)
        if (pRawFB->wBPP == gpe32Bpp)
        {
            pRawFB->cxStride = sizeof(DWORD);
        }
        else
        {
            pRawFB->cxStride = sizeof(WORD);
        }
        pRawFB->cyStride = m_pPrimarySurface->Stride();
        pRawFB->pFramePointer = (void *)m_pPrimarySurface->Buffer();

        pRawFB->cxPixels = m_nScreenWidthSave;
        pRawFB->cyPixels = m_nScreenHeightSave;
#else
#error    LCD_TYPE_UNDEFINED_ERROR
#endif

        RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV:INF] GetRawFrameBuffer() : Stride=%d, xPixel=%d, yPixel=%d, FramePointer=0x%08x\r\n"), pRawFB->cyStride, pRawFB->cxPixels, pRawFB->cyPixels, pRawFB->pFramePointer));

        RetVal = ESC_SUCCESS;
    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] GetRawFrameBuffer() : Invalid Parameter\n\r")));
        SetLastError (ERROR_INVALID_PARAMETER);
        RetVal = ESC_FAILED;
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return(RetVal);
}


ULONG
SMDKDisp::DrvEscape(SURFOBJ * pso, ULONG iEsc, ULONG cjIn, void *pvIn, ULONG cjOut, void *pvOut)
{
    ULONG Result = 0;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s(0x%08x)\n\r"), _T(__FUNCTION__), iEsc));

    if (iEsc == QUERYESCSUPPORT)
    {
        if ((*(DWORD*)pvIn == GETGXINFO)
            || (*(DWORD*)pvIn == GETRAWFRAMEBUFFER)
            || (*(DWORD*)pvIn == DRVESC_GETSCREENROTATION)
            || (*(DWORD*)pvIn == DRVESC_SETSCREENROTATION)
            || (*(DWORD*)pvIn == SETPOWERMANAGEMENT)
            || (*(DWORD*)pvIn == GETPOWERMANAGEMENT)
            || (*(DWORD*)pvIn == IOCTL_POWER_CAPABILITIES)
            || (*(DWORD*)pvIn == IOCTL_POWER_QUERY)
            || (*(DWORD*)pvIn == IOCTL_POWER_SET)
            || (*(DWORD*)pvIn == IOCTL_POWER_GET)
            || (*(DWORD*)pvIn == DRVESC_G2D_ACCEL_SET)
            || (*(DWORD*)pvIn == DRVESC_GET_FB_PHY_ADDR)
            )
        {
            // The escape is supported.
            return 1;
        }
        else
        {
            // The escape isn't supported.
#if DO_DISPPERF
            return DispPerfQueryEsc(*(DWORD*)pvIn);;
#else
            return 0;
#endif
        }
    }
    else if (iEsc == DRVESC_GETSCREENROTATION)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : DRVESC_GETSCREENROTATION\n\r")));

#if(LCD_TYPE==LCD_TYPE_LANDSCAPE)
        int iMappedRotate = DMDO_90; // default

        switch (m_iRotate)
        {
        case DMDO_0:   iMappedRotate = DMDO_90;  break;
        case DMDO_90:  iMappedRotate = DMDO_180; break;
        case DMDO_180: iMappedRotate = DMDO_270; break;
        case DMDO_270: iMappedRotate = DMDO_0; break;
        }

        *(int *)pvOut = ((DMDO_0 | DMDO_90 | DMDO_180 | DMDO_270) << 8) | ((BYTE)iMappedRotate);

        return DISP_CHANGE_SUCCESSFUL;
#elif (LCD_TYPE==LCD_TYPE_PORTRAIT)
        *(int *)pvOut = ((DMDO_0 | DMDO_90 | DMDO_180 | DMDO_270) << 8) | ((BYTE)m_iRotate);

        return DISP_CHANGE_SUCCESSFUL;
#else
#error    LCD_TYPE_UNDEFINED_ERROR
#endif
    }
    else if (iEsc == DRVESC_SETSCREENROTATION)
    {
//        DISPDRV_MSG((_T("[DISPDRV] DrvEscape() : DRVESC_SETSCREENROTATION\n\r")));

#if(LCD_TYPE==LCD_TYPE_LANDSCAPE)
        switch (cjIn)
        {
        case DMDO_0:   return DynRotate(DMDO_270);
        case DMDO_90:  return DynRotate(DMDO_0);
        case DMDO_180: return DynRotate(DMDO_90);
        case DMDO_270: return DynRotate(DMDO_180);
        }

        return DISP_CHANGE_BADMODE;
#elif (LCD_TYPE==LCD_TYPE_PORTRAIT)
        if ((cjIn == DMDO_0) || (cjIn == DMDO_90) || (cjIn == DMDO_180) || (cjIn == DMDO_270))
        {
            return DynRotate(cjIn);
        }

        return DISP_CHANGE_BADMODE;
#else
#error     LCD_TYPE_UNDEFINED_ERROR
#endif
    }
    else if (iEsc == GETGXINFO)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : GETGXINFO\n\r")));

        return GetGameXInfo(iEsc, cjIn, pvIn, cjOut, pvOut);
    }
    else if (iEsc == GETRAWFRAMEBUFFER)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : GETRAWFRAMEBUFFER\n\r")));

        return GetRawFrameBuffer(iEsc, cjIn, pvIn, cjOut, pvOut);
    }
    else if (iEsc == SETPOWERMANAGEMENT)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : SETPOWERMANAGEMENT\n\r")));

        if ((cjIn >= sizeof (VIDEO_POWER_MANAGEMENT)) && (pvIn != NULL))
        {
            PVIDEO_POWER_MANAGEMENT pvpm = (PVIDEO_POWER_MANAGEMENT)pvIn;

            if (pvpm->Length >= sizeof (VIDEO_POWER_MANAGEMENT))
            {
                SetDisplayPowerState((VIDEO_POWER_STATE)(pvpm->PowerState));
            }
        }

        if (Result != ESC_SUCCESS)
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : SETPOWERMANAGEMENT Fail\n\r")));

            // Shouldn't get here if everything was ok.
            SetLastError(ERROR_INVALID_PARAMETER);
            Result = ESC_FAILED;
        }

        return Result;
    }
    else if (iEsc == GETPOWERMANAGEMENT)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : GETPOWERMANAGEMENT\n\r")));

        if ((cjOut >= sizeof (VIDEO_POWER_MANAGEMENT)) && (pvOut != NULL))
        {
            PVIDEO_POWER_MANAGEMENT pvpm = (PVIDEO_POWER_MANAGEMENT)pvOut;

            pvpm->Length = sizeof (VIDEO_POWER_MANAGEMENT);
            pvpm->DPMSVersion = 0;

            pvpm->PowerState = m_VideoPowerState;

            Result = ESC_SUCCESS;
        }
        else
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : GETPOWERMANAGEMENT Fail\n\r")));

            // Shouldn't get here if everything was ok.
            SetLastError(ERROR_INVALID_PARAMETER);
            Result = ESC_FAILED;
        }

        return Result;
    }
    else if (iEsc == IOCTL_POWER_CAPABILITIES)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_CAPABILITIES\n\r")));

        // tell the power manager about ourselves
        if (pvOut != NULL && cjOut == sizeof(POWER_CAPABILITIES))
        {
            __try
            {
                PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES) pvOut;
                memset(ppc, 0, sizeof(*ppc));
                ppc->DeviceDx = DX_MASK(D0) | DX_MASK(D4);
                Result = ESC_SUCCESS;
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_CAPABILITIES Exception Occurs\n\r")));
                Result = ESC_FAILED;
            }
        }

        return Result;
    }
    else if(iEsc == IOCTL_POWER_QUERY)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_QUERY\n\r")));

        if(pvOut != NULL && cjOut == sizeof(CEDEVICE_POWER_STATE))
        {
            // return a good status on any valid query, since we are always ready to
            // change power states.
            __try
            {
                CEDEVICE_POWER_STATE NewDx = *(PCEDEVICE_POWER_STATE) pvOut;
                if(VALID_DX(NewDx))
                {
                    // this is a valid Dx state so return a good status
                    Result = ESC_SUCCESS;
                }
                else
                {
                    RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_QUERY Fail\n\r")));
                    Result = ESC_FAILED;
                }
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_QUERY Exception Occurs\n\r")));
                Result = ESC_FAILED;
            }
        }

        return Result;
    }
    else if(iEsc == IOCTL_POWER_SET)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_SET\n\r")));

        if(pvOut != NULL && cjOut == sizeof(CEDEVICE_POWER_STATE))
        {
            __try
            {
                CEDEVICE_POWER_STATE NewDx = *(PCEDEVICE_POWER_STATE) pvOut;
                if(VALID_DX(NewDx))
                {
                    RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_SET(D%d)\n\r"), NewDx));
                    SetDisplayPowerState(PmToVideoPowerState(NewDx));
                    Result = ESC_SUCCESS;
                }
                else
                {
                    RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_SET Fail\n\r")));
                    Result = ESC_FAILED;
                }
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_SET Exception Occurs\n\r")));
                Result = ESC_FAILED;
            }
            if(m_VideoPowerState == VideoPowerOff)
            {
                m_pBspArg->bLPDisplayOff = TRUE;
            }
            else
            {
                m_pBspArg->bLPDisplayOff = FALSE;
            }
        }

        return Result;
    }
    else if(iEsc == IOCTL_POWER_GET)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_GET\n\r")));

        if(pvOut != NULL && cjOut == sizeof(CEDEVICE_POWER_STATE))
        {
            __try
            {
                *(PCEDEVICE_POWER_STATE) pvOut = VideoToPmPowerState(GetDisplayPowerState());

                Result = ESC_SUCCESS;
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : IOCTL_POWER_GET Exception Occurs\n\r")));
                Result = ESC_FAILED;
            }
        }

        return Result;
    }
    else if(iEsc == DRVESC_G2D_ACCEL_SET)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : DRVESC_G2D_ACCEL\n\r")));
        /// Control Accelerator On/Off
        /// Adjust Acceleration Level (0~0xF0) : Predefined configuration, (0xF1~0xFE) : Reserved, (0xFF) : Force Setting
        ///     L0   0x00      No Accelration and Optimization
        ///     L1   0x01      Only SW Acceleratoin
        ///     L2   0x02      HW BitBlt
        ///     L3   0x04      HW BitBlt + HW Line
        ///     L4   0x08      HW Line + HW BitBlt + HW FillRect

        /// Return Value : Acceleration Level
        ///        Succeed : Accerleration Level ( 1 ~ 3 )
        ///        Fail : 0 (default no accleration)
        if(pvIn != NULL && cjIn == sizeof(G2D_ACCEL_CONTROL_ARGS))
        {
            __try
            {
                G2D_ACCEL_CONTROL_ARGS NewSetting = *(G2D_ACCEL_CONTROL_ARGS *) pvIn;
                RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] DrvEscape() : IOCTL_POWER_SET(D%d)\n\r"), NewSetting));

                // Detailed Setting.
                if(m_G2DControlArgs.AccelLevel == 0xFF)
                {
                    m_G2DControlArgs = NewSetting;
                }
                else
                {
                    // Decode Accleration LEVEL
                    switch(NewSetting.AccelLevel & 0xF)
                    {
                        case 0x0:
                        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[DISP_ZONE_TEMP] Level 0\n")));

                        m_G2DControlArgs.AccelLevel = NewSetting.AccelLevel;
                        m_G2DControlArgs.UseSWAccel = 0;
                        m_G2DControlArgs.UseHWAccel = 0;
                        break;
                        case 0x1:
                        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[DISP_ZONE_TEMP] Level 1\n")));
                        
                        m_G2DControlArgs.AccelLevel = NewSetting.AccelLevel;
                        m_G2DControlArgs.UseSWAccel = 0;
                        m_G2DControlArgs.UseHWAccel = 1;
                        if(m_G2DControlArgs.UseCloneBuffer)
                        {
                            CreateCloneSurf();
                        }
                        break;
                        case 0x2:
                        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[DISP_ZONE_TEMP] Level 2\n")));
                        
                        m_G2DControlArgs.AccelLevel = NewSetting.AccelLevel;
                        m_G2DControlArgs.UseSWAccel = 1;
                        m_G2DControlArgs.UseHWAccel = 0;
                        break;
                        case 0x3:
                        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[DISP_ZONE_TEMP] Level 3\n")));
                        
                        m_G2DControlArgs.AccelLevel = NewSetting.AccelLevel;
                        m_G2DControlArgs.UseSWAccel = 1;
                        m_G2DControlArgs.UseHWAccel = 1;
                        if(m_G2DControlArgs.UseCloneBuffer)
                        {
                            CreateCloneSurf();
                        }
                        break;
                        case 0x8:
                        m_G2DControlArgs.AccelLevel = NewSetting.AccelLevel;
                        m_G2DControlArgs.UseSWAccel = 1;
                        m_G2DControlArgs.UseHWAccel = 1;
                        break;
                        default:
                        //This is invalid level, so we ignore it.
                        Result = ESC_FAILED;
                        break;
                    }

                }
                Result = ESC_SUCCESS;
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DrvEscape() : DRVESC_G2D_ACCEL_SET Exception Occurs\n\r")));
                Result = ESC_FAILED;
            }
        }

        return ESC_FAILED;
    }
    else if(iEsc == DRVESC_GET_FB_PHY_ADDR)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] %s() : DRVESC_GET_FB_PHY_ADDR\n\r"),_T(__FUNCTION__)));

        if(pvOut != NULL && cjOut == sizeof(unsigned int))
        {
            __try
            {
                *(unsigned int*)pvOut = m_VideoMemoryPhysicalBase;

                Result = ESC_SUCCESS;
            }
            __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : DRVESC_GET_FB_PHY_ADDR Exception Occurs\n\r"),_T(__FUNCTION__)));
                Result = ESC_FAILED;
            }
        }
        else
        {
            Result = ESC_FAILED;
        }

        return Result;
    }

#if DO_DISPPERF
    else
    {
        return DispPerfDrvEscape(iEsc, cjIn, pvIn, cjOut,pvOut);
    }
#endif

    return 0;
}


/**
 *    Application Set GDI rotation 0 degree as Portrait.
 *    So, If Native LANDSCAPE LCD panel is used.
 *  We must Rotate This value.
 *
 */
int
SMDKDisp::GetRotateModeFromReg()
{
    HKEY hKey;
#if (LCD_TYPE == LCD_TYPE_PORTRAIT)
    int iRet = DMDO_0;
#elif (LCD_TYPE == LCD_TYPE_LANDSCAPE)
    int iRet = DMDO_90;
#else
#error     LCD_TYPE_UNDEFINED_ERROR
#endif

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\GDI\\ROTATION"), 0, 0, &hKey))
    {
        DWORD dwSize, dwAngle, dwType = REG_DWORD;

        dwSize = sizeof(DWORD);
        if (ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("ANGLE"), NULL, &dwType, (LPBYTE)&dwAngle, &dwSize))
        {
            switch (dwAngle)
            {
#if (LCD_TYPE == LCD_TYPE_PORTRAIT)
            case 0:
                iRet = DMDO_0;
                break;

            case 90:
                iRet = DMDO_90;
                break;

            case 180:
                iRet = DMDO_180;
                break;

            case 270:
                iRet = DMDO_270;
                break;

            default:
                iRet = DMDO_0;
                break;
#elif (LCD_TYPE == LCD_TYPE_LANDSCAPE)
            case 0:
                iRet = DMDO_270;
                break;

            case 90:
                iRet = DMDO_0;
                break;

            case 180:
                iRet = DMDO_90;
                break;

            case 270:
                iRet = DMDO_180;
                break;

            default:    /// Default Portrait. Logically DMDO_0
                iRet = DMDO_270;
                break;
#else
#error     LCD_TYPE_UNDEFINED_ERROR
#endif
            }
        }

        RegCloseKey(hKey);
    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] GetRotateModeFromReg() : RegOpenKeyEx() Fail\n\r")));
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s() = %d\n\r"), _T(__FUNCTION__),iRet));

    return iRet;
}

void
SMDKDisp::SetRotateParams()
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV:INF] %s() : Angle = %d\n\r"), _T(__FUNCTION__), m_iRotate));

    switch(m_iRotate)
    {
    case DMDO_90:
    case DMDO_270:
        m_nScreenHeight = m_nScreenWidthSave;
        m_nScreenWidth = m_nScreenHeightSave;
        break;

    case DMDO_0:
    case DMDO_180:
    default:
        m_nScreenWidth = m_nScreenWidthSave;
        m_nScreenHeight = m_nScreenHeightSave;
        break;
    }

    return;
}

LONG
SMDKDisp::DynRotate(int angle)
{
    GPESurfRotate * pSurf = (GPESurfRotate *)m_pPrimarySurface;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s(%d)\n\r"), _T(__FUNCTION__), angle));

    // DirectDraw and rotation can't co-exist.
    if (m_InDDraw)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DynRotate() : Can NOT Rotate in DirectDraw Mode\n\r")));
        return DISP_CHANGE_BADMODE;
    }

    CursorOff();

    m_iRotate = angle;

    SetRotateParams();

    m_pMode->width  = m_nScreenWidth;
    m_pMode->height = m_nScreenHeight;

    pSurf->SetRotation(m_nScreenWidth, m_nScreenHeight, angle);

    CursorOn();

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return DISP_CHANGE_SUCCESSFUL;
}


BOOL
SMDKDisp::AllocResource(void)
{
    DWORD dwBytes;
    DWORD dwRet;
    HKEY hDevKey = NULL;
    DWORD dwType = 0;
    DWORD dwDataLen = 0;
    LONG status;

    m_ActiveReg = new CRegistryEdit(HKEY_LOCAL_MACHINE, PC_REG_DISPLAY_CONFIG);

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s\n\r"),_T(__FUNCTION__)));
    // Get Memory Window From Registry
    DDKWINDOWINFO dwi;
    dwRet = m_ActiveReg->GetWindowInfo(&dwi);
    if ( dwRet != ERROR_SUCCESS)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("Cannot fetch Registry ErrorCode:0x%x, Check Registry Key:%s\n\r"), dwRet, PC_REG_DISPLAY_CONFIG));
        goto CleanUp;
    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISP] Open Display Device Physical address:0x%x\r\n"), dwi.memWindows[0].dwBase));
        if( dwi.dwNumMemWindows < 1 || dwi.memWindows[0].dwBase == 0)
        {
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("Incorrect information dwi.dwNumMemWindows:%d, dwi.memWindows[0].dwBase:0x%x, Check Registry Key:%s\n\r"),
                    dwi.dwNumMemWindows, dwi.memWindows[0].dwBase, PC_REG_DISPLAY_CONFIG));
            goto CleanUp;
        }
    }

    // Translate to System Address.
    m_pDispConReg = (DISPLAY_REG *)DrvLib_MapIoSpace(dwi.memWindows[0].dwBase, sizeof(DISPLAY_REG), FALSE);
    if (m_pDispConReg == NULL)
    {
        goto CleanUp;
    }

    // Read LocalPath Camera Driver
    dwDataLen = sizeof(DWORD);
    status = m_ActiveReg->RegQueryValueEx(PC_REG_DDOVERLAY_WINDOW,
                                       &dwType,
                                       (LPBYTE)&m_dwDDOverlayWinNum,
                                       &dwDataLen );

    if(!status)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISP:ERR] %s() : %s Cannot Read RegistryKey : %s%s\r\n"), _T(__FUNCTION__), PC_REG_DISPLAY_CONFIG, PC_REG_DDOVERLAY_WINDOW));
        m_dwDDOverlayWinNum = OVERLAY_WINDOW;
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISP:ERR] %s() : Try to use Default Setting Driver %d, But it can not work\r\n"), _T(__FUNCTION__), m_dwDDOverlayWinNum));
    }
    status = m_ActiveReg->RegQueryValueEx(PC_REG_PRIMARY_WINDOW,
                                       &dwType,
                                       (LPBYTE)&m_dwPrimaryWinNum,
                                       &dwDataLen );

    if(!status)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISP:ERR] %s() : %s Cannot Read RegistryKey : %s%s\r\n"), _T(__FUNCTION__), PC_REG_DISPLAY_CONFIG, PC_REG_PRIMARY_WINDOW));
        m_dwPrimaryWinNum = PRIMARY_WINDOW;
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISP:ERR] %s() : Try to use Default Setting Driver %d, But it can not work\r\n"), _T(__FUNCTION__), m_dwPrimaryWinNum));
    }

    m_pGPIOReg = (GPIO_REG *)DrvLib_MapIoSpace(BASE_REG_PA_GPIO, sizeof(GPIO_REG), FALSE);
    if (m_pGPIOReg == NULL)
    {
        goto CleanUp;
    }

    m_pBspArg = (volatile BSP_ARGS *)DrvLib_MapIoSpace(IMAGE_SHARE_ARGS_PA_START, sizeof(BSP_ARGS), FALSE);
    if (m_pBspArg == NULL)
    {
        goto CleanUp;
    }
    m_pBspArg->bLPDisplayOff = FALSE;

#ifdef USE_DSI
    m_pMIPIDSIReg = (MIPIDSI_REG *)DrvLib_MapIoSpace(BASE_REG_PA_MIPI_DSIM, sizeof(MIPIDSI_REG), FALSE);
    if (m_pMIPIDSIReg == NULL)
    {
        goto CleanUp;
    }
#else
    m_pSPIReg = (SPI_REG *)DrvLib_MapIoSpace(BASE_REG_PA_SPI0, sizeof(SPI_REG), FALSE);
    if (m_pSPIReg == NULL)
    {
        goto CleanUp;
    }
#endif

    // Open Video Engine Driver
    m_hVideoDrv = CreateFile( L"VDE0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
    if (m_hVideoDrv == NULL)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : VDE0 Open Device Failed\n\r"),_T(__FUNCTION__)));
        return FALSE;
    }

    // Request FIMD H/W Resource to Video Engine Driver
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_RSC_REQUEST_FIMD_INTERFACE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_RSC_REQUEST_FIMD_INTERFACE Failed\n\r"),_T(__FUNCTION__)));
        return FALSE;
    }

    // Request FIMD Win1 H/W Resource to Video Engine Driver for Primary Window
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_PRIMARY_WINDOW_REQUEST, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_PRIMARY_WINDOW_REQUEST Failed\n\r"),_T(__FUNCTION__)));
        return FALSE;
    }

#ifdef USE_CMM_FOR_YUVSURFACE
    //CMM init
    m_hCmmFB = CreateFile(CODEC_MEM_DRIVER_NAME,
                       GENERIC_READ|GENERIC_WRITE,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);

    if (m_hCmmFB == NULL)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : CMM Open failure\n"),_T(__FUNCTION__)));
        //return FALSE;
    }
#endif // USE_CMM_FOR_YUVSURFACE

#ifdef USE_REGISTRY_VIDMEM_VIDSIZE
    if(m_ActiveReg->IsKeyOpened())
    {
        if(!m_ActiveReg->GetRegValue(_T("VidMemBase"), (PBYTE)&m_VideoMemoryPhysicalBase, sizeof(DWORD)))
        {
            m_VideoMemoryPhysicalBase  = IMAGE_2D_FRAMEBUFFER_PA_START;
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] Cannot get registry value of 'VidMemBase', Check Registry Key:%s\n\r"), PC_REG_DISPLAY_CONFIG));
            //goto CleanUp;
        }
        if(!m_ActiveReg->GetRegValue(_T("VidMemLen"), (PBYTE)&m_VideoMemorySize, sizeof(DWORD)))
        {
            m_VideoMemorySize = IMAGE_2D_FRAMEBUFFER_SIZE;
            RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] Cannot get registry value of 'VidMemLen', Check Registry Key:%s\n\r"), PC_REG_DISPLAY_CONFIG));
            //goto CleanUp;
        }
    }
    else
    {
#endif
        m_VideoMemoryPhysicalBase  = IMAGE_2D_FRAMEBUFFER_PA_START;
        m_VideoMemorySize = IMAGE_2D_FRAMEBUFFER_SIZE;
#ifdef USE_REGISTRY_VIDMEM_VIDSIZE
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] Registry Key is not opened\n\r")));
        goto CleanUp;
    }
#endif

    m_VideoMemoryVirtualBase = (DWORD)VirtualAlloc(NULL, m_VideoMemorySize, MEM_RESERVE, PAGE_NOACCESS);

    if (NULL == VirtualCopy((void *)m_VideoMemoryVirtualBase, (void *)(m_VideoMemoryPhysicalBase>>8), m_VideoMemorySize, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] AllocResource() : m_VideoMemoryVirtualBase VirtualCopy() Failed : %x\n\r"),    GetLastError()));
        return FALSE;
    }

#if 0
    // Platform Independent
    if(CeSetMemoryAttributes((void *)m_VideoMemoryVirtualBase, (void *)(m_VideoMemoryPhysicalBase>>8), m_VideoMemorySize, PAGE_WRITECOMBINE) != TRUE)
    {
        RETAIL_DISP_MSG(DISP_ZONE_WARNING, (_T("[DISPDRV:ERR] AllocResource() : m_VideoMemoryVirtualBase CeSetMemoryAttributes() Failed : %x\n\r"), GetLastError()));
    }
#else
    // Platform Dependent, change TLB directly, as NonCachable and Bufferable attributes for ARM9, Shared Device attribute for ARM11 and Cortex
    if (m_G2DControlArgs.UseCachedVideoMemory)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[G2D] Videomemory in Cached area\n")));
        if(VirtualSetAttributes((void *)m_VideoMemoryVirtualBase, m_VideoMemorySize, 0x8, 0xc, NULL) != TRUE)
        {
            RETAIL_DISP_MSG(DISP_ZONE_WARNING, (_T("[DISPDRV:ERR] AllocResource() : m_VideoMemoryVirtualBase VirtualSetAttributes() Failed : %x\n\r"), GetLastError()));
        }
    }
    else
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP,(_T("[G2D] Videomemory in UnCached area\n")));
        if(VirtualSetAttributes((void *)m_VideoMemoryVirtualBase, m_VideoMemorySize, 0x4, 0xc, NULL) != TRUE)
        {
            RETAIL_DISP_MSG(DISP_ZONE_WARNING, (_T("[DISPDRV:ERR] AllocResource() : m_VideoMemoryVirtualBase VirtualSetAttributes() Failed : %x\n\r"), GetLastError()));
        }
    }
#endif
    RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV:INF] m_VideoMemoryPhysicalBase = 0x%08x\n\r"), m_VideoMemoryPhysicalBase));
    RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV:INF] m_VideoMemoryVirtualBase = 0x%08x\n\r"), m_VideoMemoryVirtualBase));
    RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV:INF] m_VideoMemorySize = 0x%08x\n\r"), m_VideoMemorySize));

    // Allocate SurfaceHeap
    m_pVideoMemoryHeap = new SurfaceHeap(m_VideoMemorySize, m_VideoMemoryVirtualBase, NULL, NULL);
    if(!m_pVideoMemoryHeap)
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s : SurfaceHeap() allocate Fail\n\r"),_T(__FUNCTION__)));
        return FALSE;
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s\n\r"), _T(__FUNCTION__)));

    delete m_ActiveReg;

    return TRUE;

CleanUp:

    RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] --%s : Failed\r\n"), _T(__FUNCTION__)));

    delete m_ActiveReg;

    return FALSE;
}


void
SMDKDisp::ReleaseResource(void)
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    DWORD dwBytes;

    if (m_pVideoMemoryHeap != NULL)
    {
        delete m_pVideoMemoryHeap;
    }

    if (m_VideoMemoryVirtualBase != NULL)
    {
        VirtualFree((LPVOID)m_VideoMemoryVirtualBase, 0, MEM_RELEASE);
    }

#ifdef USE_CMM_FOR_YUVSURFACE
    if(m_hCmmFB != NULL)
    {
        CloseHandle(m_hCmmFB);
    }
#endif

    if (m_pDispConReg != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_pDispConReg);
        m_pDispConReg = NULL;
    }

    if (m_pGPIOReg != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_pGPIOReg);
        m_pGPIOReg = NULL;
    }

#ifdef USE_DSI
    if (m_pMIPIDSIReg != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_pMIPIDSIReg);
        m_pMIPIDSIReg = NULL;
    }
#else
    if (m_pSPIReg != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)m_pSPIReg);
        m_pSPIReg = NULL;
    }
#endif

    // Release FIMD Win1 H/W Resource to Video Engine Driver for Primary Window
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_PRIMARY_WINDOW_RELEASE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] ReleaseResource() : IOCTL_PRIMARY_WINDOW_RELEASE Failed\n\r")));
    }

    // Release FIMD H/W Resource to Video Engine Driver
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_RSC_RELEASE_FIMD_INTERFACE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] ReleaseResource() : IOCTL_SVE_RSC_RELEASE_FIMD_INTERFACE Failed\n\r")));
    }

    // Close Video Engine Driver
    if (m_hVideoDrv!= NULL)
    {
        CloseHandle(m_hVideoDrv);
        m_hVideoDrv = NULL;
    }


    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));
}

// returns DD_OK for OK otherwise error code
// populates *pFormat, and *pPixelFormat
SCODE
SMDKDisp::DetectPixelFormat(
                DWORD                dwCaps,            // in: DDSCAPS_xxx flags
                DDPIXELFORMAT*        pDDPF,            // in: Explicit pixel format or current mode
                EGPEFormat*            pFormat,
                EDDGPEPixelFormat*    pPixelFormat
                )
{
    SCODE rv = DDGPE::DetectPixelFormat(dwCaps, pDDPF, pFormat, pPixelFormat);

    if (rv == DDERR_UNSUPPORTEDFORMAT)
    {
        if(pDDPF->dwFlags & DDPF_FOURCC)
        {
            if( pDDPF->dwFourCC == FOURCC_I420 )
            {
                *pPixelFormat = (EDDGPEPixelFormat)ddgpePixelFormat_I420;
                *pFormat = gpe16Bpp;    // 12Bpp is not defined in GPE
                return DD_OK;
            }
            else if (pDDPF->dwFourCC == FOURCC_NV12)
            {
                *pPixelFormat = (EDDGPEPixelFormat)ddgpePixelFormat_NV12;
                *pFormat = gpe16Bpp;    // 12Bpp is not defined in GPE
                return DD_OK;
            }
            else     if( pDDPF->dwFourCC == FOURCC_YVYU )
            {
                *pPixelFormat = (EDDGPEPixelFormat)ddgpePixelFormat_YVYU;
                *pFormat = gpe16Bpp;
                return DD_OK;
            }
            else     if( pDDPF->dwFourCC == FOURCC_VYUY )
            {
                *pPixelFormat = (EDDGPEPixelFormat)ddgpePixelFormat_VYUY;
                *pFormat = gpe16Bpp;
                return DD_OK;
            }
        }

        return DDERR_UNSUPPORTEDFORMAT;
    }
    else
    {
        return rv;
    }
}

void
SMDKDisp::SetDisplayPowerState(VIDEO_POWER_STATE PowerState)
{
    static BYTE * pVideoMemory = NULL;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s(%d)\n\r"), _T(__FUNCTION__), PowerState));

    // If we're already in the appropriate state, just return
    if (m_VideoPowerState == PowerState)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] SetDisplayPowerState() : Same as current State [%d]\n\r"), m_VideoPowerState));
        return;
    }

    if (PowerState == VideoPowerOn)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] SetDisplayPowerState() : VideoPowerOn\n\r")));

        if (m_VideoPowerState == VideoPowerOn)
        {
            // Do Nothing
        }
        else        // from VideoPowerOff or VideoPowerSuspend
        {
            DevPowerOn();

            DynRotate(m_iRotate);

            m_CursorDisabled = FALSE;
            //CursorOn();    // in DynRotate()
            //m_CursorVisible = TRUE;    // in CursorOn()
        }

        m_VideoPowerState = VideoPowerOn;

    }
    else if (PowerState == VideoPowerOff)
    {
        RETAIL_DISP_MSG(DISP_ZONE_TEMP, (_T("[DISPDRV] SetDisplayPowerState() : VideoPowerOff\n\r")));

        if (m_VideoPowerState == VideoPowerOff)
        {
            // Do Nothing
        }
        else        // from VideoPowerOn or VideoPowerStandby
        {
            m_CursorDisabled = TRUE;
            CursorOff();

            // Turn Off Display Controller
            DevPowerOff();
        }

        m_VideoPowerState = VideoPowerOff;
    }
#ifdef SUPPORT_APM_DISP
    Disp_power_set_APM(VideoToPmPowerState(PowerState));
#endif
}


VIDEO_POWER_STATE
SMDKDisp::GetDisplayPowerState(void)
{
    return m_VideoPowerState;
}


BOOL
SMDKDisp::WaitForVerticalBlank(VB_STATUS Status)
{
    BOOL bRet = FALSE;

    bRet = DevWaitForVerticalBlank();

    return bRet;
}


DWORD
SMDKDisp::GetScanLine(void)
{
    DWORD dwRet = 0;

    dwRet = DevGetScanLine();

    return dwRet;
}

BOOL
SMDKDisp::DevInitialize(void)
{
    SVEARG_FIMD_OUTPUT_IF tParam;
    DWORD dwBytes;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    EnterCriticalSection(&m_csDevice);

    // Initialize SFR Address of Sub Module
#ifdef USE_DSI
    // Video Output Disable
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputDisableRGBIF() : IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE Failed\n\r")));
    }

    // Power Off Video Driver
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_PM_SET_POWER_OFF, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevPowerOff() : IOCTL_SVE_PM_SET_POWER_OFF Failed : m_hVideoDrv:0x%x\n\r"),m_hVideoDrv));
    }

    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_PM_SET_POWER_ON, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevPowerOn() : IOCTL_SVE_PM_SET_POWER_ON Failed\n\r")));
    }
    LDI_DSI_initialize_register_address((void *)m_pMIPIDSIReg, (void *)m_pDispConReg, (void *)m_pGPIOReg);
#else
    LDI_initialize_register_address((void *)m_pSPIReg, (void *)m_pDispConReg, (void *)m_pGPIOReg);
#endif

    // Set LCD Module Type
#if    (LCD_MODULE == LCD_MODULE_AT070TN92)
    LDI_set_LCD_module_type(AT070TN92_RGB);
#elif    (LCD_MODULE == LCD_MODULE_HT101HD1)
    LDI_set_LCD_module_type(LDI_HT101HD1_RGB);
#elif    (LCD_MODULE == LCD_MODULE_EMUL48_PQV)
    LDI_set_LCD_module_type(AT070TN92_RGB);
#elif    (LCD_MODULE == LCD_MODULE_EMUL48_MP)
    LDI_set_LCD_module_type(AT070TN92_RGB);
#elif    (LCD_MODULE == LCD_MODULE_TL2796)
    LDI_set_LCD_module_type(LDI_TL2796_RGB);
#elif    (LCD_MODULE == LCD_MODULE_DSI_DUMMY)
    LDI_set_LCD_module_type(LDI_DUMMY);
#elif    (LCD_MODULE == LCD_MODULE_LTS222)
    LDI_set_LCD_module_type(LDI_LTS222QV_RGB);
#elif    (LCD_MODULE == LCD_MODULE_AUO27)
    LDI_set_LCD_module_type(LDI_AUO27_RGB);
#elif    (LCD_MODULE == LCD_MODULE_VGA8060)
    LDI_set_LCD_module_type(LDI_VGA8060_RGB);
#elif    (LCD_MODULE == LCD_MODULE_VGA1024)
    LDI_set_LCD_module_type(LDI_VGA1024_RGB);
#elif (LCD_MODULE == LCD_MODULE_VGA1280)
	LDI_set_LCD_module_type(LDI_VGA1280_1024_RGB);
#elif (LCD_MODULE ==LCD_MODULE_VGA1440)
	LDI_set_LCD_module_type(LDI_VGA1440_900_RGB);
#elif(LCD_MODULE == LCD_MODULE_VAG8048)
       LDI_set_LCD_module_type(LDI_VGA800_480_RGB);
#elif(LCD_MODULE == LCD_MODULE_LTV350)
	LDI_set_LCD_module_type(LDI_LTV350QV_RGB);
#endif

    // Get RGB Interface Information from LDI Library
    LDI_fill_output_device_information(&tParam.tDispDevInfo);

    // Power On Video Driver
    // All of HW State is restored by Video Driver
    RETAIL_DISP_MSG(DISP_ZONE_TEMP,(TEXT("!!!MY Test!!!\r\n")));
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_PM_SET_POWER_ON, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevPowerOn() : IOCTL_SVE_PM_SET_POWER_ON Failed\n\r")));
    }

    // Initialize Display Interface Parameter
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_INTERFACE_PARAM, &tParam, sizeof(SVEARG_FIMD_OUTPUT_IF), NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevInitialize() : IOCTL_SVE_FIMD_SET_INTERFACE_PARAM Failed\n\r")));
    }

    // Initial Output Interface
    m_eOutputInterface = tParam.tDispDevInfo.VideoOutMode;

    switch(m_eOutputInterface)
    {
    case DISP_VIDOUT_RGBIF:
        DevOutputEnableRGBIF();
        break;
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevInitialize() : Unknown Output I/F(%d)\n\r"),m_eOutputInterface));
        break;
    }

    LeaveCriticalSection(&m_csDevice);

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return TRUE;
}


BOOL
SMDKDisp::DevPowerOn(void)
{
    DWORD dwBytes;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    EnterCriticalSection(&m_csDevice);

    // Power On Video Driver
    // All of HW State is restored by Video Driver
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_PM_SET_POWER_ON, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_PM_SET_POWER_ON Failed\n\r"), _T(__FUNCTION__)));
    }

    switch(m_eOutputInterface)
    {
    case DISP_VIDOUT_RGBIF:
//#if ((LCD_MODULE != LCD_MODULE_TL2796) \
//    || (LCD_MODULE != LCD_MODULE_LTE480))
        // Initialize LCD Module
        LDI_initialize_LCD_module();
//#endif

#if(LCD_MODULE != LCD_MODULE_TL2796)
    // Backlight On
        // TODO: To be Replaced with Backlight Driver
        BACKLIGHT_ON(m_pGPIOReg);
#endif
        break;
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : Unknown Output I/F(%d)\n\r"), _T(__FUNCTION__),m_eOutputInterface));
        break;
    }

    // Video Output Enable
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_ENABLE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_LCD_SET_MODULE_ENABLE Failed\n\r"), _T(__FUNCTION__)));
    }

    LeaveCriticalSection(&m_csDevice);

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return TRUE;
}


BOOL
SMDKDisp::DevPowerOff(void)
{
    DWORD dwBytes;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    EnterCriticalSection(&m_csDevice);

    switch(m_eOutputInterface)
    {
    case DISP_VIDOUT_RGBIF:// Backlight Off
        // TODO: To be Replaced with Backlight Driver
        BACKLIGHT_OFF(m_pGPIOReg);
        break;
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : Unknown Output I/F(%d)\n\r"), _T(__FUNCTION__),m_eOutputInterface));
        break;
    }

    // Deinitialize LCD Module
    LDI_deinitialize_LCD_module();

    // Video Output Disable
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE Failed\n\r"), _T(__FUNCTION__)));
    }

    // Power Off Video Driver
    // All of HW State will be restored by Video Driver
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_PM_SET_POWER_OFF, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_PM_SET_POWER_OFF Failed : m_hVideoDrv:0x%x\n\r"), _T(__FUNCTION__),m_hVideoDrv));
    }

    LeaveCriticalSection(&m_csDevice);

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));

    return TRUE;
}


void
SMDKDisp::DevOutputEnableRGBIF(void)
{
    DWORD dwBytes;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    // Display initialize to RGB I/F
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_RGBIF, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_FIMD_SET_OUTPUT_RGBIF Failed\n\r")));
    }

    switch(m_pModeEx->ePixelFormat)
    {
    case ddgpePixelFormat_565:
        {
            SVEARG_FIMD_WIN_MODE tParam;

            tParam.dwWinMode = PRIMARY_WINDOW_MODE;
            tParam.dwBPP = DISP_16BPP_565;
            tParam.dwWidth = m_dwDeviceScreenWidth;
            tParam.dwHeight = m_dwDeviceScreenHeight;
            tParam.dwOffsetX = 0;
            tParam.dwOffsetY = 0;

            // Primary Window Initialize
            if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_MODE, &tParam, sizeof(SVEARG_FIMD_WIN_MODE), NULL, 0, &dwBytes, NULL) )
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_FIMD_SET_WINDOW_MODE Failed\n\r")));
            }

            break;
        }
    //case ddgpePixelFormat_8880:    // FIMD can not support Packed RGB888
    case ddgpePixelFormat_8888:
        {
            SVEARG_FIMD_WIN_MODE tParam;

            tParam.dwWinMode = PRIMARY_WINDOW_MODE;
            tParam.dwBPP = DISP_24BPP_888;
            tParam.dwWidth = m_dwDeviceScreenWidth;
            tParam.dwHeight = m_dwDeviceScreenHeight;
            tParam.dwOffsetX = 0;
            tParam.dwOffsetY = 0;

            // Primary Window Initialize
            if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_MODE, &tParam, sizeof(SVEARG_FIMD_WIN_MODE), NULL, 0, &dwBytes, NULL) )
            {
                RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_FIMD_SET_WINDOW_MODE Failed\n\r")));
            }

            break;
        }
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : Unknown PixelFormat %d \n\r"), m_pModeEx->ePixelFormat));
        break;
    }

    SVEARG_FIMD_WIN_ALPHA_EX tParamAlpha;
    tParamAlpha.dwWinNum = DISP_WIN2;
    tParamAlpha.dwMethod = DISP_ALPHA_PER_PLANE;
    tParamAlpha.dwAlpha0 = 0xff;
    tParamAlpha.dwAlpha1 = 0xff;
    tParamAlpha.dwABlendEq = DISP_BLDEQ_ALPHA_A;
    tParamAlpha.dwBBlendEq = DISP_BLDEQ_INV_ALPHA_A;
    tParamAlpha.dwPBlendEq = DISP_BLDEQ_ZERO;
    tParamAlpha.dwQBlendEq = DISP_BLDEQ_ZERO;
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_BLEND_ALPHA_EX, &tParamAlpha, sizeof(SVEARG_FIMD_WIN_ALPHA_EX), NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] %s() : IOCTL_SVE_FIMD_SET_WINDOW_BLEND_ALPHA_EX Failed\n\r"),_T(__FUNCTION__)));
    }
    // Set Primary Window Framebuffer
    SVEARG_FIMD_WIN_FRAMEBUFFER tParamFB;
    tParamFB.dwWinNum = PRIMARY_WINDOW;
    tParamFB.dwFrameBuffer = m_VideoMemoryPhysicalBase;
    tParamFB.bWaitForVSync = FALSE;
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_FRAMEBUFFER, &tParamFB, sizeof(SVEARG_FIMD_WIN_FRAMEBUFFER), NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_FIMD_SET_WINDOW_FRAMEBUFFER Failed\n\r")));
    }

    // Primary Window Enable
    DWORD dwParam;
    dwParam = PRIMARY_WINDOW;
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_ENABLE, &dwParam, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_FIMD_SET_WINDOW_ENABLE Failed\n\r")));
    }

//#if ((LCD_MODULE == LCD_MODULE_TL2796) \
//    || (LCD_MODULE == LCD_MODULE_LTE480))
    // Initialize LCD Module
    LDI_initialize_LCD_module();
//#endif

    // Video Output Enable
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_ENABLE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputEnableRGBIF() : IOCTL_SVE_LCD_SET_MODULE_ENABLE Failed\n\r")));
    }

    // Enable Overlay Window and Blending
    DevRecoverOverlay();

#if(LCD_MODULE != LCD_MODULE_TL2796)
    // Backlight On
    // TODO: To be Replaced with Backlight Driver
    BACKLIGHT_ON(m_pGPIOReg);
#endif

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));
}


void
SMDKDisp::DevOutputDisableRGBIF(void)
{
    DWORD dwBytes;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++%s()\n\r"), _T(__FUNCTION__)));

    // Backlight Off
    // TODO: To be Replaced with Backlight Driver
    BACKLIGHT_OFF(m_pGPIOReg);

    // Disable Overlay Window
    DevOverlayDisable();

    // Deinitialize LCD Module
    LDI_deinitialize_LCD_module();

    // Video Output Disable
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevOutputDisableRGBIF() : IOCTL_SVE_FIMD_SET_OUTPUT_DISABLE Failed\n\r")));
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --%s()\n\r"), _T(__FUNCTION__)));
}

BOOL
SMDKDisp::DevWaitForVerticalBlank(void)
{
    BOOL bRet = TRUE;
    DWORD dwBytes;

    // Wait for Frame Interrupt
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_WAIT_FRAME_INTERRUPT, NULL, 0, NULL, 0, &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevGetVerticalStatus() : IOCTL_SVE_FIMD_WAIT_FRAME_INTERRUPT Failed\n\r")));
        bRet = FALSE;
    }

    return bRet;
}


int
SMDKDisp::DevGetVerticalStatus(void)
{
    SVEARG_FIMD_OUTPUT_STAT tParam;
    DWORD dwBytes;

    // Get Output Status
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_GET_OUTPUT_STATUS, NULL, 0, &tParam, sizeof(SVEARG_FIMD_OUTPUT_STAT), &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevGetVerticalStatus() : IOCTL_SVE_FIMD_GET_OUTPUT_STATUS Failed\n\r")));
    }

    return (int)tParam.dwVerticalStatus;
}


DWORD
SMDKDisp::DevGetScanLine(void)
{
    SVEARG_FIMD_OUTPUT_STAT tParam;
    DWORD dwBytes;

    // Get Output Status
    if ( !DeviceIoControl(m_hVideoDrv, IOCTL_SVE_FIMD_GET_OUTPUT_STATUS, NULL, 0, &tParam, sizeof(SVEARG_FIMD_OUTPUT_STAT), &dwBytes, NULL) )
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] DevGetScanLine() : IOCTL_SVE_FIMD_GET_OUTPUT_STATUS Failed\n\r")));
    }

    return tParam.dwLineCnt;
}

// this routine converts a string into a GUID and returns TRUE if the
// conversion was successful.
BOOL
ConvertStringToGuid (LPCTSTR pszGuid, GUID *pGuid)
{
    UINT Data4[8];
    int  Count;
    BOOL fOk = FALSE;
    TCHAR *pszGuidFormat = _T("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}");

    DEBUGCHK(pGuid != NULL && pszGuid != NULL);
    __try
    {
        if (_stscanf(pszGuid, pszGuidFormat, &pGuid->Data1,
            &pGuid->Data2, &pGuid->Data3, &Data4[0], &Data4[1], &Data4[2], &Data4[3],
            &Data4[4], &Data4[5], &Data4[6], &Data4[7]) == 11)
        {
            for(Count = 0; Count < (sizeof(Data4) / sizeof(Data4[0])); Count++)
            {
                pGuid->Data4[Count] = (UCHAR) Data4[Count];
            }
        }
        fOk = TRUE;
    }
    __except(GetExceptionCode()==STATUS_ACCESS_VIOLATION ?
               EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        DEBUG_DISP_MSG(DISP_ZONE_ERROR, (TEXT("%s: Exception occured\n")));
        fOk=FALSE;
    }

    return fOk;
}

// This routine notifies the OS that we support the Power Manager IOCTLs (through
// ExtEscape(), which calls DrvEscape()).
BOOL
AdvertisePowerInterface(HMODULE hInst)
{
    BOOL fOk = FALSE;
    HKEY hk;
    DWORD dwStatus;
    TCHAR szTemp[MAX_PATH];
    GUID gClass;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++AdvertisePowerInterface()\n\r")));

    // assume we are advertising the default class
    fOk = ConvertStringToGuid(PMCLASS_DISPLAY, &gClass);
    DEBUGCHK(fOk);

    // check for an override in the registry
    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\GDI\\Drivers"), 0, 0, &hk);
    if(dwStatus == ERROR_SUCCESS)
    {
        DWORD dwType, dwSize;

        dwSize = sizeof(szTemp);
        dwStatus = RegQueryValueEx(hk, _T("DisplayPowerClass"), NULL, &dwType, (LPBYTE) szTemp, &dwSize);
        szTemp[MAX_PATH-1] = 0;

        if(dwStatus == ERROR_SUCCESS && dwType == REG_SZ)
        {
            // got a guid string, convert it to a guid
            GUID gTemp;

            fOk = ConvertStringToGuid(szTemp, &gTemp);
            DEBUGCHK(fOk);
            if(fOk)
            {
                gClass = gTemp;
            }
        }

        // release the registry key
        RegCloseKey(hk);
    }

    // figure out what device name to advertise
    if(fOk)
    {
        fOk = GetModuleFileName(hInst, szTemp, sizeof(szTemp) / sizeof(szTemp[0]));
        DEBUGCHK(fOk);
    }

    // now advertise the interface
    if(fOk)
    {
        fOk = AdvertiseInterface(&gClass, szTemp, TRUE);
        DEBUGCHK(fOk);
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --AdvertisePowerInterface() : %d\n\r"), fOk));

    return fOk;
}

VIDEO_POWER_STATE
PmToVideoPowerState(CEDEVICE_POWER_STATE pmDx)
{
    VIDEO_POWER_STATE vps;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++PmToVideoPowerState(%d)\n\r"), pmDx));

    switch(pmDx)
    {
    case D0:        // Display On
        vps = VideoPowerOn;
        break;
    case D1:        // Display Standby
        //vps = VideoPowerStandBy;
        //break;
    case D2:        // Display Suspend
        //vps = VideoPowerSuspend;
        //break;
    case D3:        // Display Off
    case D4:        // Display Off
        vps = VideoPowerOff;
        break;
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] PmToVideoPowerState() : Unknown PM State %d\n\r"), pmDx));
        vps = VideoPowerOn;
        break;
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --PmToVideoPowerState() : %d\n\r"), vps));

    return vps;
}

// this routine maps video power states to PM power states.
CEDEVICE_POWER_STATE
VideoToPmPowerState(VIDEO_POWER_STATE vps)
{
    CEDEVICE_POWER_STATE pmDx;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] ++VideoToPmPowerState(%d)\n\r"), vps));

    switch(vps)
    {
    case VideoPowerOn:
        pmDx = D0;
        break;
    case VideoPowerStandBy:
        pmDx = D1;
        break;
    case VideoPowerSuspend:
        pmDx = (CEDEVICE_POWER_STATE)D2;
        break;
    case VideoPowerOff:
        pmDx = (CEDEVICE_POWER_STATE)D4;
        break;
    default:
        RETAIL_DISP_MSG(DISP_ZONE_ERROR, (_T("[DISPDRV:ERR] VideoToPmPowerState() : Unknown Video State %d\n\r"), vps));
        pmDx = D0;
        break;
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER, (_T("[DISPDRV] --VideoToPmPowerState() : %d\n\r"), pmDx));

    return pmDx;
}


#ifdef SUPPORT_APM_DISP

void
SMDKDisp::Disp_power_set_APM
(CEDEVICE_POWER_STATE APM_POWER_STATUS)
{
    // 3. Message Queue notify when the device power state is changed
    //    Before sending Msg to power control, you should confirm the power state from the MS Power manager
    //      To confirm the power state you should call the DevicePowerNotify(),
    //                      and receive the confirm message "IOCTL_POWER_SET" from MS Power manager

    txmqParamDisp.bLPModeSupport = FALSE;
    txmqParamDisp.dwDeviceID = IRQ_LCD1;  // ex) IRQ_EINT31
    txmqParamDisp.dwMsg = DTOP_POWER_SET;    // This message type is also defined in bsp_args.h
    txmqParamDisp.dwLParam = APM_POWER_STATUS;
    txmqParamDisp.dwRParam = 0;

    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]++%s()\n\r"), _T(__FUNCTION__)));

    if(!WriteMsgQueue(PWCmsgQDisp, &txmqParamDisp, sizeof(MSG_DEV_STATE), INFINITE, 0))
    {
        RETAIL_DISP_MSG(DISP_ZONE_ERROR,(_T(" [DISPDRV:ERR] %s : WriteMsgQueue Error(0x%x)\r\n"),_T(__FUNCTION__),GetLastError()));
    }

    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]--%s()\n\r"), _T(__FUNCTION__)));

    return;

}

void
SMDKDisp::
Disp_power_init_APM()
{

    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]++%s()\n\r"), _T(__FUNCTION__)));

    // 2. Message Queue initialization for Device Power State transition
    memset((void *)&msgOptionsDisp, 0x0, sizeof(msgOptionsDisp));
    msgOptionsDisp.dwSize = sizeof(MSGQUEUEOPTIONS);
    msgOptionsDisp.dwFlags = 0;
    msgOptionsDisp.dwMaxMessages = 1024;        // Max number of MSG queue entries
    msgOptionsDisp.cbMaxMessage = sizeof(MSG_DEV_STATE);
    msgOptionsDisp.bReadAccess = FALSE;     // Write Only

    PWCmsgQDisp = CreateMsgQueue(OEMPM_MSGQ_NAME, &msgOptionsDisp);

    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]--%s()\n\r"), _T(__FUNCTION__)));

    return;
}

void
SMDKDisp::
Disp_power_deinit_APM()
{
    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]++%s()\n\r"), _T(__FUNCTION__)));
    CloseMsgQueue(PWCmsgQDisp);
    RETAIL_DISP_MSG(DISP_ZONE_ENTER,(_T("[DISPDRV]--%s()\n\r"), _T(__FUNCTION__)));
}

#endif // SUPPORT_APM_DISP

