SII9136添加HDCP功能

前言

     按照HDCP规范的要求,不能将带HDCP的数字内容私自解key,变为不受HDCP保护的内容,在调试sii9136时遇到这问题,记下添加HDCP的步骤。

添加HDCP步骤

①判断HDCP是否可用,芯片端可用0X30,sink可用0X29[1]

②读Aksv(0X36)、Bksv(0X2B)验证20个1和20个0,aoc品牌电视无法单独读取Aksv和Bksv的值

③请求链路安全(0X2A)

④验证本地链路、中继链路、启用完整性检测

⑤等待link secure(链路安全)状态0X29

⑥发送安全的内容

⑦定期验证link secure状态0X29

细节

A.轮询0X29[1]直到指示HDCP可用,Bksv值仅在0X29[1]=1有效

B.使用所需设置写入0X2A[0]

C.轮询0X2A[0]直到它与刚刚设置的匹配

D.轮询0X29[7:6]直到指示所需的安全级别,由于去抖,0X29补一定及时刷新可读中断0X30 bit2 bit0

//--------------------------------------------------------------
//	add hdcp funtion
//	
//	
//	
//	
//	
//	@make: faceyang 20190902
//--------------------------------------------------------------

#ifdef DEV_SUPPORT_HDCP
///
///
///*************************///
///           HDCP          ///
///*************************///
///
///
//------------------------------------------------------------------------------
// Function Name: IsHDCP_Supported()
// Function Description: Check Tx revision number to find if this Tx supports HDCP
//                  by reading the HDCP revision number from TPI register 0x30.
//
// Accepts: none
// Returns: TRUE if Tx supports HDCP. FALSE if not.
// Globals: none
//------------------------------------------------------------------------------
BYTE IsHDCP_Supported (void)
{
    	BYTE HDCP_Rev;
	BYTE HDCP_Supported;

	TPI_TRACE_PRINT((">>IsHDCP_Supported()\n"));

	HDCP_Supported = TRUE;

	// Check Device ID
    	HDCP_Rev = ReadByteTPI(TPI_HDCP_REVISION_DATA_REG);

    	if (HDCP_Rev != (HDCP_MAJOR_REVISION_VALUE | HDCP_MINOR_REVISION_VALUE))
	{
    		HDCP_Supported = FALSE;
	}

	// Even if HDCP is supported check for incorrect Device ID // for SiI_9136AYBT_DEVICEID_CHECK
	HDCP_Rev = ReadByteTPI(TPI_AKSV_1_REG);
	if (HDCP_Rev == 0x09)
	{
		HDCP_Rev = ReadByteTPI(TPI_AKSV_2_REG);
		if (HDCP_Rev == 0x00)
		{
			HDCP_Rev = ReadByteTPI(TPI_AKSV_3_REG);
			if (HDCP_Rev == 0x02)
			{
				HDCP_Rev = ReadByteTPI(TPI_AKSV_4_REG);
				if (HDCP_Rev == 0x02)
				{
					HDCP_Rev = ReadByteTPI(TPI_AKSV_5_REG);
					if (HDCP_Rev == 0x0a)
					{
						HDCP_Supported = FALSE;
						TPI_TRACE_PRINT((">>SiI9136A found, NO HDCP supported\n"));
					}
				}
			}
		}
	}
	return HDCP_Supported;
}

//------------------------------------------------------------------------------
// Function Name: AreAKSV_OK()
// Function Description: Check if AKSVs contain 20 '0' and 20 '1'
//
// Accepts: none
// Returns: TRUE if 20 zeros and 20 ones found in AKSV. FALSE OTHERWISE
// Globals: none
//------------------------------------------------------------------------------
BYTE AreAKSV_OK (void)
{
    	BYTE B_Data[AKSV_SIZE];
    	BYTE NumOfOnes = 0;
    	BYTE i, j;

	TPI_TRACE_PRINT((">>AreAKSV_OK()\n"));

    	ReadBlockTPI(TPI_AKSV_1_REG, AKSV_SIZE, B_Data);

    	for (i=0; i<AKSV_SIZE; i++)
    	{
        	for (j=0; j<BYTE_SIZE; j++)
        	{
            		if (B_Data[i] & 0x01)
            		{
                		NumOfOnes++;
            		}
            		B_Data[i] >>= 1;
        	}
     	}
     	if (NumOfOnes != NUM_OF_ONES_IN_KSV)
        	return FALSE;

    	return TRUE;
}

//------------------------------------------------------------------------------
// Function Name: HDCP_Off()
// Function Description: Switch hdcp off.
//------------------------------------------------------------------------------
void HDCP_Off (void)
{
	TPI_TRACE_PRINT((">>HDCP_Off()\n"));

	// AV MUTE
	ReadModifyWriteTPI(TPI_SYSTEM_CONTROL_DATA_REG, AV_MUTE_MASK, AV_MUTE_MUTED);
	WriteByteTPI(TPI_HDCP_CONTROL_DATA_REG, PROTECTION_LEVEL_MIN);

	g_hdcp.HDCP_Started = FALSE;
	g_hdcp.HDCP_LinkProtectionLevel = EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE;
}

//------------------------------------------------------------------------------
// Function Name: HDCP_On()
// Function Description: Switch hdcp on.
//------------------------------------------------------------------------------
void HDCP_On (void)
{
	if (g_hdcp.HDCP_Override == FALSE)
	{
		TPI_DEBUG_PRINT(("HDCP Started\n"));

		WriteByteTPI(TPI_HDCP_CONTROL_DATA_REG, PROTECTION_LEVEL_MAX);

		g_hdcp.HDCP_Started = TRUE;
	}
	else
	{
		g_hdcp.HDCP_Started = FALSE;
	}
}

//------------------------------------------------------------------------------
// Function Name: RestartHDCP()
// Function Description: Restart HDCP.
//------------------------------------------------------------------------------
void RestartHDCP (void)
{
	TPI_DEBUG_PRINT (("HDCP -> Restart\n"));

	DisableTMDS();
	HDCP_Off();
	EnableTMDS();
}

//------------------------------------------------------------------------------
// Function Name: HDCP_Init()
// Function Description: Tests Tx and Rx support of HDCP. If found, checks if
//                  and attempts to set the security level accordingly.
//
// Accepts: none
// Returns: TRUE if HW TPI started successfully. FALSE if failed to.
// Globals: HDCP_TxSupports - initialized to FALSE, set to TRUE if supported by this device
//		   HDCP_AksvValid - initialized to FALSE, set to TRUE if valid AKSVs are read from this device
//		   HDCP_Started - initialized to FALSE
//		   HDCP_LinkProtectionLevel - initialized to (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE)
//------------------------------------------------------------------------------
void HDCP_Init (void)
{
	TPI_TRACE_PRINT((">>HDCP_Init()\n"));

	g_hdcp.HDCP_TxSupports = FALSE;
	g_hdcp.HDCP_AksvValid = FALSE;
	g_hdcp.HDCP_Started = FALSE;
	g_hdcp.HDCP_LinkProtectionLevel = EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE;

	// This is TX-related... need only be done once.
    	if (!IsHDCP_Supported())
    	{
		// The TX does not support HDCP, so authentication will never be attempted.
		// Video will be shown as soon as TMDS is enabled.
		TPI_DEBUG_PRINT(("HDCP -> TX does not support HDCP\n"));
		return;
	}
	g_hdcp.HDCP_TxSupports = TRUE;

	// This is TX-related... need only be done once.
    	if (!AreAKSV_OK())
    	{
		// The TX supports HDCP, but does not have valid AKSVs.
		// Video will not be shown.
        	TPI_DEBUG_PRINT(("HDCP -> Illegal AKSV\n"));
        	return;
    	}
	g_hdcp.HDCP_AksvValid = TRUE;

	TPI_DEBUG_PRINT(("HDCP -> Supported by TX, AKSVs valid\n"));
}

//------------------------------------------------------------------------------
// Function Name: HDCP_CheckStatus()
// Function Description: Check HDCP status.
//
// Accepts: InterruptStatus
// Returns: none
// Globals: none
//------------------------------------------------------------------------------
void HDCP_CheckStatus (BYTE InterruptStatusImage)
{
	BYTE QueryData;
	BYTE LinkStatus;
	BYTE RegImage;
	BYTE NewLinkProtectionLevel;
//	static BYTE AvmuteFlag=1;
	
//	QueryData = ReadByteTPI(TPI_HDCP_QUERY_DATA_REG);
//	LinkStatus = ReadByteTPI(TPI_HDCP_CONTROL_DATA_REG);
//	printf("********* 0X29 = %02x 0X2A = %02x\n",QueryData,LinkStatus);

	
	if ((g_hdcp.HDCP_TxSupports == TRUE) && (g_hdcp.HDCP_AksvValid == TRUE))
	{
		if ((g_hdcp.HDCP_LinkProtectionLevel == (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE)) && (g_hdcp.HDCP_Started == FALSE))
		{
			QueryData = ReadByteTPI(TPI_HDCP_QUERY_DATA_REG);

			if (QueryData & PROTECTION_TYPE_MASK)   // Is HDCP avaialable
			{
//				AvmuteFlag=1;
				HDCP_On();
			}
//			else
//			{
//				if(AvmuteFlag==1)
//				{
//					AvmuteFlag=0;
//					ReadModifyWriteTPI(TPI_SYSTEM_CONTROL_DATA_REG, TMDS_OUTPUT_CONTROL_MASK |
//			    	AV_MUTE_MASK, TMDS_OUTPUT_CONTROL_POWER_DOWN | AV_MUTE_MUTED);
//				}
//			}
		}

		// Check if Link Status has changed:
		if (InterruptStatusImage & SECURITY_CHANGE_EVENT) 
		{
			TPI_DEBUG_PRINT (("HDCP -> "));

			LinkStatus = ReadByteTPI(TPI_HDCP_QUERY_DATA_REG);
			LinkStatus &= LINK_STATUS_MASK;

			ClearInterrupt(SECURITY_CHANGE_EVENT);

			switch (LinkStatus)
			{
				case LINK_STATUS_NORMAL:
					TPI_DEBUG_PRINT (("Link = Normal\n"));
					break;

				case LINK_STATUS_LINK_LOST:
					TPI_DEBUG_PRINT (("Link = Lost\n"));
					RestartHDCP();
					break;

				case LINK_STATUS_RENEGOTIATION_REQ:
					TPI_DEBUG_PRINT (("Link = Renegotiation Required\n"));
					HDCP_Off();
					HDCP_On();
					break;

				case LINK_STATUS_LINK_SUSPENDED:
					TPI_DEBUG_PRINT (("Link = Suspended\n"));
					HDCP_On();
					break;
			}
		}

		// Check if HDCP state has changed:
		if (InterruptStatusImage & HDCP_CHANGE_EVENT)
		{
			RegImage = ReadByteTPI(TPI_HDCP_QUERY_DATA_REG);

			NewLinkProtectionLevel = RegImage & (EXTENDED_LINK_PROTECTION_MASK | LOCAL_LINK_PROTECTION_MASK);
			if (NewLinkProtectionLevel != g_hdcp.HDCP_LinkProtectionLevel)
			{
				TPI_DEBUG_PRINT (("HDCP -> "));

				g_hdcp.HDCP_LinkProtectionLevel = NewLinkProtectionLevel;

				switch (g_hdcp.HDCP_LinkProtectionLevel)
				{
					case (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE):
						TPI_DEBUG_PRINT (("Protection = None\n"));
						RestartHDCP();
						break;

					case LOCAL_LINK_PROTECTION_SECURE:

						if (IsHDMI_Sink())
						{
							ReadModifyWriteTPI(TPI_AUDIO_INTERFACE_REG, AUDIO_MUTE_MASK, AUDIO_MUTE_NORMAL);
						}

						ReadModifyWriteTPI(TPI_SYSTEM_CONTROL_DATA_REG, AV_MUTE_MASK, AV_MUTE_NORMAL);
						TPI_DEBUG_PRINT (("Protection = Local, Video Unmuted\n"));
						break;

					case (EXTENDED_LINK_PROTECTION_SECURE | LOCAL_LINK_PROTECTION_SECURE):
						TPI_DEBUG_PRINT (("Protection = Extended\n"));
						break;

					default:
						TPI_DEBUG_PRINT (("Protection = Extended but not Local?\n"));
						RestartHDCP();
						break;
				}
			}
			ClearInterrupt(HDCP_CHANGE_EVENT);
		}
	}
}
#endif

 


版权声明:本文为qq_42677883原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。