//
// Copyright  2009 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_interrupt.c

Abstract:       Implementation of tvout interrupt Library
                This module implements Low Level HW control

Functions:


Notes:


--*/

#include <windows.h>
#include <bsp.h>    // for reference HCLK, ECLK
#include <register_map.h>
#include "tvout_global.h"
#include "stda_common.h"
#include "stda_context.h"
#include "stda_hdmi.h"
#include "stda_interrupt.h"

// global variables

/*============================================================================*/
// Pre-defined functions
/*============================================================================*/



BOOL
STDA_interrupt_initialize_interrupt
(void)
	{

#if (USE_VMIXER_INTERRUPT || USE_SDOUT_INTERRUPT || USE_HDMI_INTERRUPT)
	STDAContext *pCtxt = STDA_get_context();
	STDAPowerContext *pPMCtxt = STDA_get_power_context();
	DWORD dwIRQ;
#endif

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_initialize_interrupt()\n\r")));

#if USE_SDOUT_INTERRUPT
	// Interrupt for SDout (Vsync Interrupt)
	dwIRQ = IRQ_TVENC;
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(DWORD), &(pCtxt->dwSysIntrSDout), sizeof(DWORD), NULL))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : IOCTL_HAL_REQUEST_SYSINTR dwSysIntrSDout Failed\n\r")));
		pCtxt->dwSysIntrSDout = SYSINTR_UNDEFINED;
		goto CleanUp;
	}

	pCtxt->hInterruptSDout = CreateEvent(NULL, FALSE, FALSE, NULL);
	if(NULL == pCtxt->hInterruptSDout)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : CreateEvent() hInterruptSDout Failed \n\r")));
		goto CleanUp;
	}

	if (!(InterruptInitialize(pCtxt->dwSysIntrSDout, pCtxt->hInterruptSDout, 0, 0)))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : InterruptInitialize() hInterruptSDout Failed \n\r")));
		goto CleanUp;
	}
#endif

#if USE_HDMI_INTERRUPT
	// HDMI D/D is not maked
	// Interrupt for HDMI
	dwIRQ = IRQ_HDMI;
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(DWORD), &(pCtxt->dwSysIntrHDMI), sizeof(DWORD), NULL))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : IOCTL_HAL_REQUEST_SYSINTR dwSysIntrHDMI Failed\n\r")));
		pCtxt->dwSysIntrHDMI = SYSINTR_UNDEFINED;
		goto CleanUp;
	}

	pCtxt->hInterruptHDMI = CreateEvent(NULL, FALSE, FALSE, NULL);
	if(NULL == pCtxt->hInterruptHDMI)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : CreateEvent() hInterruptHDMI Failed \n\r")));
		goto CleanUp;
	}

	if (!(InterruptInitialize(pCtxt->dwSysIntrHDMI, pCtxt->hInterruptHDMI, 0, 0)))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : InterruptInitialize() hInterruptHDMI Failed \n\r")));
		goto CleanUp;
	}

	// Interrupt for HPD
	////////////////////////////////////////////////////////////////////////////////
	// HPD use EINT5 in SMDKV210
	////////////////////////////////////////////////////////////////////////////////
	if(pCtxt->pGpioReg == NULL)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : pCtxt->pGpioReg NULL pointer parameter\n\r")));
		goto CleanUp;
	}

	//pPMCtxt->bHPDStatus = (Get_PinData(pCtxt->pGpioReg, HDMI_HPD_EINT))? TRUE:FALSE;
	pPMCtxt->bHPDStatus = (Get_PinData(pCtxt->pGpioReg, HDMI_HPD_EINT))? FALSE:TRUE; // modified by terry for x210 

	DBGMSG(TV_USR1,(_T("pPMCtxt->bHPDStatus = (%d)\n\r"),pPMCtxt->bHPDStatus));

	// added by terry for test
	RETAILMSG(1,(_T("STDA_interrupt_initialize_interrupt    pPMCtxt->bHPDStatus = (%d)\n\r"),pPMCtxt->bHPDStatus));



	
	dwIRQ = IRQ_EINT13;
	////////////////////////////////////////////////////////////////////////////////
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(DWORD), &(pCtxt->dwSysIntrHPD), sizeof(DWORD), NULL))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : IOCTL_HAL_REQUEST_SYSINTR dwSysIntrHPD Failed\n\r")));
		pCtxt->dwSysIntrHPD = SYSINTR_UNDEFINED;
		goto CleanUp;
	}

	pCtxt->hInterruptHPD = CreateEvent(NULL, FALSE, FALSE, NULL);
	if(NULL == pCtxt->hInterruptHPD)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : CreateEvent() hInterruptHPD Failed \n\r")));
		goto CleanUp;
	}

	if (!(InterruptInitialize(pCtxt->dwSysIntrHPD, pCtxt->hInterruptHPD, 0, 0)))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : InterruptInitialize() hInterruptHPD Failed \n\r")));
		goto CleanUp;
	}


	//Default HDMI is not run -> EINT
	STDA_HDMI_HpdSetMode(HDMI_EINT_MODE, TRUE);

#endif

#if USE_VMIXER_INTERRUPT
	// Video Mixer Interrupt is used only for debug
	// Interrupt for Video Mixer (fifo under-run for debug)
	dwIRQ = IRQ_MIXER;
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(DWORD), &(pCtxt->dwSysIntrVM), sizeof(DWORD), NULL))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : IOCTL_HAL_REQUEST_SYSINTR dwSysIntrVM Failed\n\r")));
		pCtxt->dwSysIntrVM = SYSINTR_UNDEFINED;
		goto CleanUp;
	}

	pCtxt->hInterruptVM = CreateEvent(NULL, FALSE, FALSE, NULL);
	if(NULL == pCtxt->hInterruptVM)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : CreateEvent() hInterruptVM Failed \n\r")));
		goto CleanUp;
	}

	if (!(InterruptInitialize(pCtxt->dwSysIntrVM, pCtxt->hInterruptVM, 0, 0)))
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_interrupt() : InterruptInitialize() hInterruptVM Failed \n\r")));
		goto CleanUp;
	}
#endif

	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_initialize_interrupt()\n\r")));

	return TRUE;

#if (USE_VMIXER_INTERRUPT || USE_SDOUT_INTERRUPT || USE_HDMI_INTERRUPT)
CleanUp:

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

	return FALSE;
#endif
	}

void
STDA_interrupt_deinitialize_interrupt
(void)
{

	pSTDAContext pCtxt;

	return;


	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_deinitialize_interrupt()\n\r")));

	pCtxt = STDA_get_context();

	// Interrupt for SDout (Vsync Interrupt)
	if (pCtxt->dwSysIntrSDout != SYSINTR_UNDEFINED)
	{
		InterruptDisable(pCtxt->dwSysIntrSDout);
	}

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

	if (pCtxt->dwSysIntrSDout != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pCtxt->dwSysIntrSDout), sizeof(DWORD), NULL, 0, NULL);
		pCtxt->dwSysIntrSDout = SYSINTR_UNDEFINED;
	}

	// Interrupt for HDMI
	if (pCtxt->dwSysIntrHDMI != SYSINTR_UNDEFINED)
	{
		InterruptDisable(pCtxt->dwSysIntrHDMI);
	}

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

	if (pCtxt->dwSysIntrHDMI != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pCtxt->dwSysIntrHDMI), sizeof(DWORD), NULL, 0, NULL);
		pCtxt->dwSysIntrHDMI = SYSINTR_UNDEFINED;
	}

	// Interrupt for HPD
	if (pCtxt->dwSysIntrHPD != SYSINTR_UNDEFINED)
	{
		InterruptDisable(pCtxt->dwSysIntrHPD);
	}

	if (pCtxt->hInterruptHPD != NULL)
	{
		Mask_EXTINT(pCtxt->pGpioReg, EINT_HPD);
		Clear_EXTINT(pCtxt->pGpioReg, EINT_HPD);

		CloseHandle(pCtxt->hInterruptHPD);
		pCtxt->hInterruptHPD = NULL;
		
	}

	if (pCtxt->dwSysIntrHPD != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pCtxt->dwSysIntrHPD), sizeof(DWORD), NULL, 0, NULL);
		pCtxt->dwSysIntrHPD = SYSINTR_UNDEFINED;
	}

	


	// Interrupt for HDMI I2C
	if (pCtxt->dwSysIntrHDMII2C != SYSINTR_UNDEFINED)
	{
		InterruptDisable(pCtxt->dwSysIntrHDMII2C);
	}

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

	if (pCtxt->dwSysIntrHDMII2C != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pCtxt->dwSysIntrHDMII2C), sizeof(DWORD), NULL, 0, NULL);
		pCtxt->dwSysIntrHDMII2C = SYSINTR_UNDEFINED;
	}


	// Video Mixer Interrupt is used only for debug
	// Interrupt for Video Mixer (fifo under-run for debug)
	if (pCtxt->dwSysIntrVM != SYSINTR_UNDEFINED)
	{
		InterruptDisable(pCtxt->dwSysIntrVM);
	}

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

	if (pCtxt->dwSysIntrVM != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &(pCtxt->dwSysIntrVM), sizeof(DWORD), NULL, 0, NULL);
		pCtxt->dwSysIntrVM = SYSINTR_UNDEFINED;
	}


	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_deinitialize_interrupt()\n\r")));
}

BOOL
STDA_interrupt_initialize_thread
(void)
{

#if (USE_VMIXER_INTERRUPT || USE_SDOUT_INTERRUPT || USE_HDMI_INTERRUPT)
	pSTDAContext pCtxt;
#endif

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_initialize_thread()\n\r")));

#if (USE_VMIXER_INTERRUPT || USE_SDOUT_INTERRUPT || USE_HDMI_INTERRUPT)
	pCtxt = STDA_get_context();
#endif

#if USE_SDOUT_INTERRUPT
	// SDout
	pCtxt->bSDoutThrdExit = FALSE;
	pCtxt->hSDoutIST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)STDA_interrupt_sdout_intr_thread, NULL, 0, NULL);
	if (pCtxt->hSDoutIST == NULL)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_thread() : hSDoutIST CreateThread() Fail\n\r")));
		goto CleanUp;
	}
#endif

#if USE_HDMI_INTERRUPT
	// HDMI D/D is not maked
	// HDMI
	pCtxt->bHDMIThrdExit = FALSE;
	pCtxt->hHDMIIST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)STDA_interrupt_hdmi_Intr_thread, NULL, 0, NULL);
	if (pCtxt->hHDMIIST == NULL)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_thread() : hHDMIIST CreateThread() Fail\n\r")));
		goto CleanUp;
	}

	// HPD
	pCtxt->bHPDThrdExit = FALSE;
	pCtxt->hHPDIST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)STDA_interrupt_hpd_Intr_thread, NULL, 0, NULL);
	if (pCtxt->hHPDIST == NULL)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_thread() : hHPDIST CreateThread() Fail\n\r")));
		goto CleanUp;
	}

#endif

#if USE_VMIXER_INTERRUPT
	// Video Mixer Interrupt is used only for debug
	// Video Mixer
	pCtxt->bVMThrdExit = FALSE;
	pCtxt->hVMIST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)STDA_interrupt_vmixer_intr_thread, NULL, 0, NULL);
	if (pCtxt->hVMIST == NULL)
	{
		DBGMSG(TV_USR1,(_T("[TVINTR:ERR] STDA_interrupt_initialize_thread() : hVMIST CreateThread() Fail\n\r")));
		goto CleanUp;
	}
#endif

	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_initialize_thread()\n\r")));

	return TRUE;

#if (USE_VMIXER_INTERRUPT || USE_SDOUT_INTERRUPT || USE_HDMI_INTERRUPT)
CleanUp:

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

	return FALSE;
#endif
}

void
STDA_interrupt_deinitialize_thread
(void)
{
	pSTDAContext pCtxt;


	return;

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_deinitialize_thread()\n\r")));

	pCtxt = STDA_get_context();

	// SDout
	if (pCtxt->hSDoutIST != NULL)
	{
		pCtxt->bSDoutThrdExit = TRUE;
	}

	// HDMI
	if (pCtxt->hHDMIIST != NULL)
	{
		pCtxt->bHDMIThrdExit = TRUE;
	}

	if (pCtxt->hHPDIST != NULL)
	{
		pCtxt->bHPDThrdExit = TRUE;
	}

	if (pCtxt->hHDMII2CIST != NULL)
	{
		pCtxt->bHDMII2CThrdExit = TRUE;
	}

	// Video Mixer Interrupt is used only for debug
	if (pCtxt->hVMIST != NULL)
	{
		pCtxt->bVMThrdExit = TRUE;
	}


	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_deinitialize_thread()\n\r")));
}


// set
//  - set functions are only called under running tvout interrupt

// etc
//  -
DWORD
STDA_interrupt_vmixer_intr_thread
(void)
{
	pSTDAContext pCtxt;
	BOOL bVideo;
	BOOL bGrp0;
	BOOL bGpr1;
	BOOL bInt;

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[TVINTR] ++STDA_interrupt_vmixer_intr_thread()\n\r")));

	pCtxt = STDA_get_context();

	CeSetThreadPriority(pCtxt->hVMIST, TVOUT_IST_PRIORITY);
	while(!pCtxt->bVMThrdExit)
	{
		WaitForSingleObject(pCtxt->hInterruptVM, INFINITE);

		if(VMixer_get_vsync_interrupt_fired())
		{
			//Do Something


			//Clear Vsync
			VMixer_clear_vsync_interrupt();
		}


		VMixer_get_underflow_interrupt_fired(&bVideo, &bGrp0, &bGpr1, &bInt);

		if(bInt)
		{
			if(bVideo)
			{
				DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[TVINTR:INFO] ++STDA_interrupt_vmixer_intr_thread()VP fifo under run!!\n\r")));
			}

			if(bGrp0)
			{
				DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[TVINTR:INFO] ++STDA_interrupt_vmixer_intr_thread()GRP0 fifo under run!!\n\r")));
			}

			if(bGpr1)
			{
				DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[TVINTR:INFO] ++STDA_interrupt_vmixer_intr_thread()GRP1 fifo under run!!\n\r")));
			}

			// Clear Interrupt Pending
			VMixer_clear_underflow_interrupt(bVideo, bGrp0, bGpr1, bInt);
		}

		InterruptDone(pCtxt->dwSysIntrVM);

		PulseEvent(pCtxt->hVMCmdDone);
	}

	DBGMSG((TV_FUNC&&TV_UNDER_RUN),(_T("[TVINTR] --STDA_interrupt_vmixer_intr_thread()\n\r")));

	return 0;
}

DWORD
STDA_interrupt_sdout_intr_thread
(void)
{
	pSTDAContext pCtxt;

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_sdout_intr_thread()\n\r")));

	pCtxt = STDA_get_context();

	CeSetThreadPriority(pCtxt->hSDoutIST, TVOUT_IST_PRIORITY);
	while(!pCtxt->bSDoutThrdExit)
	{
		WaitForSingleObject(pCtxt->hInterruptSDout, INFINITE);

		if(Sdout_get_interrupt_pending())
		{
			// Clear Interrupt Pending
			Sdout_clear_interrupt_pending();
			DBGMSG(TV_FUNC,(_T("[TVINTR:INFO] ++STDA_interrupt_sdout_intr_thread() VSync!!\n\r")));
		}

		InterruptDone(pCtxt->dwSysIntrSDout);

		PulseEvent(pCtxt->hSDoutCmdDone);
	}

	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_sdout_intr_thread()\n\r")));

	return 0;
}

DWORD
STDA_interrupt_hdmi_Intr_thread
(void)
{
	pSTDAContext pCtxt;
	STDAPowerContext *pPMCtxt = STDA_get_power_context();
	unsigned int uiTimeout = INFINITE;
	unsigned int uiHdmiIntcFlag = 0;
	BOOL bOldHpdStatus;	
	STDA_ARG_HDMI_AVAILABLE_MODE tHdmiAvailableMode;
	
	unsigned int * uiWaitTime = &uiTimeout;

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_hdmi_Intr_thread()\n\r")));

	pCtxt = STDA_get_context();


	CeSetThreadPriority(pCtxt->hHDMIIST, TVOUT_IST_PRIORITY);
	while(!pCtxt->bHDMIThrdExit)
	{
		WaitForSingleObject(pCtxt->hInterruptHDMI, (*uiWaitTime));

		DBGMSG(TV_FUNC,(_T("[TVINTR] HDMI_INTC_FLAG[0x%x]\n\r"),pCtxt->pHDMISSReg->HDMI_INTC_FLAG));

		EnterCriticalSection(&pCtxt->csProcIntr);
	
		uiHdmiIntcFlag = pCtxt->pHDMISSReg->HDMI_INTC_FLAG;
		bOldHpdStatus = pPMCtxt->bHPDStatus;

		if(!HDMIEventHandler())
		{

		}

		LeaveCriticalSection(&pCtxt->csProcHPDInfo);
		
		if(uiHdmiIntcFlag & (1<<HDMI_IRQ_HPD_UNPLUG))
		{
//			pPMCtxt->bHPDStatus = FALSE;
		}
		else if(uiHdmiIntcFlag & (1<<HDMI_IRQ_HPD_PLUG))
		{
		}

		Sleep(50);

		//pPMCtxt->bHPDStatus = Get_PinData(pCtxt->pGpioReg, HDMI_HPD_FUNC);
 		pPMCtxt->bHPDStatus = (Get_PinData(pCtxt->pGpioReg, HDMI_HPD_EINT))? FALSE:TRUE; // modified by terry for x210 
		DBGMSG(TV_USR1,(_T("pPMCtxt->bHPDStatus = (%d)\n\r"),pPMCtxt->bHPDStatus));

		RETAILMSG(1,(_T("[HDMI THREAD] pPMCtxt->bHPDStatus = (%d)\n\r"),pPMCtxt->bHPDStatus));

		if((bOldHpdStatus != pPMCtxt->bHPDStatus) && (pPMCtxt->bHPDStatus == FALSE))
		{

			if(pPMCtxt->bTVoutOutputEnable &&
				pPMCtxt->tTvOutputParam.outMode >= TVOUT_OUTPUT_HDMI_YCBCR)
			{
//				StopHdcp();
				if(!HDCPStop())
				{
					DBGMSG(TV_USR1,(_T("[TVINTR] HDCPStop Error\n\r")));
				}
			}

			//Reset EDIDData
			memset((void *)(&tHdmiAvailableMode), 0,	sizeof(STDA_ARG_HDMI_AVAILABLE_MODE));
			STDA_HDMI_set_edid_info(&tHdmiAvailableMode);

	
///////////////////////////////////////////////////////////////////////
////////  You should stop TVour IF
////////  In here or Application
////////  I recommand to stop in Application
///////////////////////////////////////////////////////////////////////
////			STDA_TVoutIF_stop();

			if(!SetEvent(pCtxt->hHPDCmdDone))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hdmi_Intr_thread() SetEvent hHPDCmdDone is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForVP))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hdmi_Intr_thread() SetEvent hHPDCmdDoneForVP is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForGRP0))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hdmi_Intr_thread() SetEvent hHPDCmdDoneForGRP0 is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForGRP1))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hdmi_Intr_thread() SetEvent hHPDCmdDoneForGRP1 is Failed\n\r")));
			}
			
		}
		else if(uiHdmiIntcFlag & (1<<HDMI_IRQ_HPD_UNPLUG))
		{
			//Never come here
		}
		
		InterruptDone(pCtxt->dwSysIntrHDMI);
		
		PulseEvent(pCtxt->hHDMICmdDone);
	}


	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_hdmi_Intr_thread()\n\r")));

	return 0;
}

DWORD
STDA_interrupt_hpd_Intr_thread
(void)
{
	STDAContext *pCtxt = STDA_get_context();
	STDAPowerContext *pPMCtxt = STDA_get_power_context();
	BOOL bOldHpdStatus;
	BOOL bCurHpdStatus;
	STDA_ARG_HDMI_AVAILABLE_MODE tHdmiAvailableMode;

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_hpd_Intr_thread()\n\r")));

	if(pPMCtxt->bHPDStatus)
	{
		if(!STDA_HDMI_read_edid_info(&tHdmiAvailableMode))
		{
			memset((void *)(&tHdmiAvailableMode), 0,
			sizeof(STDA_ARG_HDMI_AVAILABLE_MODE));
		}
	}
	else
	{
		memset((void *)(&tHdmiAvailableMode), 0,
		sizeof(STDA_ARG_HDMI_AVAILABLE_MODE));
	}
	STDA_HDMI_set_edid_info(&tHdmiAvailableMode);
	CeSetThreadPriority(pCtxt->hHPDIST, TVOUT_IST_PRIORITY);
	while(!pCtxt->bHPDThrdExit)
	{
		WaitForSingleObject(pCtxt->hInterruptHPD, INFINITE);

		// TODO: need to IST code
		////////////////////////////////////////////////////////////////////////////////
		// HPD use EINT5 in SMDKV210
		////////////////////////////////////////////////////////////////////////////////
/*
		pCtxt->pGpioReg->WEINT0_MASK |= (1<<5);
		pCtxt->pGpioReg->WEINT0_PEND = (1<<5);
*/

		Mask_EXTINT(pCtxt->pGpioReg, EINT_HPD);
		Clear_EXTINT(pCtxt->pGpioReg, EINT_HPD);
			
		bOldHpdStatus = pPMCtxt->bHPDStatus;
		RETAILMSG(1,(_T("[HDP THREAD ]  bOldHpdStatus = %d\r\n"),bOldHpdStatus));	
		
		Sleep(3000);
 		//bCurHpdStatus = (Get_PinData(pCtxt->pGpioReg, HDMI_HPD_EINT))? TRUE:FALSE;
 		bCurHpdStatus = (Get_PinData(pCtxt->pGpioReg, HDMI_HPD_EINT))? FALSE:TRUE; // modified by terry for x210 

	
		RETAILMSG(1,(_T("[HDP THREAD]  pPMCtxt->bHPDStatus = %d\n\r"),bCurHpdStatus));	

			
		DBGMSG(TV_INFO,(_T("[TVINTR]  bOldHpdStatus = %d\n\r"),bOldHpdStatus));
		DBGMSG(TV_INFO,(_T("[TVINTR]  pPMCtxt->bHPDStatus = %d\n\r"),pPMCtxt->bHPDStatus));
		DBGMSG(TV_INFO,(_T("[TVINTR]  pCtxt->pGpioReg->GPH1.GP_DAT = %x\n\r"),pCtxt->pGpioReg->GPH1.GP_DAT));

		DBGMSG(TV_USR1,(_T("[TVINTR] bOldHpdStatus = %d\n\r"),bOldHpdStatus));
		DBGMSG(TV_USR1,(_T("[TVINTR] pPMCtxt->bHPDStatus = %d\n\r"),pPMCtxt->bHPDStatus));
		DBGMSG(TV_USR1,(_T("[TVINTR] pCtxt->pGpioReg->GPH1.GP_DAT = %x\n\r"),pCtxt->pGpioReg->GPH1.GP_DAT));

		DBGMSG(TV_USR1,(_T("[TVINTR] pCtxt->pGpioReg->EINTCON.EXT_INT1_CON = 0x%x\n\r"),pCtxt->pGpioReg->EINTCON.EXT_INT1_CON));

		////////////////////////////////////////////////////////////////////////////////
		if((bCurHpdStatus)&&(!bOldHpdStatus))        	
		{

			//Tvout_clk_set_hdmi_i2c_clk_onoff(TRUE);
			if(!STDA_HDMI_read_edid_info(&tHdmiAvailableMode))
			{
				memset((void *)(&tHdmiAvailableMode), 0,
				sizeof(STDA_ARG_HDMI_AVAILABLE_MODE));
			}
		//Tvout_clk_set_hdmi_i2c_clk_onoff(FALSE);
		}
		else
		{
			memset((void *)(&tHdmiAvailableMode), 0,
				sizeof(STDA_ARG_HDMI_AVAILABLE_MODE));

			if(pPMCtxt->bTVoutOutputEnable &&
			pPMCtxt->tTvOutputParam.outMode >= TVOUT_OUTPUT_HDMI_YCBCR)
			{
//				StopHdcp();
				if(!HDCPStop())
				{
					DBGMSG(TV_USR1,(_T("[TVINTR] HDCPStop Error\n\r")));
				}
				
				DBGMSG(TV_FUNC,(_T("[TVINTR] HPD is removed!!\n\r")));
			}
		}
		STDA_HDMI_set_edid_info(&tHdmiAvailableMode);

		pPMCtxt->bHPDStatus = bCurHpdStatus;
		InterruptDone(pCtxt->dwSysIntrHPD);

		if(bOldHpdStatus != bCurHpdStatus)
		{
			if(!SetEvent(pCtxt->hHPDCmdDone))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hpd_Intr_thread() SetEvent hHPDCmdDone is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForVP))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hpd_Intr_thread() SetEvent hHPDCmdDoneForVP is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForGRP0))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hpd_Intr_thread() SetEvent hHPDCmdDoneForGRP0 is Failed\n\r")));
			}
			if(!SetEvent(pCtxt->hHPDCmdDoneForGRP1))
			{
				DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_hpd_Intr_thread() SetEvent hHPDCmdDoneForGRP1 is Failed\n\r")));
			}
		}
		////////////////////////////////////////////////////////////////////////////////
		// HPD use EINT5 in SMDKV210
		////////////////////////////////////////////////////////////////////////////////
/*
		pCtxt->pGpioReg->WEINT0_MASK &= ~(1<<5);
*/
		// Power Button -> GPH3_7 : EINT31
		Unmask_EXTINT(pCtxt->pGpioReg, EINT_HPD);

		////////////////////////////////////////////////////////////////////////////////


		//For Debug
#if 0
		if(pCtxt->pGpioReg->EINTCON.EXT_INT1_CON == 0x8000)
		{
			DBGMSG(TV_USR1,(_T("[TVINTR] ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!0x%x\n\r"),pCtxt->pGpioReg->EINTCON.EXT_INT1_CON));			
//			pCtxt->pGpioReg->EINTCON.EXT_INT1_CON = 0x300000;
		}
#endif
		//Set EINT Falling or Rising
//		STDA_HDMI_HpdSetFalling(pPMCtxt->bHPDStatus);
		Set_EXTINT_TRLVL(pCtxt->pGpioReg, EINT_HPD, sgip_BOTH_EDGE);

	}

	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_hpd_Intr_thread()\n\r")));

	return 0;
}

DWORD
STDA_interrupt_hdmi_i2c_Intr_thread
(void)
{
//	pSTDAContext pCtxt;

	DBGMSG(TV_FUNC,(_T("[TVINTR] ++STDA_interrupt_hdmi_i2c_Intr_thread()\n\r")));

//	pCtxt = STDA_get_context();

/*
	CeSetThreadPriority(pCtxt->hHDMII2CIST, TVOUT_IST_PRIORITY);
	while(!pCtxt->bHDMII2CThrdExit)
	{
		WaitForSingleObject(pCtxt->hInterruptHDMII2C, INFINITE);

		// TODO: need to IST code

		InterruptDone(pCtxt->dwSysIntrHDMII2C);

		PulseEvent(pCtxt->hHDMII2CCmdDone);
	}
*/

	DBGMSG(TV_FUNC,(_T("[TVINTR] --STDA_interrupt_hdmi_i2c_Intr_thread()\n\r")));

	return 0;
}

DWORD
STDA_interrupt_wait_vmixer_cmd_done
(void)
{
	pSTDAContext pCtxt;

	pCtxt = STDA_get_context();

	return WaitForSingleObject(pCtxt->hVMCmdDone, TVOUT_VM_CMD_TIMEOUT);
}

DWORD
STDA_interrupt_wait_sdout_cmd_done
(void)
{
	pSTDAContext pCtxt;

	pCtxt = STDA_get_context();

	return WaitForSingleObject(pCtxt->hSDoutCmdDone, TVOUT_SDOUT_CMD_TIMEOUT);
}

DWORD
STDA_interrupt_wait_hdmi_cmd_done
(void)
{
	pSTDAContext pCtxt;

	pCtxt = STDA_get_context();

	return WaitForSingleObject(pCtxt->hHDMICmdDone, TVOUT_HDMI_CMD_TIMEOUT);
}

DWORD
STDA_interrupt_wait_hpd_cmd_done
(DWORD dwWaitTime)
{
	STDAContext *pCtxt = STDA_get_context();
	DWORD dRet = WaitForSingleObject(pCtxt->hHPDCmdDone, dwWaitTime);

	DBGMSG(TV_USR4,(_T("[TVINTR] ++STDA_interrupt_wait_hpd_cmd_done(%d)\n\r"),dwWaitTime));

	if(dRet == WAIT_OBJECT_0)
	{
		if(!ResetEvent(pCtxt->hHPDCmdDone))
		{
			DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_wait_hpd_cmd_done() ResetEvent is Failed\n\r")));
		}
	}

	return dRet;
}

DWORD
STDA_interrupt_wait_hpdVP_cmd_done
(DWORD dwWaitTime)
{
	STDAContext *pCtxt = STDA_get_context();
	DWORD dRet = WaitForSingleObject(pCtxt->hHPDCmdDoneForVP, dwWaitTime);

	DBGMSG(TV_USR4,(_T("[TVINTR] ++STDA_interrupt_wait_hpdVP_cmd_done(%d)\n\r"),dwWaitTime));

	if(dRet == WAIT_OBJECT_0)
	{
		if(!ResetEvent(pCtxt->hHPDCmdDoneForVP))
		{
			DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_wait_hpdVP_cmd_done() ResetEvent is Failed\n\r")));
		}
	}

	return dRet;
}

DWORD
STDA_interrupt_wait_hpdGRP0_cmd_done
(DWORD dwWaitTime)
{
	STDAContext *pCtxt = STDA_get_context();
	DWORD dRet = WaitForSingleObject(pCtxt->hHPDCmdDoneForGRP0, dwWaitTime);

	DBGMSG(TV_USR4,(_T("[TVINTR] ++STDA_interrupt_wait_hpdGRP0_cmd_done(%d)\n\r"),dwWaitTime));

	if(dRet == WAIT_OBJECT_0)
	{
		if(!ResetEvent(pCtxt->hHPDCmdDoneForGRP0))
		{
			DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_wait_hpdGRP0_cmd_done() ResetEvent is Failed\n\r")));
		}
	}

	return dRet;
}

DWORD
STDA_interrupt_wait_hpdGRP1_cmd_done
(DWORD dwWaitTime)
{
	STDAContext *pCtxt = STDA_get_context();
	DWORD dRet = WaitForSingleObject(pCtxt->hHPDCmdDoneForGRP1, dwWaitTime);

	DBGMSG(TV_USR4,(_T("[TVINTR] ++STDA_interrupt_wait_hpdGRP1_cmd_done(%d)\n\r"),dwWaitTime));

	if(dRet == WAIT_OBJECT_0)
	{
		if(!ResetEvent(pCtxt->hHPDCmdDoneForGRP1))
		{
			DBGMSG(TV_USR1,(_T("[TVINTR] ++STDA_interrupt_wait_hpdGRP1_cmd_done() ResetEvent is Failed\n\r")));
		}
	}

	return dRet;
}

DWORD
STDA_interrupt_wait_hdmi_i2c_cmd_done
(void)
{
	pSTDAContext pCtxt;

	pCtxt = STDA_get_context();

	return WaitForSingleObject(pCtxt->hHDMII2CCmdDone, TVOUT_HDMI_I2C_CMD_TIMEOUT);
}


// start
//  - start functions are only called under stopping tvout interrupt


// stop
//  - stop functions are only called under running tvout interrupt


// interrupt
//  - for debug

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

