mirror of
https://github.com/marqs85/ossc.git
synced 2024-08-17 01:28:59 +00:00
3539 lines
110 KiB
C
3539 lines
110 KiB
C
/////////////////////////////////////////////////////////////////////
|
|
// 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 EnableAudioOutput4OSSC(ULONG VideoPixelClock,BYTE bAudioDwSampl,BYTE bAudioSwapLR)
|
|
{
|
|
// set N and CTS
|
|
ULONG n = 12288;
|
|
ULONG cts = VideoPixelClock/1000;
|
|
|
|
if (bAudioDwSampl == 0x1)
|
|
n = n>>1;
|
|
|
|
//program 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));
|
|
//program CTS
|
|
HDMITX_WriteI2C_Byte(REGPktAudCTS0, cts & 0xff);
|
|
HDMITX_WriteI2C_Byte(REGPktAudCTS1,(cts>>8) & 0xff);
|
|
HDMITX_WriteI2C_Byte(REGPktAudCTS2,(cts>>16) & 0xff);
|
|
Switch_HDMITX_Bank(0);
|
|
|
|
#ifdef MANUAL_CTS
|
|
HDMITX_WriteI2C_Byte(0xF8, 0xC3);
|
|
HDMITX_WriteI2C_Byte(0xF8, 0xA5);
|
|
HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,B_SW_CTS);
|
|
HDMITX_WriteI2C_Byte(0xF8, 0xFF);
|
|
#else
|
|
HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,0); // D[1] = 0,HW auto count CTS
|
|
#endif
|
|
|
|
|
|
// set audio format
|
|
Instance[0].TMDSClock = VideoPixelClock;
|
|
BYTE fs = bAudioDwSampl == 0x1 ? AUDFS_48KHz : AUDFS_96KHz;
|
|
Instance[0].bAudFs = fs;
|
|
Instance[0].bOutputAudioMode = B_AUDFMT_32BIT_I2S;
|
|
Instance[0].bAudioChannelSwap = bAudioSwapLR == 0x1 ? 0xf : 0x0; // swap channels
|
|
BYTE AudioEnable = (0x1 & ~(M_AUD_SWL|B_SPDIFTC)) | M_AUD_24BIT;
|
|
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable & 0xF0);
|
|
|
|
if (bAudioDwSampl == 0x1)
|
|
HDMITX_SetREG_Byte(REG_TX_CLK_CTRL1,~M_AUD_DIV,B_AUD_DIV2);
|
|
else
|
|
HDMITX_SetREG_Byte(REG_TX_CLK_CTRL1,~M_AUD_DIV,B_AUD_NODIV);
|
|
|
|
HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_AUD_RST|B_AREF_RST));
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,Instance[0].bOutputAudioMode);
|
|
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,B_AUD_SPXFLAT_SRC3|B_AUD_SPXFLAT_SRC2|B_AUD_SPXFLAT_SRC1|B_AUD_ERR2FLAT); // only two channels
|
|
|
|
Switch_HDMITX_Bank(1) ;
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,0); // 2 audio channel without pre-emphasis
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,0);
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,1);
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,0);
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0xC0|fs); // choose clock
|
|
fs = ~fs; // OFS is the one's complement of FS
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(fs<<4)|AUD_SWL_24); // 24 bit Audio
|
|
|
|
Switch_HDMITX_Bank(0);
|
|
HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable);
|
|
|
|
Instance[0].bAudioChannelEnable = AudioEnable;
|
|
|
|
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=0 ;
|
|
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 (DDC_STATUS = %02X). \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<<i) )
|
|
{
|
|
count++ ;
|
|
}
|
|
}
|
|
return count ;
|
|
}
|
|
|
|
static void
|
|
HDCP_Reset()
|
|
{
|
|
BYTE uc ;
|
|
uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_HDCP_RST ;
|
|
HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc) ;
|
|
HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,0) ;
|
|
HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0) ;
|
|
HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHOST) ;
|
|
ClearDDCFIFO() ;
|
|
AbortDDC() ;
|
|
}
|
|
|
|
static SYS_STATUS
|
|
HDCP_Authenticate()
|
|
{
|
|
BYTE ucdata ;
|
|
BYTE BCaps ;
|
|
USHORT BStatus ;
|
|
USHORT TimeOut ;
|
|
|
|
// richard BYTE revoked = FALSE ;
|
|
BYTE BKSV[5] ;
|
|
|
|
Instance[0].bAuthenticated = FALSE ;
|
|
|
|
// Authenticate should be called after AFE setup up.
|
|
|
|
ErrorF("HDCP_Authenticate():\n") ;
|
|
HDCP_Reset() ;
|
|
// ClearDDCFIFO() ;
|
|
// AbortDDC() ;
|
|
|
|
if(HDCP_GetBCaps(&BCaps,&BStatus) != ER_SUCCESS)
|
|
{
|
|
ErrorF("HDCP_GetBCaps fail.\n") ;
|
|
return ER_FAIL ;
|
|
}
|
|
|
|
|
|
if(Instance[0].bHDMIMode)
|
|
{
|
|
if((BStatus & B_CAP_HDMI_MODE)==0)
|
|
{
|
|
ErrorF("Not a HDMI mode,do not authenticate and encryption. BCaps = %x BStatus = %x\n",BCaps,BStatus) ;
|
|
return ER_FAIL ;
|
|
}
|
|
}
|
|
|
|
ErrorF("BCaps = %02X BStatus = %04X\n",BCaps,BStatus) ;
|
|
/*
|
|
if((BStatus & M_DOWNSTREAM_COUNT)> 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);
|
|
}
|
|
|
|
void TX_SetPixelRepetition(BYTE pixelrep, BYTE via_infoframe) {
|
|
BYTE pllpr;
|
|
|
|
Switch_HDMITX_Bank(0);
|
|
pllpr = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1) & 0x2F;
|
|
|
|
if (!via_infoframe)
|
|
pllpr |= (1<<4)|((pixelrep&0x3)<<6);
|
|
|
|
HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, pllpr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// 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
|