mirror of
https://github.com/marqs85/ossc.git
synced 2024-11-18 14:06:03 +00:00
1ba8d68aab
The change should fix interlace compatibility with some Denon AV receivers.
551 lines
16 KiB
C
551 lines
16 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
// This is the sample program for CAT6611 driver usage.
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "hdmitx.h"
|
|
#include "it6613_sys.h" // richard add
|
|
#include "edid.h" // richard add
|
|
|
|
extern int TX_HDP; // richard add
|
|
int gEnableColorDepth = 1; //richard add
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// EDID
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
static _XDATA unsigned char EDID_Buf[128] ;
|
|
// richard static RX_CAP _XDATA RxCapability ;
|
|
RX_CAP _XDATA RxCapability ;
|
|
// richard static BOOL bChangeMode = FALSE ;
|
|
BOOL bChangeMode = FALSE ;
|
|
_XDATA AVI_InfoFrame AviInfo;
|
|
_XDATA Audio_InfoFrame AudioInfo ;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Program utility.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// move to .h BOOL ParseEDID() ;
|
|
// richard static BOOL ParseCEAEDID(BYTE *pCEAEDID) ;
|
|
void ConfigAVIInfoFrame(BYTE VIC, BYTE pixelrep) ;
|
|
void ConfigAudioInfoFrm() ;
|
|
|
|
|
|
#ifndef SUPPORT_SYNCEMB
|
|
_IDATA BYTE bInputColorMode = F_MODE_RGB444; //F_MODE_RGB444;
|
|
_IDATA BYTE bInputSignalType = 0 ;
|
|
// BYTE bInputSignalType = T_MODE_INDDR ; // for DDR mode input
|
|
#else
|
|
// BYTE bInputSignalType = T_MODE_SYNCEMB ; // for 16 bit sync embedded
|
|
_IDATA BYTE bInputColorMode = F_MODE_YUV422 ;
|
|
_IDATA BYTE bInputSignalType = T_MODE_SYNCEMB | T_MODE_CCIR656 ; // for 16 bit sync embedded
|
|
#endif // SUPPORT_SYNCEMB
|
|
|
|
_IDATA BYTE iVideoModeSelect=0 ;
|
|
|
|
_IDATA BYTE bOutputColorMode = F_MODE_RGB444; //F_MODE_RGB444 ;
|
|
_XDATA ULONG VideoPixelClock ;
|
|
_XDATA BYTE VIC ; // 480p60
|
|
_XDATA BYTE pixelrep ; // no pixelrepeating
|
|
_XDATA HDMI_Aspec aspec ;
|
|
_XDATA HDMI_Colorimetry Colorimetry ;
|
|
|
|
BOOL bHDMIMode, bAudioEnable ;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Function Body.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//richard, move to .h void HDMITX_ChangeDisplayOption(HDMI_Video_Type VideoMode, HDMI_OutputColorMode OutputColorMode) ;
|
|
//richard, move to .hvoid HDMITX_SetOutput() ;
|
|
//richard richard, move to .h void HDMITX_DevLoopProc() ;
|
|
|
|
void
|
|
HDMITX_SetOutput()
|
|
{
|
|
VIDEOPCLKLEVEL level ;
|
|
unsigned long TMDSClock = VideoPixelClock*(pixelrep+1);
|
|
|
|
#ifdef SUPPORT_SYNCEMB
|
|
ProgramSyncEmbeddedVideoMode(VIC, bInputSignalType) ; // inf CCIR656 input
|
|
#endif
|
|
|
|
//TMDSClock = 745000000; //????? richard
|
|
if( TMDSClock>80000000 )
|
|
{
|
|
level = PCLK_HIGH ;
|
|
}
|
|
else if(TMDSClock>20000000)
|
|
{
|
|
level = PCLK_MEDIUM ;
|
|
}
|
|
else
|
|
{
|
|
level = PCLK_LOW ;
|
|
}
|
|
|
|
|
|
|
|
//BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) ;
|
|
//EnableVideoOutput(level,bInputColorMode, bInputSignalType, bOutputColorMode,bHDMIMode) ;
|
|
EnableVideoOutput(level,bInputColorMode, bOutputColorMode,bHDMIMode) ; // richard modify
|
|
|
|
if( bHDMIMode )
|
|
{
|
|
OS_PRINTF("ConfigAVIInfoFrame, VIC=%d\n", VIC);
|
|
ConfigAVIInfoFrame(VIC, pixelrep) ;
|
|
|
|
EnableHDCP(TRUE) ;
|
|
if( bAudioEnable )
|
|
{
|
|
//BOOL EnableAudioOutput(ULONG VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF)
|
|
//EnableAudioOutput(TMDSClock,48000, 2, FALSE);
|
|
bool bSPDIF = FALSE;
|
|
EnableAudioOutput(TMDSClock,AUDFS_48KHz, 2, 16, bSPDIF); // richard modify
|
|
ConfigAudioInfoFrm() ;
|
|
}
|
|
}
|
|
SetAVMute(FALSE) ;
|
|
bChangeMode = FALSE ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
HDMITX_ChangeDisplayOption(HDMI_Video_Type OutputVideoTiming, HDMI_OutputColorMode OutputColorMode)
|
|
{
|
|
//HDMI_Video_Type t=HDMI_480i60_16x9;
|
|
switch(OutputVideoTiming)
|
|
{
|
|
case HDMI_640x480p60:
|
|
VIC = 1 ;
|
|
VideoPixelClock = 25000000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_4x3 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_480p60:
|
|
VIC = 2 ;
|
|
VideoPixelClock = 27000000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_4x3 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_480p60_16x9:
|
|
VIC = 3 ;
|
|
VideoPixelClock = 27000000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_720p60:
|
|
VIC = 4 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_1080i60:
|
|
VIC = 5 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_480i60:
|
|
VIC = 6 ;
|
|
VideoPixelClock = 13500000 ;
|
|
pixelrep = 1 ;
|
|
aspec = HDMI_4x3 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_480i60_16x9:
|
|
VIC = 7 ;
|
|
VideoPixelClock = 13500000 ;
|
|
pixelrep = 1 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_1080p60:
|
|
VIC = 16 ;
|
|
VideoPixelClock = 148500000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_576p50:
|
|
VIC = 17 ;
|
|
VideoPixelClock = 27000000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_4x3 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_576p50_16x9:
|
|
VIC = 18 ;
|
|
VideoPixelClock = 27000000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_720p50:
|
|
VIC = 19 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_1080i50:
|
|
VIC = 20 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_576i50:
|
|
VIC = 21 ;
|
|
VideoPixelClock = 13500000 ;
|
|
pixelrep = 1 ;
|
|
aspec = HDMI_4x3 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_576i50_16x9:
|
|
VIC = 22 ;
|
|
VideoPixelClock = 13500000 ;
|
|
pixelrep = 1 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;
|
|
case HDMI_1080p50:
|
|
VIC = 31 ;
|
|
VideoPixelClock = 148500000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
/* case HDMI_1080p24:
|
|
VIC = 32 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_1080p25:
|
|
VIC = 33 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_1080p30:
|
|
VIC = 34 ;
|
|
VideoPixelClock = 74250000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU709 ;
|
|
break ;
|
|
case HDMI_1080i120:// richard add
|
|
VIC = 46 ;
|
|
VideoPixelClock = 148500000 ;
|
|
pixelrep = 0 ;
|
|
aspec = HDMI_16x9 ;
|
|
Colorimetry = HDMI_ITU601 ;
|
|
break ;*/
|
|
|
|
|
|
default:
|
|
VIC = 0; // richard add
|
|
bChangeMode = FALSE ;
|
|
return ;
|
|
}
|
|
|
|
switch(OutputColorMode)
|
|
{
|
|
case HDMI_YUV444:
|
|
bOutputColorMode = F_MODE_YUV444 ;
|
|
break ;
|
|
case HDMI_YUV422:
|
|
bOutputColorMode = F_MODE_YUV422 ;
|
|
break ;
|
|
case HDMI_RGB444:
|
|
default:
|
|
bOutputColorMode = F_MODE_RGB444 ;
|
|
break ;
|
|
}
|
|
|
|
if( Colorimetry == HDMI_ITU709 )
|
|
{
|
|
bInputColorMode |= F_VIDMODE_ITU709 ;
|
|
}
|
|
else
|
|
{
|
|
bInputColorMode &= ~F_VIDMODE_ITU709 ;
|
|
}
|
|
|
|
if( OutputVideoTiming != HDMI_640x480p60)
|
|
{
|
|
bInputColorMode |= F_VIDMODE_16_235 ;
|
|
}
|
|
else
|
|
{
|
|
bInputColorMode &= ~F_VIDMODE_16_235 ;
|
|
}
|
|
|
|
bChangeMode = TRUE ;
|
|
}
|
|
|
|
|
|
void
|
|
ConfigAVIInfoFrame(BYTE VIC, BYTE pixelrep)
|
|
{
|
|
// AVI_InfoFrame AviInfo;
|
|
|
|
AviInfo.pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ;
|
|
AviInfo.pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ;
|
|
AviInfo.pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ;
|
|
|
|
switch(bOutputColorMode)
|
|
{
|
|
case F_MODE_YUV444:
|
|
// AviInfo.info.ColorMode = 2 ;
|
|
AviInfo.pktbyte.AVI_DB[0] = (2<<5)|(1<<4) ;
|
|
break ;
|
|
case F_MODE_YUV422:
|
|
// AviInfo.info.ColorMode = 1 ;
|
|
AviInfo.pktbyte.AVI_DB[0] = (1<<5)|(1<<4) ;
|
|
break ;
|
|
case F_MODE_RGB444:
|
|
default:
|
|
// AviInfo.info.ColorMode = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[0] = (0<<5)|(1<<4) ;
|
|
break ;
|
|
}
|
|
AviInfo.pktbyte.AVI_DB[1] = 8 ;
|
|
AviInfo.pktbyte.AVI_DB[1] |= (aspec != HDMI_16x9)?(1<<4):(2<<4) ; // 4:3 or 16:9
|
|
AviInfo.pktbyte.AVI_DB[1] |= (Colorimetry != HDMI_ITU709)?(1<<6):(2<<6) ; // 4:3 or 16:9
|
|
AviInfo.pktbyte.AVI_DB[2] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[3] = VIC ;
|
|
AviInfo.pktbyte.AVI_DB[4] = pixelrep & 3 ;
|
|
AviInfo.pktbyte.AVI_DB[5] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[6] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[7] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[8] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[9] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[10] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[11] = 0 ;
|
|
AviInfo.pktbyte.AVI_DB[12] = 0 ;
|
|
|
|
EnableAVIInfoFrame(TRUE, (unsigned char *)&AviInfo) ;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Function: ConfigAudioInfoFrm
|
|
// Parameter: NumChannel, number from 1 to 8
|
|
// Return: ER_SUCCESS for successfull.
|
|
// Remark: Evaluate. The speakerplacement is only for reference.
|
|
// For production, the caller of SetAudioInfoFrame should program
|
|
// Speaker placement by actual status.
|
|
// Side-Effect:
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
ConfigAudioInfoFrm()
|
|
{
|
|
int i ;
|
|
ErrorF("ConfigAudioInfoFrm(%d)\n",2) ;
|
|
|
|
AudioInfo.pktbyte.AUD_HB[0] = AUDIO_INFOFRAME_TYPE ;
|
|
AudioInfo.pktbyte.AUD_HB[1] = 1 ;
|
|
AudioInfo.pktbyte.AUD_HB[2] = AUDIO_INFOFRAME_LEN ;
|
|
AudioInfo.pktbyte.AUD_DB[0] = 1 ;
|
|
for( i = 1 ;i < AUDIO_INFOFRAME_LEN ; i++ )
|
|
{
|
|
AudioInfo.pktbyte.AUD_DB[i] = 0 ;
|
|
}
|
|
EnableAudioInfoFrame(TRUE, (unsigned char *)&AudioInfo) ;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// ParseEDID()
|
|
// Check EDID check sum and EDID 1.3 extended segment.
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL
|
|
ParseEDID()
|
|
{
|
|
// collect the EDID ucdata of segment 0
|
|
BYTE CheckSum ;
|
|
BYTE BlockCount ;
|
|
BOOL err = FALSE ;
|
|
BOOL bValidCEA = FALSE ;
|
|
int i ;
|
|
|
|
RxCapability.ValidCEA = FALSE ;
|
|
|
|
// richard GetEDIDData(0, EDID_Buf);
|
|
if (!GetEDIDData(0, EDID_Buf))
|
|
return FALSE;
|
|
|
|
|
|
for( i = 0, CheckSum = 0 ; i < 128 ; i++ )
|
|
{
|
|
CheckSum += EDID_Buf[i] ; CheckSum &= 0xFF ;
|
|
}
|
|
|
|
//Eep_Write(0x80, 0x80, EDID_Buf) ;
|
|
if( CheckSum != 0 ) // 128-byte EDID sum shall equal zero
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
// check EDID Header
|
|
if( EDID_Buf[0] != 0x00 ||
|
|
EDID_Buf[1] != 0xFF ||
|
|
EDID_Buf[2] != 0xFF ||
|
|
EDID_Buf[3] != 0xFF ||
|
|
EDID_Buf[4] != 0xFF ||
|
|
EDID_Buf[5] != 0xFF ||
|
|
EDID_Buf[6] != 0xFF ||
|
|
EDID_Buf[7] != 0x00)
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
|
|
BlockCount = EDID_Buf[0x7E] ; // Extention Flash: Number of 128-byte EDID extesion blocks to follow
|
|
|
|
if( BlockCount == 0 )
|
|
{
|
|
return TRUE ; // do nothing.
|
|
}
|
|
else if ( BlockCount > 4 )
|
|
{
|
|
BlockCount = 4 ;
|
|
}
|
|
|
|
// read all segment for test
|
|
for( i = 1 ; i <= BlockCount ; i++ )
|
|
{
|
|
err = GetEDIDData(i, EDID_Buf) ;
|
|
|
|
if( err )
|
|
{
|
|
if( !bValidCEA && EDID_Buf[0] == 0x2 && EDID_Buf[1] == 0x3 ) //EDID_Buf[0] == 0x2 ==> Additional timing data type 2
|
|
{
|
|
// richard change
|
|
//err = ParseCEAEDID(EDID_Buf) ;
|
|
err = ParseCEAEDID(EDID_Buf, &RxCapability);
|
|
if( err )
|
|
{
|
|
|
|
if(RxCapability.IEEEOUI==0x0c03)
|
|
{
|
|
RxCapability.ValidHDMI = TRUE ;
|
|
bValidCEA = TRUE ;
|
|
}
|
|
else
|
|
{
|
|
RxCapability.ValidHDMI = FALSE ;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return err?FALSE:TRUE ; // richard modify
|
|
|
|
}
|
|
|
|
/* richard: use the one defined edid.c
|
|
static BOOL
|
|
ParseCEAEDID(BYTE *pCEAEDID)
|
|
{
|
|
BYTE offset,End ;
|
|
BYTE count ;
|
|
BYTE tag ;
|
|
int i ;
|
|
|
|
// richard if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) return ER_SUCCESS ; // not a CEA BLOCK.
|
|
if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) // not a CEA BLOCK.
|
|
return FALSE;
|
|
End = pCEAEDID[2] ; // CEA description.
|
|
RxCapability.VideoMode = pCEAEDID[3] ;
|
|
|
|
RxCapability.VDOModeCount = 0 ;
|
|
RxCapability.idxNativeVDOMode = 0xff ;
|
|
|
|
for( offset = 4 ; offset < End ; )
|
|
{
|
|
tag = pCEAEDID[offset] >> 5 ;
|
|
count = pCEAEDID[offset] & 0x1f ;
|
|
switch( tag )
|
|
{
|
|
case 0x01: // Audio Data Block ;
|
|
RxCapability.AUDDesCount = count/3 ;
|
|
offset++ ;
|
|
for( i = 0 ; i < RxCapability.AUDDesCount ; i++ )
|
|
{
|
|
RxCapability.AUDDes[i].uc[0] = pCEAEDID[offset++] ;
|
|
RxCapability.AUDDes[i].uc[1] = pCEAEDID[offset++] ;
|
|
RxCapability.AUDDes[i].uc[2] = pCEAEDID[offset++] ;
|
|
}
|
|
|
|
break ;
|
|
|
|
case 0x02: // Video Data Block ;
|
|
//RxCapability.VDOModeCount = 0 ;
|
|
offset ++ ;
|
|
for( i = 0,RxCapability.idxNativeVDOMode = 0xff ; i < count ; i++, offset++ )
|
|
{
|
|
BYTE VIC ;
|
|
VIC = pCEAEDID[offset] & (~0x80) ;
|
|
// if( FindModeTableEntryByVIC(VIC) != -1 )
|
|
{
|
|
RxCapability.VDOMode[RxCapability.VDOModeCount] = VIC ;
|
|
if( pCEAEDID[offset] & 0x80 )
|
|
{
|
|
RxCapability.idxNativeVDOMode = (BYTE)RxCapability.VDOModeCount ;
|
|
iVideoModeSelect = RxCapability.VDOModeCount ;
|
|
}
|
|
|
|
RxCapability.VDOModeCount++ ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case 0x03: // Vendor Specific Data Block ;
|
|
offset ++ ;
|
|
RxCapability.IEEEOUI = (ULONG)pCEAEDID[offset+2] ;
|
|
RxCapability.IEEEOUI <<= 8 ;
|
|
RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset+1] ;
|
|
RxCapability.IEEEOUI <<= 8 ;
|
|
RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset] ;
|
|
offset += count ; // ignore the remaind.
|
|
|
|
break ;
|
|
|
|
case 0x04: // Speaker Data Block ;
|
|
offset ++ ;
|
|
RxCapability.SpeakerAllocBlk.uc[0] = pCEAEDID[offset] ;
|
|
RxCapability.SpeakerAllocBlk.uc[1] = pCEAEDID[offset+1] ;
|
|
RxCapability.SpeakerAllocBlk.uc[2] = pCEAEDID[offset+2] ;
|
|
offset += 3 ;
|
|
break ;
|
|
case 0x05: // VESA Data Block ;
|
|
offset += count+1 ;
|
|
break ;
|
|
case 0x07: // Extended Data Block ;
|
|
offset += count+1 ; //ignore
|
|
break ;
|
|
default:
|
|
offset += count+1 ; // ignore
|
|
}
|
|
}
|
|
RxCapability.ValidCEA = TRUE ;
|
|
return TRUE ;
|
|
}
|
|
*/
|
|
|