📄 hdcp.c
字号:
/*
$Workfile: hdcp.c $
$Revision: 1.9 $
$Date: Aug 23 2006 23:28:22 $
*/
//******************************************************************
//
// Copyright (C) 2002. GENESIS MICROCHIP INC.
// All rights reserved. No part of this program may be reproduced.
//
// Genesis Microchip Corp., 2150 Gold Street
// Alviso, CA 95002 USA
// Genesis Microchip Inc., 165 Commerce Valley Dr. West
// Thornhill, Ontario, Canada, L3T 7V8
//
//================================================================
//
// MODULE: hdcp.c
//
// USAGE : This module contains function related to loading and maintaining
// the HDCP keys.
//
//******************************************************************
//******************************************************************
// I N C L U D E F I L E S
//******************************************************************
#include "inc\all.h"
#include <mem.h>
#include "MCU186.h"
#if !defined(TUCSON) && HDCP_ENABLE_4TH
#define DEBUG_HDCP 0
#define DEBUG_HDCP_EXTENDED 0
#if DEBUG_HDCP && DEBUG_MSG
#define msg(a,b) gm_Print((const char far *)a,b)
#else
#define msg(a,b)
#endif
#if DEBUG_HDCP_EXTENDED && DEBUG_MSG
#define msgx(a,b) gm_Print((const char far *)a,b)
#else
#define msgx(a,b)
#endif
#define DVI_OffOn_Interval 220 //unit in 10ms
#define Hot_Plug_Pulse_Width 3 //unit in 10ms
#define Maximum_DVI_TimingStable_Time 10 //unit in 100ms
typedef struct HDCPStruct
{
// WORD IsHDCPReStarted : 1;
// WORD IsHDCPWait : 1;
WORD IsHDCPOK : 1;
WORD IsTemp_DVIBlockOff : 1;
} HDCPStruct;
static HDCPStruct HDCPS;
void Hdcp_DVIPowerON(void);
void Hdcp_DVIPowerOFF(void);
gmt_RET_STAT InitHdcpTableFromCode(void);
gmt_RET_STAT Hdcp_Authentication_TimerStart(WORD time);
gmt_RET_STAT Hdcp_Authentication_TimerCheck(void);
void Hdcp_TimingTransitionToStableEND(void);
gmt_RET_STAT Hdcp_TimingTransitionFromStable(void);
void Hdcp_TimingStable(void);
void Hdcp_DVI_Temporary_Off();
void Hdcp_DVI_Temporary_Off_Down();
gmt_RET_STAT Is_Hdcp_DVI_Temporary_Off();
#if defined(PHOENIX_U) && !DDCCI_CUSTOM_SUPPORT
void far interrupt IRQ4Manager (void);
#endif
#if HDCP_USE_DVI_HOTPLUG
void Hdcp_HotPlug_Touch(void);
#endif
gmt_RET_STAT HDCP_Init(void)
{
msg("--->> HDCP_Init",0);
#ifdef gmvb_ExtCusFlags
//**************************************//The flag is just to infrom Gsel Library
gmvb_ExtCusFlags|=gmd_HDCP_ENABLE; //HDCP is enabled. This way keeps Gsel Library
//**************************************//Uniform.
#endif
#ifdef PHOENIX_U
gm_SetRegBitsByte(DDC2B_CTRL2, DDC2B_HDCP_EN); //Need to enable this bit for HDCP and DDC2Bi co-existence
#if !DDCCI_CUSTOM_SUPPORT
SET_VECTOR(INT4_VECTOR, IRQ4Manager); // ddc2bi interrupt
#endif
#endif
#if HDCP_SHOW_DEBUG_SIGNAL
Hdcp_Debug_Signal_Ctrl_Set(); //Setup GPIO if necessary...
#endif
HDCPS.IsHDCPOK=gmd_FALSE;
HDCPS.IsTemp_DVIBlockOff=gmd_FALSE;
#if (HDCP_KEYS_IN_NVRAM)
return gm_InitHdcpTableFromNVRAM(HDCPData_ID, HDCP_DDC_ADDR);
#else
return InitHdcpTableFromCode();
#endif //(HDCP_KEYS_IN_NVRAM)
}
#if (HDCP_KEYS_IN_NVRAM == 0)
#include "hdcp_keys.c"
gmt_RET_STAT InitHdcpTableFromCode(void)
{
BYTE B_Count;
BYTE* Bp_HdcpRAM;
msg("--->> InitHdcpTableFromCode",0);
#if(HDCP_GENCRYPT_EN)
gm_WriteRegByte(HDCP_CONTROL, KEYLOAD_EN | DECRYPT_EN);
#else
gm_WriteRegByte(HDCP_CONTROL, KEYLOAD_EN);
#endif
gm_WriteRegByte(HDCP_ADDR, 0x00);
#if HDCP_SHOW_DEBUG_SIGNAL
Hdcp_Debug_Signal_HDCP_Off();
#endif
// write BKSV to BKSV registers.
for(B_Count=0; B_Count < BKSV_SIZE; B_Count++)
{
gm_WriteRegByte(HDCP_BKSV0 + B_Count, BA_Hdcp_Keys[B_Count]);
}
Bp_HdcpRAM = (BYTE *)IRAM_HDCPKeyRAMStart;
for(B_Count=0; B_Count < NUM_SECRET_KEYS; B_Count++)
{
// write key data to internal RAM table
_fmemcpy(Bp_HdcpRAM, &BA_Hdcp_Keys[BKSV_SIZE + (B_Count * SECRET_KEY_SIZE)], SECRET_KEY_SIZE);
Bp_HdcpRAM += HDCP_MEM_ROW_SIZE;
}
// Put Keyram in read mode (disable KEYLOAD_EN)
gm_ClearRegBitsByte(HDCP_CONTROL, KEYLOAD_EN);
return gmd_OK;
}
#endif //(HDCP_KEYS_IN_NVRAM == 0)
void Hdcp_DVIPowerOFF(void)
{
msg("--->> Hdcp_DVIPowerOFF", 0);
gm_WriteRegByte(HDCP_ADDR, 0);
Hdcp_Authentication_TimerStart(DVI_OffOn_Interval);
}
void Hdcp_DVIPowerON(void)
{
msg("--->> Hdcp_DVIPowerON", 0);
while(Hdcp_Authentication_TimerCheck());
gm_WriteRegByte(HDCP_ADDR, HDCP_DDC_ADDR);
}
gmt_RET_STAT Hdcp_Authentication_TimerStart(WORD time)
{
msg("------>>> Hdcp_Authentication_TimerStart %d0 ms", time);
gm_TimerStart(HDCP_AUTHENTICATION_10MS_TMR, time);
return gmd_FALSE;
}
gmt_RET_STAT Hdcp_Authentication_TimerCheck(void)
{
if (gm_TimerCheck(HDCP_AUTHENTICATION_10MS_TMR) == gmd_TMR_ACTIVE)
return gmd_TRUE;
else
return gmd_FALSE;
}
void Hdcp_TimingTransitionToStableEND(void)
{
msg("Hdcp_TimingTransitionToStableEND", 0);
gm_TimerStart(HDCP_DVI_TimingStable_100ms_TMR,Maximum_DVI_TimingStable_Time);
HDCPS.IsHDCPOK=gmd_FALSE;
}
gmt_RET_STAT Hdcp_TimingTransitionFromStable(void)
{
msg("Hdcp_TimingTransitionFromStable", 0);
return HDCPS.IsHDCPOK;
}
void Hdcp_TimingStable(void)
{
if (!HDCPS.IsHDCPOK)
{
if (gm_TimerCheck(HDCP_DVI_TimingStable_100ms_TMR) != gmd_TMR_ACTIVE)
{
HDCPS.IsHDCPOK=gmd_TRUE;
msg("HDCPS.IsHDCPOK = gmd_TRUE",0);
}
}
}
void Hdcp_DVI_Temporary_Off()
{
HDCPS.IsTemp_DVIBlockOff=gmd_TRUE;
msg("HDCPS.IsTemp_DVIBlockOff = gmd_TRUE",0);
}
void Hdcp_DVI_Temporary_Off_Down()
{
HDCPS.IsTemp_DVIBlockOff=gmd_FALSE;
msg("HDCPS.IsTemp_DVIBlockOff = gmd_FALSE",0);
}
gmt_RET_STAT Is_Hdcp_DVI_Temporary_Off()
{
return HDCPS.IsTemp_DVIBlockOff;
}
#if HDCP_USE_DVI_HOTPLUG
void Hdcp_HotPlug_Touch(void)
{
//If the platform has implemented the HOTPLUG pin control. Modify and place the code here
#if (defined(RD3_57XX) && ( BOARD == RD3_57XX )) || (defined(EV_BD_B_57XX) && ( BOARD == EV_BD_B_57XX ))
//For RD3_57xx board. But have to modify hardware to connect the GPIO32 (Pin21)
gm_SetRegBitsByte(BYPASS, TCON_SIGNALS_OFF);
gm_SetRegBitsByte(GPIO_DIRCTRL4, GPIO32_33_IO); //GPIO 32 (Pin 21)
gm_SetRegBitsByte(GPOUTPUT4, GPIO32_OUT); //Pull Down HotPlug pin
gm_Delay10ms(Hot_Plug_Pulse_Width);
gm_ClearRegBitsByte(GPOUTPUT4, GPIO32_OUT); //Release HotPlug pin
#elif (defined(RD1) && ( BOARD == RD1)) || (defined(RD1_57XX) && ( BOARD == RD1_57XX )) || (defined(EV_BD_57XX) && ( BOARD == EV_BD_57XX ))
//For EV_Board or RD1/RD1_57xx board. But have to modify hardware to connect the GPIO11 (Pin123)
gm_SetRegBitsByte(BYPASS, TCON_SIGNALS_OFF);
gm_SetRegBitsByte(GPO_OPENDRAIN_EN1, BIT3);
gm_SetRegBitsByte(GPIO_DIRCTRL1, BIT3); //GPIO 11
gm_ClearRegBitsByte(GPOUTPUT1, BIT3); //Pull Down HotPlug pin
gm_Delay10ms(Hot_Plug_Pulse_Width);
gm_SetRegBitsByte(GPOUTPUT1, BIT3); //Release HotPlug pin
#endif
#if 0 //if 1: Turn on HDCP Block right away after Hot_plug pin release
gm_SetRegBitsByte(HDCP_CONTROL, HDCP_EN);
gm_Print("HDCP on after HotPlug release! ++++++++++++++++++++++++",0);
#if HDCP_SHOW_DEBUG_SIGNAL
Hdcp_Debug_Signal_HDCP_On();
#endif
#endif
}
#endif // HDCP_USE_DVI_HOTPLUG
#if defined(PHOENIX_U) && !DDCCI_CUSTOM_SUPPORT
void far (*Irom_ServiceDDC2Bi)(void far) = NULL_PTR;
/****************************************************************************************************************/
/* When HDCP and DDC2Bi coexisten is enable and DDC2Bi channel is set to DVI. Once data error occurs, */
/* DDC2Bi channel will be re-initialed in Irom function . However, DDC2B_HDCP_EN bit will be cleared as well. */
/* Therefore, the external IRQ4 interrupt service routine is added to workaround this issue. */
/****************************************************************************************************************/
void far interrupt IRQ4Manager (void)
{
BYTE status;
Irom_ServiceDDC2Bi =(void far*)0xFA0053B1UL; // FA00:53B1 The address of _ServiceDDC2B subroutine in Phoenix_U IRom
status = gm_ReadRegByte(INPUT_STATUS) & DDC2Bi_MASK;
if (status)
Irom_ServiceDDC2Bi();
gm_SetRegBitsByte(DDC2B_CTRL2, DDC2B_HDCP_EN); //Always set DDC2B_HDCP_EN bit after ServiceDDC2Bi subroutine is called.
gm_WriteRegByte (INPUT_STATUS, status);
WRITE_PCB_REG(EOI, INT4_VTYPE); // Interrupt exit
}
#endif //!DDCCI_CUSTOM_SUPPORT
#endif // !defined(TUCSON) && HDCP_ENABLE_4TH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -