///////////////////////////////////////////////////////////////////// // IT6613.C // Driver code for platform independent ///////////////////////////////////////////////////////////////////// #include "hdmitx.h" //#include "dss_sha.h" #define MSCOUNT 1000 #define LOADING_UPDATE_TIMEOUT (3000/32) // 3sec // USHORT u8msTimer = 0 ; // USHORT TimerServF = TRUE ; ////////////////////////////////////////////////////////////////////// // Authentication status ////////////////////////////////////////////////////////////////////// // #define TIMEOUT_WAIT_AUTH MS(2000) #define Switch_HDMITX_Bank(x) HDMITX_WriteI2C_Byte(0x0f,(x)&1) #define HDMITX_OrREG_Byte(reg,ormask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) | (ormask))) #define HDMITX_AndREG_Byte(reg,andmask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) & (andmask))) #define HDMITX_SetREG_Byte(reg,andmask,ormask) HDMITX_WriteI2C_Byte(reg,((HDMITX_ReadI2C_Byte(reg) & (andmask))|(ormask))) ////////////////////////////////////////////////////////////////////// // General global variables ////////////////////////////////////////////////////////////////////// // static _IDATA TXVideo_State_Type VState ; // static _IDATA TXAudio_State_Type AState ; // static _XDATA MODE_DESCRIPTION ModeID = MODE_InvalidMode; // BYTE I2C_DEV ; // BYTE I2C_ADDR ; ////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////// // // Interrupt Type // ///////////////////////////////////////////////// // BYTE bIntType = 0 ; // ///////////////////////////////////////////////// // // Video Property // ///////////////////////////////////////////////// // BYTE bInputVideoMode ; // BYTE bOutputVideoMode ; // BYTE Instance[0].bInputVideoSignalType = 0 /* | T_MODE_CCIR656 | T_MODE_SYNCEMB | T_MODE_INDDR */ ; // for Sync Embedded,CCIR656,InputDDR // BOOL Instance[0].bAuthenticated = FALSE ; // ///////////////////////////////////////////////// // // Video Property // ///////////////////////////////////////////////// // BYTE bOutputAudioMode = 0 ; // BYTE bAudioChannelSwap = 0 ; ////////////////////////////////////////////////////////////////////// // BOOL Instance[0].bHDMIMode = FALSE; // BOOL Instance[0].bIntPOL = FALSE ; // 0 = Low Active // BOOL bHPD ; INSTANCE Instance[HDMITX_INSTANCE_MAX] ; ////////////////////////////////////////////////////////////////////// // Function Prototype ////////////////////////////////////////////////////////////////////// // static BOOL IsRxSense() ; static void SetInputMode(BYTE InputMode,BYTE bInputSignalType) ; static void SetCSCScale(BYTE bInputMode,BYTE bOutputMode) ; // static void SetupAFE(BYTE ucFreqInMHz) ; static void SetupAFE(VIDEOPCLKLEVEL PCLKLevel) ; static void FireAFE() ; static SYS_STATUS SetAudioFormat(BYTE NumChannel,BYTE AudioEnable,BYTE bSampleFreq,BYTE AudSWL,BYTE AudioCatCode) ; static SYS_STATUS SetNCTS(ULONG PCLK,ULONG Fs) ; static void AutoAdjustAudio() ; static void SetupAudioChannel() ; static SYS_STATUS SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame) ; static SYS_STATUS SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame) ; static SYS_STATUS SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame) ; static SYS_STATUS SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame) ; static SYS_STATUS ReadEDID(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count) ; static void AbortDDC() ; static void ClearDDCFIFO() ; static void ClearDDCFIFO() ; static void GenerateDDCSCLK() ; static SYS_STATUS HDCP_EnableEncryption() ; static void HDCP_ResetAuth() ; static void HDCP_Auth_Fire() ; static void HDCP_StartAnCipher() ; static void HDCP_StopAnCipher() ; static void HDCP_GenerateAn() ; // RICHARD static SYS_STATUS HDCP_GetVr(ULONG *pVr) ; static SYS_STATUS HDCP_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus) ; static SYS_STATUS HDCP_GetBKSV(BYTE *pBKSV) ; static SYS_STATUS HDCP_Authenticate() ; static SYS_STATUS HDCP_Authenticate_Repeater() ; static SYS_STATUS HDCP_VerifyIntegration() ; static SYS_STATUS HDCP_GetKSVList(BYTE *pKSVList,BYTE cDownStream) ; static SYS_STATUS HDCP_CheckSHA(BYTE M0[],USHORT BStatus,BYTE KSVList[],int devno,BYTE Vr[]) ; static void HDCP_ResumeAuthentication() ; static void HDCP_Reset() ; static void ENABLE_NULL_PKT() ; static void ENABLE_ACP_PKT() ; static void ENABLE_ISRC1_PKT() ; static void ENABLE_ISRC2_PKT() ; static void ENABLE_AVI_INFOFRM_PKT() ; static void ENABLE_AUD_INFOFRM_PKT() ; static void ENABLE_SPD_INFOFRM_PKT() ; static void ENABLE_MPG_INFOFRM_PKT() ; static void DISABLE_NULL_PKT() ; static void DISABLE_ACP_PKT() ; static void DISABLE_ISRC1_PKT() ; static void DISABLE_ISRC2_PKT() ; static void DISABLE_AVI_INFOFRM_PKT() ; static void DISABLE_AUD_INFOFRM_PKT() ; static void DISABLE_SPD_INFOFRM_PKT() ; static void DISABLE_MPG_INFOFRM_PKT() ; static BYTE countbit(BYTE b) ; #ifdef HDMITX_REG_DEBUG static void DumpCatHDMITXReg() ; #endif // DEBUG ////////////////////////////////////////////////////////////////////// // Function Body. ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // utility function for main.. ////////////////////////////////////////////////////////////////////// // int aiNonCEAVIC[] = { 2 } ; // Y,C,RGB offset // for register 73~75 static _CODE BYTE bCSCOffset_16_235[] = { 0x00,0x80,0x00 }; static _CODE BYTE bCSCOffset_0_255[] = { 0x10,0x80,0x10 }; #ifdef SUPPORT_INPUTRGB static _CODE BYTE bCSCMtx_RGB2YUV_ITU601_16_235[] = { 0xB2,0x04,0x64,0x02,0xE9,0x00, 0x93,0x3C,0x16,0x04,0x56,0x3F, 0x49,0x3D,0x9F,0x3E,0x16,0x04 } ; static _CODE BYTE bCSCMtx_RGB2YUV_ITU601_0_255[] = { 0x09,0x04,0x0E,0x02,0xC8,0x00, 0x0E,0x3D,0x83,0x03,0x6E,0x3F, 0xAC,0x3D,0xD0,0x3E,0x83,0x03 } ; static _CODE BYTE bCSCMtx_RGB2YUV_ITU709_16_235[] = { 0xB8,0x05,0xB4,0x01,0x93,0x00, 0x49,0x3C,0x16,0x04,0x9F,0x3F, 0xD9,0x3C,0x10,0x3F,0x16,0x04 } ; static _CODE BYTE bCSCMtx_RGB2YUV_ITU709_0_255[] = { 0xE5,0x04,0x78,0x01,0x81,0x00, 0xCE,0x3C,0x83,0x03,0xAE,0x3F, 0x49,0x3D,0x33,0x3F,0x83,0x03 } ; #endif /* #ifdef SUPPORT_INPUTYUV static _CODE BYTE bCSCMtx_YUV2RGB_ITU601_16_235[] = { 0x00,0x08,0x6A,0x3A,0x4F,0x3D, 0x00,0x08,0xF7,0x0A,0x00,0x00, 0x00,0x08,0x00,0x00,0xDB,0x0D } ; static _CODE BYTE bCSCMtx_YUV2RGB_ITU601_0_255[] = { 0x4F,0x09,0x81,0x39,0xDF,0x3C, 0x4F,0x09,0xC2,0x0C,0x00,0x00, 0x4F,0x09,0x00,0x00,0x1E,0x10 } ; static _CODE BYTE bCSCMtx_YUV2RGB_ITU709_16_235[] = { 0x00,0x08,0x53,0x3C,0x89,0x3E, 0x00,0x08,0x51,0x0C,0x00,0x00, 0x00,0x08,0x00,0x00,0x87,0x0E } ; static _CODE BYTE bCSCMtx_YUV2RGB_ITU709_0_255[] = { 0x4F,0x09,0xBA,0x3B,0x4B,0x3E, 0x4F,0x09,0x56,0x0E,0x00,0x00, 0x4F,0x09,0x00,0x00,0xE7,0x10 } ; #endif*/ #ifdef SUPPORT_INPUTYUV BYTE bCSCMtx_YUV2RGB_ITU601_16_235[] = { 0x00,0x08,0x6A,0x3A,0x4F,0x3D, 0x00,0x08,0xF7,0x0A,0x00,0x00, 0x00,0x08,0x00,0x00,0xDB,0x0D } ; BYTE bCSCMtx_YUV2RGB_ITU601_0_255[] = { 0x4F,0x09,0x81,0x39,0xDF,0x3C, 0x4F,0x09,0xC2,0x0C,0x00,0x00, 0x4F,0x09,0x00,0x00,0x1E,0x10 } ; BYTE bCSCMtx_YUV2RGB_ITU709_16_235[] = { 0x00,0x08,0x53,0x3C,0x89,0x3E, 0x00,0x08,0x51,0x0C,0x00,0x00, 0x00,0x08,0x00,0x00,0x87,0x0E } ; BYTE bCSCMtx_YUV2RGB_ITU709_0_255[] = { 0x4F,0x09,0xBA,0x3B,0x4B,0x3E, 0x4F,0x09,0x56,0x0E,0x00,0x00, 0x4F,0x09,0x00,0x00,0xE7,0x10 } ; #endif ////////////////////////////////////////////////////////////////////// // external Interface // ////////////////////////////////////////////////////////////////////// void HDMITX_InitInstance(INSTANCE *pInstance) { if(pInstance && 0 < HDMITX_INSTANCE_MAX) { Instance[0] = *pInstance ; } } static BYTE InitIT6613_HDCPROM() { BYTE uc[5] ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(0xF8,0xC3) ; //password HDMITX_WriteI2C_Byte(0xF8,0xA5) ; // password HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x60) ; // Richard, ???? I2C_Read_ByteN(0xE0,0x00,uc,5) ; // richard note. internal rom is used if(uc[0] == 1 && uc[1] == 1 && uc[2] == 1 && uc[3] == 1 && uc[4] == 1) { // with internal eMem HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xE0) ; HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x48) ; } else { // with external ROM HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xA0) ; // ROMHeader HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x00) ; // Richard, ???? } HDMITX_WriteI2C_Byte(0xF8,0xFF) ; // password // richard add return ER_SUCCESS; } void InitIT6613() { // config interrupt HDMITX_WriteI2C_Byte(REG_TX_INT_CTRL,Instance[0].bIntType) ; Instance[0].bIntPOL = (Instance[0].bIntType&B_INTPOL_ACTH)?TRUE:FALSE ; // Reset HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_REF_RST|B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; DelayMS(1) ; HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; #if 0 // Enable clock ring (richard add according toe programming guide) HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL, 0x10); // Set default DVI mode (richard add according toe programming guide) // HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE, 0x01); // set HDMI mode HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE, 0x00); // set DVI mode #endif // Avoid power loading in un play status. HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; // set interrupt mask,mask value 0 is interrupt available. // richard HDMITX_WriteI2C_Byte(REG_TX_INT_MASK1,0xB2) ; // enable interrupt: HPD, DDCBusHangMask, HDMITX_WriteI2C_Byte(REG_TX_INT_MASK1,0xB2) ; // enable interrupt: HPD, DDCBusHangMask, HDMITX_WriteI2C_Byte(REG_TX_INT_MASK2,0xF8) ; // enable interrupt: AuthFailMask, AUthDoneMask, KSVListChkMask HDMITX_WriteI2C_Byte(REG_TX_INT_MASK3,0x37) ; // enable interrupt: PktAudMask, PktDBDMask, PkMpgMask, AUdCTSMask, HDCPSynDetMask Switch_HDMITX_Bank(0) ; DISABLE_NULL_PKT() ; DISABLE_ACP_PKT() ; DISABLE_ISRC1_PKT() ; DISABLE_ISRC2_PKT() ; DISABLE_AVI_INFOFRM_PKT() ; DISABLE_AUD_INFOFRM_PKT() ; DISABLE_SPD_INFOFRM_PKT() ; DISABLE_MPG_INFOFRM_PKT(); ////////////////////////////////////////////////////////////////// // Setup Output Audio format. ////////////////////////////////////////////////////////////////// HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,Instance[0].bOutputAudioMode) ; // regE1 bOutputAudioMode should be loaded from ROM image. ////////////////////////////////////////////////////////////////// // Setup HDCP ROM ////////////////////////////////////////////////////////////////// #ifdef SUPPORT_HDCP InitIT6613_HDCPROM() ; #endif // #ifdef EXTERN_HDCPROM // #pragma message("EXTERN ROM CODED") ; // HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xA0) ; // #endif } ////////////////////////////////////////////////////////////////////// // export this for dynamic change input signal ////////////////////////////////////////////////////////////////////// BOOL SetupVideoInputSignal(BYTE inputSignalType) { Instance[0].bInputVideoSignalType = inputSignalType ; // SetInputMode(inputColorMode,Instance[0].bInputVideoSignalType) ; return TRUE ; } BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) { // bInputVideoMode,bOutputVideoMode,Instance[0].bInputVideoSignalType,bAudioInputType,should be configured by upper F/W or loaded from EEPROM. // should be configured by initsys.c WORD i ; BYTE uc ; // VIDEOPCLKLEVEL level ; HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; Instance[0].bHDMIMode = (BYTE)bHDMI ; if(Instance[0].bHDMIMode) { SetAVMute(TRUE) ; } SetInputMode(inputColorMode,Instance[0].bInputVideoSignalType) ; SetCSCScale(inputColorMode,outputColorMode) ; if(Instance[0].bHDMIMode) { HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_HDMI_MODE) ; } else { HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_DVI_MODE) ; } #ifdef INVERT_VID_LATCHEDGE uc = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1) ; uc |= B_VDO_LATCH_EDGE ; HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, uc) ; #endif HDMITX_WriteI2C_Byte(REG_TX_SW_RST, B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; // if (pVTiming->VideoPixelClock>80000000) // { // level = PCLK_HIGH ; // } // else if (pVTiming->VideoPixelClock>20000000) // { // level = PCLK_MEDIUM ; // } // else // { // level = PCLK_LOW ; // } SetupAFE(level) ; // pass if High Freq request for(i = 0 ; i < 100 ; i++) { if(HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) { break ; } DelayMS(1) ; } // Clive suggestion. // clear int3 video stable interrupt. HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,B_CLR_VIDSTABLE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; FireAFE() ; return TRUE ; } BOOL EnableAudioOutput(ULONG VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF) { BYTE bAudioChannelEnable ; // richard unsigned long N ; Instance[0].TMDSClock = VideoPixelClock ; Instance[0].bAudFs = bAudioSampleFreq ; ErrorF("EnableAudioOutput(%d,%ld,%x,%d,%d,%d);\n",0,VideoPixelClock,bAudioSampleFreq,ChannelNumber,bAudSWL,bSPDIF) ; switch(ChannelNumber) { case 7: case 8: bAudioChannelEnable = 0xF ; break ; case 6: case 5: bAudioChannelEnable = 0x7 ; break ; case 4: case 3: bAudioChannelEnable = 0x3 ; break ; case 2: case 1: default: bAudioChannelEnable = 0x1 ; break ; } if(bSPDIF) bAudioChannelEnable |= B_AUD_SPDIF ; if( bSPDIF ) { Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REGPktAudCTS0,0x50) ; HDMITX_WriteI2C_Byte(REGPktAudCTS1,0x73) ; HDMITX_WriteI2C_Byte(REGPktAudCTS2,0x00) ; HDMITX_WriteI2C_Byte(REGPktAudN0,0) ; HDMITX_WriteI2C_Byte(REGPktAudN1,0x18) ; HDMITX_WriteI2C_Byte(REGPktAudN2,0) ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(0xC5, 2) ; // D[1] = 0, HW auto count CTS } else { SetNCTS(VideoPixelClock,bAudioSampleFreq) ; } /* if(VideoPixelClock != 0) { SetNCTS(VideoPixelClock,bAudioSampleFreq) ; } else { switch(bAudioSampleFreq) { case AUDFS_32KHz: N = 4096; break; case AUDFS_44p1KHz: N = 6272; break; case AUDFS_48KHz: N = 6144; break; case AUDFS_88p2KHz: N = 12544; break; case AUDFS_96KHz: N = 12288; break; case AUDFS_176p4KHz: N = 25088; break; case AUDFS_192KHz: N = 24576; break; default: N = 6144; } Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REGPktAudN0,(BYTE)((N)&0xFF)) ; HDMITX_WriteI2C_Byte(REGPktAudN1,(BYTE)((N>>8)&0xFF)) ; HDMITX_WriteI2C_Byte(REGPktAudN2,(BYTE)((N>>16)&0xF)) ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,0) ; // D[1] = 0,HW auto count CTS } */ //HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_AUD_RST|B_AREF_RST)) ; SetAudioFormat(ChannelNumber,bAudioChannelEnable,bAudioSampleFreq,bAudSWL,bSPDIF) ; #ifdef HDMITX_REG_DEBUG DumpCatHDMITXReg() ; #endif // HDMITX_REG_DEBUG return TRUE ; } BOOL GetEDIDData(int EDIDBlockID,BYTE *pEDIDData) { if(!pEDIDData) { return FALSE ; } if(ReadEDID(pEDIDData,EDIDBlockID/2,(EDIDBlockID%2)*128,128) == ER_FAIL) { return FALSE ; } return TRUE ; } BOOL EnableHDCP(BYTE bEnable) { if(bEnable) { if(ER_FAIL == HDCP_Authenticate()) { HDCP_ResetAuth() ; return FALSE ; } } else { HDCP_ResetAuth() ; } return TRUE ; } BOOL CheckHDMITX(BYTE *pHPD,BYTE *pHPDChange) { BYTE intdata1,intdata2,intdata3,sysstat; BYTE intclr3 = 0 ; BOOL PrevHPD = Instance[0].bHPD ; BOOL HPD ; sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; // read system status register // OS_PRINTF("sysstat(REG[0x0E])=%02Xh\r\n", sysstat); HPD = ((sysstat & (B_HPDETECT|B_RXSENDETECT)) == (B_HPDETECT|B_RXSENDETECT))?TRUE:FALSE ; // 2007/06/20 added by jj_tseng@chipadvanced.com if(pHPDChange) { *pHPDChange = FALSE ; } //~jj_tseng@chipadvanced.com 2007/06/20 if(!HPD) { Instance[0].bAuthenticated = FALSE ; } if(sysstat & B_INT_ACTIVE) // interrupt is activce { intdata1 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) ; // reg 0x06 //ErrorF("INT_Handler: reg%02x = %02x\n",REG_TX_INT_STAT1,intdata1) ; if(intdata1 & B_INT_DDCFIFO_ERR) { //ErrorF("DDC FIFO Error.\n") ; ClearDDCFIFO() ; } if(intdata1 & B_INT_DDC_BUS_HANG) { ErrorF("DDC BUS HANG.\n") ; AbortDDC() ; if(Instance[0].bAuthenticated) { ErrorF("when DDC hang,and aborted DDC,the HDCP authentication need to restart.\n") ; HDCP_ResumeAuthentication() ; } } if(intdata1 & (B_INT_HPD_PLUG|B_INT_RX_SENSE)) { if(pHPDChange) *pHPDChange = TRUE ; if(!HPD) { // reset HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_AREF_RST|B_VID_RST|B_AUD_RST|B_HDCP_RST) ; DelayMS(1) ; HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; //ErrorF("Unplug,%x %x\n",HDMITX_ReadI2C_Byte(REG_TX_SW_RST),HDMITX_ReadI2C_Byte(REG_TX_AFE_DRV_CTRL)) ; // VState = TXVSTATE_Unplug ; } } intdata2 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; // reg 0x07 //ErrorF("INT_Handler: reg%02x = %02x\n",REG_TX_INT_STAT2,intdata2) ; #ifdef SUPPORT_HDCP if(intdata2 & B_INT_AUTH_DONE) { ErrorF("interrupt Authenticate Done.\n") ; HDMITX_OrREG_Byte(REG_TX_INT_MASK2,B_T_AUTH_DONE_MASK) ; Instance[0].bAuthenticated = TRUE ; SetAVMute(FALSE) ; } if(intdata2 & B_INT_AUTH_FAIL) { ErrorF("interrupt Authenticate Fail.\n") ; AbortDDC(); // @emily add HDCP_ResumeAuthentication() ; } #endif // SUPPORT_HDCP intdata3 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT3) ; // reg 0x08 if(intdata3 & B_INT_VIDSTABLE) { sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; if(sysstat & B_TXVIDSTABLE) { FireAFE() ; } } HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0xFF) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0xFF) ; intclr3 = (HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS))|B_CLR_AUD_CTS | B_INTACTDONE ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3) ; // clear interrupt. intclr3 &= ~(B_INTACTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3) ; // INTACTDONE reset to zero. } else { if(pHPDChange) { *pHPDChange = (HPD != PrevHPD)?TRUE:FALSE ; if(*pHPDChange &&(!HPD)) { HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; } } } SetupAudioChannel() ; // 2007/12/12 added by jj_tseng if(pHPD) { *pHPD = HPD ? TRUE:FALSE ; } Instance[0].bHPD = (BYTE)HPD ; return HPD ; } void DisableIT6613() { HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_AREF_RST|B_VID_RST|B_AUD_RST|B_HDCP_RST) ; DelayMS(1) ; HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; } void DisableVideoOutput() { BYTE uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_VID_RST ; HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc) ; HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; } void DisableAudioOutput() { BYTE uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_AUD_RST ; HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc) ; } BOOL EnableAVIInfoFrame(BYTE bEnable,BYTE *pAVIInfoFrame) { if(!bEnable) { DISABLE_AVI_INFOFRM_PKT() ; return TRUE ; } if(SetAVIInfoFrame((AVI_InfoFrame *)pAVIInfoFrame) == ER_SUCCESS) { return TRUE ; } return FALSE ; } BOOL EnableAudioInfoFrame(BYTE bEnable,BYTE *pAudioInfoFrame) { if(!bEnable) { // richard modify, DISABLE_AVI_INFOFRM_PKT() ; DISABLE_AUD_INFOFRM_PKT(); return TRUE ; } if(SetAudioInfoFrame((Audio_InfoFrame *)pAudioInfoFrame) == ER_SUCCESS) { return TRUE ; } return FALSE ; } void SetAVMute(BYTE bEnable) { BYTE uc ; Switch_HDMITX_Bank(0) ; uc = HDMITX_ReadI2C_Byte(REG_TX_GCP) ; uc &= ~B_TX_SETAVMUTE ; uc |= bEnable?B_TX_SETAVMUTE:0 ; HDMITX_WriteI2C_Byte(REG_TX_GCP,uc) ; HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; } void SetOutputColorDepthPhase(BYTE ColorDepth,BYTE bPhase) { BYTE uc ; BYTE bColorDepth ; if(ColorDepth == 30) { bColorDepth = B_CD_30 ; } else if (ColorDepth == 36) { bColorDepth = B_CD_36 ; } else if (ColorDepth == 24) { bColorDepth = B_CD_24 ; } else { bColorDepth = 0 ; // not indicated } Switch_HDMITX_Bank(0) ; uc = HDMITX_ReadI2C_Byte(REG_TX_GCP) ; uc &= ~B_COLOR_DEPTH_MASK ; uc |= bColorDepth&B_COLOR_DEPTH_MASK; HDMITX_WriteI2C_Byte(REG_TX_GCP,uc) ; } void Get6613Reg(BYTE *pReg) { int i ; BYTE reg ; Switch_HDMITX_Bank(0) ; for(i = 0 ; i < 0x100 ; i++) { reg = i & 0xFF ; pReg[i] = HDMITX_ReadI2C_Byte(reg) ; } Switch_HDMITX_Bank(1) ; for(reg = 0x30 ; reg < 0xB0 ; i++,reg++) { pReg[i] = HDMITX_ReadI2C_Byte(reg) ; } Switch_HDMITX_Bank(0) ; } ////////////////////////////////////////////////////////////////////// // SubProcedure process // ////////////////////////////////////////////////////////////////////// #ifdef SUPPORT_DEGEN typedef struct { MODE_ID id ; BYTE Reg90; BYTE Reg92; BYTE Reg93; BYTE Reg94; BYTE Reg9A; BYTE Reg9B; BYTE Reg9C; BYTE Reg9D; BYTE Reg9E; BYTE Reg9F; } DEGEN_Setting ; static _CODE DEGEN_Setting DeGen_Table[] = { {CEA_640x480p60 ,0x01,0x8E,0x0E,0x30,0x22,0x02,0x20,0xFF,0xFF,0xFF}, // HDES = 142, HDEE = 782, VDES = 34, VDEE = 514 {CEA_720x480p60 ,0x01,0x78,0x48,0x30,0x23,0x03,0x20,0xFF,0xFF,0xFF}, // HDES = 120, HDEE = 840, VDES = 35, VDEE = 515 {CEA_1280x720p60 ,0x07,0x02,0x02,0x61,0x18,0xE8,0x20,0xFF,0xFF,0xFF}, // HDES = 258, HDEE = 1538, VDES = 24, VDEE = 744 // {CEA_1920x1080i60 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x45,0x61,0x42}, // // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 581, VDE2 = 1121 {CEA_1920x1080i60 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x46,0x62,0x42}, // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 582, VDE2 = 1122 {CEA_720x480i60 ,0x01,0x75,0x45,0x30,0x11,0x01,0x10,0x17,0x07,0x21}, // HDES = 117, HDEE = 837, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 {CEA_720x240p60 ,0x01,0x75,0x45,0x30,0x11,0x01,0x10,0xFF,0xFF,0xFF}, // HDES = 117, HDEE = 837, VDES = 17, VDEE = 257 {CEA_1440x480i60 ,0x01,0xEC,0x8C,0x60,0x11,0x01,0x10,0x17,0x07,0x21}, // HDES = 236, HDEE = 1676, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 {CEA_1440x240p60 ,0x01,0xEC,0x8C,0x60,0x11,0x01,0x10,0xFF,0xFF,0xFF}, // HDES = 236, HDEE = 1676, VDES = 17, VDEE = 257 {CEA_2880x480i60 ,0x01,0x16,0x56,0xD2,0x11,0x01,0x10,0x17,0x07,0x21}, // HDES = 534, HDEE = 3414, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 {CEA_2880x240p60 ,0x01,0x16,0x56,0xD2,0x11,0x01,0x10,0xFF,0xFF,0xFF}, // HDES = 534, HDEE = 3414, VDES = 17, VDEE = 257 {CEA_1440x480p60 ,0x01,0xF2,0x92,0x60,0x23,0x03,0x20,0xFF,0xFF,0xFF}, // HDES = 242, HDEE = 1682, VDES = 35, VDEE = 515 {CEA_1920x1080p60 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 {CEA_720x576p50 ,0x01,0x82,0x52,0x30,0x2b,0x6b,0x20,0xFF,0xFF,0xFF}, // HDES = 130, HDEE = 850, VDES = 43, VDEE = 619 {CEA_1280x720p50 ,0x07,0x02,0x02,0x61,0x18,0xE8,0x20,0xFF,0xFF,0xFF}, // HDES = 258, HDEE = 1538, VDES = 24, VDEE = 744 {CEA_1920x1080i50 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x46,0x62,0x42}, // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 582, VDE2 = 1122 {CEA_720x576i50 ,0x01,0x82,0x52,0x30,0x15,0x35,0x10,0x4D,0x6D,0x21}, // HDES = 130, HDEE = 850, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 {CEA_1440x576i50 ,0x01,0x06,0xA6,0x61,0x15,0x35,0x10,0x4D,0x6D,0x21}, // HDES = 262, HDEE = 1702, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 {CEA_720x288p50 ,0x01,0x82,0x52,0x30,0x15,0x35,0x10,0xFF,0xFF,0xFF}, // HDES = 130, HDEE = 850, VDES = 21, VDEE = 309 {CEA_1440x288p50 ,0x01,0x06,0xA6,0x61,0x15,0x35,0x10,0xFF,0xFF,0xFF}, // HDES = 262, HDEE = 1702, VDES = 21, VDEE = 309 {CEA_2880x576i50 ,0x01,0x0E,0x4E,0xD2,0x15,0x35,0x10,0x4D,0x6D,0x21}, // HDES = 526, HDEE = 3406, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 {CEA_2880x288p50 ,0x01,0x0E,0x4E,0xD2,0x15,0x35,0x10,0xFF,0xFF,0xFF}, // HDES = 526, HDEE = 3406, VDES = 21, VDEE = 309 {CEA_1440x576p50 ,0x05,0x06,0xA6,0x61,0x2B,0x6B,0x20,0xFF,0xFF,0xFF}, // HDES = 262, HDEE = 1702, VDES = 43, VDEE = 619 {CEA_1920x1080p50 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 {CEA_1920x1080p24 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 {CEA_1920x1080p25 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 {CEA_1920x1080p30 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 {VESA_640x350p85 ,0x03,0x9E,0x1E,0x30,0x3E,0x9C,0x10,0xFF,0xFF,0xFF}, // HDES = 158, HDEE = 798, VDES = 62, VDEE = 412 {VESA_640x400p85 ,0x05,0x9E,0x1E,0x30,0x2B,0xBB,0x10,0xFF,0xFF,0xFF}, // HDES = 158, HDEE = 798, VDES = 43, VDEE = 443 {VESA_720x400p85 ,0x05,0xB2,0x82,0x30,0x2C,0xBC,0x10,0xFF,0xFF,0xFF}, // HDES = 178, HDEE = 898, VDES = 44, VDEE = 444 {VESA_640x480p60 ,0x01,0x8E,0x0E,0x30,0x22,0x02,0x20,0xFF,0xFF,0xFF}, // HDES = 142, HDEE = 782, VDES = 34, VDEE = 514 {VESA_640x480p72 ,0x01,0xA6,0x26,0x30,0x1E,0xFE,0x10,0xFF,0xFF,0xFF}, // HDES = 166, HDEE = 806, VDES = 30, VDEE = 510 {VESA_640x480p75 ,0x01,0xB6,0x36,0x30,0x12,0xF2,0x10,0xFF,0xFF,0xFF}, // HDES = 182, HDEE = 822, VDES = 18, VDEE = 498 {VESA_640x480p85 ,0x01,0x86,0x06,0x30,0x1B,0xFB,0x10,0xFF,0xFF,0xFF}, // HDES = 134, HDEE = 774, VDES = 27, VDEE = 507 {VESA_800x600p56 ,0x07,0xC6,0xE6,0x30,0x17,0x6F,0x20,0xFF,0xFF,0xFF}, // HDES = 198, HDEE = 998, VDES = 23, VDEE = 623 {VESA_800x600p60 ,0x07,0xD6,0xF6,0x30,0x1A,0x72,0x20,0xFF,0xFF,0xFF}, // HDES = 214, HDEE = 1014, VDES = 26, VDEE = 626 {VESA_800x600p72 ,0x07,0xB6,0xD6,0x30,0x1C,0x74,0x20,0xFF,0xFF,0xFF}, // HDES = 182, HDEE = 982, VDES = 28, VDEE = 628 {VESA_800x600p75 ,0x07,0xEE,0x0E,0x40,0x17,0x6F,0x20,0xFF,0xFF,0xFF}, // HDES = 238, HDEE = 1038, VDES = 23, VDEE = 623 {VESA_800X600p85 ,0x07,0xD6,0xF6,0x30,0x1D,0x75,0x20,0xFF,0xFF,0xFF}, // HDES = 214, HDEE = 1014, VDES = 29, VDEE = 629 {VESA_840X480p60 ,0x07,0xDE,0x2E,0x40,0x1E,0xFE,0x10,0xFF,0xFF,0xFF}, // HDES = 222, HDEE = 1070, VDES = 30, VDEE = 510 {VESA_1024x768p60 ,0x01,0x26,0x26,0x51,0x22,0x22,0x30,0xFF,0xFF,0xFF}, // HDES = 294, HDEE = 1318, VDES = 34, VDEE = 802 {VESA_1024x768p70 ,0x01,0x16,0x16,0x51,0x22,0x22,0x30,0xFF,0xFF,0xFF}, // HDES = 278, HDEE = 1302, VDES = 34, VDEE = 802 {VESA_1024x768p75 ,0x07,0x0E,0x0E,0x51,0x1E,0x1E,0x30,0xFF,0xFF,0xFF}, // HDES = 270, HDEE = 1294, VDES = 30, VDEE = 798 {VESA_1024x768p85 ,0x07,0x2E,0x2E,0x51,0x26,0x26,0x30,0xFF,0xFF,0xFF}, // HDES = 302, HDEE = 1326, VDES = 38, VDEE = 806 {VESA_1152x864p75 ,0x07,0x7E,0xFE,0x51,0x22,0x82,0x30,0xFF,0xFF,0xFF}, // HDES = 382, HDEE = 1534, VDES = 34, VDEE = 898 {VESA_1280x768p60R ,0x03,0x6E,0x6E,0x50,0x12,0x12,0x30,0xFF,0xFF,0xFF}, // HDES = 110, HDEE = 1390, VDES = 18, VDEE = 786 {VESA_1280x768p60 ,0x05,0x3E,0x3E,0x61,0x1A,0x1A,0x30,0xFF,0xFF,0xFF}, // HDES = 318, HDEE = 1598, VDES = 26, VDEE = 794 {VESA_1280x768p75 ,0x05,0x4E,0x4E,0x61,0x21,0x21,0x30,0xFF,0xFF,0xFF}, // HDES = 334, HDEE = 1614, VDES = 33, VDEE = 801 {VESA_1280x768p85 ,0x05,0x5E,0x5E,0x61,0x25,0x25,0x30,0xFF,0xFF,0xFF}, // HDES = 350, HDEE = 1630, VDES = 37, VDEE = 805 {VESA_1280x960p60 ,0x07,0xA6,0xA6,0x61,0x26,0xE6,0x30,0xFF,0xFF,0xFF}, // HDES = 422, HDEE = 1702, VDES = 38, VDEE = 998 {VESA_1280x960p85 ,0x07,0x7E,0x7E,0x61,0x31,0xF1,0x30,0xFF,0xFF,0xFF}, // HDES = 382, HDEE = 1662, VDES = 49, VDEE = 1009 {VESA_1280x1024p60 ,0x07,0x66,0x66,0x61,0x28,0x28,0x40,0xFF,0xFF,0xFF}, // HDES = 358, HDEE = 1638, VDES = 40, VDEE = 1064 {VESA_1280x1024p75 ,0x07,0x86,0x86,0x61,0x28,0x28,0x40,0xFF,0xFF,0xFF}, // HDES = 390, HDEE = 1670, VDES = 40, VDEE = 1064 {VESA_1280X1024p85 ,0x07,0x7E,0x7E,0x61,0x2E,0x2E,0x40,0xFF,0xFF,0xFF}, // HDES = 382, HDEE = 1662, VDES = 46, VDEE = 1070 {VESA_1360X768p60 ,0x07,0x6E,0xBE,0x61,0x17,0x17,0x30,0xFF,0xFF,0xFF}, // HDES = 366, HDEE = 1726, VDES = 23, VDEE = 791 {VESA_1400x768p60R ,0x03,0x6E,0xE6,0x50,0x1A,0x34,0x40,0xFF,0xFF,0xFF}, // HDES = 110, HDEE = 1510, VDES = 26, VDEE = 1076 {VESA_1400x768p60 ,0x05,0x76,0xEE,0x61,0x23,0x3D,0x40,0xFF,0xFF,0xFF}, // HDES = 374, HDEE = 1774, VDES = 35, VDEE = 1085 {VESA_1400x1050p75 ,0x05,0x86,0xFE,0x61,0x2D,0x47,0x40,0xFF,0xFF,0xFF}, // HDES = 390, HDEE = 1790, VDES = 45, VDEE = 1095 {VESA_1400x1050p85 ,0x05,0x96,0x0E,0x71,0x33,0x4D,0x40,0xFF,0xFF,0xFF}, // HDES = 406, HDEE = 1806, VDES = 51, VDEE = 1101 {VESA_1440x900p60R ,0x03,0x6E,0x0E,0x60,0x16,0x9A,0x30,0xFF,0xFF,0xFF}, // HDES = 110, HDEE = 1550, VDES = 22, VDEE = 922 {VESA_1440x900p60 ,0x05,0x7E,0x1E,0x71,0x1E,0xA2,0x30,0xFF,0xFF,0xFF}, // HDES = 382, HDEE = 1822, VDES = 30, VDEE = 930 {VESA_1440x900p75 ,0x05,0x8E,0x2E,0x71,0x26,0xAA,0x30,0xFF,0xFF,0xFF}, // HDES = 398, HDEE = 1838, VDES = 38, VDEE = 938 {VESA_1440x900p85 ,0x05,0x96,0x36,0x71,0x2C,0xB0,0x30,0xFF,0xFF,0xFF}, // HDES = 406, HDEE = 1846, VDES = 44, VDEE = 944 {VESA_1600x1200p60 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 {VESA_1600x1200p65 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 {VESA_1600x1200p70 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 {VESA_1600x1200p75 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 {VESA_1600x1200p85 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 {VESA_1680x1050p60R ,0x03,0x6E,0xFE,0x60,0x1A,0x34,0x40,0xFF,0xFF,0xFF}, // HDES = 110, HDEE = 1790, VDES = 26, VDEE = 1076 {VESA_1680x1050p60 ,0x05,0xC6,0x56,0x81,0x23,0x3D,0x40,0xFF,0xFF,0xFF}, // HDES = 454, HDEE = 2134, VDES = 35, VDEE = 1085 {VESA_1680x1050p75 ,0x05,0xD6,0x66,0x81,0x2D,0x47,0x40,0xFF,0xFF,0xFF}, // HDES = 470, HDEE = 2150, VDES = 45, VDEE = 1095 {VESA_1680x1050p85 ,0x05,0xDE,0x6E,0x81,0x33,0x4D,0x40,0xFF,0xFF,0xFF}, // HDES = 478, HDEE = 2158, VDES = 51, VDEE = 1101 {VESA_1792x1344p60 ,0x05,0x0E,0x0E,0x92,0x30,0x70,0x50,0xFF,0xFF,0xFF}, // HDES = 526, HDEE = 2318, VDES = 48, VDEE = 1392 {VESA_1792x1344p75 ,0x05,0x36,0x36,0x92,0x47,0x87,0x50,0xFF,0xFF,0xFF}, // HDES = 566, HDEE = 2358, VDES = 71, VDEE = 1415 {VESA_1856x1392p60 ,0x05,0x3E,0x7E,0x92,0x2D,0x9D,0x50,0xFF,0xFF,0xFF}, // HDES = 574, HDEE = 2430, VDES = 45, VDEE = 1437 {VESA_1856x1392p75 ,0x05,0x3E,0x7E,0x92,0x6A,0xDA,0x50,0xFF,0xFF,0xFF}, // HDES = 574, HDEE = 2430, VDES = 106, VDEE = 1498 {VESA_1920x1200p60R ,0x03,0x6E,0xEE,0x70,0x1F,0xCF,0x40,0xFF,0xFF,0xFF}, // HDES = 110, HDEE = 2030, VDES = 31, VDEE = 1231 {VESA_1920x1200p60 ,0x05,0x16,0x96,0x92,0x29,0xD9,0x40,0xFF,0xFF,0xFF}, // HDES = 534, HDEE = 2454, VDES = 41, VDEE = 1241 {VESA_1920x1200p75 ,0x05,0x26,0xA6,0x92,0x33,0xE3,0x40,0xFF,0xFF,0xFF}, // HDES = 550, HDEE = 2470, VDES = 51, VDEE = 1251 {VESA_1920x1200p85 ,0x05,0x2E,0xAE,0x92,0x3A,0xEA,0x40,0xFF,0xFF,0xFF}, // HDES = 558, HDEE = 2478, VDES = 58, VDEE = 1258 {VESA_1920x1440p60 ,0x05,0x26,0xA6,0x92,0x3A,0xDA,0x50,0xFF,0xFF,0xFF}, // HDES = 550, HDEE = 2470, VDES = 58, VDEE = 1498 {VESA_1920x1440p75 ,0x05,0x3E,0xBE,0x92,0x3A,0xDA,0x50,0xFF,0xFF,0xFF}, // HDES = 574, HDEE = 2494, VDES = 58, VDEE = 1498 {UNKNOWN_MODE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} } ; BOOL ProgramDEGenModeByID(MODE_ID id,BYTE bInputSignalType) { int i ; if( (bInputSignalType & (T_MODE_DEGEN|T_MODE_SYNCGEN|T_MODE_SYNCEMB) )==(T_MODE_DEGEN)) { for( i = 0 ; DeGen_Table[i].id != UNKNOWN_MODE ; i++ ) { if( id == DeGen_Table[i].id ) break ; } if( DeGen_Table[i].id == UNKNOWN_MODE ) { return FALSE ; } Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(0x90,DeGen_Table[i].Reg90) ; HDMITX_WriteI2C_Byte(0x92,DeGen_Table[i].Reg92) ; HDMITX_WriteI2C_Byte(0x93,DeGen_Table[i].Reg93) ; HDMITX_WriteI2C_Byte(0x94,DeGen_Table[i].Reg94) ; HDMITX_WriteI2C_Byte(0x9A,DeGen_Table[i].Reg9A) ; HDMITX_WriteI2C_Byte(0x9B,DeGen_Table[i].Reg9B) ; HDMITX_WriteI2C_Byte(0x9C,DeGen_Table[i].Reg9C) ; HDMITX_WriteI2C_Byte(0x9D,DeGen_Table[i].Reg9D) ; HDMITX_WriteI2C_Byte(0x9E,DeGen_Table[i].Reg9E) ; HDMITX_WriteI2C_Byte(0x9F,DeGen_Table[i].Reg9F) ; return TRUE ; } return FALSE ; } #endif #ifdef SUPPORT_SYNCEMBEDDED /* ****************************************************** */ // sync embedded table setting,defined as comment. /* ****************************************************** */ struct SyncEmbeddedSetting { BYTE fmt ; BYTE RegHVPol ; // Reg90 BYTE RegHfPixel ; // Reg91 BYTE RegHSSL ; // Reg95 BYTE RegHSEL ; // Reg96 BYTE RegHSH ; // Reg97 BYTE RegVSS1 ; // RegA0 BYTE RegVSE1 ; // RegA1 BYTE RegVSS2 ; // RegA2 BYTE RegVSE2 ; // RegA3 ULONG PCLK ; BYTE VFreq ; } ; static _CODE struct SyncEmbeddedSetting SyncEmbTable[] = { // {FMT,0x90,0x91, // 0x95,0x96,0x97,0xA0,0xA1,0xA2,0xA3,PCLK,VFREQ}, { 1,0xF0,0x31,0x0E,0x6E,0x00,0x0A,0xC0,0xFF,0xFF,25175000,60}, { 2,0xF0,0x31,0x0E,0x4c,0x00,0x09,0xF0,0xFF,0xFF,27000000,60}, { 3,0xF0,0x31,0x0E,0x4c,0x00,0x09,0xF0,0xFF,0xFF,27000000,60}, { 4,0x76,0x33,0x6c,0x94,0x00,0x05,0xA0,0xFF,0xFF,74175000,60}, { 5,0x26,0x4A,0x56,0x82,0x00,0x02,0x70,0x34,0x92,74175000,60}, { 6,0xE0,0x1B,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,27000000,60}, { 7,0xE0,0x1B,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,27000000,60}, { 8,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,27000000,60}, { 9,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,27000000,60}, { 10,0xe0,0x1b,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,54000000,60}, { 11,0xe0,0x1b,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,54000000,60}, { 12,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,54000000,60}, { 13,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,54000000,60}, { 14,0x00,0xff,0x1e,0x9A,0x00,0x09,0xF0,0xFF,0xFF,54000000,60}, { 15,0x00,0xff,0x1e,0x9A,0x00,0x09,0xF0,0xFF,0xFF,54000000,60}, { 16,0x06,0xff,0x56,0x82,0x00,0x04,0x90,0xFF,0xFF,148350000,60}, { 17,0x00,0xff,0x0a,0x4A,0x00,0x05,0xA0,0xFF,0xFF,27000000,50}, { 18,0x00,0xff,0x0a,0x4A,0x00,0x05,0xA0,0xFF,0xFF,27000000,50}, { 19,0x06,0xff,0xB6,0xDE,0x11,0x05,0xA0,0xFF,0xFF,74250000,50}, { 20,0x66,0x73,0x0e,0x3A,0x22,0x02,0x70,0x34,0x92,74250000,50}, { 21,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,27000000,50}, { 22,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,27000000,50}, { 23,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,27000000,50}, { 24,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,27000000,50}, { 25,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,54000000,50}, { 26,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,54000000,50}, { 27,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,54000000,50}, { 28,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,54000000,50}, { 29,0x04,0xff,0x16,0x96,0x00,0x05,0xA0,0xFF,0xFF,54000000,50}, { 30,0x04,0xff,0x16,0x96,0x00,0x05,0xA0,0xFF,0xFF,54000000,50}, { 31,0x06,0xff,0x0e,0x3a,0x22,0x04,0x90,0xFF,0xFF,148500000,50}, {0xFF,0xFF,0xff,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0} } ; BOOL ProgramSyncEmbeddedVideoMode(BYTE VIC,BYTE bInputSignalType) { int i ; // if Embedded Video,need to generate timing with pattern register ErrorF("ProgramSyncEmbeddedVideoMode(%d,%x)\n",VIC,bInputSignalType) ; if( bInputSignalType & T_MODE_SYNCEMB ) { for(i = 0 ; SyncEmbTable[i].fmt != 0xFF ; i++) { if(VIC == SyncEmbTable[i].fmt) { break ; } } if(SyncEmbTable[i].fmt == 0xFF) { return FALSE ; } HDMITX_WriteI2C_Byte(REG_TX_HVPol,SyncEmbTable[i].RegHVPol) ; // Reg90 HDMITX_WriteI2C_Byte(REG_TX_HfPixel,SyncEmbTable[i].RegHfPixel) ; // Reg91 HDMITX_WriteI2C_Byte(REG_TX_HSSL,SyncEmbTable[i].RegHSSL) ; // Reg95 HDMITX_WriteI2C_Byte(REG_TX_HSEL,SyncEmbTable[i].RegHSEL) ; // Reg96 HDMITX_WriteI2C_Byte(REG_TX_HSH,SyncEmbTable[i].RegHSH) ; // Reg97 HDMITX_WriteI2C_Byte(REG_TX_VSS1,SyncEmbTable[i].RegVSS1) ; // RegA0 HDMITX_WriteI2C_Byte(REG_TX_VSE1,SyncEmbTable[i].RegVSE1) ; // RegA1 HDMITX_WriteI2C_Byte(REG_TX_VSS2,SyncEmbTable[i].RegVSS2) ; // RegA2 HDMITX_WriteI2C_Byte(REG_TX_VSE2,SyncEmbTable[i].RegVSE2) ; // RegA3 } return TRUE ; } #endif // SUPPORT_SYNCEMBEDDED //~jj_tseng@chipadvanced.com 2007/01/02 ////////////////////////////////////////////////////////////////////// // Function: SetInputMode // Parameter: InputMode,bInputSignalType // InputMode - use [1:0] to identify the color space for reg70[7:6], // definition: // #define F_MODE_RGB444 0 // #define F_MODE_YUV422 1 // #define F_MODE_YUV444 2 // #define F_MODE_CLRMOD_MASK 3 // bInputSignalType - defined the CCIR656 D[0],SYNC Embedded D[1],and // DDR input in D[2]. // Return: N/A // Remark: program Reg70 with the input value. // Side-Effect: Reg70. ////////////////////////////////////////////////////////////////////// static void SetInputMode(BYTE InputMode,BYTE bInputSignalType) { BYTE ucData ; ErrorF("SetInputMode(%02X,%02X)\n",InputMode,bInputSignalType) ; ucData = HDMITX_ReadI2C_Byte(REG_TX_INPUT_MODE) ; ucData &= ~(M_INCOLMOD|B_2X656CLK|B_SYNCEMB|B_INDDR|B_PCLKDIV2) ; switch(InputMode & F_MODE_CLRMOD_MASK) { case F_MODE_YUV422: ucData |= B_IN_YUV422 ; break ; case F_MODE_YUV444: ucData |= B_IN_YUV444 ; break ; case F_MODE_RGB444: default: ucData |= B_IN_RGB ; break ; } if(bInputSignalType & T_MODE_PCLKDIV2) { ucData |= B_PCLKDIV2 ; ErrorF("PCLK Divided by 2 mode\n") ; } if(bInputSignalType & T_MODE_CCIR656) { ucData |= B_2X656CLK ; ErrorF("CCIR656 mode\n") ; } if(bInputSignalType & T_MODE_SYNCEMB) { ucData |= B_SYNCEMB ; ErrorF("Sync Embedded mode\n") ; } if(bInputSignalType & T_MODE_INDDR) { ucData |= B_INDDR ; ErrorF("Input DDR mode\n") ; } HDMITX_WriteI2C_Byte(REG_TX_INPUT_MODE,ucData) ; } ////////////////////////////////////////////////////////////////////// // Function: SetCSCScale // Parameter: bInputMode - // D[1:0] - Color Mode // D[4] - Colorimetry 0: ITU_BT601 1: ITU_BT709 // D[5] - Quantization 0: 0_255 1: 16_235 // D[6] - Up/Dn Filter 'Required' // 0: no up/down filter // 1: enable up/down filter when csc need. // D[7] - Dither Filter 'Required' // 0: no dither enabled. // 1: enable dither and dither free go "when required". // bOutputMode - // D[1:0] - Color mode. // Return: N/A // Remark: reg72~reg8D will be programmed depended the input with table. // Side-Effect: ////////////////////////////////////////////////////////////////////// static void SetCSCScale(BYTE bInputMode,BYTE bOutputMode) { BYTE ucData,csc ; BYTE filter = 0 ; // filter is for Video CTRL DN_FREE_GO,EN_DITHER,and ENUDFILT // (1) YUV422 in,RGB/YUV444 output (Output is 8-bit,input is 12-bit) // (2) YUV444/422 in,RGB output (CSC enable,and output is not YUV422) // (3) RGB in,YUV444 output (CSC enable,and output is not YUV422) // // YUV444/RGB24 <-> YUV422 need set up/down filter. switch(bInputMode&F_MODE_CLRMOD_MASK) { #ifdef SUPPORT_INPUTYUV444 case F_MODE_YUV444: ErrorF("Input mode is YUV444 ") ; switch(bOutputMode&F_MODE_CLRMOD_MASK) { case F_MODE_YUV444: ErrorF("Output mode is YUV444\n") ; csc = B_CSC_BYPASS ; break ; case F_MODE_YUV422: ErrorF("Output mode is YUV422\n") ; if(bInputMode & F_MODE_EN_UDFILT) // YUV444 to YUV422 need up/down filter for processing. { filter |= B_TX_EN_UDFILTER ; } csc = B_CSC_BYPASS ; break ; case F_MODE_RGB444: ErrorF("Output mode is RGB24\n") ; csc = B_CSC_YUV2RGB ; if(bInputMode & F_MODE_EN_DITHER) // YUV444 to RGB24 need dither { filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; } break ; } break ; #endif #ifdef SUPPORT_INPUTYUV422 case F_MODE_YUV422: ErrorF("Input mode is YUV422\n") ; switch(bOutputMode&F_MODE_CLRMOD_MASK) { case F_MODE_YUV444: ErrorF("Output mode is YUV444\n") ; csc = B_CSC_BYPASS ; if(bInputMode & F_MODE_EN_UDFILT) // YUV422 to YUV444 need up filter { filter |= B_TX_EN_UDFILTER ; } if(bInputMode & F_MODE_EN_DITHER) // YUV422 to YUV444 need dither { filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; } break ; case F_MODE_YUV422: ErrorF("Output mode is YUV422\n") ; csc = B_CSC_BYPASS ; break ; case F_MODE_RGB444: ErrorF("Output mode is RGB24\n") ; csc = B_CSC_YUV2RGB ; if(bInputMode & F_MODE_EN_UDFILT) // YUV422 to RGB24 need up/dn filter. { filter |= B_TX_EN_UDFILTER ; } if(bInputMode & F_MODE_EN_DITHER) // YUV422 to RGB24 need dither { filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; } break ; } break ; #endif #ifdef SUPPORT_INPUTRGB case F_MODE_RGB444: ErrorF("Input mode is RGB24\n") ; switch(bOutputMode&F_MODE_CLRMOD_MASK) { case F_MODE_YUV444: ErrorF("Output mode is YUV444\n") ; csc = B_CSC_RGB2YUV ; if(bInputMode & F_MODE_EN_DITHER) // RGB24 to YUV444 need dither { filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; } break ; case F_MODE_YUV422: ErrorF("Output mode is YUV422\n") ; if(bInputMode & F_MODE_EN_UDFILT) // RGB24 to YUV422 need down filter. { filter |= B_TX_EN_UDFILTER ; } if(bInputMode & F_MODE_EN_DITHER) // RGB24 to YUV422 need dither { filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; } csc = B_CSC_RGB2YUV ; break ; case F_MODE_RGB444: ErrorF("Output mode is RGB24\n") ; csc = B_CSC_BYPASS ; break ; } break ; #endif } #ifdef SUPPORT_INPUTRGB // set the CSC metrix registers by colorimetry and quantization if(csc == B_CSC_RGB2YUV) { ErrorF("CSC = RGB2YUV %x ",csc) ; switch(bInputMode&(F_MODE_ITU709|F_MODE_16_235)) { case F_MODE_ITU709|F_MODE_16_235: ErrorF("ITU709 16-235 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU709_16_235,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU709|F_MODE_0_255: ErrorF("ITU709 0-255 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU709_0_255,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU601|F_MODE_16_235: ErrorF("ITU601 16-235 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU601_16_235,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU601|F_MODE_0_255: default: ErrorF("ITU601 0-255 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU601_0_255,SIZEOF_CSCMTX) ; break ; } } #endif #ifdef SUPPORT_INPUTYUV if (csc == B_CSC_YUV2RGB) { int i; ErrorF("CSC = YUV2RGB %x ",csc) ; switch(bInputMode&(F_MODE_ITU709|F_MODE_16_235)) { case F_MODE_ITU709|F_MODE_16_235: ErrorF("ITU709 16-235 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU709_16_235,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU709|F_MODE_0_255: ErrorF("ITU709 0-255 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU709_0_255,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU601|F_MODE_16_235: ErrorF("ITU601 16-235 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU601_16_235,SIZEOF_CSCMTX) ; break ; case F_MODE_ITU601|F_MODE_0_255: default: //????? debug ErrorF("ITU601 0-255 ") ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU601_0_255,SIZEOF_CSCMTX) ; break ; } } #endif ucData = HDMITX_ReadI2C_Byte(REG_TX_CSC_CTRL) & ~(M_CSC_SEL|B_TX_DNFREE_GO|B_TX_EN_DITHER|B_TX_EN_UDFILTER) ; ucData |= filter|csc ; HDMITX_WriteI2C_Byte(REG_TX_CSC_CTRL,ucData) ; // set output Up/Down Filter,Dither control } ////////////////////////////////////////////////////////////////////// // Function: SetupAFE // Parameter: VIDEOPCLKLEVEL level // PCLK_LOW - for 13.5MHz (for mode less than 1080p) // PCLK MEDIUM - for 25MHz~74MHz // PCLK HIGH - PCLK > 80Hz (for 1080p mode or above) // Return: N/A // Remark: set reg62~reg65 depended on HighFreqMode // reg61 have to be programmed at last and after video stable input. // Side-Effect: ////////////////////////////////////////////////////////////////////// static void // SetupAFE(BYTE ucFreqInMHz) SetupAFE(VIDEOPCLKLEVEL level) { // @emily turn off reg61 before SetupAFE parameters. HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST) ;/* 0x10 */ // HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0x3) ; ErrorF("SetupAFE()\n") ; //TMDS Clock < 80MHz TMDS Clock > 80MHz //Reg61 0x03 0x03 //Reg62 0x18 0x88 //Reg63 Default Default //Reg64 0x08 0x80 //Reg65 Default Default //Reg66 Default Default //Reg67 Default Default switch(level) { case PCLK_HIGH: HDMITX_WriteI2C_Byte(REG_TX_AFE_XP_CTRL,0x88) ; // reg62 HDMITX_WriteI2C_Byte(REG_TX_AFE_ISW_CTRL, 0x10) ; // reg63 HDMITX_WriteI2C_Byte(REG_TX_AFE_IP_CTRL,0x84) ; // reg64 break ; default: HDMITX_WriteI2C_Byte(REG_TX_AFE_XP_CTRL,0x18) ; // reg62 HDMITX_WriteI2C_Byte(REG_TX_AFE_ISW_CTRL, 0x10) ; // reg63 HDMITX_WriteI2C_Byte(REG_TX_AFE_IP_CTRL,0x0C) ; // reg64 break ; } //HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_REF_RST|B_VID_RST|B_AREF_RST|B_HDMI_RST)) ; DelayMS(1) ; HDMITX_AndREG_Byte(REG_TX_SW_RST,B_VID_RST|B_AREF_RST|B_AUD_RST|B_HDCP_RST) ; DelayMS(100) ; HDMITX_AndREG_Byte(REG_TX_SW_RST, B_AREF_RST|B_AUD_RST|B_HDCP_RST) ; // REG_TX_AFE_DRV_CTRL have to be set at the last step of setup . } ////////////////////////////////////////////////////////////////////// // Function: FireAFE // Parameter: N/A // Return: N/A // Remark: write reg61 with 0x04 // When program reg61 with 0x04,then audio and video circuit work. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static void FireAFE() { BYTE reg; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0) ; for(reg = 0x61 ; reg <= 0x67 ; reg++) { ErrorF("Reg[%02X] = %02X\n",reg,HDMITX_ReadI2C_Byte(reg)) ; } } ////////////////////////////////////////////////////////////////////// // Audio Output ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Function: SetAudioFormat // Parameter: // NumChannel - number of channel,from 1 to 8 // AudioEnable - Audio source and type bit field,value of bit field are // ENABLE_SPDIF (1<<4) // ENABLE_I2S_SRC3 (1<<3) // ENABLE_I2S_SRC2 (1<<2) // ENABLE_I2S_SRC1 (1<<1) // ENABLE_I2S_SRC0 (1<<0) // SampleFreq - the audio sample frequence in Hz // AudSWL - Audio sample width,only support 16,18,20,or 24. // AudioCatCode - The audio channel catalogy code defined in IEC 60958-3 // Return: ER_SUCCESS if done,ER_FAIL for otherwise. // Remark: program audio channel control register and audio channel registers // to enable audio by input. // Side-Effect: register bank will keep in bank zero. ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetAudioFormat(BYTE NumChannel,BYTE AudioEnable,BYTE bSampleFreq,BYTE AudSWL,BYTE AudioCatCode) { BYTE fs = bSampleFreq ; BYTE SWL ; BYTE SourceValid ; BYTE SoruceNum ; ErrorF("SetAudioFormat(%d channel,%02X,SampleFreq %d,AudSWL %d,%02X)\n",NumChannel,AudioEnable,bSampleFreq,AudSWL,AudioCatCode) ; //richard remove Instance[0].bOutputAudioMode |= 0x41 ; if(NumChannel > 6) { SourceValid = B_AUD_ERR2FLAT | B_AUD_S3VALID | B_AUD_S2VALID | B_AUD_S1VALID ; SoruceNum = 4 ; } else if (NumChannel > 4) { SourceValid = B_AUD_ERR2FLAT | B_AUD_S2VALID | B_AUD_S1VALID ; SoruceNum = 3 ; } else if (NumChannel > 2) { SourceValid = B_AUD_ERR2FLAT | B_AUD_S1VALID ; SoruceNum = 2 ; } else { SourceValid = B_AUD_ERR2FLAT ; // only two channel. SoruceNum = 1 ; Instance[0].bOutputAudioMode &= ~0x40 ; } AudioEnable &= ~ (M_AUD_SWL|B_SPDIFTC) ; switch(AudSWL) { case 16: SWL = AUD_SWL_16 ; AudioEnable |= M_AUD_16BIT ; break ; case 18: SWL = AUD_SWL_18 ; AudioEnable |= M_AUD_18BIT ; break ; case 20: SWL = AUD_SWL_20 ; AudioEnable |= M_AUD_20BIT ; break ; case 24: SWL = AUD_SWL_24 ; AudioEnable |= M_AUD_24BIT ; break ; default: return ER_FAIL ; } Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable&0xF0) ; HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_AUD_RST|B_AREF_RST)) ; HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,Instance[0].bOutputAudioMode) ; // regE1 bOutputAudioMode should be loaded from ROM image. HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4) ; // default mapping. HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,(Instance[0].bAudioChannelSwap&0xF)|(AudioEnable&B_AUD_SPDIF)) ; HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,SourceValid) ; // suggested to be 0x41 // Switch_HDMITX_Bank(1) ; // HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,0 |((NumChannel == 1)?1:0)) ; // 2 audio channel without pre-emphasis,if NumChannel set it as 1. // HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,AudioCatCode) ; // HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,SoruceNum) ; // HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,0x21) ; // HDMITX_WriteI2C_Byte(REG_TX_AUD1CHST_CHTNUM,0x43) ; // HDMITX_WriteI2C_Byte(REG_TX_AUD2CHST_CHTNUM,0x65) ; // HDMITX_WriteI2C_Byte(REG_TX_AUD3CHST_CHTNUM,0x87) ; // HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock // fs = ~fs ; // OFS is the one's complement of FS // HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(fs<<4)|SWL) ; // Switch_HDMITX_Bank(0) ; Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,0 |((NumChannel == 1)?1:0)) ; // 2 audio channel without pre-emphasis,if NumChannel set it as 1. HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,AudioCatCode) ; HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,SoruceNum) ; HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,0) ; HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock fs = ~fs ; // OFS is the one's complement of FS HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(fs<<4)|SWL) ; Switch_HDMITX_Bank(0) ; // richard modify (could be bug), if(!(AudioEnable | B_AUD_SPDIF)) if(!(AudioEnable & B_AUD_SPDIF)) { HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable) ; } Instance[0].bAudioChannelEnable = AudioEnable ; // HDMITX_AndREG_Byte(REG_TX_SW_RST,B_AUD_RST) ; // enable Audio return ER_SUCCESS; } static void AutoAdjustAudio() { unsigned long SampleFreq ; unsigned long N ; unsigned long CTS ; BYTE fs, uc ; // bPendingAdjustAudioFreq = TRUE ; // if( CAT6611_AudioChannelEnable & B_AUD_SPDIF ) // { // if(!(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK)) // { // return ; // } // } Switch_HDMITX_Bank(1) ; N = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN2)&0xF) << 16 ; N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN1)) <<8 ; N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN0)) ; CTS = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt2)&0xF) << 16 ; CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt1)) <<8 ; CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt0)) ; Switch_HDMITX_Bank(0) ; // CTS = TMDSCLK * N / ( 128 * SampleFreq ) // SampleFreq = TMDSCLK * N / (128*CTS) if( CTS == 0 ) { return ; } SampleFreq = Instance[0].TMDSClock/CTS ; SampleFreq *= N ; SampleFreq /= 128 ; if( SampleFreq>31000 && SampleFreq<=38050 ) { Instance[0].bAudFs = AUDFS_32KHz ; fs = AUDFS_32KHz ;; } else if (SampleFreq < 46050 ) // 44.1KHz { Instance[0].bAudFs = AUDFS_44p1KHz ; fs = AUDFS_44p1KHz ;; } else if (SampleFreq < 68100 ) // 48KHz { Instance[0].bAudFs = AUDFS_48KHz ; fs = AUDFS_48KHz ;; } else if (SampleFreq < 92100 ) // 88.2 KHz { Instance[0].bAudFs = AUDFS_88p2KHz ; fs = AUDFS_88p2KHz ;; } else if (SampleFreq < 136200 ) // 96KHz { Instance[0].bAudFs = AUDFS_96KHz ; fs = AUDFS_96KHz ;; } else if (SampleFreq < 184200 ) // 176.4KHz { Instance[0].bAudFs = AUDFS_176p4KHz ; fs = AUDFS_176p4KHz ;; } else if (SampleFreq < 240200 ) // 192KHz { Instance[0].bAudFs = AUDFS_192KHz ; fs = AUDFS_192KHz ;; } else { Instance[0].bAudFs = AUDFS_OTHER; fs = AUDFS_OTHER;; } // bPendingAdjustAudioFreq = FALSE ; SetNCTS(Instance[0].TMDSClock, Instance[0].bAudFs) ; // set N, CTS by new generated clock. Switch_HDMITX_Bank(1) ; // adjust the new fs in channel status registers HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock fs = ~fs ; // OFS is the one's complement of FS uc = HDMITX_ReadI2C_Byte(REG_TX_AUDCHST_OFS_WL) ; uc &= 0xF ; uc |= fs << 4 ; HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,uc) ; Switch_HDMITX_Bank(0) ; } static void SetupAudioChannel() { static BYTE bEnableAudioChannel=FALSE ; if( (HDMITX_ReadI2C_Byte(REG_TX_SW_RST) & (B_AUD_RST|B_AREF_RST)) == 0) // audio enabled { Switch_HDMITX_Bank(0) ; if((HDMITX_ReadI2C_Byte(REG_TX_AUDIO_CTRL0) & 0xf) == 0) { if(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK) { SetNCTS(Instance[0].TMDSClock, Instance[0].bAudFs) ; // to enable automatic progress setting for N/CTS DelayMS(5); AutoAdjustAudio() ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, Instance[0].bAudioChannelEnable) ; bEnableAudioChannel=TRUE ; } } else { if((HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK)==0) { // AutoAdjustAudio() ; // ForceSetNCTS(CurrentPCLK, CurrentSampleFreq) ; if( bEnableAudioChannel == TRUE ) { Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, Instance[0].bAudioChannelEnable&0xF0) ; } bEnableAudioChannel=FALSE ; } } } } ////////////////////////////////////////////////////////////////////// // Function: SetNCTS // Parameter: PCLK - video clock in Hz. // Fs - audio sample frequency in Hz // Return: ER_SUCCESS if success // Remark: set N value,the CTS will be auto generated by HW. // Side-Effect: register bank will reset to bank 0. ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetNCTS(ULONG PCLK,ULONG Fs) { ULONG n,MCLK ; MCLK = Fs * 256 ; // MCLK = fs * 256 ; ErrorF("SetNCTS(%ld,%ld): MCLK = %ld\n",PCLK,Fs,MCLK) ; if( PCLK ) { switch (Fs) { case AUDFS_32KHz: switch (PCLK) { case 74175000: n = 11648; break; case 14835000: n = 11648; break; default: n = 4096; } break; case AUDFS_44p1KHz: switch (PCLK) { case 74175000: n = 17836; break; case 14835000: n = 8918; break; default: n = 6272; } break; case AUDFS_48KHz: switch (PCLK) { case 74175000: n = 11648; break; case 14835000: n = 5824; break; default: n = 6144; } break; case AUDFS_88p2KHz: switch (PCLK) { case 74175000: n = 35672; break; case 14835000: n = 17836; break; default: n = 12544; } break; case AUDFS_96KHz: switch (PCLK) { case 74175000: n = 23296; break; case 14835000: n = 11648; break; default: n = 12288; } break; case AUDFS_176p4KHz: switch (PCLK) { case 74175000: n = 71344; break; case 14835000: n = 35672; break; default: n = 25088; } break; case AUDFS_192KHz: switch (PCLK) { case 74175000: n = 46592; break; case 14835000: n = 23296; break; default: n = 24576; } break; default: n = MCLK / 2000; } } else { switch(Fs) { case AUDFS_32KHz: n = 4096; break; case AUDFS_44p1KHz: n = 6272; break; case AUDFS_48KHz: n = 6144; break; case AUDFS_88p2KHz: n = 12544; break; case AUDFS_96KHz: n = 12288; break; case AUDFS_176p4KHz: n = 25088; break; case AUDFS_192KHz: n = 24576; break; default: n = 6144; } } ErrorF("N = %ld\n",n) ; Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REGPktAudN0,(BYTE)((n)&0xFF)) ; HDMITX_WriteI2C_Byte(REGPktAudN1,(BYTE)((n>>8)&0xFF)) ; HDMITX_WriteI2C_Byte(REGPktAudN2,(BYTE)((n>>16)&0xF)) ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,0) ; // D[1] = 0,HW auto count CTS HDMITX_SetREG_Byte(REG_TX_CLK_CTRL0,~M_EXT_MCLK_SEL,B_EXT_256FS) ; return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // DDC Function. ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Function: ClearDDCFIFO // Parameter: N/A // Return: N/A // Remark: clear the DDC FIFO. // Side-Effect: DDC master will set to be HOST. ////////////////////////////////////////////////////////////////////// static void ClearDDCFIFO() { HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR) ; } static void GenerateDDCSCLK() { HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_GEN_SCLCLK) ; } ////////////////////////////////////////////////////////////////////// // Function: AbortDDC // Parameter: N/A // Return: N/A // Remark: Force abort DDC and reset DDC bus. // Side-Effect: ////////////////////////////////////////////////////////////////////// static void AbortDDC() { BYTE CPDesire,SWReset,DDCMaster ; BYTE uc, timeout ; // save the SW reset,DDC master,and CP Desire setting. SWReset = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) ; CPDesire = HDMITX_ReadI2C_Byte(REG_TX_HDCP_DESIRE) ; DDCMaster = HDMITX_ReadI2C_Byte(REG_TX_DDC_MASTER_CTRL) ; HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,CPDesire&(~B_CPDESIRE)) ; // @emily change order HDMITX_WriteI2C_Byte(REG_TX_SW_RST,SWReset|B_HDCP_RST) ; // @emily change order HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_ABORT) ; for( timeout = 0 ; timeout < 200 ; timeout++ ) { uc = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if (uc&B_DDC_DONE) { break ; // success } if( uc & (B_DDC_NOACK|B_DDC_WAITBUS|B_DDC_ARBILOSE) ) { ErrorF("AbortDDC Fail by reg16=%02X\n",uc) ; break ; } DelayMS(1) ; // delay 1 ms to stable. } // restore the SW reset,DDC master,and CP Desire setting. HDMITX_WriteI2C_Byte(REG_TX_SW_RST,SWReset) ; HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,CPDesire) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,DDCMaster) ; } ////////////////////////////////////////////////////////////////////// // Packet and InfoFrame ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////// // // Function: SetAVMute() // // Parameter: N/A // // Return: N/A // // Remark: set AVMute as TRUE and enable GCP sending. // // Side-Effect: N/A // //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // void // SetAVMute() // { // Switch_HDMITX_Bank(0) ; // HDMITX_WriteI2C_Byte(REG_TX_GCP,B_SET_AVMUTE) ; // HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; // } // //////////////////////////////////////////////////////////////////////////////// // // Function: SetAVMute(FALSE) // // Parameter: N/A // // Return: N/A // // Remark: clear AVMute as TRUE and enable GCP sending. // // Side-Effect: N/A // //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // void // SetAVMute(FALSE) // { // Switch_HDMITX_Bank(0) ; // HDMITX_WriteI2C_Byte(REG_TX_GCP,B_CLR_AVMUTE) ; // HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; // } ////////////////////////////////////////////////////////////////////// // Function: ReadEDID // Parameter: pData - the pointer of buffer to receive EDID ucdata. // bSegment - the segment of EDID readback. // offset - the offset of EDID ucdata in the segment. in byte. // count - the read back bytes count,cannot exceed 32 // Return: ER_SUCCESS if successfully getting EDID. ER_FAIL otherwise. // Remark: function for read EDID ucdata from reciever. // Side-Effect: DDC master will set to be HOST. DDC FIFO will be used and dirty. ////////////////////////////////////////////////////////////////////// static SYS_STATUS ReadEDID(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count) { SHORT RemainedCount,ReqCount ; BYTE bCurrOffset ; SHORT TimeOut ; BYTE *pBuff = pData ; BYTE ucdata ; // ErrorF("ReadEDID(%08lX,%d,%d,%d)\n",(ULONG)pData,bSegment,offset,Count) ; if(!pData) { ErrorF("ReadEDID(): Invallid pData pointer %08lX\n",(ULONG)pData) ; return ER_FAIL ; } if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_DDC_BUS_HANG) { ErrorF("Called AboutDDC()\n") ; AbortDDC() ; } ClearDDCFIFO() ; RemainedCount = Count ; bCurrOffset = offset ; Switch_HDMITX_Bank(0) ; while(RemainedCount > 0) { ReqCount = (RemainedCount > DDC_FIFO_MAXREQ)?DDC_FIFO_MAXREQ:RemainedCount ; ErrorF("ReadEDID(): ReqCount = %d,bCurrOffset = %d\n",ReqCount,bCurrOffset) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR) ; for(TimeOut = 0 ; TimeOut < 200 ; TimeOut++) { ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata&B_DDC_DONE) { break ; } if((ucdata & B_DDC_ERROR)||(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_DDC_BUS_HANG)) { ErrorF("Called AboutDDC()\n") ; AbortDDC() ; return ER_FAIL ; } } HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_EDID_ADDRESS) ; // for EDID ucdata get HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,bCurrOffset) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,(BYTE)ReqCount) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_EDIDSEG,bSegment) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_EDID_READ) ; bCurrOffset += ReqCount ; RemainedCount -= ReqCount ; for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --) { DelayMS(1) ; ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata & B_DDC_DONE) { break ; } if(ucdata & B_DDC_ERROR) { ErrorF("ReadEDID(): DDC_STATUS = %02X,fail.\n",ucdata) ; return ER_FAIL ; } } if(TimeOut == 0) { ErrorF("ReadEDID(): DDC TimeOut. \n",ucdata) ; return ER_FAIL ; } do { *(pBuff++) = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO) ; ReqCount -- ; }while(ReqCount > 0) ; } return ER_SUCCESS ; } #ifdef SUPPORT_HDCP ////////////////////////////////////////////////////////////////////// // Authentication ////////////////////////////////////////////////////////////////////// static void HDCP_ClearAuthInterrupt() { BYTE uc ; uc = HDMITX_ReadI2C_Byte(REG_TX_INT_MASK2) & (~(B_KSVLISTCHK_MASK|B_T_AUTH_DONE_MASK|B_AUTH_FAIL_MASK)); HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL|B_CLR_AUTH_DONE|B_CLR_KSVLISTCHK) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; } static void HDCP_ResetAuth() { HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0) ; HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,0) ; HDMITX_OrREG_Byte(REG_TX_SW_RST,B_HDCP_RST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDCP_ClearAuthInterrupt() ; AbortDDC() ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_EnableEncryption // Parameter: N/A // Return: ER_SUCCESS if done. // Remark: Set regC1 as zero to enable continue authentication. // Side-Effect: register bank will reset to zero. ////////////////////////////////////////////////////////////////////// static SYS_STATUS HDCP_EnableEncryption() { Switch_HDMITX_Bank(0) ; return HDMITX_WriteI2C_Byte(REG_TX_ENCRYPTION,B_ENABLE_ENCRYPTION); } ////////////////////////////////////////////////////////////////////// // Function: HDCP_Auth_Fire() // Parameter: N/A // Return: N/A // Remark: write anything to reg21 to enable HDCP authentication by HW // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static void HDCP_Auth_Fire() { // ErrorF("HDCP_Auth_Fire():\n") ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHDCP) ; // MASTERHDCP,no need command but fire. HDMITX_WriteI2C_Byte(REG_TX_AUTHFIRE,1); } ////////////////////////////////////////////////////////////////////// // Function: HDCP_StartAnCipher // Parameter: N/A // Return: N/A // Remark: Start the Cipher to free run for random number. When stop,An is // ready in Reg30. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static void HDCP_StartAnCipher() { HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_START_CIPHER_GEN) ; DelayMS(1) ; // delay 1 ms } ////////////////////////////////////////////////////////////////////// // Function: HDCP_StopAnCipher // Parameter: N/A // Return: N/A // Remark: Stop the Cipher,and An is ready in Reg30. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static void HDCP_StopAnCipher() { HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_STOP_CIPHER_GEN) ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_GenerateAn // Parameter: N/A // Return: N/A // Remark: start An ciper random run at first,then stop it. Software can get // an in reg30~reg38,the write to reg28~2F // Side-Effect: ////////////////////////////////////////////////////////////////////// static void HDCP_GenerateAn() { BYTE Data[8] ; HDCP_StartAnCipher() ; // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_START_CIPHER_GEN) ; // DelayMS(1) ; // delay 1 ms // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_STOP_CIPHER_GEN) ; HDCP_StopAnCipher() ; Switch_HDMITX_Bank(0) ; // new An is ready in reg30 HDMITX_ReadI2C_ByteN(REG_TX_AN_GEN,Data,8) ; HDMITX_WriteI2C_ByteN(REG_TX_AN,Data,8) ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_GetBCaps // Parameter: pBCaps - pointer of byte to get BCaps. // pBStatus - pointer of two bytes to get BStatus // Return: ER_SUCCESS if successfully got BCaps and BStatus. // Remark: get B status and capability from HDCP reciever via DDC bus. // Side-Effect: ////////////////////////////////////////////////////////////////////// static SYS_STATUS HDCP_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus) { BYTE ucdata ; BYTE TimeOut ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x40) ; // BCaps offset HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,3) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) { DelayMS(1) ; ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata & B_DDC_DONE) { //ErrorF("HDCP_GetBCaps(): DDC Done.\n") ; break ; } if(ucdata & B_DDC_ERROR) { ErrorF("HDCP_GetBCaps(): DDC fail by reg16=%02X.\n",ucdata) ; return ER_FAIL ; } } if(TimeOut == 0) { return ER_FAIL ; } HDMITX_ReadI2C_ByteN(REG_TX_BSTAT,(PBYTE)pBStatus,2) ; *pBCaps = HDMITX_ReadI2C_Byte(REG_TX_BCAP) ; return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_GetBKSV // Parameter: pBKSV - pointer of 5 bytes buffer for getting BKSV // Return: ER_SUCCESS if successfuly got BKSV from Rx. // Remark: Get BKSV from HDCP reciever. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static SYS_STATUS HDCP_GetBKSV(BYTE *pBKSV) { BYTE ucdata ; BYTE TimeOut ; Switch_HDMITX_Bank(0) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x00) ; // BKSV offset HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,5) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) { DelayMS(1) ; ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata & B_DDC_DONE) { ErrorF("HDCP_GetBCaps(): DDC Done.\n") ; break ; } if(ucdata & B_DDC_ERROR) { ErrorF("HDCP_GetBCaps(): DDC No ack or arbilose,%x,maybe cable did not connected. Fail.\n",ucdata) ; return ER_FAIL ; } } if(TimeOut == 0) { return ER_FAIL ; } HDMITX_ReadI2C_ByteN(REG_TX_BKSV,(PBYTE)pBKSV,5) ; return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function:HDCP_Authenticate // Parameter: N/A // Return: ER_SUCCESS if Authenticated without error. // Remark: do Authentication with Rx // Side-Effect: // 1. Instance[0].bAuthenticated global variable will be TRUE when authenticated. // 2. Auth_done interrupt and AUTH_FAIL interrupt will be enabled. ////////////////////////////////////////////////////////////////////// static BYTE countbit(BYTE b) { BYTE i,count ; for( i = 0, count = 0 ; i < 8 ; i++ ) { if( b & (1< 6) { ErrorF("Down Stream Count %d is over maximum supported number 6,fail.\n",(BStatus & M_DOWNSTREAM_COUNT)) ; return ER_FAIL ; } */ HDCP_GetBKSV(BKSV) ; ErrorF("BKSV %02X %02X %02X %02X %02X\n",BKSV[0],BKSV[1],BKSV[2],BKSV[3],BKSV[4]) ; for(TimeOut = 0, ucdata = 0 ; TimeOut < 5 ; TimeOut ++) { ucdata += countbit(BKSV[TimeOut]) ; } if( ucdata != 20 ) return ER_FAIL ; #ifdef SUPPORT_REVOKE_KSV HDCP_VerifyRevocationList(SRM1,BKSV,&revoked) ; if(revoked) { ErrorF("BKSV is revoked\n") ; return ER_FAIL ; } ErrorF("BKSV %02X %02X %02X %02X %02X is NOT %srevoked\n",BKSV[0],BKSV[1],BKSV[2],BKSV[3],BKSV[4],revoked?"not ":"") ; #endif // SUPPORT_DSSSHA Switch_HDMITX_Bank(0) ; // switch bank action should start on direct register writting of each function. // 2006/08/11 added by jjtseng // enable HDCP on CPDired enabled. HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_HDCP_RST)) ; //~jjtseng 2006/08/11 // if(BCaps & B_CAP_HDCP_1p1) // { // ErrorF("RX support HDCP 1.1\n") ; // HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,B_ENABLE_HDPC11|B_CPDESIRE) ; // } // else // { // ErrorF("RX not support HDCP 1.1\n") ; HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,B_CPDESIRE) ; // } // HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_DONE|B_CLR_AUTH_FAIL|B_CLR_KSVLISTCHK) ; // HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; // don't clear other settings. // ucdata = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; // ucdata = (ucdata & M_CTSINTSTEP) | B_INTACTDONE ; // HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,ucdata) ; // clear action. // HDMITX_AndREG_Byte(REG_TX_INT_MASK2,~(B_AUTH_FAIL_MASK|B_T_AUTH_DONE_MASK)) ; // enable GetBCaps Interrupt HDCP_ClearAuthInterrupt() ; ErrorF("int2 = %02X DDC_Status = %02X\n",HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2),HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS)) ; HDCP_GenerateAn() ; HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0) ; Instance[0].bAuthenticated = FALSE ; if((BCaps & B_CAP_HDMI_REPEATER) == 0) { HDCP_Auth_Fire(); // wait for status ; for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --) { DelayMS(5) ; // delay 1ms ucdata = HDMITX_ReadI2C_Byte(REG_TX_AUTH_STAT) ; ErrorF("reg46 = %02x reg16 = %02x\n",ucdata,HDMITX_ReadI2C_Byte(0x16)) ; if(ucdata & B_T_AUTH_DONE) { Instance[0].bAuthenticated = TRUE ; break ; } ucdata = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; if(ucdata & B_INT_AUTH_FAIL) { /* HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; */ ErrorF("HDCP_Authenticate(): Authenticate fail\n") ; Instance[0].bAuthenticated = FALSE ; return ER_FAIL ; } } if(TimeOut == 0) { ErrorF("HDCP_Authenticate(): Time out. return fail\n") ; Instance[0].bAuthenticated = FALSE ; return ER_FAIL ; } return ER_SUCCESS ; } return HDCP_Authenticate_Repeater() ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_VerifyIntegration // Parameter: N/A // Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail. // Remark: no used now. // Side-Effect: ////////////////////////////////////////////////////////////////////// static SYS_STATUS HDCP_VerifyIntegration() { // richard BYTE ucdata ; // if any interrupt issued a Auth fail,returned the Verify Integration fail. if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_AUTH_FAIL) { HDCP_ClearAuthInterrupt() ; Instance[0].bAuthenticated = FALSE ; return ER_FAIL ; } if(Instance[0].bAuthenticated == TRUE) { return ER_SUCCESS ; } return ER_FAIL ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_Authenticate_Repeater // Parameter: BCaps and BStatus // Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail. // Remark: // Side-Effect: as Authentication ////////////////////////////////////////////////////////////////////// static _XDATA BYTE KSVList[32] ; static _XDATA BYTE Vr[20] ; static _XDATA BYTE M0[8] ; static void HDCP_CancelRepeaterAuthenticate() { ErrorF("HDCP_CancelRepeaterAuthenticate") ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; AbortDDC() ; HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_LISTFAIL|B_LISTDONE) ; HDCP_ClearAuthInterrupt() ; } static void HDCP_ResumeRepeaterAuthenticate() { HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_LISTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHDCP) ; } static SYS_STATUS HDCP_GetKSVList(BYTE *pKSVList,BYTE cDownStream) { BYTE TimeOut = 100 ; BYTE ucdata ; if(cDownStream == 0 || pKSVList == NULL) { return ER_FAIL ; } HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x43) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,cDownStream * 5) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) { ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata & B_DDC_DONE) { ErrorF("HDCP_GetKSVList(): DDC Done.\n") ; break ; } if(ucdata & B_DDC_ERROR) { ErrorF("HDCP_GetKSVList(): DDC Fail by REG_TX_DDC_STATUS = %x.\n",ucdata) ; return ER_FAIL ; } DelayMS(5) ; } if(TimeOut == 0) { return ER_FAIL ; } ErrorF("HDCP_GetKSVList(): KSV") ; for(TimeOut = 0 ; TimeOut < cDownStream * 5 ; TimeOut++) { pKSVList[TimeOut] = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO) ; ErrorF(" %02X",pKSVList[TimeOut]) ; } ErrorF("\n") ; return ER_SUCCESS ; } static SYS_STATUS HDCP_GetVr(BYTE *pVr) { BYTE TimeOut ; BYTE ucdata ; if(pVr == NULL) { // richard return NULL ; return ER_FAIL; } HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHOST) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x20) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,20) ; HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) { ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; if(ucdata & B_DDC_DONE) { ErrorF("HDCP_GetVr(): DDC Done.\n") ; break ; } if(ucdata & B_DDC_ERROR) { ErrorF("HDCP_GetVr(): DDC fail by REG_TX_DDC_STATUS = %x.\n",ucdata) ; return ER_FAIL ; } DelayMS(5) ; } if(TimeOut == 0) { ErrorF("HDCP_GetVr(): DDC fail by timeout.\n",ucdata) ; return ER_FAIL ; } Switch_HDMITX_Bank(0) ; for(TimeOut = 0 ; TimeOut < 5 ; TimeOut++) { HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL ,TimeOut) ; pVr[TimeOut*4+3] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1) ; pVr[TimeOut*4+2] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2) ; pVr[TimeOut*4+1] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3) ; pVr[TimeOut*4] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4) ; ErrorF("V' = %02X %02X %02X %02X\n",pVr[TimeOut*4],pVr[TimeOut*4+1],pVr[TimeOut*4+2],pVr[TimeOut*4+3]) ; } return ER_SUCCESS ; } static SYS_STATUS HDCP_GetM0(BYTE *pM0) { int i ; if(!pM0) { return ER_FAIL ; } HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,5) ; // read m0[31:0] from reg51~reg54 pM0[0] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1) ; pM0[1] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2) ; pM0[2] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3) ; pM0[3] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4) ; HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,0) ; // read m0[39:32] from reg55 pM0[4] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,1) ; // read m0[47:40] from reg55 pM0[5] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,2) ; // read m0[55:48] from reg55 pM0[6] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,3) ; // read m0[63:56] from reg55 pM0[7] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; ErrorF("M[] =") ; for(i = 0 ; i < 8 ; i++){ ErrorF("0x%02x,",pM0[i]) ; } ErrorF("\n") ; return ER_SUCCESS ; } static _XDATA BYTE SHABuff[64] ; static _XDATA BYTE V[20] ; static _XDATA ULONG w[80]; static _XDATA ULONG sha[5] ; #define rol(x,y) (((x) << (y)) | (((ULONG)x) >> (32-y))) static void SHATransform(ULONG * h); // richard add void SHATransform(ULONG * h) { LONG t; for (t = 16; t < 80; t++) { ULONG tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]; w[t] = rol(tmp,1); printf("w[%2d] = %08lX\n",t,w[t]) ; } h[0] = 0x67452301 ; h[1] = 0xefcdab89; h[2] = 0x98badcfe; h[3] = 0x10325476; h[4] = 0xc3d2e1f0; for (t = 0; t < 20; t++) { ULONG tmp = rol(h[0],5) + ((h[1] & h[2]) | (h[3] & ~h[1])) + h[4] + w[t] + 0x5a827999; printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; h[4] = h[3]; h[3] = h[2]; h[2] = rol(h[1],30); h[1] = h[0]; h[0] = tmp; } for (t = 20; t < 40; t++) { ULONG tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t] + 0x6ed9eba1; printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; h[4] = h[3]; h[3] = h[2]; h[2] = rol(h[1],30); h[1] = h[0]; h[0] = tmp; } for (t = 40; t < 60; t++) { ULONG tmp = rol(h[0], 5) + ((h[1] & h[2]) | (h[1] & h[3]) | (h[2] & h[3])) + h[4] + w[t] + 0x8f1bbcdc; printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; h[4] = h[3]; h[3] = h[2]; h[2] = rol(h[1],30); h[1] = h[0]; h[0] = tmp; } for (t = 60; t < 80; t++) { ULONG tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t] + 0xca62c1d6; printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; h[4] = h[3]; h[3] = h[2]; h[2] = rol(h[1],30); h[1] = h[0]; h[0] = tmp; } printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; h[0] += 0x67452301 ; h[1] += 0xefcdab89; h[2] += 0x98badcfe; h[3] += 0x10325476; h[4] += 0xc3d2e1f0; printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; } /* ---------------------------------------------------------------------- * Outer SHA algorithm: take an arbitrary length byte string, * convert it into 16-word blocks with the prescribed padding at * the end,and pass those blocks to the core SHA algorithm. */ void SHA_Simple(void *p,LONG len,BYTE *output) { // SHA_State s; int i, t ; ULONG c ; char *pBuff = p ; for( i = 0 ; i < len ; i++ ) { t = i/4 ; if( i%4 == 0 ) { w[t] = 0 ; } c = pBuff[i] ; c <<= (3-(i%4))*8 ; w[t] |= c ; printf("pBuff[%d] = %02x, c = %08lX, w[%d] = %08lX\n",i,pBuff[i],c,t,w[t]) ; } t = i/4 ; if( i%4 == 0 ) { w[t] = 0 ; } c = 0x80 << ((3-i%4)*24) ; w[t]|= c ; t++ ; for( ; t < 15 ; t++ ) { w[t] = 0 ; } w[15] = len*8 ; for( t = 0 ; t< 16 ; t++ ) { printf("w[%2d] = %08lX\n",t,w[t]) ; } SHATransform(sha) ; for( i = 0 ; i < 5 ; i++ ) { output[i*4] = (BYTE)((sha[i]>>24)&0xFF) ; output[i*4+1] = (BYTE)((sha[i]>>16)&0xFF) ; output[i*4+2] = (BYTE)((sha[i]>>8)&0xFF) ; output[i*4+3] = (BYTE)(sha[i]&0xFF) ; } } static SYS_STATUS HDCP_CheckSHA(BYTE pM0[],USHORT BStatus,BYTE pKSVList[],int cDownStream,BYTE Vr[]) { int i,n ; for(i = 0 ; i < cDownStream*5 ; i++) { SHABuff[i] = pKSVList[i] ; } SHABuff[i++] = BStatus & 0xFF ; SHABuff[i++] = (BStatus>>8) & 0xFF ; for(n = 0 ; n < 8 ; n++,i++) { SHABuff[i] = pM0[n] ; } n = i ; // SHABuff[i++] = 0x80 ; // end mask for(; i < 64 ; i++) { SHABuff[i] = 0 ; } // n = cDownStream * 5 + 2 /* for BStatus */ + 8 /* for M0 */ ; // n *= 8 ; // SHABuff[62] = (n>>8) & 0xff ; // SHABuff[63] = (n>>8) & 0xff ; for(i = 0 ; i < 64 ; i++) { if(i % 16 == 0) printf("SHA[]: ") ; printf(" %02X",SHABuff[i]) ; if((i%16)==15) printf("\n") ; } SHA_Simple(SHABuff,n,V) ; printf("V[] =") ; for(i = 0 ; i < 20 ; i++) { printf(" %02X",V[i]) ; } printf("\nVr[] =") ; for(i = 0 ; i < 20 ; i++) { printf(" %02X",Vr[i]) ; } for(i = 0 ; i < 20 ; i++) { if(V[i] != Vr[i]) { return ER_FAIL ; } } return ER_SUCCESS ; } static SYS_STATUS HDCP_Authenticate_Repeater() { BYTE uc ; #ifdef SUPPORT_DSSSHA BYTE revoked ; int i ; #else int i; // richard add BYTE revoked; // richard add #endif // _DSS_SHA_ // BYTE test; // BYTE test06; // BYTE test07; // BYTE test08; BYTE cDownStream ; BYTE BCaps; USHORT BStatus ; USHORT TimeOut ; ErrorF("Authentication for repeater\n") ; // emily add for test,abort HDCP // 2007/10/01 marked by jj_tseng@chipadvanced.com // HDMITX_WriteI2C_Byte(0x20,0x00) ; // HDMITX_WriteI2C_Byte(0x04,0x01) ; // HDMITX_WriteI2C_Byte(0x10,0x01) ; // HDMITX_WriteI2C_Byte(0x15,0x0F) ; // DelayMS(100); // HDMITX_WriteI2C_Byte(0x04,0x00) ; // HDMITX_WriteI2C_Byte(0x10,0x00) ; // HDMITX_WriteI2C_Byte(0x20,0x01) ; // DelayMS(100); // test07 = HDMITX_ReadI2C_Byte(0x7) ; // test06 = HDMITX_ReadI2C_Byte(0x6); // test08 = HDMITX_ReadI2C_Byte(0x8); //~jj_tseng@chipadvanced.com // end emily add for test ////////////////////////////////////// // Authenticate Fired ////////////////////////////////////// HDCP_GetBCaps(&BCaps,&BStatus) ; DelayMS(2); HDCP_Auth_Fire(); DelayMS(550); // emily add for test for(TimeOut = 250*6 ; TimeOut > 0 ; TimeOut --) { uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) ; if(uc & B_INT_DDC_BUS_HANG) { ErrorF("DDC Bus hang\n") ; goto HDCP_Repeater_Fail ; } uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; if(uc & B_INT_AUTH_FAIL) { /* HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; */ ErrorF("HDCP_Authenticate_Repeater(): B_INT_AUTH_FAIL.\n") ; goto HDCP_Repeater_Fail ; } // emily add for test // test =(HDMITX_ReadI2C_Byte(0x7)&0x4)>>2 ; if(uc & B_INT_KSVLIST_CHK) { HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_KSVLISTCHK) ; HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; ErrorF("B_INT_KSVLIST_CHK\n") ; break ; } DelayMS(5) ; } if(TimeOut == 0) { ErrorF("Time out for wait KSV List checking interrupt\n") ; goto HDCP_Repeater_Fail ; } /////////////////////////////////////// // clear KSVList check interrupt. /////////////////////////////////////// for(TimeOut = 500 ; TimeOut > 0 ; TimeOut --) { if((TimeOut % 100) == 0) { ErrorF("Wait KSV FIFO Ready %d\n",TimeOut) ; } if(HDCP_GetBCaps(&BCaps,&BStatus) == ER_FAIL) { ErrorF("Get BCaps fail\n") ; goto HDCP_Repeater_Fail ; } if(BCaps & B_CAP_KSV_FIFO_RDY) { ErrorF("FIFO Ready\n") ; break ; } DelayMS(5) ; } if(TimeOut == 0) { ErrorF("Get KSV FIFO ready TimeOut\n") ; goto HDCP_Repeater_Fail ; } ErrorF("Wait timeout = %d\n",TimeOut) ; ClearDDCFIFO() ; GenerateDDCSCLK() ; cDownStream = (BStatus & M_DOWNSTREAM_COUNT) ; if(cDownStream == 0 || cDownStream > 6 || BStatus & (B_MAX_CASCADE_EXCEEDED|B_DOWNSTREAM_OVER)) { ErrorF("Invalid Down stream count,fail\n") ; goto HDCP_Repeater_Fail ; } if(HDCP_GetKSVList(KSVList,cDownStream) == ER_FAIL) { goto HDCP_Repeater_Fail ; } for(i = 0 ; i < cDownStream ; i++) { revoked=FALSE ; uc = 0 ; for( TimeOut = 0 ; TimeOut < 5 ; TimeOut++ ) { // check bit count uc += countbit(KSVList[i*5+TimeOut]) ; } if( uc != 20 ) revoked = TRUE ; #ifdef SUPPORT_REVOKE_KSV HDCP_VerifyRevocationList(SRM1,&KSVList[i*5],&revoked) ; #endif if(revoked) { ErrorF("KSVFIFO[%d] = %02X %02X %02X %02X %02X is revoked\n",i,KSVList[i*5],KSVList[i*5+1],KSVList[i*5+2],KSVList[i*5+3],KSVList[i*5+4]) ; goto HDCP_Repeater_Fail ; } } if(HDCP_GetVr(Vr) == ER_FAIL) { goto HDCP_Repeater_Fail ; } if(HDCP_GetM0(M0) == ER_FAIL) { goto HDCP_Repeater_Fail ; } // do check SHA if(HDCP_CheckSHA(M0,BStatus,KSVList,cDownStream,Vr) == ER_FAIL) { goto HDCP_Repeater_Fail ; } HDCP_ResumeRepeaterAuthenticate() ; Instance[0].bAuthenticated = TRUE ; return ER_SUCCESS ; HDCP_Repeater_Fail: HDCP_CancelRepeaterAuthenticate() ; return ER_FAIL ; } ////////////////////////////////////////////////////////////////////// // Function: HDCP_ResumeAuthentication // Parameter: N/A // Return: N/A // Remark: called by interrupt handler to restart Authentication and Encryption. // Side-Effect: as Authentication and Encryption. ////////////////////////////////////////////////////////////////////// static void HDCP_ResumeAuthentication() { SetAVMute(TRUE) ; if(HDCP_Authenticate() == ER_SUCCESS) { HDCP_EnableEncryption() ; } SetAVMute(FALSE) ; } #endif // SUPPORT_HDCP static void ENABLE_NULL_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_ACP_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_ISRC1_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_ISRC2_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_AVI_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_AUD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_SPD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void ENABLE_MPG_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); } static void DISABLE_NULL_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,0); } static void DISABLE_ACP_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,0); } static void DISABLE_ISRC1_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,0); } static void DISABLE_ISRC2_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,0); } static void DISABLE_AVI_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,0); } static void DISABLE_AUD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,0); } static void DISABLE_SPD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,0); } static void DISABLE_MPG_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,0); } ////////////////////////////////////////////////////////////////////// // Function: SetAVIInfoFrame() // Parameter: pAVIInfoFrame - the pointer to HDMI AVI Infoframe ucData // Return: N/A // Remark: Fill the AVI InfoFrame ucData,and count checksum,then fill into // AVI InfoFrame registers. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame) { int i ; byte ucData ; if(!pAVIInfoFrame) { return ER_FAIL ; } Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB1,pAVIInfoFrame->pktbyte.AVI_DB[0]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB2,pAVIInfoFrame->pktbyte.AVI_DB[1]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB3,pAVIInfoFrame->pktbyte.AVI_DB[2]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB4,pAVIInfoFrame->pktbyte.AVI_DB[3]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB5,pAVIInfoFrame->pktbyte.AVI_DB[4]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB6,pAVIInfoFrame->pktbyte.AVI_DB[5]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB7,pAVIInfoFrame->pktbyte.AVI_DB[6]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB8,pAVIInfoFrame->pktbyte.AVI_DB[7]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB9,pAVIInfoFrame->pktbyte.AVI_DB[8]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB10,pAVIInfoFrame->pktbyte.AVI_DB[9]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB11,pAVIInfoFrame->pktbyte.AVI_DB[10]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB12,pAVIInfoFrame->pktbyte.AVI_DB[11]); HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB13,pAVIInfoFrame->pktbyte.AVI_DB[12]); for(i = 0,ucData = 0; i < 13 ; i++) { ucData -= pAVIInfoFrame->pktbyte.AVI_DB[i] ; } ErrorF("SetAVIInfo(): ") ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB1)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB2)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB3)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB4)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB5)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB6)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB7)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB8)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB9)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB10)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB11)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB12)) ; //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB13)) ; ErrorF("\n") ; ucData -= 0x80+AVI_INFOFRAME_VER+AVI_INFOFRAME_TYPE+AVI_INFOFRAME_LEN ; HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_SUM,ucData); Switch_HDMITX_Bank(0) ; ENABLE_AVI_INFOFRM_PKT(); return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function: SetAudioInfoFrame() // Parameter: pAudioInfoFrame - the pointer to HDMI Audio Infoframe ucData // Return: N/A // Remark: Fill the Audio InfoFrame ucData,and count checksum,then fill into // Audio InfoFrame registers. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame) { int i ; BYTE ucData ; if(!pAudioInfoFrame) { return ER_FAIL ; } Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CC,pAudioInfoFrame->pktbyte.AUD_DB[0]); HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SF,pAudioInfoFrame->pktbyte.AUD_DB[1]); HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CA,pAudioInfoFrame->pktbyte.AUD_DB[3]); HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_DM_LSV,pAudioInfoFrame->pktbyte.AUD_DB[4]) ; for(i = 0,ucData = 0 ; i< 5 ; i++) { ucData -= pAudioInfoFrame->pktbyte.AUD_DB[i] ; } ucData -= 0x80+AUDIO_INFOFRAME_VER+AUDIO_INFOFRAME_TYPE+AUDIO_INFOFRAME_LEN ; HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SUM,ucData) ; Switch_HDMITX_Bank(0) ; ENABLE_AUD_INFOFRM_PKT(); return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function: SetSPDInfoFrame() // Parameter: pSPDInfoFrame - the pointer to HDMI SPD Infoframe ucData // Return: N/A // Remark: Fill the SPD InfoFrame ucData,and count checksum,then fill into // SPD InfoFrame registers. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame) { int i ; BYTE ucData ; if(!pSPDInfoFrame) { return ER_FAIL ; } Switch_HDMITX_Bank(1) ; for(i = 0,ucData = 0 ; i < 25 ; i++) { ucData -= pSPDInfoFrame->pktbyte.SPD_DB[i] ; HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_PB1+i,pSPDInfoFrame->pktbyte.SPD_DB[i]) ; } ucData -= 0x80+SPD_INFOFRAME_VER+SPD_INFOFRAME_TYPE+SPD_INFOFRAME_LEN ; HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_SUM,ucData) ; // checksum Switch_HDMITX_Bank(0) ; ENABLE_SPD_INFOFRM_PKT(); return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function: SetMPEGInfoFrame() // Parameter: pMPEGInfoFrame - the pointer to HDMI MPEG Infoframe ucData // Return: N/A // Remark: Fill the MPEG InfoFrame ucData,and count checksum,then fill into // MPEG InfoFrame registers. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// static SYS_STATUS SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame) { int i ; BYTE ucData ; if(!pMPGInfoFrame) { return ER_FAIL ; } Switch_HDMITX_Bank(1) ; HDMITX_WriteI2C_Byte(REG_TX_PKT_MPGINFO_FMT,pMPGInfoFrame->info.FieldRepeat|(pMPGInfoFrame->info.MpegFrame<<1)) ; HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB0,pMPGInfoFrame->pktbyte.MPG_DB[0]) ; HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB1,pMPGInfoFrame->pktbyte.MPG_DB[1]) ; HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB2,pMPGInfoFrame->pktbyte.MPG_DB[2]) ; HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB3,pMPGInfoFrame->pktbyte.MPG_DB[3]) ; for(ucData = 0,i = 0 ; i < 5 ; i++) { ucData -= pMPGInfoFrame->pktbyte.MPG_DB[i] ; } ucData -= 0x80+MPEG_INFOFRAME_VER+MPEG_INFOFRAME_TYPE+MPEG_INFOFRAME_LEN ; HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_SUM,ucData) ; Switch_HDMITX_Bank(0) ; ENABLE_SPD_INFOFRM_PKT() ; return ER_SUCCESS ; } ////////////////////////////////////////////////////////////////////// // Function: DumpCatHDMITXReg() // Parameter: N/A // Return: N/A // Remark: Debug function,dumps the registers of CAT6611. // Side-Effect: N/A ////////////////////////////////////////////////////////////////////// #ifdef HDMITX_REG_DEBUG static void DumpCatHDMITXReg() { int i,j ; BYTE reg ; BYTE bank ; BYTE ucData ; ErrorF(" ") ; for(j = 0 ; j < 16 ; j++) { ErrorF(" %02X",j) ; if((j == 3)||(j==7)||(j==11)) { ErrorF(" ") ; } } ErrorF("\n -----------------------------------------------------\n") ; Switch_HDMITX_Bank(0) ; for(i = 0 ; i < 0x100 ; i+=16) { ErrorF("[%3X] ",i) ; for(j = 0 ; j < 16 ; j++) { ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF)) ; ErrorF(" %02X",ucData) ; if((j == 3)||(j==7)||(j==11)) { ErrorF(" -") ; } } ErrorF("\n") ; if((i % 0x40) == 0x30) { ErrorF(" -----------------------------------------------------\n") ; } } Switch_HDMITX_Bank(1) ; for(i = 0x130; i < 0x1B0 ; i+=16) { ErrorF("[%3X] ",i) ; for(j = 0 ; j < 16 ; j++) { ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF)) ; ErrorF(" %02X",ucData) ; if((j == 3)||(j==7)||(j==11)) { ErrorF(" -") ; } } ErrorF("\n") ; if(i == 0x160) { ErrorF(" -----------------------------------------------------\n") ; } } Switch_HDMITX_Bank(0) ; } #endif