Esempio n. 1
0
unsigned char EP956Controller_Task(void)
{
	//
	// Read from EP956 and Report Status
	//

	// Polling Interrupt Flag and updat the internal information
	EP956Controller_Interrupt();


	// Polling Hot-Plug (MHL Link) / RSEN every 55ms
	EP956Control_Link_Task();	 
	
	
	//
	// Update some controls from the user any time
	//

	// Power Control
	if(pEP956C_Registers->Power_Control & (EP956E_Power_Control__PD_HDMI | EP956E_Power_Control__PD_TOT) ) {
		is_Source_Ready = 0;
		pEP956C_Registers->Power_Control |= EP956E_Power_Control__PD_HDMI;
		
#ifndef MHL_CODE
		EP956_Reg_Set_Bit(EP956_TX_PHY_Control_1, EP956_TX_PHY_Control_1__RSEN_DIS);
#endif
	}
	else {
	
#ifndef MHL_CODE
		EP956_Reg_Clear_Bit(EP956_TX_PHY_Control_1, EP956_TX_PHY_Control_1__RSEN_DIS);
#endif

		if( is_VideoChanging  || is_AudioChanging || (pEP956C_Registers->Video_Input_Format[0] == 0) ) {
			is_Source_Ready = 0;
					
//			if(ConnectionState == CBUS_LINK_STATE__Connected) {
//				MHL_MSC_Cmd_MSC_MSG(MSC_RAP, RAP_CONTENT_OFF);
//			}
		}
		else {
			is_Source_Ready = 1;
					
//			if(ConnectionState == CBUS_LINK_STATE__Connected) {
//				MHL_MSC_Cmd_MSC_MSG(MSC_RAP, RAP_CONTENT_ON);
//			}
		}
	}

	// Mute Control
	if( (pEP956C_Registers->System_Configuration & EP956E_System_Configuration__AUDIO_DIS) || (TX_State < TXS_Stream) ) {
		HDMI_Tx_AMute_Enable();	
	}
	else {
		HDMI_Tx_AMute_Disable();
	}
	if( (pEP956C_Registers->System_Configuration & EP956E_System_Configuration__VIDEO_DIS) || (TX_State < TXS_Stream) ) {
		HDMI_Tx_VMute_Enable();
	}
	else {
		HDMI_Tx_VMute_Disable();
	}
	
	// Auto Handle AVMute
	Handle_AVMute(pEP956C_Registers->System_Configuration & EP956E_System_Configuration__AVMUTE_EN);



	//
	// Handle the main HDMI Link State and HDCP Authentication State
	// The state transition: [Search_EDID] => [Wait_Upstream] => [Stream] => [HDCP]
	//

	switch(TX_State) {
		case TXS_Search_EDID:
			if(is_Connected && is_PATH_EN) {
				//if(ReadEDID_TimeCount > 200/EP956C_TIMER_PERIOD) 
				//EP_DEV_DBG("delay 200ms+\n");
				delay_100ms(2);
				//EP_DEV_DBG("delay 200ms-\n");
				{
					unsigned char EDID_DDC_Status;
					static BYTE detectCount = 0;

					// Confirm Hot-Plug (time-out after 1s)
					if(!is_Hot_Plug) {
						//if(ReadEDID_TimeCount <= 1000/EP956C_TIMER_PERIOD) break;
						if(detectCount++ < 5) break;
						detectCount = 0;
						EP_DEV_DBG("Err: EDID detected without Hot-Plug for 1s\n");
					}

					// Read EDID
					EP_DEV_DBG("State Transist: Read EDID -> [TXS_Wait_Upstream]\n");				
					memset(pEP956C_Registers->Readed_EDID, 0xFF, 256);
					EDID_DDC_Status = Downstream_Rx_read_EDID(pEP956C_Registers->Readed_EDID);
					if(EDID_DDC_Status) {
						static BYTE failCount = 0;
						EP_DEV_DBG("Err: EDID read failed 0x%02X\n", (int)EDID_DDC_Status);
						//if(ReadEDID_TimeCount <= 500/EP956C_TIMER_PERIOD) break;
						if(failCount++ < 3)	break;
						failCount = 0;
					}
					//ReadEDID_TimeCount = 0;
 
					// Set Output
					if(pEP956C_Registers->System_Configuration & EP956E_System_Configuration__FORCE_HDMI_CAP) {
						is_Cap_HDMI = 1;
					}
					else {
						is_Cap_HDMI = EDID_GetHDMICap(pEP956C_Registers->Readed_EDID);
					}
					if(is_Cap_HDMI) {			
						EP_DEV_DBG("Support HDMI");

						// Default Capability
						is_Cap_YCC444 =	is_Cap_YCC422 = 0;
						pEP956C_Registers->EDID_ASFreq = 0x07;
						pEP956C_Registers->EDID_AChannel_PCM = 1;

						pEP956C_Registers->EDID_VideoDataAddr = 0x00;
						pEP956C_Registers->EDID_AudioDataAddr = 0x00;
						pEP956C_Registers->EDID_SpeakerDataAddr = 0x00;
						pEP956C_Registers->EDID_VendorDataAddr = 0x00;

						if(!EDID_DDC_Status) {
							if(pEP956C_Registers->Readed_EDID[131] & 0x20) {	// Support YCC444
								is_Cap_YCC444 = 1;
								EP_DEV_DBG(" YCC444");
							}
							if(pEP956C_Registers->Readed_EDID[131] & 0x10) {	// Support YCC422
								is_Cap_YCC422 = 1;
								EP_DEV_DBG(" YCC422");
							}
							EP_DEV_DBG("\n");
							pEP956C_Registers->EDID_ASFreq = EDID_GetPCMFreqCap(pEP956C_Registers->Readed_EDID);
							pEP956C_Registers->EDID_AChannel_PCM = EDID_GetChannelCap(pEP956C_Registers->Readed_EDID, 1); // Get PCM Max Channel
							pEP956C_Registers->EDID_AChannel_DSD = EDID_GetChannelCap(pEP956C_Registers->Readed_EDID, 9); // Get DSD Max Channel
							
							pEP956C_Registers->EDID_VideoDataAddr = EDID_GetDataBlockAddr(pEP956C_Registers->Readed_EDID, 0x40);
							pEP956C_Registers->EDID_AudioDataAddr = EDID_GetDataBlockAddr(pEP956C_Registers->Readed_EDID, 0x20);
							pEP956C_Registers->EDID_SpeakerDataAddr = EDID_GetDataBlockAddr(pEP956C_Registers->Readed_EDID, 0x80);
							pEP956C_Registers->EDID_VendorDataAddr = EDID_GetDataBlockAddr(pEP956C_Registers->Readed_EDID, 0x60);
						}
					}
					else {
						EP_DEV_DBG("Support DVI RGB only\n");
						is_Cap_YCC444 =	is_Cap_YCC422 = 0;
						pEP956C_Registers->EDID_ASFreq = pEP956C_Registers->EDID_AChannel_PCM = 0;
					}
					
					if(is_Cap_HDMI)
						pEP956C_Registers->EDID_Status = EDID_DDC_Status | EP956E_EDID_Status__HDMI;
					else
						pEP956C_Registers->EDID_Status = EDID_DDC_Status;
					EP_DEV_DBG("Support Max PCM Audio Channel %d\n", (int)pEP956C_Registers->EDID_AChannel_PCM+1);
					EP_DEV_DBG("Support Audio Freq 0x%02X\n", (int)pEP956C_Registers->EDID_ASFreq);

					// Report EDID Change
					pEP956C_Registers->Interrupt_Flags |= EP956E_Interrupt_Flags__EDID_CHG;
					if(EP956C_GenerateInt && (pEP956C_Registers->Interrupt_Enable & EP956E_Interrupt_Enable__EDID_CHG) ) EP956C_GenerateInt();
	
					TX_State = TXS_Wait_Upstream;
				}
			}
			else {	
				pEP956C_Registers->EDID_Status = EDID_STATUS_NoAct;
				//ReadEDID_TimeCount = 0;
			}
			break;
			
		case TXS_Wait_Upstream:

			if(!is_Connected || !is_PATH_EN) {

				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(is_Source_Ready && is_ReceiverSense) { // EP956 can detect RSEN in power down mode
				EP_DEV_DBG("State Transist: Power Up -> [TXS_Stream]\n");							

				// Set to DVI mode
				HDMI_Tx_DVI();	

				// Power Up
				HDMI_Tx_Power_Up();

				is_HDMI_Mode_Set = 1;
				//HDMI_Mode_Set_TimeCount = 0;

				TX_State = TXS_Stream;
			}
			else {
				// Check Force HDMI BOOL
				if(!is_Cap_HDMI) {
					if(pEP956C_Registers->System_Configuration & EP956E_System_Configuration__FORCE_HDMI_CAP) {
						TXS_RollBack_Wait_Upstream();
						TX_State = TXS_Search_EDID;
					}
				}
			}
			break;

		case TXS_Stream:

			//if(HDMI_Mode_Set_TimeCount > 10/EP956C_TIMER_PERIOD) 
			//EP_DEV_DBG("delay 10ms+\n");

			//EP_DEV_DBG("delay 10ms-\n");
			if(is_HDMI_Mode_Set)			
			{
				delay_1ms(10);
				//HDMI_Mode_Set_TimeCount = 0;
				is_HDMI_Mode_Set = 0;

				// HDMI Mode
				if(!is_Cap_HDMI || (pEP956C_Registers->System_Configuration & EP956E_System_Configuration__HDMI_DIS) ) {
					HDMI_Tx_DVI();	// Set to DVI mode (The Info Frame and Audio Packets would not be send)
				}
				else {
					HDMI_Tx_HDMI();	// Set to HDMI mode
				}
#ifdef MHL_CODE
				if(EP956_VDO_Settings[Video_Params.VideoSettingIndex].Pix_Freq_Type > PIX_FREQ_74250KHz) {
					is_PackedPixelMode = 1;
					
					if(is_PATH_EN)
						MHL_MSC_Cmd_WRITE_STATE(MSC_STATUS_LINK_MODE, CLK_MODE__PacketPixel | PATH_EN);
					else
						MHL_MSC_Cmd_WRITE_STATE(MSC_STATUS_LINK_MODE, CLK_MODE__PacketPixel);
			
					MHL_Clock_Mode(1);			
				}
				else {
					is_PackedPixelMode = 0;
					
					if(is_PATH_EN)
						MHL_MSC_Cmd_WRITE_STATE(MSC_STATUS_LINK_MODE, CLK_MODE__Normal | PATH_EN);
					else
						MHL_MSC_Cmd_WRITE_STATE(MSC_STATUS_LINK_MODE, CLK_MODE__Normal);
			
					MHL_Clock_Mode(0);
				}
#endif
			}
			
			if(!is_Connected || !is_PATH_EN) {

				TXS_RollBack_Stream();
				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(!is_Source_Ready || !is_ReceiverSense) {

				TXS_RollBack_Stream();
				TX_State = TXS_Wait_Upstream;
			}
			else if(!(pEP956C_Registers->System_Configuration & EP956E_System_Configuration__HDCP_DIS)) {
				if(is_HDMI_Mode_Set == 0) {
					EP_DEV_DBG("State Transist: Start HDCP -> [TXS_HDCP]\n");
					
					// Enable mute for transmiter video and audio
					HDMI_Tx_Mute_Enable();
	
					TX_State = TXS_HDCP;
				}
			}
			
			if(Dump_Timer++ > 2000/EP956C_TIMER_PERIOD)
			{
			
				Dump_Timer = 0;
				EP956_Reg_Read(EP956_CTS, Temp_Byte, 3);
				EP_DEV_DBG("CTS %02X %02X %02X\n", Temp_Byte[0], Temp_Byte[1], Temp_Byte[2]);
				
				EP956_Reg_Read(EP956_N, Temp_Byte, 3);
				EP_DEV_DBG("N %02X %02X %02X\n", Temp_Byte[0], Temp_Byte[1], Temp_Byte[2]);

				EP956_Reg_Read(EP956_Color_Space_Control, Temp_Byte, 1);
				EP_DEV_DBG("EP956_Color_Space_Control %X\n", Temp_Byte[0]);
				EP956_Reg_Read(EP956_General_Control_8, Temp_Byte, 1);
				EP_DEV_DBG("EP956_General_Control_8 %X\n", Temp_Byte[0]);
				EP956_Reg_Read(EP956_IIS_Control, Temp_Byte, 1);
				EP_DEV_DBG("EP956_IIS_Control %X\n", Temp_Byte[0]);
				
				HDMI_Dump_Status();
			}

			break;

		case TXS_HDCP:
		
			if(!is_Connected || !is_PATH_EN) {

				TXS_RollBack_HDCP();
				TXS_RollBack_Stream();
				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(!is_Source_Ready || !is_ReceiverSense) {

				TXS_RollBack_HDCP();
				TXS_RollBack_Stream();
				TX_State = TXS_Wait_Upstream;
			}
			else if(pEP956C_Registers->System_Configuration & EP956E_System_Configuration__HDCP_DIS) {

				TXS_RollBack_HDCP();
				TX_State = TXS_Stream;
			}
			else if(!is_Hot_Plug || is_VideoChanging || (pEP956C_Registers->System_Configuration & EP956E_System_Configuration__VIDEO_DIS) ) {
			
				// Enable mute for transmiter video and audio
				HDMI_Tx_Mute_Enable();

				HDCP_Stop();
			}
			else {
				pEP956C_Registers->HDCP_State = HDCP_Authentication_Task();
				pEP956C_Registers->HDCP_Status = HDCP_Get_Status();
			}
			break;
	}



	//
	// Combine the EDID capability and the source information to set the EP956 video/audio settings 
	//

	//
	// Update Video Params
	//

	// Video Interface
	Video_Params.Interface = pEP956C_Registers->Video_Interface[0];

	// Video Timing
	if(pEP956C_Registers->Video_Input_Format[0]) { 
		// Semi Auto Detect Video Timing
		if(pEP956C_Registers->Video_Input_Format[0] < 128) {
			if(pEP956C_Registers->Video_Input_Format[0] < 112) {
				Video_Params.VideoSettingIndex = pEP956C_Registers->Video_Input_Format[0];
			}
			else {
				Video_Params.VideoSettingIndex = pEP956C_Registers->Video_Input_Format[0] - (112 - EP956_VDO_Settings_Rep_Start);
			}
		}
		else {
			Video_Params.VideoSettingIndex = pEP956C_Registers->Video_Input_Format[0] - (128 - EP956_VDO_Settings_IT_Start);
		}
	} 

	// Select Sync Mode
	Video_Params.SyncMode = (pEP956C_Registers->Video_Interface[1] & EP956E_Video_Interface_Setting_1__SYNC) >> 2;

	// Select Color Space
	switch(pEP956C_Registers->Video_Interface[1] & EP956E_Video_Interface_Setting_1__COLOR) {
		default:
		case EP956E_Video_Interface_Setting_1__COLOR__Auto:
			switch(Video_Params.VideoSettingIndex) {
				case  4: case  5: case 16: case 19: case 20: case 31: case 32: 
				case 33: case 34: case 39: case 40: case 41: case 46: case 47:		// HD Timing
					Video_Params.ColorSpace = COLORSPACE_709;
					break;

				default:
					if(Video_Params.VideoSettingIndex && Video_Params.VideoSettingIndex < EP956_VDO_Settings_IT_Start) { // SD Timing
						Video_Params.ColorSpace = COLORSPACE_601;
					}
					else {															// IT Timing
						Video_Params.ColorSpace = COLORSPACE_709;
					}
			}
			break;
		case EP956E_Video_Interface_Setting_1__COLOR__601:
			Video_Params.ColorSpace = COLORSPACE_601;
			break;
		case EP956E_Video_Interface_Setting_1__COLOR__709:
			Video_Params.ColorSpace = COLORSPACE_709;
			break;
	}

	// Set Input Format
	switch(pEP956C_Registers->Video_Interface[1] & EP956E_Video_Interface_Setting_1__VIN_FMT) {
		default:
		case EP956E_Video_Interface_Setting_1__VIN_FMT__RGB:
			Video_Params.FormatIn = COLORFORMAT_RGB;
			break;
		case EP956E_Video_Interface_Setting_1__VIN_FMT__YCC444:
			Video_Params.FormatIn = COLORFORMAT_YCC444;
			break;
		case EP956E_Video_Interface_Setting_1__VIN_FMT__YCC422:
			Video_Params.FormatIn = COLORFORMAT_YCC422;
			break;
	}

	// Set Output Format
	switch(pEP956C_Registers->Video_Input_Format[2] & EP956E_Video_Output_Format_2__VOUT_FMT) {
		default:
		case EP956E_Video_Output_Format_2__VOUT_FMT__Auto:
			if(is_Cap_YCC444) {
				Video_Params.FormatOut = COLORFORMAT_YCC444;
			}
			else if(is_Cap_YCC422) {
				Video_Params.FormatOut = COLORFORMAT_YCC422;
			}
			else {
				Video_Params.FormatOut = COLORFORMAT_RGB;
			}
			break;
		case EP956E_Video_Output_Format_2__VOUT_FMT__YCC444:
			Video_Params.FormatOut = COLORFORMAT_YCC444;
			break;
		case EP956E_Video_Output_Format_2__VOUT_FMT__YCC422:
			Video_Params.FormatOut = COLORFORMAT_YCC422;
			break;
		case EP956E_Video_Output_Format_2__VOUT_FMT__RGB:
			Video_Params.FormatOut = COLORFORMAT_RGB;
			break;
	}
#ifdef MHL_CODE
	// Pack Pixel Mode
	if(EP956_VDO_Settings[Video_Params.VideoSettingIndex].Pix_Freq_Type > PIX_FREQ_74250KHz) {
		// Force to YCC422
		Video_Params.FormatOut = COLORFORMAT_YCC422;
	}
#endif
	
	// DVI mode settings overwrite
	if(!is_Cap_HDMI || (pEP956C_Registers->System_Configuration & EP956E_System_Configuration__HDMI_DIS) ) {
		Video_Params.FormatOut = COLORFORMAT_RGB;
	}

	// AFAR
	Video_Params.AFARate = ((pEP956C_Registers->Video_Input_Format[1] & EP956E_Video_Output_Format_1__AFAR) >> 4) | 0x08;

	// Video Change
	if(memcmp(&Video_Params, &pEP956C_Registers->Video_Params_Backup, 4) != 0) {
		// Timing change that AVMute is needed
		pEP956C_Registers->Video_Params_Backup = Video_Params;
		
		//VideoChg_TimeCount = 0;
		is_VideoChanging = 1;
		EP_DEV_DBG("Video Changing......\n");
	}
	else if(memcmp(&Video_Params, &pEP956C_Registers->Video_Params_Backup, sizeof(VDO_PARAMS)) != 0) {
		// Format change which can by applied immediately
		pEP956C_Registers->Video_Params_Backup = Video_Params;
		HDMI_Tx_VideoFMT_Config(&Video_Params);
	}

	// Video Change Debouncing
	if(is_VideoChanging) {
		//if(VideoChg_TimeCount > AV_STABLE_TIME/EP956C_TIMER_PERIOD) 
		//EP_DEV_DBG("delay 500ms+\n");
		delay_100ms(5);
		//EP_DEV_DBG("delay 500ms-\n");
		{
			HDMI_Tx_Video_Config(&Video_Params);
			is_VideoChanging = 0;
			//VideoChg_TimeCount = 0;
			
			// Report Video Change
			pEP956C_Registers->Interrupt_Flags |= EP956E_Interrupt_Flags__VIDEO_CHG;
			if(EP956C_GenerateInt && (pEP956C_Registers->Interrupt_Enable & EP956E_Interrupt_Enable__VIDEO_CHG) ) EP956C_GenerateInt();
		}
	}

	//
	// Update Audio Params
	//
	Audio_Params.Interface = pEP956C_Registers->Audio_Interface & 0x8F; // DSDCK_POL, ..., SD_DIR, WS_M, WS_POL, SCK_POL
	Audio_Params.VideoSettingIndex = Video_Params.VideoSettingIndex;

	// Update Audio Type
	Audio_Params.AudioType = (pEP956C_Registers->Audio_Input_Format[0] & EP956E_Audio_Output_Format__AUDIO_TYPE) >> 6;

	// Update Audio Channel Number
	if(Audio_Params.AudioType == AUDIO_TYPE_IIS) {
		if(EP956_VDO_Settings[Video_Params.VideoSettingIndex].Pix_Freq_Type <= PIX_FREQ_27027KHz) {
			Audio_Params.ChannelNumber = 1;
		}
		else {
			Audio_Params.ChannelNumber = min(((pEP956C_Registers->Audio_Interface & 0x70) >> 4), pEP956C_Registers->EDID_AChannel_PCM);
		}
	}
	else if(Audio_Params.AudioType == AUDIO_TYPE_DSD) {
Esempio n. 2
0
unsigned char EP932Controller_Task(void)
{
    //DBG_printf(("EP932 EP932Controller_Task \r\n"));

	// Read Interrupt Flag and updat the internal information
	ReadInterruptFlags();

	// Polling Hot-Plug every 80ms
	if(HTP_TimeCount > 80/EP932C_TIMER_PERIOD) {
		HTP_TimeCount = 0;
		
		ConnectionState = HDMI_Tx_HTPLG();

		HTPLG_NOW = ConnectionState;
		if(HTPLG_LAST != HTPLG_NOW)
		{
			HTPLG_LAST = HTPLG_NOW;
			if(HTPLG_NOW == 0)
			{
				DBG_printf(("Without HotPlug\r\n"));	
				EP_HDMI_DumpMessage();				
			}
			else
			{
				DBG_printf(("Detect HotPlug \r\n"));	
			}
		}
		
		is_Hot_Plug = (ConnectionState == 1)? 1:0;
		if(is_Connected != ((ConnectionState)?1:0) ) {
			if(HP_ChangeCount++ >= 1) { // Accept continuous 1 error = 1*80 ms = 80 ms (Skip when low period < 80 ms)
				HP_ChangeCount = 0;

				is_Connected = ((ConnectionState)?1:0);
			}
		}
		else {
			HP_ChangeCount = 0;
		}
		if(is_Hot_Plug) {
			pEP932C_Registers->System_Status |= EP932E_System_Status__HTPLG;
		}
		else {
			pEP932C_Registers->System_Status &= ~EP932E_System_Status__HTPLG;
		}

		is_ReceiverSense = HDMI_Tx_RSEN(); // Only valid when TX is powered on

		if(TX_State > TXS_Wait_Upstream) { // Powered Up and have Input
			
			// Update RSEN
			if(is_ReceiverSense) {
				pEP932C_Registers->System_Status |= EP932E_System_Status__RSEN;
			}
			else {
				pEP932C_Registers->System_Status &= ~EP932E_System_Status__RSEN;
			}
			RSEN_ChangeCount = 0;

			// Read HSO VSO POL information
			EP932_Reg_Read(EP932_General_Control_4, DDC_Data, 1);
			Video_Params.HVPol = 0;//DDC_Data[0] & (EP932_DE_Control__VSO_POL | EP932_DE_Control__HSO_POL);	
		}
		else {
			if(RSEN_ChangeCount++ >= 8) { // Accept continuous 8 error = 8*80 ms = 640 ms (Skip when low period < 640 ms)
				RSEN_ChangeCount = 0;

				pEP932C_Registers->System_Status &= ~EP932E_System_Status__RSEN;
			}
		}
	}

	//
	// Update EP932 Registers according to the System Process
	//
	//DBG_printf(("TX_State=%d \n",TX_State));
	switch(TX_State) {
		case TXS_Search_EDID:
			if(is_Connected) {
				if(ReadEDID_TimeCount > 200/EP932C_TIMER_PERIOD) {
					unsigned char EDID_DDC_Status = 0;

					// Confirm Hot-Plug (time-out after 1s)
					if(!is_Hot_Plug) {
						if(ReadEDID_TimeCount <= 1000/EP932C_TIMER_PERIOD) break;
						DBG_printf(("WARNING: EDID detected without Hot-Plug for 1s\r\n"));
					}

					// Read EDID
					DBG_printf(("\r\nState Transist: Read EDID -> [TXS_Wait_Upstream] 0x%x\r\n",pEP932C_Registers->System_Configuration));
					memset(pEP932C_Registers->Readed_EDID, 0xFF, 256);
                    if(!(pEP932C_Registers->System_Configuration & EP932E_System_Configuration__FORCE_HDMI_CAP)){
    					EDID_DDC_Status = Downstream_Rx_read_EDID(pEP932C_Registers->Readed_EDID);
    					
    					if(EDID_DDC_Status) {
    						//if(EDID_DDC_Status == EDID_STATUS_NoAct) {
    						if(EDID_DDC_Status != EDID_STATUS_ChecksumError) {
    							DBG_printf(("WARNING: EDID read failed 0x%02X\r\n", (int)EDID_DDC_Status));
    							if(ReadEDID_TimeCount <= 500/EP932C_TIMER_PERIOD) break;
    						}
    					}
                    }
					ReadEDID_TimeCount = 0;
 
					// Set Output
					if(pEP932C_Registers->System_Configuration & EP932E_System_Configuration__FORCE_HDMI_CAP) {
						is_Cap_HDMI = 1;
					}
					else {
						is_Cap_HDMI = EDID_GetHDMICap(pEP932C_Registers->Readed_EDID);
					}
					if(is_Cap_HDMI) {			
						DBG_printf(("Support HDMI"));

						// Default Capability
						is_Cap_YCC444 =	is_Cap_YCC422 = 0;
						pEP932C_Registers->EDID_ASFreq = 0x07;
						pEP932C_Registers->EDID_AChannel = 1;

						pEP932C_Registers->EDID_VideoDataAddr = 0x00;
						pEP932C_Registers->EDID_AudioDataAddr = 0x00;
						pEP932C_Registers->EDID_SpeakerDataAddr = 0x00;
						pEP932C_Registers->EDID_VendorDataAddr = 0x00;

						if(!EDID_DDC_Status) {

							if(pEP932C_Registers->Readed_EDID[131] & 0x20) {	// Support YCC444
								is_Cap_YCC444 = 1;
								DBG_printf((" YCC444"));
							}
							if(pEP932C_Registers->Readed_EDID[131] & 0x10) {	// Support YCC422
								is_Cap_YCC422 = 1;
								DBG_printf((" YCC422"));
							}
							DBG_printf(("\r\n"));
							pEP932C_Registers->EDID_ASFreq = EDID_GetPCMFreqCap(pEP932C_Registers->Readed_EDID);
							DBG_printf(("EDID ASFreq = 0x%02X\r\n",(int)pEP932C_Registers->EDID_ASFreq));

							pEP932C_Registers->EDID_AChannel = EDID_GetPCMChannelCap(pEP932C_Registers->Readed_EDID);
							DBG_printf(("EDID AChannel = 0x%02X\r\n",(int)pEP932C_Registers->EDID_AChannel));

							pEP932C_Registers->EDID_VideoDataAddr = EDID_GetDataBlockAddr(pEP932C_Registers->Readed_EDID, 0x40);
							pEP932C_Registers->EDID_AudioDataAddr = EDID_GetDataBlockAddr(pEP932C_Registers->Readed_EDID, 0x20);
							pEP932C_Registers->EDID_SpeakerDataAddr = EDID_GetDataBlockAddr(pEP932C_Registers->Readed_EDID, 0x80);
							pEP932C_Registers->EDID_VendorDataAddr = EDID_GetDataBlockAddr(pEP932C_Registers->Readed_EDID, 0x60);
						}
					}
					else {
						DBG_printf(("Support DVI RGB only\r\n"));
						is_Cap_YCC444 =	is_Cap_YCC422 = 0;
						pEP932C_Registers->EDID_ASFreq = pEP932C_Registers->EDID_AChannel = 0;
					}

					if(is_Cap_HDMI)
						pEP932C_Registers->EDID_Status = EDID_DDC_Status | EP932E_EDID_Status__HDMI;
					else
						pEP932C_Registers->EDID_Status = EDID_DDC_Status;
					DBG_printf(("Support Max Audio Channel %d\r\n", (int)pEP932C_Registers->EDID_AChannel+1));
					DBG_printf(("Support Audio Freq 0x%02X\r\n", (int)pEP932C_Registers->EDID_ASFreq));

					// Report EDID Change
					pEP932C_Registers->Interrupt_Flags |= EP932E_Interrupt_Flags__EDID_CHG;
					if(EP932C_GenerateInt && (pEP932C_Registers->Interrupt_Enable & EP932E_Interrupt_Enable__EDID_CHG) ) EP932C_GenerateInt();
	
					TX_State = TXS_Wait_Upstream;
				}
			}
			else {	
				pEP932C_Registers->EDID_Status = EDID_STATUS_NoAct;
				ReadEDID_TimeCount = 0;
			}
			break;
			
		case TXS_Wait_Upstream:

			if(!is_Connected) {

				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(!(pEP932C_Registers->Power_Control & (EP932E_Power_Control__PD_HDMI | EP932E_Power_Control__PD_TOT)) ) {
				DBG_printf(("\r\nState Transist: Power Up -> [TXS_Stream]\r\n"));							

				// Power Up
				HDMI_Tx_Power_Up();

				TX_State = TXS_Stream;
			}
			else {
				// Check Force HDMI bit
				if(!is_Cap_HDMI) {
					if(pEP932C_Registers->System_Configuration & EP932E_System_Configuration__FORCE_HDMI_CAP) {
						TXS_RollBack_Wait_Upstream();
						TX_State = TXS_Search_EDID;
					}
				}
			}
			break;

		case TXS_Stream:

#if defined(Enable_HDCP)
			if(!is_HDCP_Info_BKSV_Rdy && is_ReceiverSense && is_Hot_Plug) {
				// Get HDCP Info
		    	if(!Downstream_Rx_read_BKSV(pEP932C_Registers->HDCP_BKSV)) {
					pEP932C_Registers->HDCP_Status = EP932E_HDCP_Status__BKSV;
				}
				pEP932C_Registers->HDCP_BCAPS3[0] = Downstream_Rx_BCAPS();
				is_HDCP_Info_BKSV_Rdy = 1;
			}
#endif			

			if(!is_Connected) {

				TXS_RollBack_Stream();
				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(pEP932C_Registers->Power_Control & (EP932E_Power_Control__PD_HDMI | EP932E_Power_Control__PD_TOT) ) {
				pEP932C_Registers->Power_Control |= EP932E_Power_Control__PD_HDMI;

				TXS_RollBack_Stream();
				TX_State = TXS_Wait_Upstream;
			}
			
#if defined(Enable_HDCP)
			else if(!((pEP932C_Registers->System_Configuration & EP932E_System_Configuration__HDCP_DIS) || is_VideoChanging) && is_ReceiverSense) {
				// Enable mute for transmiter video and audio
				HDMI_Tx_Mute_Enable();

				DBG_printf(("\r\nState Transist: Start HDCP -> [TXS_HDCP]\r\n"));
				TX_State = TXS_HDCP;
			}
#endif			

			break;
			
#if defined(Enable_HDCP)
		case TXS_HDCP:
		
			if(!is_Connected || !is_Hot_Plug) {

				TXS_RollBack_HDCP();
				TXS_RollBack_Stream();
				TXS_RollBack_Wait_Upstream();
				TX_State = TXS_Search_EDID;
			}
			else if(pEP932C_Registers->Power_Control & (EP932E_Power_Control__PD_HDMI | EP932E_Power_Control__PD_TOT) ) {
				pEP932C_Registers->Power_Control |= EP932E_Power_Control__PD_HDMI;

				TXS_RollBack_HDCP();
				TXS_RollBack_Stream();
				TX_State = TXS_Wait_Upstream;
			}
			else if((pEP932C_Registers->System_Configuration & EP932E_System_Configuration__HDCP_DIS) || is_VideoChanging) {
	
				TXS_RollBack_HDCP();
				TX_State = TXS_Stream;
			}
			else {
				pEP932C_Registers->HDCP_State = HDCP_Authentication_Task(is_ReceiverSense && is_Hot_Plug);
				pEP932C_Registers->HDCP_Status = HDCP_Get_Status();
			}
			break;
#endif

	}

	//
	// Update EP932 Registers for any time
	//

	// Mute Control
	if( (pEP932C_Registers->System_Configuration & EP932E_System_Configuration__AUDIO_DIS) || (TX_State < TXS_Stream) || is_VideoChanging  || is_AudioChanging ) {
		HDMI_Tx_AMute_Enable();	
	}
	else {
		HDMI_Tx_AMute_Disable();
	}
	
	if( (pEP932C_Registers->System_Configuration & EP932E_System_Configuration__VIDEO_DIS) || (TX_State < TXS_Stream) || is_VideoChanging ) {
		HDMI_Tx_VMute_Enable();		
	}
	else {
		HDMI_Tx_VMute_Disable();
	}

	// HDMI Mode
	if(!is_Cap_HDMI || (pEP932C_Registers->System_Configuration & EP932E_System_Configuration__HDMI_DIS) ) {
		HDMI_Tx_DVI();		// Set to DVI mode (The Info Frame and Audio Packets would not be send)
	}
	else {
		HDMI_Tx_HDMI();	// Set to HDMI mode
	}

	++Process_Dispatch_ID;
	if(Process_Dispatch_ID > 2) Process_Dispatch_ID = 0;

	switch(Process_Dispatch_ID) {

		case 0:
			//
			// Update Video Params
			//
		
			// Video Interface
			Video_Params.Interface = pEP932C_Registers->Video_Interface[0];
		
			// Video Timing
			if(pEP932C_Registers->Video_Input_Format[0]) { 
				// Manul set the Video Timing
				if(pEP932C_Registers->Video_Input_Format[0] < 128) {
					Video_Params.VideoSettingIndex = pEP932C_Registers->Video_Input_Format[0];
				}
				else {
					Video_Params.VideoSettingIndex = pEP932C_Registers->Video_Input_Format[0] - (128 - EP932_VDO_Settings_IT_Start);
				}
			} 
		
			// Select Sync Mode
			Video_Params.SyncMode = (pEP932C_Registers->Video_Interface[1] & EP932E_Video_Interface_Setting_1__SYNC) >> 2;
		
			// Select Color Space
			switch(pEP932C_Registers->Video_Interface[1] & EP932E_Video_Interface_Setting_1__COLOR) {
				default:
				case EP932E_Video_Interface_Setting_1__COLOR__Auto:
					switch(Video_Params.VideoSettingIndex) {
						case  4: case  5: case 16: case 19: case 20: case 31: case 32: 
						case 33: case 34: case 39: case 40: case 41: case 46: case 47:		// HD Timing
							Video_Params.ColorSpace = COLORSPACE_709;
							break;
		
						default:
							if(Video_Params.VideoSettingIndex && Video_Params.VideoSettingIndex < EP932_VDO_Settings_IT_Start) { // SD Timing
								Video_Params.ColorSpace = COLORSPACE_601;
							}
							else {															// IT Timing
								Video_Params.ColorSpace = COLORSPACE_709;
							}
					}
					break;
				case EP932E_Video_Interface_Setting_1__COLOR__601:
					Video_Params.ColorSpace = COLORSPACE_601;
					break;
				case EP932E_Video_Interface_Setting_1__COLOR__709:
					Video_Params.ColorSpace = COLORSPACE_709;
					break;
			}
		
			// Set Input Format
			switch(pEP932C_Registers->Video_Interface[1] & EP932E_Video_Interface_Setting_1__VIN_FMT) {
				default:
				case EP932E_Video_Interface_Setting_1__VIN_FMT__RGB:
					Video_Params.FormatIn = COLORFORMAT_RGB;
					Video_Params.FormatOut = COLORFORMAT_RGB;
					break;
				case EP932E_Video_Interface_Setting_1__VIN_FMT__YCC444:
					Video_Params.FormatIn = COLORFORMAT_YCC444;
					if(is_Cap_YCC444) {
						Video_Params.FormatOut = COLORFORMAT_YCC444;
					}
					else if(is_Cap_YCC422) {
						Video_Params.FormatOut = COLORFORMAT_YCC422;
					}
					else {
						Video_Params.FormatOut = COLORFORMAT_RGB;
					}
					break;
				case EP932E_Video_Interface_Setting_1__VIN_FMT__YCC422:
					Video_Params.FormatIn = COLORFORMAT_YCC422;
					if(is_Cap_YCC444) {
						Video_Params.FormatOut = COLORFORMAT_YCC444;
					}
					else if(is_Cap_YCC422) {
						Video_Params.FormatOut = COLORFORMAT_YCC422;
					}
					else {
						Video_Params.FormatOut = COLORFORMAT_RGB;
					}
					break;
			}

	//add by eric.lu
	
			// Set Output Format
			switch(pEP932C_Registers->Video_Output_Format) {
				default:
				case 0:		// Auto, don't need change setting.
					break;
					
				case 1:		// Force to YUV444 output format
					Video_Params.FormatOut = COLORFORMAT_YCC444;
					break;
					
				case 2:		// Force to YUV422 output format
					Video_Params.FormatOut = COLORFORMAT_YCC422;
					break;
					
				case 3:		// Force to RGB444 output format
					Video_Params.FormatOut = COLORFORMAT_RGB;
					break;
			}
			
	// end of add

			// DVI mode settings overwrite
			if(!is_Cap_HDMI || (pEP932C_Registers->System_Configuration & EP932E_System_Configuration__HDMI_DIS) ) {
				Video_Params.FormatOut = COLORFORMAT_RGB;
			}
		
			// AFAR
			Video_Params.AFARate = ((pEP932C_Registers->Video_Input_Format[1] & EP932E_Video_Input_Format_1__AFAR) >> 4) | 0x08;

		// add by eric.lu
			// SCAN			
			Video_Params.SCAN = (pEP932C_Registers->Video_Input_Format[1] & EP932E_Video_Input_Format_1__SCAN);
		// end of add
		
			// Video Change
			if(memcmp(&Video_Params, &pEP932C_Registers->Video_Params_Backup, sizeof(VDO_PARAMS)) != 0) {
				if(memcmp(&Video_Params, &pEP932C_Registers->Video_Params_Backup, 6) != 0) {
					is_TimingChanging = 1;
				}
//				DBG_printf(("Video_Params new: interface 0x%02X, Vindex 0x%02X, HV 0x%02X, mode 0x%02X, Fin 0x%02X, Fout 0x%02X, color 0x%02X, AFAR 0x%02X\r\n",(int)Video_Params.Interface, (int)Video_Params.VideoSettingIndex, (int)Video_Params.HVPol ,(int)Video_Params.SyncMode, (int)Video_Params.FormatIn, (int)Video_Params.FormatOut, (int)Video_Params.ColorSpace, (int)Video_Params.AFARate));
//				DBG_printf(("Video_Params old: interface 0x%02X, Vindex 0x%02X, HV 0x%02X, mode 0x%02X, Fin 0x%02X, Fout 0x%02X, color 0x%02X, AFAR 0x%02X\r\n",(int)pEP932C_Registers->Video_Params_Backup.Interface, (int)pEP932C_Registers->Video_Params_Backup.VideoSettingIndex, (int)pEP932C_Registers->Video_Params_Backup.HVPol ,(int)pEP932C_Registers->Video_Params_Backup.SyncMode, (int)pEP932C_Registers->Video_Params_Backup.FormatIn, (int)pEP932C_Registers->Video_Params_Backup.FormatOut, (int)pEP932C_Registers->Video_Params_Backup.ColorSpace, (int)pEP932C_Registers->Video_Params_Backup.AFARate));
				
				pEP932C_Registers->Video_Params_Backup = Video_Params;
				
				VideoChg_TimeCount = 0;
				is_VideoChanging = 1;
			}
		
			// Video Change Debouncing
			if(is_VideoChanging) {				
				if(VideoChg_TimeCount > AV_STABLE_TIME/EP932C_TIMER_PERIOD) {

					DBG_printf(("### VideoChanging \r\n"));

					if(is_TimingChanging) 
						EP932Controller_Reset();

					HDMI_Tx_Video_Config(&Video_Params);

					if(is_TimingChanging) {
						if(!is_AudioChanging) 
							HDMI_Tx_Audio_Config(&Audio_Params);
					}

					is_TimingChanging = 0;
					is_VideoChanging = 0;
					VideoChg_TimeCount = 0;
					
					// Report Video Change
					pEP932C_Registers->Interrupt_Flags |= EP932E_Interrupt_Flags__VIDEO_CHG;
					if(EP932C_GenerateInt && (pEP932C_Registers->Interrupt_Enable & EP932E_Interrupt_Enable__VIDEO_CHG) ) EP932C_GenerateInt();
				}
			}
			break;

		case 1:
			//
			// Update Audio Params
			//
			Audio_Params.Interface = pEP932C_Registers->Audio_Interface & 0x0F; // IIS, WS_M, WS_POL, SCK_POL
			Audio_Params.VideoSettingIndex = Video_Params.VideoSettingIndex;

			// Update Audio Channel Number
			if(EP932_VDO_Settings[Video_Params.VideoSettingIndex].Pix_Freq_Type <= PIX_FREQ_27027KHz) {
				Audio_Params.ChannelNumber = 1;
			}
			else {
				Audio_Params.ChannelNumber = min(((pEP932C_Registers->Audio_Interface & 0x70) >> 4), pEP932C_Registers->EDID_AChannel);
			}

			// Update VFS
			if(Audio_Params.VideoSettingIndex < EP932_VDO_Settings_IT_Start) {
				// Pixel Clock Type shift (59.94/60)
				Audio_Params.VFS = (pEP932C_Registers->Video_Input_Format[1] & EP932E_Video_Input_Format_1__VIF)? 1:0;
			}
			else {
				Audio_Params.VFS = 0;
			}
			Audio_Params.NoCopyRight = (pEP932C_Registers->Audio_Input_Format & EP932E_Audio_Input_Format__NoCopyRight)?1:0;
		
			// Write Frequency info (Use ADO_FREQ or Auto)
			switch( pEP932C_Registers->Audio_Input_Format & EP932E_Audio_Input_Format__ADO_FREQ ) {
		
				case EP932E_Audio_Input_Format__ADO_FREQ__32000Hz:
					Audio_Params.InputFrequency = ADSFREQ_32000Hz;
					// Disable Down Sample
					Audio_Params.ADSRate = 0;
					break;
		
				default:
				case EP932E_Audio_Input_Format__ADO_FREQ__44100Hz:
					Audio_Params.InputFrequency = ADSFREQ_44100Hz;
					// Disable Down Sample
					Audio_Params.ADSRate = 0;
					break;
		
				case EP932E_Audio_Input_Format__ADO_FREQ__48000Hz:
					Audio_Params.InputFrequency = ADSFREQ_48000Hz;
					// Disable Down Sample
					Audio_Params.ADSRate = 0;
					break;
		
				case EP932E_Audio_Input_Format__ADO_FREQ__88200Hz:
					Audio_Params.InputFrequency = ADSFREQ_88200Hz;
					if(pEP932C_Registers->EDID_ASFreq & 0x08) { // 88.2kHz
						// Disable Down Sample
						Audio_Params.ADSRate = 0;
					}
					else {
						// Enable Down Sample 1/2
						Audio_Params.ADSRate = 1;
					}
					break;
		
				case EP932E_Audio_Input_Format__ADO_FREQ__96000Hz:
					Audio_Params.InputFrequency = ADSFREQ_96000Hz;
					if(pEP932C_Registers->EDID_ASFreq & 0x10) { // 96kHz
						// Disable Down Sample
						Audio_Params.ADSRate = 0;
					}
					else {
						if(pEP932C_Registers->EDID_ASFreq & 0x04) { // 48kHz
							// Enable Down Sample 1/2
							Audio_Params.ADSRate = 1;
						}
						else {
							// Enable Down Sample 1/3
							Audio_Params.ADSRate = 2;
						}
					}
					break;
		
				case EP932E_Audio_Input_Format__ADO_FREQ__176400Hz:
					Audio_Params.InputFrequency = ADSFREQ_176400Hz;
					if(pEP932C_Registers->EDID_ASFreq & 0x20) { // 176kHz
						// Disable Down Sample
						Audio_Params.ADSRate = 0;
					}
					else {
						if(pEP932C_Registers->EDID_ASFreq & 0x08) { // 88.2kHz
							// Enable Down Sample 1/2
							Audio_Params.ADSRate = 1;
						}
						else {
							// Enable Down Sample 1/4
							Audio_Params.ADSRate = 3;
						}
					}
					break;
		
				case EP932E_Audio_Input_Format__ADO_FREQ__192000Hz:
					Audio_Params.InputFrequency = ADSFREQ_192000Hz;
					if(pEP932C_Registers->EDID_ASFreq & 0x40) { // 192kHz
						// Disable Down Sample
						Audio_Params.ADSRate = 0;
					}
					else {
						if(pEP932C_Registers->EDID_ASFreq & 0x10) { // 96kHz
							// Enable Down Sample 1/2
							Audio_Params.ADSRate = 1;
						}
						else {
							// Enable Down Sample 1/4
							Audio_Params.ADSRate = 3;
						}
					}
					break;
			}
		
			// Audio Change
			if(memcmp(&Audio_Params, &pEP932C_Registers->Audio_Params_Backup, sizeof(ADO_PARAMS)) != 0) {
				pEP932C_Registers->Audio_Params_Backup = Audio_Params;
		
				AudioChg_TimeCount = 0;
				is_AudioChanging = 1;
			}

			// Audio Change Debouncing
			if(is_AudioChanging) {
				if(AudioChg_TimeCount > AV_STABLE_TIME/EP932C_TIMER_PERIOD) {
					HDMI_Tx_Audio_Config(&Audio_Params);
					is_AudioChanging = 0;
					AudioChg_TimeCount = 0;
					
					// Report Audio Change
					pEP932C_Registers->Interrupt_Flags |= EP932E_Interrupt_Flags__AUDIO_CHG;
					if(EP932C_GenerateInt && (pEP932C_Registers->Interrupt_Enable & EP932E_Interrupt_Enable__AUDIO_CHG) ) EP932C_GenerateInt();
				}
			}
			break;

		case 2:

			// Update TREG
			if(pEP932C_Registers->Analog_Test_Control != Backup_Analog_Test_Control) {
				Backup_Analog_Test_Control = pEP932C_Registers->Analog_Test_Control;
		
				if(pEP932C_Registers->Analog_Test_Control & 0x01) {
					EP932_Reg_Set_Bit(EP932_Color_Space_Control, 0x01);
				}
				else {
					EP932_Reg_Clear_Bit(EP932_Color_Space_Control, 0x01);
				}
				if(pEP932C_Registers->Analog_Test_Control & 0x02) {
					EP932_Reg_Set_Bit(EP932_Color_Space_Control, 0x02);
				}
				else {
					EP932_Reg_Clear_Bit(EP932_Color_Space_Control, 0x02);
				}
			}
			break;
	}

	// Return the status
	if(pEP932C_Registers->Power_Control & (EP932E_Power_Control__PD_HDMI | EP932E_Power_Control__PD_TOT)) {
		return EP932C_TASK_Idle;
	}
	else {
		return EP932C_TASK_Pending;
	}
}