⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 anx9021.c

📁 HDMI anx9021的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
//*******************************************************************************************************
//*******************************************************************************************************
// ********************************     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 + -