1
0
mirror of https://github.com/marqs85/ossc.git synced 2024-11-18 14:06:03 +00:00
ossc/software/sys_controller/it6613/it6613_sys.c
marqs 1ba8d68aab set HDMI AVI Infoframe VIC in passthru modes
The change should fix interlace compatibility with some Denon AV receivers.
2019-07-01 01:24:18 +03:00

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 ;
}
*/