📄 anx9021.c
字号:
//*******************************************************************************************************
//*******************************************************************************************************
// ******************************** Firmware for ANX9021 ****************************************
//*******************************************************************************************************
//*******************************************************************************************************
//******************************************************************************
// ANX Company SRC
// Ver 1.51
// 2006/05/11
//******************************************************************************
//******************************************************************************
// Version 1.52 2006/05/19
// Disable HDCP auto reset before PLL reset and enable HDCP auto reset after PLL reset
// updated by XiaoYong
//******************************************************************************
//******************************************************************************
// Version 1.53 2006/05/24
// Change POP Noise handling sequence and add more time slot for POP Noise handling routine "void ANX9021_POPNoise(void);"
// updated by XiaoYong
//******************************************************************************
//******************************************************************************
// Version 1.54 2006/06/06
// Use hardware solution to handle POP Noise, change two registers' ( [0x60:0xB7] and [0x60:0xB4] ) value
// And remove the software POP Noise handling routine "void ANX9021_POPNoise(void);"
// updated by XiaoYong
//******************************************************************************
//******************************************************************************
// Version 1.55 2006/11/08
// Remove some operation to INTR2_MASK_REG to control the interrupt pin;
// Add hardware reset operation in the beginning of the main():ANX9021_Chip_Located();
// Modify the operation when sync lost then quickly found
// Before shut down AVC, config some video registers
// Kill all boost
// updated by zy
//******************************************************************************
//******************************************************************************
// Version 1.56 2007/01/23
// 1. Remove all the chip power down operation in 0x60:0x08;
//
// 2. Added routine "ANX9021_Align_ODCK_Repeated_Mode(void)" to align the data
// and clock in 480i(divided mode).
//
// 3. Add routine "ANX9021_Auth_Start_Int()".
//
// 4. Remove the auto reset HDCP function.
//
// 5. In routine "ANX9021_HDMI_Port_Switch()", enable DDC after HPD .
//
// 6. Add routine "ANX9021_PLL_Reset()" to reset PLL.
//
// 7. Add routine "ANX9021_RGBin_Range_Scaling()" to scale input range when RGB in,
// YCbCr out.
//
// 8. Set state to MONITOR_CKDT when no TMDS clock;
//
// 9. Added some macros to configure chip settings(input color space, DAC output).
// This code is in the file ANX9021.h;
//
// 10. Reset chip and firmware if register INTR1_MASK_REG turn to default value;
//
// 11. Check if the AVI infoframe existed or not before RGB input range scaling.
//
// 12. Add routine "ANX9021_Show_Video_Info()" to show basic information.
//
// 13. Add API routine "ANX9021_PowerCtrl_API()" to power down or power up ANX9021.
//
// 14. Modified the HPD routines.
//
// updated by zy
//
//******************************************************************************
//******************************************************************************
// I N C L U D E F I L E S
//******************************************************************************
#include "ANX9021.h"
#include "i2c_intf.h"
#include "Timer.h"
#include "mcu.h"
//******************************************************************************
// G L O B A L V A R I A B L E S
//******************************************************************************
BYTE g_HDMI_DVI_Status;
BYTE g_Sys_State;
BYTE g_Cur_Pix_Clk;
BYTE g_Video_Stable_Cntr;
BYTE g_Audio_Stable_Cntr;
BYTE g_Sync_Expire_Cntr;
BYTE g_Timer_Slot ;
BYTE g_HDCP_Err_Cnt;
BYTE g_Sync_Change; //record sync interrupt
WORD g_Cur_H_Res;
WORD g_Cur_V_Res;
BOOL g_Video_Muted;
BOOL g_Audio_Muted;
BOOL g_CTS_Got;
BOOL g_Audio_Got;
BOOL g_Restart_System;
BOOL g_Auth_Start;
//******************************************************************************
// F U N C T I O N P R O T O T Y P E S
//******************************************************************************
static void ANX9021_Init_var(void);
static void ANX9021_Video_Timer_Slot(void);
static void ANX9021_Audio_Timer_Slot(void);
static void ANX9021_Timer_Slot2(void);
static void ANX9021_Set_Sys_State(BYTE ss);
static void ANX9021_Sync_Det_Int(void);
static void ANX9021_Cts_Rcv_Int(void);
static void ANX9021_Audio_Rcv_Int(void);
static void ANX9021_HDCP_Error_Int(void);
static void ANX9021_Aac_Done_Int(void);
static void ANX9021_HDMI_DVI_Int(void);
static void ANX9021_Auth_Start_Int(BYTE s1);
static void ANX9021_Get_Video_Info(void);
static char ANX9021_Is_Video_Change(void);
static void ANX9021_Mute_Video(void);
static void ANX9021_Unmute_Video(void);
static void ANX9021_Mute_Audio(void);
static void ANX9021_Unmute_Audio(void);
static void ANX9021_Restart_Audio_Chk(void);
static void ANX9021_Clk_Detected_Int(void);
static BYTE ANX9021_Initialize(void);
static void ANX9021_PLL_Reset(void);
static void ANX9021_Align_ODCK_Repeated_Mode(void);
static void ANX9021_RGBin_Range_Scaling(void);
static void ANX9021_Show_Video_Info(void);
static void ANX9021_New_AVI_Int(void);
//******************************************************************************
// F U N C T I O N S D E F I N I T I O N
//******************************************************************************
void ANX9021_PowerCtrl_API(BYTE onoff)
{
BYTE c;
if(onoff) //power on ANX9021
{
ANX9021_ReadI2C_RX0(SYS_CTRL1_REG, &c);
ANX9021_WriteI2C_RX0(SYS_CTRL1_REG, c | 0x01); // power up all
}
else //power off ANX9021
{
ANX9021_ReadI2C_RX0(SYS_CTRL1_REG, &c);
ANX9021_WriteI2C_RX0(SYS_CTRL1_REG, c & 0xfe); // power off all
}
}
void ANX9021_Int_Process(void)
{
BYTE c;
BYTE s1, s2, s3, s4, s5, s6;
ANX9021_ReadI2C_RX0(STATE_REG, &c);
if (c & ANX9021_SYNC_DECT) // sync is found
{
if (g_Sys_State == WAIT_SCDT)
{
ANX9021_ReadI2C_RX0(INTR2_REG, &s2);
if(!(s2 & ANX9021_SCDT_CHANGE))
{
debug_puts("\n\n++++++++ Sync Interrput lost +++++++.\n\n");
ANX9021_ReadI2C_RX0(AEC_CTRL_REG, &c);
ANX9021_WriteI2C_RX0(AEC_CTRL_REG, c | 0x04);
ANX9021_Set_Sys_State(WAIT_VIDEO);
g_Video_Stable_Cntr = 0;
}
}
}
ANX9021_ReadI2C_RX0(STATE_REG, &c);
if( c&0x02 ) // Pixel clock is existed
{
if (g_Sys_State == MONITOR_CKDT)
{
ANX9021_PLL_Reset();
}
else
{
ANX9021_ReadI2C_RX0(INTR1_REG, &s1);
ANX9021_WriteI2C_RX0(INTR1_REG, s1);
ANX9021_ReadI2C_RX0(INTR2_REG, &s2);
ANX9021_WriteI2C_RX0(INTR2_REG, s2);
ANX9021_ReadI2C_RX0(INTR3_REG, &s3);
ANX9021_WriteI2C_RX0(INTR3_REG, s3);
ANX9021_ReadI2C_RX0(INTR4_REG, &s4);
ANX9021_WriteI2C_RX0(INTR4_REG, s4);
ANX9021_ReadI2C_RX0(INTR5_REG, &s5);
ANX9021_WriteI2C_RX0(INTR5_REG, s5);
ANX9021_ReadI2C_RX0(INTR6_REG, &s6);
ANX9021_WriteI2C_RX0(INTR6_REG, s6);
if (s2 & 0x10)//clk detect change interrupt
{
ANX9021_Clk_Detected_Int();
}
if (s2 & ANX9021_SCDT_CHANGE) // SYNC detect interrupt
{
ANX9021_Sync_Det_Int();
}
if (s2 & ANX9021_HDMI_DVI_MODE_CHANGE) // HDMI_DVI detect interrupt
{
ANX9021_HDMI_DVI_Int();
}
if (s3 & ANX9021_NEW_AVI_DECT)
{
ANX9021_New_AVI_Int();
}
if (s1 & ANX9021_CTS_ACR_CHANGE)
{
debug_puts("*ANX9021 Interrupt: Audio Error(4 Bits).");
ANX9021_Restart_Audio_Chk();
}
if (s2 & ANX9021_CTS_RECV)
{
ANX9021_Cts_Rcv_Int();
}
if (s2 & ANX9021_AUDIO_RECV)
{
ANX9021_Audio_Rcv_Int();
}
if (s1 & 0x02) // Authentication start interrupt
{
ANX9021_Auth_Start_Int(s1);
}
if ( (s4 & ANX9021_HDCP_ERROR) && g_Auth_Start ) // HDCP error
{
ANX9021_HDCP_Error_Int();
}
else
{
g_HDCP_Err_Cnt = 0;
}
if (s5 & ANX9021_AAC_MUTE) // AAC done
{
ANX9021_Aac_Done_Int();
}
// align odck when sync changed and pixel clock divider enabled
ANX9021_Align_ODCK_Repeated_Mode();
}
}
else // no TMDS clock
{
if(g_Sys_State != MONITOR_CKDT)
{
debug_puts("No TMDS clock.");
ANX9021_Set_Sys_State(MONITOR_CKDT);
g_Sync_Expire_Cntr = 0;
}
}
}
void ANX9021_Video_Timer_Slot(void)
{
BYTE c;
BYTE AVMUTE_STATUS;
if (g_Sys_State == MONITOR_CKDT) { return; }
if (g_Sys_State == WAIT_SCDT) // No sync in WAIT_SCDT
{
delay_ms(100);
ANX9021_ReadI2C_RX0(STATE_REG, &c);
if( (c & ANX9021_SYNC_DECT) != ANX9021_SYNC_DECT)
{
debug_puts("WAIT_SCDT: No Sync for 100ms.");
ANX9021_Set_Sys_State(MONITOR_CKDT);
}
return;
}
ANX9021_ReadI2C_RX0(STATE_REG, &c);
if (!(c & ANX9021_SYNC_DECT)) // No sync in WAIT_VIDEO, WAIT_AUDIO, PLAYBACK
{
if (g_Sync_Expire_Cntr >= SCDT_EXPIRE_TH)
{
//ANX9021_ReadI2C_RX0(SYS_CTRL1_REG, &c);
//ANX9021_WriteI2C_RX0 (SYS_CTRL1_REG, c & 0xfe);
debug_puts("No sync for long time.");
ANX9021_Set_Sys_State(MONITOR_CKDT);
g_Sync_Expire_Cntr = 0;
}
else
{
g_Sync_Expire_Cntr++;
}
return;
}
else// clear sync expire counter
{
g_Sync_Expire_Cntr = 0;
}
if ( g_Sys_State < WAIT_VIDEO )
{
g_HDMI_DVI_Status = DVI_MODE;
return;
}
//General Control Packet AV mute handler
ANX9021_ReadI2C_RX1(HDMI_STAT_REG, &c);
AVMUTE_STATUS = (c & ANX9021_AV_MUTE_STAT);
if(AVMUTE_STATUS == ANX9021_AV_MUTE_STAT)
{
debug_puts("ANX9021 AV mute packet received.");
if (!g_Video_Muted)
{
ANX9021_Mute_Video();
}
if (!g_Audio_Muted)
{
ANX9021_Mute_Audio();
}
ANX9021_Set_Sys_State(WAIT_VIDEO);
}
if (ANX9021_Is_Video_Change())
{
debug_puts("Video Changed , mute video and mute audio");
ANX9021_Set_Sys_State(WAIT_VIDEO);
g_Video_Stable_Cntr = 0;
if (!g_Video_Muted)
{
ANX9021_Mute_Video();
}
if (!g_Audio_Muted)
{
ANX9021_Mute_Audio();
}
}
else if (g_Video_Stable_Cntr < VIDEO_STABLE_TH)
{
g_Video_Stable_Cntr++;
debug_puts("WAIT_VIDEO: Wait for video stable cntr.");
}
else if ((g_Sys_State == WAIT_VIDEO) && (AVMUTE_STATUS==0x00))
{
if (g_HDMI_DVI_Status)
{
if (g_Sys_State == WAIT_VIDEO)
{
ANX9021_Get_Video_Info();
debug_puts("HDMI mode: Video is stable.");
ANX9021_Unmute_Video();
ANX9021_Set_Sys_State(WAIT_AUDIO);
}
}
else
{
ANX9021_Get_Video_Info();
debug_puts("DVI mode: Video is stable.");
ANX9021_Unmute_Video();
ANX9021_Unmute_Audio();
ANX9021_Set_Sys_State(PLAYBACK);
ANX9021_Show_Video_Info();
}
}
if(g_Sys_State >= WAIT_VIDEO) //Check R2Y scaling
{
ANX9021_ReadI2C_RX0(VID_AOF_REG, &c);
if(c & 0x80) //output is YCbCr
{
ANX9021_RGBin_Range_Scaling();
}
else //output is RGB
{
ANX9021_ReadI2C_RX0(AEC_CTRL_REG, &c);
ANX9021_WriteI2C_RX0(AEC_CTRL_REG, c | 0x04);
}
}
ANX9021_Get_Video_Info();
}
void ANX9021_Audio_Timer_Slot(void)
{
BYTE c;//,c1,c2,c3;
if (g_Sys_State == MONITOR_CKDT)
{
return;
}
ANX9021_ReadI2C_RX0(SHD_BSTAT2_REG, &c);
if (!(c & ANX9021_HDMI_MODE)) // if not HDMI mode, do nothing
{
return;
}
if (g_Sys_State == PLAYBACK)
{
ANX9021_ReadI2C_RX1(HDMI_MUTE_REG, &c);
if (c & ANX9021_AUD_MUTE)
{
ANX9021_Set_Sys_State(WAIT_AUDIO);
}
}
if ((g_Sys_State != WAIT_AUDIO))
{
return;
}
ANX9021_ReadI2C_RX0(STATE_REG, &c);
if (!(c & ANX9021_SYNC_DECT))
{
return ;
}
if (g_CTS_Got && g_Audio_Got)
{
if (g_Audio_Stable_Cntr >= AUDIO_STABLE_TH)
{
ANX9021_Unmute_Audio();
ANX9021_Unmute_Video();
g_Audio_Stable_Cntr = 0;
ANX9021_Set_Sys_State(PLAYBACK);
ANX9021_Show_Video_Info();
}
else
{
g_Audio_Stable_Cntr++;
}
}
else
{
g_Audio_Stable_Cntr = 0;
}
}
void ANX9021_Timer_Slot2(void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -