//
// 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:    stda_context.c

Abstract:       Implementation of stda context Library
                This module implements Middle Level HW control

Functions:


Notes:


--*/

#include <windows.h>
#include <bsp.h>    // for reference HCLK, ECLK
#include <register_map.h>
#include "stda_common.h"
#include "stda_resource.h"
#include "stda_tvout_if.h"
#include "stda_interrupt.h"
#include "stda_video_layer.h"
#include "stda_grp.h"
#include "libedid.h"
#include "stda_context.h"
#include "stda_context_internal.h"
#include "tvout_board_dep.h"
#include <DrvLib_mem.h>
#include "stda_hdmi.h"

/*============================================================================*/
// STDA context functions
/*============================================================================*/


BOOL
STDA_initialize_tvout_engine
(void)
{
	STDAContext *pCtxt;
	
	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_initialize_tvout_engine()\r\n")));

	pCtxt = STDA_get_context();
	
	// Clear Context
	STDA_initialize_context();
	STDA_initialize_power_context();

	// map device SFR address
	if (STDA_map_device_address() == FALSE)
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_initialize_video_engine() : STDA_map_device_address() Failed\r\n")));
		goto CleanUp;
	}

	// Initialize SFR Address of Sub Module
	Sdout_initialize_register_address((void *) pCtxt->pSDoutReg);
	VMixer_initialize_register_address((void *) pCtxt->pVMReg);
	VProc_initialize_register_address((void *) pCtxt->pVPReg);

	Tvout_clk_initialize_register_address((void *) pCtxt->pCmuClkCon, (void *) pCtxt->pCmuMiscCon);
	Tvout_power_initialize_register_address((void *) pCtxt->pPmuPmCon, (void *) pCtxt->pPmuMiscCon);

	HDMI_initialize_register_address((void *) pCtxt->pHDMISSReg, 
								(void *) pCtxt->pHDMICoreReg, 
								(void *)pCtxt->pHDCPReg,
								(void *)pCtxt->pGpioReg,
								(void *)pCtxt->pCmuClkCon,
								(void *)pCtxt->pHDMIIICReg,
								(void *)pCtxt->pHDMITGReg);

	Tvout_board_dep_initialize_register_address((void *)pCtxt->pGpioReg);

	if(HDMIInit(pCtxt->pHDMISSReg, 
		pCtxt->pHDMICoreReg, 
		pCtxt->pHDCPReg,
		pCtxt->pHDMIEfuseReg,
		pCtxt->pIISReg, 
		pCtxt->pSPDIFReg,
		pCtxt->pCmuClkCon,
		pCtxt->pHDMIIICReg) != 1)
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_initialize_video_engine() : HDMIInit() Failed\r\n")));
		goto CleanUp;

	}

	// Intialize interrupt
	if (STDA_interrupt_initialize_interrupt() == FALSE)
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_initialize_video_engine() : STDA_intialize_interrupt() Failed\r\n")));
		goto CleanUp;
	}

	// Create Interrupt Thread
	if (STDA_interrupt_initialize_thread() == FALSE)
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_initialize_video_engine() : STDA_initialize_thread() Failed\r\n")));
		goto CleanUp;
	}


	// Power & Clock Off
	if(Tvout_power_get_power_status())
	{
		TVout_power_off();
		Tvout_clk_stop();
	}

	//HDMI Phy Off
#if HDMIPHY_ON_OFF	
	Tvout_clk_set_clk_src_init();

//	Tvout_clk_set_mixer_src(TVOUT_MIXER_CLK_SRCCLK_HDMI_PHY);
//	TVout_clk_set_hdmi_phy_con_onoff();
//	Tvout_clk_set_hdmi_clk_onoff(TRUE);
	TVout_clk_set_hdmi_i2c_phy_clk_onoff(TRUE);
//	Tvout_power_set_hdmi_div(0x96);
	Tvout_power_set_hdmi_en(TRUE);

	SetHDMIPHYOnOff(FALSE);		
	
	Tvout_power_set_hdmi_en(FALSE);
	TVout_clk_set_hdmi_i2c_phy_clk_onoff(FALSE);


#endif


#ifdef SUPPORT_APM_TVD
	TVout_power_init_APM();
#endif

	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_initialize_tvout_engine()\r\n")));

	return TRUE;

	CleanUp:

	STDA_deinitialize_tvout_engine();

	DBGMSG(TV_USR1,(_T("[STDA:ERR] --STDA_initialize_tvout_engine() : Failed\r\n")));


	return FALSE;
}


void
STDA_deinitialize_tvout_engine
(void)
{

	STDAContext *pCtxt;
	pCtxt = STDA_get_context();

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_deinitialize_tvout_engine()\r\n")));

	STDA_deinitialize_context();
	STDA_deinitialize_power_context();
	STDA_unmap_device_address();
	STDA_interrupt_deinitialize_interrupt();
	STDA_interrupt_deinitialize_thread();

	Tvout_board_dep_deinitialize_register_address((void *)pCtxt->pGpioReg);

#ifdef SUPPORT_APM_TVD
	TVout_power_deinit_APM();
#endif
	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_deinitialize_tvout_engine()\r\n")));
}

STDAContext*
STDA_get_context
(void)
{
	return &g_tSTDACtxt;
}

STDAPowerContext*
STDA_get_power_context
(void)
{
	return &g_tSTDAPwrCtxt;
}

BOOL STDA_map_device_address(void)
{
	STDAContext *pCtxt;
	PHYSICAL_ADDRESS    ioPhysicalBase = { 0,0};

	DBGMSG(TV_FUNC,(_T("[STDA] STDA_map_device_address\r\n")));

	pCtxt = STDA_get_context();

	pCtxt->pVPReg = 
		(VP_REG *)DrvLib_MapIoSpace(BASE_REG_PA_VP, 
									sizeof(VP_REG), 
									FALSE);

	if (pCtxt->pVPReg == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pVMReg = 
		(VMIXER_REG *)DrvLib_MapIoSpace(BASE_REG_PA_MIXER, 
										sizeof(VMIXER_REG), 
										FALSE);

	if (pCtxt->pVMReg == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pSDoutReg = 
		(SDOUT_REG *)DrvLib_MapIoSpace(BASE_REG_PA_TVENC, 
									sizeof(SDOUT_REG), 
									FALSE);

	if (pCtxt->pSDoutReg == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pHDMISSReg = 
		(HDMI_SS_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS, 
										sizeof(HDMI_SS_REG), 
										FALSE);

	if (pCtxt->pHDMISSReg == NULL)
	{
		goto CleanUp;
	}


	pCtxt->pHDMICoreReg = 
		(HDMI_CORE_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS+0x10000, 
										sizeof(HDMI_CORE_REG), 
										FALSE);

	if (pCtxt->pHDMICoreReg == NULL)
	{
		goto CleanUp;
	}


	pCtxt->pHDMITGReg = 
		(HDMI_TG_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS+0x50000, 
										sizeof(HDMI_TG_REG), 
										FALSE);

	if (pCtxt->pHDMITGReg == NULL)
	{
		goto CleanUp;
	}


	pCtxt->pHDMIEfuseReg = 
		(HDMI_EFUSE_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS+0x60000, 
										sizeof(HDMI_EFUSE_REG), 
										FALSE);

	if (pCtxt->pHDMIEfuseReg == NULL)
	{
		goto CleanUp;
	}



	pCtxt->pHDCPReg = 
		(HDMI_HDCP_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS+0x10000 + 0x600, 
										sizeof(HDMI_HDCP_REG), 
										FALSE);

	if (pCtxt->pHDCPReg == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pIISReg= 
		(HDMI_I2S_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS + 0x40000, 
										sizeof(HDMI_I2S_REG), 
										FALSE); 

	if (pCtxt->pIISReg == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pSPDIFReg= 
		(HDMI_SPDIF_REG *)DrvLib_MapIoSpace(BASE_REG_PA_HDMISS + 0x30000, 
										sizeof(HDMI_SPDIF_REG), 
										FALSE); 

	if (pCtxt->pSPDIFReg == NULL)
	{
		goto CleanUp;
	}




	pCtxt->pHDMIIICReg = 
		(IIC_REG *)DrvLib_MapIoSpace(BASE_REG_PA_I2C_HDMI_PHY, 
										sizeof(IIC_REG), 
										FALSE); 

	if (pCtxt->pHDMIIICReg == NULL)
	{
		goto CleanUp;
	}



	



	pCtxt->pCmuClkCon = 
		(CMU_CLK_REG *)DrvLib_MapIoSpace(BASE_REG_PA_CMU_CLK, 
										sizeof(CMU_CLK_REG), 
										FALSE); 

	if (pCtxt->pCmuClkCon == NULL)
	{
		goto CleanUp;
	}


	pCtxt->pCmuMiscCon = 
		(CMU_MISC_REG *)DrvLib_MapIoSpace(BASE_REG_PA_CMU_MISC, 
										sizeof(CMU_MISC_REG), 
										FALSE); 

	if (pCtxt->pCmuMiscCon == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pPmuPmCon = 
		(PMU_PM_REG *)DrvLib_MapIoSpace(BASE_REG_PA_PMU_PM, 
										sizeof(PMU_PM_REG), 
										FALSE); 

	if (pCtxt->pPmuPmCon == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pPmuMiscCon = 
		(PMU_MISC_REG *)DrvLib_MapIoSpace(BASE_REG_PA_PMU_MISC, 
										sizeof(PMU_MISC_REG), 
										FALSE); 

	if (pCtxt->pPmuMiscCon == NULL)
	{
		goto CleanUp;
	}

	pCtxt->pGpioReg = 
		(GPIO_REG *)DrvLib_MapIoSpace(BASE_REG_PA_GPIO, 
										sizeof(GPIO_REG), 
										FALSE); 

	if (pCtxt->pGpioReg == NULL)
	{
		goto CleanUp;
	}


	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pSDoutReg = 0x%08x\n\r"), pCtxt->pSDoutReg));
	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pVPReg = 0x%08x\n\r"), pCtxt->pVPReg));
	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pVMReg = 0x%08x\n\r"), pCtxt->pVMReg));

	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pCmuClkCon = 0x%08x\n\r"), pCtxt->pCmuClkCon));    
	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pCmuMiscCon = 0x%08x\n\r"), pCtxt->pCmuMiscCon));    

	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pPmuPmCon = 0x%08x\n\r"), pCtxt->pPmuPmCon));    
	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pPmuMiscCon = 0x%08x\n\r"), pCtxt->pPmuMiscCon));       

	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pHDMISSReg = 0x%08x\n\r"), pCtxt->pHDMISSReg));       
	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pHDMICoreReg = 0x%08x\n\r"), pCtxt->pHDMICoreReg));       

	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pHDMIIICReg = 0x%08x\n\r"), pCtxt->pHDMIIICReg));       

	DBGMSG(TV_INFO, (_T("[STDA] pCtxt->pGpioReg = 0x%08x\n\r"), pCtxt->pGpioReg));       

	DBGMSG(TV_INFO,(_T("[STDA] STDA_map_device_address\r\n")));

	return TRUE;

CleanUp:

	DBGMSG(TV_USR1,(_T("[STDA:ERR] Failed, ioPhysicalBase(0x%x,0x%x)\r\n"), ioPhysicalBase.LowPart, ioPhysicalBase.HighPart));

	return FALSE;
}

void STDA_unmap_device_address(void)
{
	STDAContext *pCtxt;

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_unmap_device_address()\r\n")));

	pCtxt = STDA_get_context();


	if (pCtxt->pVPReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pVPReg);
		pCtxt->pVPReg = NULL;
	}

	if (pCtxt->pVMReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pVMReg);
		pCtxt->pVMReg = NULL;
	}

	if (pCtxt->pSDoutReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pSDoutReg);
		pCtxt->pSDoutReg = NULL;
	}

	if (pCtxt->pHDMISSReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDMISSReg);
		pCtxt->pHDMISSReg = NULL;
	}

	if (pCtxt->pHDMICoreReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDMICoreReg);
		pCtxt->pHDMICoreReg = NULL;
	}

	if (pCtxt->pHDMITGReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDMITGReg);
		pCtxt->pHDMITGReg = NULL;
	}

	if (pCtxt->pHDCPReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDCPReg);
		pCtxt->pHDCPReg = NULL;
	}

	if (pCtxt->pHDMIEfuseReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDMIEfuseReg);
		pCtxt->pHDMIEfuseReg = NULL;
	}


	if (pCtxt->pIISReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pIISReg);
		pCtxt->pIISReg = NULL;
	}

	if (pCtxt->pSPDIFReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pSPDIFReg);
		pCtxt->pSPDIFReg = NULL;
	}
	



	if (pCtxt->pHDMIIICReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pHDMIIICReg);
		pCtxt->pHDMIIICReg = NULL;
	}




	if (pCtxt->pCmuClkCon != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pCmuClkCon);
		pCtxt->pCmuClkCon = NULL;
	}

	if (pCtxt->pCmuMiscCon != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pCmuMiscCon);
		pCtxt->pCmuMiscCon = NULL;
	}

	if (pCtxt->pPmuPmCon != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pPmuPmCon);
		pCtxt->pPmuPmCon = NULL;
	}

	if (pCtxt->pPmuMiscCon != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pPmuMiscCon);
		pCtxt->pPmuMiscCon = NULL;
	}

	if (pCtxt->pGpioReg != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)pCtxt->pGpioReg);
		pCtxt->pGpioReg = NULL;
	}


	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_unmap_device_address()\r\n")));

}


void 
STDA_initialize_context
(void)
{
	STDAContext *pCtxt;

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_initialize_context()\r\n")));

	pCtxt = STDA_get_context();

	// Clear Context
	memset(pCtxt, 0x0, sizeof(STDAContext));

	pCtxt->dwSignature = TVOUT_DRIVER_SIGNITURE;
	pCtxt->dwLastOpenContext = TVOUT_DRIVER_SIGNITURE;

	pCtxt->dwSysIntrVM = SYSINTR_UNDEFINED;
	pCtxt->dwSysIntrSDout = SYSINTR_UNDEFINED;
	pCtxt->dwSysIntrHDMI = SYSINTR_UNDEFINED;
	pCtxt->dwSysIntrHDMII2C = SYSINTR_UNDEFINED;
	pCtxt->hInterruptVM = INVALID_HANDLE_VALUE;
	pCtxt->hInterruptSDout = INVALID_HANDLE_VALUE;
	pCtxt->hInterruptHDMI = INVALID_HANDLE_VALUE;
	pCtxt->hInterruptHDMII2C = INVALID_HANDLE_VALUE;

	// Critical Section for IOCTL
	InitializeCriticalSection(&pCtxt->csProc);
	InitializeCriticalSection(&pCtxt->csProcWaitHPD);
	InitializeCriticalSection(&pCtxt->csProcWaitHPDVP);
	InitializeCriticalSection(&pCtxt->csProcWaitHPDGRP0);
	InitializeCriticalSection(&pCtxt->csProcWaitHPDGRP1);
	InitializeCriticalSection(&pCtxt->csProcHPDInfo);
	InitializeCriticalSection(&pCtxt->csProcIntr);

	// GRP0 Command Context
	InitializeCriticalSection(&pCtxt->GRP0pCmdCtxt.csCmd);
	pCtxt->GRP0pCmdCtxt.bCmdSetSrcBuffer = FALSE;        // Depricated
	pCtxt->GRP0pCmdCtxt.bCmdSetOffset = FALSE;

	// GRP1 Command Context
	InitializeCriticalSection(&pCtxt->GRP1pCmdCtxt.csCmd);
	pCtxt->GRP1pCmdCtxt.bCmdSetSrcBuffer = FALSE;        // Depricated
	pCtxt->GRP1pCmdCtxt.bCmdSetOffset = FALSE;

	// Command Event
	pCtxt->hSDoutCmdDone = CreateEvent(NULL, TRUE, FALSE, NULL);    // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hVMCmdDone = CreateEvent(NULL, TRUE, FALSE, NULL);       // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHDMICmdDone = CreateEvent(NULL, TRUE, FALSE, NULL);     // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHPDCmdDone = CreateEvent(NULL, TRUE, FALSE, NULL);     // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHPDCmdDoneForVP= CreateEvent(NULL, TRUE, FALSE, NULL);     // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHPDCmdDoneForGRP0= CreateEvent(NULL, TRUE, FALSE, NULL);     // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHPDCmdDoneForGRP1= CreateEvent(NULL, TRUE, FALSE, NULL);     // Manual Reset, You should call ResetEvent() or use PulseEvent() Only
	pCtxt->hHDMII2CCmdDone = CreateEvent(NULL, TRUE, FALSE, NULL);  // Manual Reset, You should call ResetEvent() or use PulseEvent() Only

	// Disable HW status Flags
	pCtxt->bVPEnable = FALSE;
	pCtxt->bGRPEnable[0] = FALSE;
	pCtxt->bGRPEnable[1] = FALSE;
	pCtxt->bSDoutEnable = FALSE;
	pCtxt->bHDMIEnable = FALSE;

	// SFR
	pCtxt->pVPReg = NULL;
	pCtxt->pVMReg = NULL;
	pCtxt->pSDoutReg = NULL;

	pCtxt->pHDMISSReg = NULL;
	pCtxt->pHDMICoreReg = NULL;
	pCtxt->pHDMITGReg = NULL;
	pCtxt->pHDCPReg = NULL;
	
	pCtxt->pHDMIIICReg = NULL;
	
	pCtxt->pCmuClkCon = NULL;
	pCtxt->pCmuMiscCon = NULL;
	pCtxt->pPmuPmCon = NULL;
	pCtxt->pPmuMiscCon = NULL;

	pCtxt->pGpioReg = NULL;

	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_initialize_context()\r\n")));
}


void
STDA_deinitialize_context
(void)
{
	STDAContext *pCtxt;

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_deinitialize_context()\r\n")));

	pCtxt = STDA_get_context();

	// GRP0 Command Context
	DeleteCriticalSection(&pCtxt->GRP0pCmdCtxt.csCmd);

	// GRP1 Command Context
	DeleteCriticalSection(&pCtxt->GRP1pCmdCtxt.csCmd);

	// Critical Section for IOCTL
	DeleteCriticalSection(&pCtxt->csProc);
	DeleteCriticalSection(&pCtxt->csProcWaitHPD);
	DeleteCriticalSection(&pCtxt->csProcWaitHPDVP);
	DeleteCriticalSection(&pCtxt->csProcWaitHPDGRP0);
	DeleteCriticalSection(&pCtxt->csProcWaitHPDGRP1);
	DeleteCriticalSection(&pCtxt->csProcHPDInfo);
	DeleteCriticalSection(&pCtxt->csProcIntr);

	if (pCtxt->hSDoutCmdDone != NULL)
	{
		CloseHandle(pCtxt->hSDoutCmdDone);
	}

	if (pCtxt->hVMCmdDone != NULL)
	{
		CloseHandle(pCtxt->hVMCmdDone);
	}

	if (pCtxt->hHDMICmdDone != NULL)
	{
		CloseHandle(pCtxt->hHDMICmdDone);
	}

	if (pCtxt->hHPDCmdDone != NULL)
	{
		CloseHandle(pCtxt->hHPDCmdDone);
	}

	if (pCtxt->hHPDCmdDoneForVP!= NULL)
	{
		CloseHandle(pCtxt->hHPDCmdDoneForVP);
	}

	if (pCtxt->hHPDCmdDoneForGRP0!= NULL)
	{
		CloseHandle(pCtxt->hHPDCmdDoneForGRP0);
	}

	if (pCtxt->hHPDCmdDoneForGRP1!= NULL)
	{
		CloseHandle(pCtxt->hHPDCmdDoneForGRP1);
	}

	if (pCtxt->hHDMII2CCmdDone != NULL)
	{
		CloseHandle(pCtxt->hHDMII2CCmdDone);
	}

	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_deinitialize_context()\r\n")));
}

DWORD
STDA_get_api_function_code
(DWORD dwCode)
{
//#define CTL_CODE( DeviceType, Function, Method, Access ) ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
	return ((dwCode>>2)&0xFFF);
}

DWORD
STDA_get_driver_signature
(void)
{
	return (STDA_get_context()->dwSignature);
}

DWORD
STDA_add_open_context
(void)
{
	STDAContext *pCtxt = STDA_get_context();

	pCtxt->dwOpenCount++;
	pCtxt->dwLastOpenContext++;

	DBGMSG(TV_INFO,(_T("[STDA] STDA_add_open_context() : OpenCount = %d, OpenContext = 0x%08x\r\n"), pCtxt->dwOpenCount, pCtxt->dwLastOpenContext));

	return (pCtxt->dwLastOpenContext);
}

BOOL
STDA_remove_open_context
(DWORD dwOpenContext)
{
	STDAContext *pCtxt = STDA_get_context();

	if (pCtxt->dwOpenCount > 0)
	{
		// Release H/W Resource
		if (pCtxt->dwOccupantTVout == dwOpenContext) pCtxt->dwOccupantTVout = 0;
		if (pCtxt->dwOccupantVP == dwOpenContext) pCtxt->dwOccupantVP = 0;
		if (pCtxt->dwOccupantGRP0 == dwOpenContext) pCtxt->dwOccupantGRP0 = 0;
		if (pCtxt->dwOccupantGRP1 == dwOpenContext) pCtxt->dwOccupantGRP1 = 0;

		pCtxt->dwOpenCount--;

		DBGMSG(TV_FUNC,(_T("[STDA] STDA_remove_open_context(0x%08x) : OpenCount = %d\r\n"), pCtxt->dwLastOpenContext, pCtxt->dwOpenCount));

		return TRUE;
	}
	else
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_remove_open_context() : Current Open Count is 0 !!!\r\n")));

		return FALSE;
	}
}

DWORD
STDA_get_current_open_count
(void)
{
	return (STDA_get_context()->dwOpenCount);
}

/*============================================================================*/
// STDA power context functions
/*============================================================================*/

void STDA_initialize_power_context(void)
{
	STDAPowerContext *pPMCtxt;

	DBGMSG(TV_FUNC,(_T("[STDA] STDA_initialize_context()\r\n")));

	pPMCtxt = STDA_get_power_context();

	memset(pPMCtxt, 0x0, sizeof(STDAPowerContext));

	//Initialize Power Status
	pPMCtxt->powerState = D0;
	pPMCtxt->powerStateChange = D3;
	pPMCtxt->bChangePowerState = FALSE;

	//Initialize GRPx Layer Parameters to Default Values
	pPMCtxt->grpBurst = VM_BURST_16;
	pPMCtxt->grpEndian = TVOUT_LITTLE_ENDIAN_MODE;

	//Initialize Mixer Limiter Parameters
	//0xeb, 0x10, 0xf0, 0x10, 0x0 -> For SDTV

	pPMCtxt->uiVMLimitYUpper = 0xeb;
	pPMCtxt->uiVMLimitYLower = 0x10;
	pPMCtxt->uiVMLimitCUpper = 0xf0;
	pPMCtxt->uiVMLimitCUppe = 0x10;

	// Initialize BG Layer Parameters to Default Values
	pPMCtxt->tBGColor[0].uiColorY= 0;
	pPMCtxt->tBGColor[0].uiColorCb = 128;
	pPMCtxt->tBGColor[0].uiColorCr = 128;
	pPMCtxt->tBGColor[1].uiColorY= 0;
	pPMCtxt->tBGColor[1].uiColorCb = 128;
	pPMCtxt->tBGColor[1].uiColorCr = 128;
	pPMCtxt->tBGColor[2].uiColorY= 0;
	pPMCtxt->tBGColor[2].uiColorCb = 128;
	pPMCtxt->tBGColor[2].uiColorCr = 128;

	// Initialize Video Mixer Parameters to Default Values
	pPMCtxt->bVMCscCoefDefault = TRUE;

	// Initialize SDout Parameters to Default Values
	pPMCtxt->sdoutSyncPin = SDOUT_SYNC_SIG_YG;
	pPMCtxt->tSDoutVbi.bWssCVBS = TRUE;
//	pPMCtxt->tSDoutVbi.captionCVBS = SDOUT_INS_OTHERS;
	pPMCtxt->tSDoutVbi.captionCVBS = SDOUT_INS_2;
	pPMCtxt->tSDoutVbi.bWssYSideo = TRUE;
	pPMCtxt->tSDoutVbi.captionYSideo = SDOUT_INS_OTHERS;
	pPMCtxt->tSDoutVbi.bCgmsaRGB = TRUE;
	pPMCtxt->tSDoutVbi.bWssRGB = TRUE;
	pPMCtxt->tSDoutVbi.captionRGB = SDOUT_INS_OTHERS;
	pPMCtxt->tSDoutVbi.bCgmsaYPbPr = TRUE;
	pPMCtxt->tSDoutVbi.bWssYPbPr = TRUE;
	pPMCtxt->tSDoutVbi.captionYPbPr = SDOUT_INS_OTHERS;
	pPMCtxt->tSDoutOffsetGain[0].channel = SDOUT_CHANNEL_0;
	pPMCtxt->tSDoutOffsetGain[0].uiOffset = 0;
	pPMCtxt->tSDoutOffsetGain[0].uiGain = 0x800;
	pPMCtxt->tSDoutOffsetGain[1].channel = SDOUT_CHANNEL_1;
	pPMCtxt->tSDoutOffsetGain[1].uiOffset = 0;
	pPMCtxt->tSDoutOffsetGain[1].uiGain = 0x800;
	pPMCtxt->tSDoutOffsetGain[2].channel = SDOUT_CHANNEL_2;
	pPMCtxt->tSDoutOffsetGain[2].uiOffset = 0;
	pPMCtxt->tSDoutOffsetGain[2].uiGain = 0x800;
	pPMCtxt->tSDoutDelay.uiDelayY = 0x00;
	pPMCtxt->tSDoutDelay.uiOffsetVideoStart = 0xfa;
	pPMCtxt->tSDoutDelay.uiOffsetVideoEnd = 0x00;
	pPMCtxt->bSDoutColorSubCarrierPhaseAdjustment = FALSE;

	pPMCtxt->tSDoutBriHueSat.bBriHueSatAdj = FALSE;
	pPMCtxt->tSDoutBriHueSat.uiGainBrightness = 0x80;
	pPMCtxt->tSDoutBriHueSat.uiOffsetBrightness = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiGain0CbHueSaturation = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiGain1CbHueSaturation = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiGain0CrHueSaturation = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiGain1CrHueSaturation = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiOffsetCbHueSaturation = 0x00;
	pPMCtxt->tSDoutBriHueSat.uiOffsetCrHueSaturation = 0x00;
	pPMCtxt->bSDoutYPbPrComp = FALSE;
	pPMCtxt->tSDoutRGBCompen.bRGBcolorCompensation = FALSE;
	pPMCtxt->tSDoutRGBCompen.uiMaxRGBCube = 0xeb;
	pPMCtxt->tSDoutRGBCompen.uiMinRGBCube = 0x10;
	pPMCtxt->tSDoutCVBSCompen.bCVBSCcolorCompensaton = FALSE;
	pPMCtxt->tSDoutCVBSCompen.uiYLowerMid = 0x200;
	pPMCtxt->tSDoutCVBSCompen.uiYBottom = 0x000;
	pPMCtxt->tSDoutCVBSCompen.uiYTop = 0x3ff;
	pPMCtxt->tSDoutCVBSCompen.uiYUpperMid = 0x200;
	pPMCtxt->tSDoutCVBSCompen.uiRadius = 0x1ff;
	pPMCtxt->tSDoutSvideoCompen.bYCcolorCompensaton = FALSE;
	pPMCtxt->tSDoutSvideoCompen.uiYTop = 0x3ff;
	pPMCtxt->tSDoutSvideoCompen.uiYBottom = 0x000;
	pPMCtxt->tSDoutSvideoCompen.uiYCCylinder = 0x1ff;
	pPMCtxt->tSDoutCompPorch.ui525Back = 0x8a;
	pPMCtxt->tSDoutCompPorch.ui525Front = 0x359;
	pPMCtxt->tSDoutCompPorch.ui625Back = 0x96;
	pPMCtxt->tSDoutCompPorch.ui625Front = 0x35c;
	pPMCtxt->tSDoutRGBSync.syncType = SDOUT_VESA_RGB_SYNC_COMPOSITE;
	pPMCtxt->tSDoutRGBSync.vsyncActive = TVOUT_POL_ACTIVE_HIGH;
	pPMCtxt->tSDoutRGBSync.hsyncActive = TVOUT_POL_ACTIVE_HIGH;
	pPMCtxt->tSDoutXtalkCC[0].channel = SDOUT_CHANNEL_0;
	pPMCtxt->tSDoutXtalkCC[0].uiCoeff2 = 0;
	pPMCtxt->tSDoutXtalkCC[0].uiCoeff1 = 0;
	pPMCtxt->tSDoutXtalkCC[1].channel = SDOUT_CHANNEL_1;
	pPMCtxt->tSDoutXtalkCC[1].uiCoeff2 = 0;
	pPMCtxt->tSDoutXtalkCC[1].uiCoeff1 = 0;
	pPMCtxt->tSDoutXtalkCC[2].channel = SDOUT_CHANNEL_2;
	pPMCtxt->tSDoutXtalkCC[2].uiCoeff2 = 0;
	pPMCtxt->tSDoutXtalkCC[2].uiCoeff1 = 0;
	pPMCtxt->tSDoutClosedCapt.uiDisplayCC = 0;
	pPMCtxt->tSDoutClosedCapt.uiNonDisplayCC = 0;
	pPMCtxt->tSDoutWSS525.copyPermit = SDO_525_COPY_PERMIT;
	pPMCtxt->tSDoutWSS525.mvPsp = SDO_525_MV_PSP_OFF;
	pPMCtxt->tSDoutWSS525.copyInfo = SDO_525_COPY_INFO;
	pPMCtxt->tSDoutWSS525.bAnalogOn = FALSE;
	pPMCtxt->tSDoutWSS525.displayRatio = SDO_525_4_3_NORMAL;
	pPMCtxt->tSDoutWSS625.bSurrounfSound = FALSE;
	pPMCtxt->tSDoutWSS625.bCopyright = FALSE;
	pPMCtxt->tSDoutWSS625.bCopyProtection = FALSE;
	pPMCtxt->tSDoutWSS625.bTextSubtitles = FALSE;
	pPMCtxt->tSDoutWSS625.openSubtitles = SDO_625_NO_OPEN_SUBTITLES;
	pPMCtxt->tSDoutWSS625.cameraFilm = SDO_625_CAMERA;
	pPMCtxt->tSDoutWSS625.colorEncoding = SDO_625_NORMAL_PAL;
	pPMCtxt->tSDoutWSS625.bHelperSignal = FALSE;
	pPMCtxt->tSDoutWSS625.displayRatio = SDO_625_4_3_FULL_576;
	pPMCtxt->tSDoutCGMS525.copyPermit = SDO_525_COPY_PERMIT;
	pPMCtxt->tSDoutCGMS525.mvPsp = SDO_525_MV_PSP_OFF;
	pPMCtxt->tSDoutCGMS525.copyInfo = SDO_525_COPY_INFO;
	pPMCtxt->tSDoutCGMS525.bAnalogOn = FALSE;
	pPMCtxt->tSDoutCGMS525.displayRatio = SDO_525_4_3_NORMAL;
	pPMCtxt->tSDoutCGMS625.bSurrounfSound = FALSE;
	pPMCtxt->tSDoutCGMS625.bCopyright = FALSE;
	pPMCtxt->tSDoutCGMS625.bCopyProtection = FALSE;
	pPMCtxt->tSDoutCGMS625.bTextSubtitles = FALSE;
	pPMCtxt->tSDoutCGMS625.openSubtitles = SDO_625_NO_OPEN_SUBTITLES;
	pPMCtxt->tSDoutCGMS625.cameraFilm = SDO_625_CAMERA;
	pPMCtxt->tSDoutCGMS625.colorEncoding = SDO_625_NORMAL_PAL;
	pPMCtxt->tSDoutCGMS625.bHelperSignal = FALSE;
	pPMCtxt->tSDoutCGMS625.displayRatio = SDO_625_4_3_FULL_576;

	// Initialize HDMI video Parameters to Default Values
	pPMCtxt->tHdmiVideoBlueScreen.bEn = FALSE;
	pPMCtxt->tHdmiColorRange.ucYMin = 1;
	pPMCtxt->tHdmiColorRange.ucYMax = 254;
	pPMCtxt->tHdmiColorRange.ucCMin = 1;
	pPMCtxt->tHdmiColorRange.ucCMin = 254;
	pPMCtxt->tHdmiAviInfoFrame.transType = HDMI_DO_NOT_TANS;
	pPMCtxt->tHdmiAviInfoFrame.ucCheckSum = 0;
	pPMCtxt->tHdmiAviInfoFrame.pucData = pPMCtxt->ucAviByte;
	pPMCtxt->tHdmiMpgInfoFrame.transType = HDMI_DO_NOT_TANS;
	pPMCtxt->tHdmiMpgInfoFrame.ucCheckSum = 0;
	pPMCtxt->tHdmiMpgInfoFrame.pucData = pPMCtxt->ucMpgByte;
	memset((void *)(pPMCtxt->ucAviByte), 0, 13);
	memset((void *)(pPMCtxt->ucMpgByte), 0, 5);
	pPMCtxt->tHdmiTgCmd.bTimingCorrectionEn = FALSE;
	pPMCtxt->tHdmiTgCmd.bBT656SyncEn = FALSE;
	pPMCtxt->tHdmiTgCmd.bTgEn = FALSE;

	// Initialize HDMI Parameters to Default Values
	pPMCtxt->tHdmiSpdInfoFrame.transType = HDMI_DO_NOT_TANS;
	pPMCtxt->tHdmiSpdInfoFrame.pucSpdHeader = pPMCtxt->ucSpdHeader;
	pPMCtxt->tHdmiSpdInfoFrame.pucSpdData = pPMCtxt->ucSpdData;
	memset((void *)(pPMCtxt->ucSpdHeader), 0, 3);
	memset((void *)(pPMCtxt->ucSpdData), 0, 8);
	pPMCtxt->bHDCPEn = FALSE;
	pPMCtxt->hdmiAudioType = HDMI_AUDIO_NO;
	pPMCtxt->bAudioEn = TRUE;

	// Initialize Video Layer Parameters to Default Values
	pPMCtxt->uiVLSrcXFractStep = 0;
	pPMCtxt->vlFiledId = VPROC_TOP_FIELD;
	pPMCtxt->tVlOpMode.toggleID = VPROC_FILED_ID_TOGGLE_VSYNC;

	pPMCtxt->bVLPolyFilterDefault = TRUE;
	pPMCtxt->bVLByPassPostProcess = FALSE;


	pPMCtxt->tVLSharpness.uiThHNoise = 0x05;

	pPMCtxt->tVLSharpness.sharpness = VPROC_SHARPNESS_NO;

	pPMCtxt->uiVLBrightOffset = 0x00;

	pPMCtxt->tVLCscControl.bSubYOffsetEn = FALSE;
	pPMCtxt->tVLCscControl.bCscEn = FALSE;
	pPMCtxt->bVLCscCoefDefault = TRUE;
	pPMCtxt->tVLBCControl[0].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[1].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[2].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[3].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[4].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[5].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[6].eqNum = VProc_LINE_EQ_7+1;
	pPMCtxt->tVLBCControl[7].eqNum = VProc_LINE_EQ_7+1;

	pPMCtxt->uiVLBCControl = VProc_LINE_EQ_7+1;

}

void STDA_deinitialize_power_context(void)
{
	// Currently, Power Context is static global variable
	// So, we don't need to any deinit procedure
	DBGMSG(TV_FUNC, (_T("[STDA] STDA_deinitialize_power_context()\r\n")));
	return;
}

BOOL STDA_tvout_wakeup(void)
{
	STDAContext *pCtxt = STDA_get_context();
	STDAPowerContext *pPMCtxt = STDA_get_power_context();

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_tvout_wakeup()\r\n")));

	//Check powerState -> D0
	pPMCtxt->powerState = D0;

	if(!(pPMCtxt->bTVoutOutputEnable))
	{
		DBGMSG(TV_FUNC,(_T("[STDA:INF] STDA_tvout_wakeup() : TVout is Disable\r\n")));
		return TRUE;
	}

	//-------------------------------
	// Start TVout I/F
	//-------------------------------
	if(!(STDA_TVoutIF_start()))
	{
		DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_wakeup() : Failed\r\n")));
		return FALSE;
	}

	switch(pPMCtxt->tTvOutputParam.outMode)
	{
		case TVOUT_OUTPUT_HDMI:
		case TVOUT_OUTPUT_DVI:
		case TVOUT_OUTPUT_HDMI_YCBCR:
			pCtxt->bHDMIEnable = TRUE;
			break;
		default:
			pCtxt->bSDoutEnable = TRUE;
			break;
	}

	//---------------------------
	// Video Layer Reconfiguration
	//---------------------------
	if (pPMCtxt->bVPLayerEnable)
	{
		if(!(STDA_VideoLayer_start()))
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_wakeup() : Failed\r\n")));
			return FALSE;
		}
		
		pCtxt->bVPEnable = TRUE;
	}

	//---------------------------
	// GRP0 Layer Reconfiguration
	//---------------------------
	if (pPMCtxt->bGRPLayerEnable[0])
	{
		if(!(STDA_Grp_start(VM_GPR0_LAYER)))
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_wakeup() : Failed\r\n")));
			return FALSE;
		}

		pCtxt->bGRPEnable[0] = TRUE;
	}

	//---------------------------
	// GRP1 Layer Reconfiguration
	//---------------------------
	if (pPMCtxt->bGRPLayerEnable[1])
	{
		if(!(STDA_Grp_start(VM_GPR1_LAYER)))
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_wakeup() : Failed\r\n")));
			return FALSE;
		}

		pCtxt->bGRPEnable[1] = TRUE;
	}

	if((pCtxt->bVPEnable == TRUE)||
		(pCtxt->bGRPEnable[0] == TRUE)||
		(pCtxt->bGRPEnable[1] == TRUE)||
		(pPMCtxt->bTVoutOutputEnable))
	{
		pPMCtxt->powerState = D0;
	}
	else
	{
		//It should DEAD_CODE
		pPMCtxt->powerState = D3;
	}

	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_tvout_wakeup()\r\n")));

	return TRUE;
}

BOOL STDA_tvout_sleep(void)
{
	STDAContext *pCtxt = STDA_get_context();
	STDAPowerContext *pPMCtxt = STDA_get_power_context();

	DBGMSG(TV_FUNC,(_T("[STDA] ++STDA_tvout_sleep()\r\n")));

	if(!pPMCtxt->bTVoutOutputEnable)
	{
		DBGMSG(TV_FUNC,(_T("[STDA:INF] STDA_tvout_sleep() : TVout is Disable\r\n")));
		return TRUE;
	}

	//-----------------------
	// Disable Video Engine HW
	//-----------------------

	// Disable Video Layer output
	if (pPMCtxt->bVPLayerEnable)
	{
		if(STDA_VideoLayer_stop())
		{
			pPMCtxt->bVPLayerEnable = TRUE;
		}
		else
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_sleep() : STDA_VideoLayer_stop() Failed\r\n")));
			return FALSE;
		}
	}

	// Disable GRP0 Layer output
	if (pPMCtxt->bGRPLayerEnable[0])
	{
		if(STDA_Grp_stop(VM_GPR0_LAYER))
		{
			pPMCtxt->bGRPLayerEnable[0] = TRUE;
		}
		else
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_sleep() : STDA_Grp_stop(0) Failed\r\n")));
			return FALSE;
		}
	}

	// Disable GRP1 Layer output
	if (pPMCtxt->bGRPLayerEnable[1])
	{
		if(STDA_Grp_stop(VM_GPR1_LAYER))
		{
			pPMCtxt->bGRPLayerEnable[1] = TRUE;
		}
		else
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_sleep() : STDA_Grp_stop(1) Failed\r\n")));
			return FALSE;
		}
	}

	// Disable TVout I/F
	if (pPMCtxt->bTVoutOutputEnable)
	{
		if(STDA_TVoutIF_stop())
		{
			pPMCtxt->bTVoutOutputEnable = TRUE;
			pPMCtxt->bTvOutputParam = TRUE;
		}
		else
		{
			DBGMSG(TV_USR1,(_T("[STDA:ERR] STDA_tvout_sleep() : STDA_TVoutIF_stop() Failed\r\n")));
			return FALSE;
		}
	}

	// Disable HW status Flags
	pCtxt->bVPEnable = FALSE;
	pCtxt->bGRPEnable[0] = FALSE;
	pCtxt->bGRPEnable[1] = FALSE;
	pCtxt->bSDoutEnable = FALSE;
	pCtxt->bHDMIEnable = FALSE;

	DBGMSG(TV_FUNC,(_T("[STDA] --STDA_tvout_sleep()\r\n")));

	return TRUE;
}

/*============================================================================*/

