kernel_samsung_a34x-permissive/drivers/gpu/drm/mediatek/mtk_dp_hdcp2.c

1131 lines
27 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include "mtk_dp_hdcp2.h"
#include "mtk_dp.h"
#include "mtk_dp_reg.h"
#include "mtk_dp_hal.h"
#include "ca/tlcDpHdcp.h"
#ifdef DPTX_HDCP_ENABLE
struct hdcp2_info_tx {
UINT8 rtx[HDCP2_RTX_SIZE];
UINT8 txCaps[HDCP2_TXCAPS_SIZE];
UINT8 Ekpub_km[HDCP2_EKPUBKM_SIZE];
UINT8 Eks[HDCP2_EDKEYKS_SIZE];
UINT8 VPrime[HDCP2_VPRIME_SIZE];
UINT8 rn[HDCP2_RN_SIZE];
UINT8 riv[HDCP2_RIV_SIZE];
UINT8 seq_num_M[HDCP2_SEQ_NUM_M_SIZE];
UINT8 k[HDCP2_K_SIZE];
UINT8 u8StreamIDType[HDCP2_STREAMID_TYPE_SIZE];
};
struct hdcp2_info_rx {
UINT8 cert[HDCP2_CERTRX_SIZE];
UINT8 rrx[HDCP2_RRX_SIZE];
UINT8 rxCaps[HDCP2_RXCAPS_SIZE];
UINT8 rxInfo[HDCP2_RXINFO_SIZE];
UINT8 Ekh_km[HDCP2_EKHKM_SIZE];
UINT8 VPrime[HDCP2_VPRIME_SIZE];
UINT8 MPrime[HDCP2_REP_MPRIME_SIZE];
UINT8 HPrime[HDCP2_HPRIME_SIZE];
UINT8 LPrime[HDCP2_LPRIME_SIZE];
UINT8 RecvIDList[HDCP2_MAX_DEVICE_COUNT * HDCP2_RECVID_SIZE];
UINT8 u8SeqNumV[HDCP2_SEQ_NUM_V_SIZE];
};
struct hdcp2_info_tx rhdcp_tx;
struct hdcp2_info_rx rhdcp_rx;
UINT8 g_u8LC128_real[16] = {
// need add LC128(16Bytes)
};
UINT8 t_kpubdcp_real[385] = {
//add DCP LLC Public Key (HDCP22 SPEC p73)
};
UINT8 t_rtx[HDCP2_RTX_SIZE] = {
0x18, 0xfa, 0xe4, 0x20, 0x6a, 0xfb, 0x51, 0x49
};
UINT8 t_txCaps[HDCP2_TXCAPS_SIZE] = {
0x02, 0x00, 0x00
};
UINT8 t_rn[HDCP2_RN_SIZE] = {
0x32, 0x75, 0x3e, 0xa8, 0x78, 0xa6, 0x38, 0x1c
};
UINT8 t_riv[HDCP2_RIV_SIZE] = {
0x40, 0x2b, 0x6b, 0x43, 0xc5, 0xe8, 0x86, 0xd8
};
struct HDCP2_HANDLER {
BYTE u8MainState;
BYTE u8SubState;
BYTE u8DownStreamDevCnt;
BYTE u8HDCPRxVer;
bool bSendAKEInit:1;
bool bGetRecvIDList:1;
bool bStoredKm:1;
bool bSendLCInit:1;
bool bSendACK:1;
bool bSinkIsRepeater:1;
bool bRecvMsg:1;
bool bSendPair:1;
DWORD u32SeqNumVCnt;
uint32_t u8RetryCnt;
};
struct HDCP2_HANDLER g_stHdcpHandler;
struct HDCP2_PAIRING_INFO g_stStoredPairingInfo;
static DWORD g_u32PreTime;
void HDCPTx_cmmDumpHex(const char *pName, const unsigned char *data, int len)
{
int pos = 0;
if (data == NULL || len <= 0)
return;
DPTXDBG("----Start Dump:%s %d---\n", pName, len);
while (pos < len) {
DPTXDBG("[%d]|0x%x\n", pos, data[pos]);
pos++;
}
DPTXDBG("--------END---------\n");
}
void HDCPTx_Hdcp2SetState(BYTE u8MainState, BYTE u8SubState)
{
g_stHdcpHandler.u8MainState = u8MainState;
g_stHdcpHandler.u8SubState = u8SubState;
}
void HDCPTx_Hdcp2xSetAuthPass(struct mtk_dp *mtk_dp, bool bEnable)
{
if (bEnable) {
msWriteByteMask(mtk_dp, REG_3400_DP_TRANS_P0 + 1, BIT3, BIT3);
msWriteByteMask(mtk_dp, REG_34A4_DP_TRANS_P0, BIT4, BIT4);
} else {
msWriteByteMask(mtk_dp, REG_3400_DP_TRANS_P0 + 1, 0, BIT3);
msWriteByteMask(mtk_dp, REG_34A4_DP_TRANS_P0, 0, BIT4);
}
}
void HDCPTx_Hdcp2EnableAuth(struct mtk_dp *mtk_dp, bool bEnable)
{
DPTXFUNC();
HDCPTx_Hdcp2xSetAuthPass(mtk_dp, bEnable);
if (bEnable) {
uint32_t version = HDCP_V2_3;
if (rhdcp_rx.rxInfo[1] & BIT0)
version = HDCP_V1;
else if (rhdcp_rx.rxInfo[1] & BIT1)
version = HDCP_V2;
tee_hdcp_enableEncrypt(bEnable, version);
} else
tee_hdcp_enableEncrypt(bEnable, HDCP_NONE);
}
int HDCPTx_Hdcp2Init(struct mtk_dp *mtk_dp)
{
int enErrCode = HDCP_ERR_NONE;
DPTXFUNC();
memset(&rhdcp_tx, 0, sizeof(struct hdcp2_info_tx));
memset(&rhdcp_rx, 0, sizeof(struct hdcp2_info_rx));
memcpy(rhdcp_tx.rtx, t_rtx, HDCP2_RTX_SIZE);
memcpy(rhdcp_tx.txCaps, t_txCaps, HDCP2_TXCAPS_SIZE);
memcpy(rhdcp_tx.rn, t_rn, HDCP2_RN_SIZE);
memcpy(rhdcp_tx.riv, t_riv, HDCP2_RIV_SIZE);
memset(&g_stHdcpHandler, 0, sizeof(struct HDCP2_HANDLER));
memset(&g_stStoredPairingInfo, 0, sizeof(struct HDCP2_PAIRING_INFO));
g_u32PreTime = 0;
HDCPTx_Hdcp2EnableAuth(mtk_dp, false);
return enErrCode;
}
void mdrv_DPTx_HDCP2_RestVariable(struct mtk_dp *mtk_dp)
{
mtk_dp->info.hdcp2_info.bReadcertrx = false;
mtk_dp->info.hdcp2_info.bReadHprime = false;
mtk_dp->info.hdcp2_info.bReadPairing = false;
mtk_dp->info.hdcp2_info.bReadLprime = false;
mtk_dp->info.hdcp2_info.bksExchangeDone = false;
mtk_dp->info.hdcp2_info.bReadVprime = false;
}
void mhal_DPTx_HDCP2_FillStreamType(struct mtk_dp *mtk_dp, BYTE ucType)
{
msWriteByte(mtk_dp, REG_34D0_DP_TRANS_P0, ucType);
}
bool HDCPTx_Hdcp2xIncSeqNumM(void)
{
BYTE i = 0;
DWORD u32TempValue = 0;
for (i = 0; i < HDCP2_SEQ_NUM_M_SIZE; i++)
u32TempValue |= rhdcp_tx.seq_num_M[i] << (i*8);
if (u32TempValue == 0xFFFFFF)
return false;
u32TempValue++;
for (i = 0; i < HDCP2_SEQ_NUM_M_SIZE; i++)
rhdcp_tx.seq_num_M[i]
= (u32TempValue & ((DWORD)0xFF << (i*8))) >> (i*8);
return true;
}
bool HDCPTx_Hdcp2ProcessRepAuthStreamManage(struct mtk_dp *mtk_dp)
{
bool ret = false;
rhdcp_tx.k[0] = 0x00;
rhdcp_tx.k[1] = 0x01;
rhdcp_tx.u8StreamIDType[0] = 0x00; //Payload ID
rhdcp_tx.u8StreamIDType[1] = mtk_dp->info.hdcp2_info.uStreamIDType;
ret = HDCPTx_Hdcp2xIncSeqNumM();
return ret;
}
bool HDCPTx_Hdcp2RecvRepAuthSendRecvIDList(struct mtk_dp *mtk_dp)
{
bool ret = false;
uint8_t *buffer = NULL;
uint32_t len = 0, len_RecvIDList = 0;
len_RecvIDList
= mtk_dp->info.hdcp2_info.uDeviceCount * HDCP2_RECVID_SIZE;
len = len_RecvIDList + HDCP2_RXINFO_SIZE + HDCP2_SEQ_NUM_V_SIZE;
buffer = kmalloc(len, GFP_KERNEL);
if (!buffer) {
DPTXERR("Out of Memory\n");
return ret;
}
memcpy(buffer, rhdcp_rx.RecvIDList, len_RecvIDList);
memcpy(buffer + len_RecvIDList, rhdcp_rx.rxInfo, HDCP2_RXINFO_SIZE);
memcpy(buffer + len_RecvIDList + HDCP2_RXINFO_SIZE,
rhdcp_rx.u8SeqNumV, HDCP2_SEQ_NUM_V_SIZE);
if (tee_hdcp2_ComputeCompareV(buffer, len,
rhdcp_rx.VPrime, rhdcp_tx.VPrime) == RET_COMPARE_PASS) {
ret = true;
DPTXMSG("V' is PASS!!\n");
} else
DPTXMSG("V' is FAIL!!\n");
kfree(buffer);
return ret;
}
bool HDCPTx_Hdcp2RecvRepAuthStreamReady(struct mtk_dp *mtk_dp)
{
bool ret = false;
uint8_t *buffer = NULL;
uint32_t len = 0;
len = HDCP2_STREAMID_TYPE_SIZE + HDCP2_SEQ_NUM_M_SIZE;
buffer = kmalloc(len, GFP_KERNEL);
if (!buffer) {
DPTXERR("Out of Memory\n");
return ret;
}
memcpy(buffer, rhdcp_tx.u8StreamIDType, HDCP2_STREAMID_TYPE_SIZE);
memcpy(buffer + HDCP2_STREAMID_TYPE_SIZE, rhdcp_tx.seq_num_M,
HDCP2_SEQ_NUM_M_SIZE);
if (tee_hdcp2_ComputeCompareM(buffer, len, rhdcp_rx.MPrime)
== RET_COMPARE_PASS) {
ret = true;
DPTXMSG("M' is PASS!!\n");
} else
DPTXMSG("M' is FAIL!!\n");
kfree(buffer);
return ret;
}
bool HDCPTx_Hdcp2CheckSeqNumV(struct mtk_dp *mtk_dp)
{
if (((rhdcp_rx.u8SeqNumV[0] == 0x00)
&& (rhdcp_rx.u8SeqNumV[1] == 0x00)
&& (rhdcp_rx.u8SeqNumV[2] == 0x00))
&& g_stHdcpHandler.u32SeqNumVCnt > 0xFFFFFF) {
DPTXMSG("SeqNumV Rollover!\n");
return false;
}
if ((rhdcp_rx.u8SeqNumV[0]
!= (BYTE)((g_stHdcpHandler.u32SeqNumVCnt & 0xFF0000) >> 16))
|| (rhdcp_rx.u8SeqNumV[1]
!= (BYTE)((g_stHdcpHandler.u32SeqNumVCnt & 0x00FF00) >> 8))
|| (rhdcp_rx.u8SeqNumV[2]
!= (BYTE)((g_stHdcpHandler.u32SeqNumVCnt & 0x0000FF)))) {
DPTXMSG("Invalid Seq_num_V!\n");
return false;
}
g_stHdcpHandler.u32SeqNumVCnt++;
return true;
}
void HDCPTx_ERRHandle(int errMsg, int line)
{
DPTXERR("MainState:%d; SubState:%d;\n", g_stHdcpHandler.u8MainState,
g_stHdcpHandler.u8SubState);
switch (errMsg) {
case HDCP_ERR_UNKNOWN_STATE:
DPTXERR("Unknown State, line:%d\n", line);
HDCPTx_Hdcp2SetState(HDCP2_MS_H1P1, HDCP2_MSG_AUTH_FAIL);
break;
case HDCP_ERR_SEND_MSG_FAIL:
DPTXERR("Send Msg Fail, line:%d\n", line);
HDCPTx_Hdcp2SetState(HDCP2_MS_A0F0, HDCP2_MSG_ZERO);
break;
case HDCP_ERR_RESPONSE_TIMEROUT:
DPTXERR("Response Timeout, line:%d!\n", line);
HDCPTx_Hdcp2SetState(HDCP2_MS_A0F0, HDCP2_MSG_ZERO);
break;
case HDCP_ERR_PROCESS_FAIL:
DPTXERR("Process Fail, line:%d!\n", line);
HDCPTx_Hdcp2SetState(HDCP2_MS_A0F0, HDCP2_MSG_ZERO);
break;
default:
DPTXERR("NO ERROR!");
break;
}
}
bool HDCPTx_ReadMsg(struct mtk_dp *mtk_dp, BYTE u8CmdID)
{
bool bRet = false;
uint8_t size = 0;
switch (u8CmdID) {
case HDCP2_MSG_AKE_SEND_CERT:
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_6900B, rhdcp_rx.cert,
HDCP2_CERTRX_SIZE);
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_69215, rhdcp_rx.rrx,
HDCP2_RRX_SIZE);
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_6921D, rhdcp_rx.rxCaps,
HDCP2_RXCAPS_SIZE);
mtk_dp->info.hdcp2_info.bReadcertrx = false;
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_AKE_SEND_CERT\n");
break;
case HDCP2_MSG_AKE_SEND_H_PRIME:
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_692C0, rhdcp_rx.HPrime,
HDCP2_HPRIME_SIZE);
mtk_dp->info.hdcp2_info.bReadHprime = false;
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_AKE_SEND_H_PRIME\n");
break;
case HDCP2_MSG_AKE_SEND_PAIRING_INFO:
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_692E0, rhdcp_rx.Ekh_km,
HDCP2_EKHKM_SIZE);
mtk_dp->info.hdcp2_info.bReadPairing = false;
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_AKE_SEND_PAIRING_INFO\n");
break;
case HDCP2_MSG_LC_SEND_L_PRIME:
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_692F8, rhdcp_rx.LPrime,
HDCP2_LPRIME_SIZE);
mtk_dp->info.hdcp2_info.bReadLprime = false;
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_LC_SEND_L_PRIME\n");
break;
case HDCP2_MSG_REPAUTH_SEND_RECVID_LIST:
drm_dp_dpcd_read(&mtk_dp->aux,
DPCD_69330,
rhdcp_rx.rxInfo,
HDCP2_RXINFO_SIZE);
mtk_dp->info.hdcp2_info.uDeviceCount
= ((rhdcp_rx.rxInfo[1] & MASKBIT(7:4)) >> 4)
| ((rhdcp_rx.rxInfo[0] & BIT0) << 4);
drm_dp_dpcd_read(&mtk_dp->aux,
DPCD_69332,
rhdcp_rx.u8SeqNumV,
HDCP2_SEQ_NUM_V_SIZE);
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_69335,
rhdcp_rx.VPrime,
HDCP2_VPRIME_SIZE);
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_69345,
rhdcp_rx.RecvIDList,
mtk_dp->info.hdcp2_info.uDeviceCount
* HDCP2_RECVID_SIZE);
mtk_dp->info.hdcp2_info.bReadVprime = false;
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_REPAUTH_SEND_RECVID_LIST\n");
break;
case HDCP2_MSG_REPAUTH_STREAM_READY:
size = drm_dp_dpcd_read(&mtk_dp->aux,
DPCD_69473,
rhdcp_rx.MPrime,
HDCP2_REP_MPRIME_SIZE);
if (size == HDCP2_REP_MPRIME_SIZE)
g_stHdcpHandler.bRecvMsg = true;
bRet = true;
DPTXMSG("HDCP2_MSG_REPAUTH_STREAM_READY\n");
break;
default:
DPTXMSG("Invalid DPTX_HDCP2_OffSETADDR_ReadMessage !\n");
break;
}
return bRet;
}
bool HDCPTx_WriteMsg(struct mtk_dp *mtk_dp, BYTE u8CmdID)
{
bool bRet = false;
switch (u8CmdID) {
case HDCP2_MSG_AKE_INIT:
tee_hdcp2_softRst();
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_69000, rhdcp_tx.rtx,
HDCP2_RTX_SIZE);
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_69008, rhdcp_tx.txCaps,
HDCP2_TXCAPS_SIZE);
bRet = true;
DPTXMSG("HDCP2_MSG_AKE_Init !\n");
break;
case HDCP2_MSG_AKE_NO_STORED_KM:
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_69220, rhdcp_tx.Ekpub_km,
HDCP2_EKPUBKM_SIZE);
bRet = true;
DPTXMSG("HDCP2_MSG_AKE_NO_STORED_KM !\n");
break;
case HDCP2_MSG_AKE_STORED_KM:
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_692A0,
g_stStoredPairingInfo.u8EkhKM, HDCP2_EKHKM_SIZE);
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_692B0,
g_stStoredPairingInfo.u8M, HDCP2_M_SIZE);
bRet = true;
DPTXMSG("DPTX_HDCP2_MSG_AKE_STORED_KM !\n");
break;
case HDCP2_MSG_LC_INIT:
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_692F0,
rhdcp_tx.rn,
HDCP2_RN_SIZE);
mtk_dp->info.hdcp2_info.bReadLprime = true;
bRet = true;
DPTXMSG("HDCP2_MSG_LC_INIT !\n");
break;
case HDCP2_MSG_SKE_SEND_EKS:
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_69318,
rhdcp_tx.Eks,
HDCP2_EDKEYKS_SIZE);
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_69328,
rhdcp_tx.riv,
HDCP2_RIV_SIZE);
mtk_dp->info.hdcp2_info.bksExchangeDone = true;
bRet = true;
DPTXMSG("HDCP2_MSG_SKE_SEND_EKS !\n");
break;
case HDCP2_MSG_REPAUTH_SEND_ACK:
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_693E0,
rhdcp_tx.VPrime,
HDCP2_VPRIME_SIZE);
bRet = true;
DPTXMSG("HDCP2_MSG_SEND_ACK !\n");
break;
case HDCP2_MSG_REPAUTH_STREAM_MANAGE:
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_693F0,
rhdcp_tx.seq_num_M,
HDCP2_SEQ_NUM_M_SIZE);
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_693F3,
rhdcp_tx.k,
HDCP2_K_SIZE);
drm_dp_dpcd_write(&mtk_dp->aux,
DPCD_693F5,
rhdcp_tx.u8StreamIDType,
HDCP2_STREAMID_TYPE_SIZE);
mhal_DPTx_HDCP2_FillStreamType(mtk_dp,
mtk_dp->info.hdcp2_info.uStreamIDType);
bRet = true;
DPTXMSG("HDCP2_MSG_STREAM_MANAGE !\n");
break;
default:
DPTXMSG("Invalid HDCP2_OffSETADDR_WriteMessage !\n");
break;
}
return bRet;
}
int HDCPTx_Hdcp2FSM(struct mtk_dp *mtk_dp)
{
static WORD u16TimeoutValue;
int enErrCode = HDCP_ERR_NONE;
static BYTE u8PreMain;
static BYTE u8PreSub;
bool bStored = false;
if ((u8PreMain != g_stHdcpHandler.u8MainState)
|| (g_stHdcpHandler.u8SubState != u8PreSub)) {
DPTXMSG("Port(M : S)= (%d, %d)", g_stHdcpHandler.u8MainState,
g_stHdcpHandler.u8SubState);
u8PreMain = g_stHdcpHandler.u8MainState;
u8PreSub = g_stHdcpHandler.u8SubState;
}
switch (g_stHdcpHandler.u8MainState) {
case HDCP2_MS_H1P1:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
break;
case HDCP2_MSG_AUTH_FAIL:
DPTXERR("HDCP2.x Authentication Fail\n");
HDCPTx_Hdcp2EnableAuth(mtk_dp, false);
mtk_dp->info.bAuthStatus = AUTH_FAIL;
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A0F0:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
if (mtk_dp->info.hdcp2_info.bEnable) {
HDCPTx_Hdcp2Init(mtk_dp);
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_ZERO);
DPTXMSG("Sink Support Hdcp2x!\n");
} else {
HDCPTx_Hdcp2SetState(HDCP2_MS_H1P1,
HDCP2_MSG_AUTH_FAIL);
DPTXMSG("Sink Doesn't Support Hdcp2x!\n");
}
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A1F1:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
if (mtk_dp->info.hdcp2_info.uRetryCount
< HDCP2_TX_RETRY_CNT) {
tee_hdcp2_setKey(t_kpubdcp_real,
g_u8LC128_real);
mtk_dp->info.hdcp2_info.uRetryCount++;
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_AKE_INIT);
} else {
HDCPTx_Hdcp2SetState(HDCP2_MS_H1P1,
HDCP2_MSG_AUTH_FAIL);
DPTXERR("Try Max Count\n");
}
break;
case HDCP2_MSG_AKE_INIT:
if (!HDCPTx_WriteMsg(mtk_dp, HDCP2_MSG_AKE_INIT)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
mdrv_DPTx_HDCP2_RestVariable(mtk_dp);
mtk_dp->info.hdcp2_info.bReadcertrx = true;
g_stHdcpHandler.bSendAKEInit = true;
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_AKE_SEND_CERT);
g_u32PreTime = getSystemTime();
break;
case HDCP2_MSG_AKE_SEND_CERT:
if (mtk_dp->info.hdcp2_info.bReadcertrx)
HDCPTx_ReadMsg(mtk_dp, HDCP2_MSG_AKE_SEND_CERT);
if (getTimeDiff(g_u32PreTime) > HDCP2_AKESENDCERT_WDT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!g_stHdcpHandler.bRecvMsg)
break;
if (tee_akeCertificate(rhdcp_rx.cert,
&bStored,
g_stStoredPairingInfo.u8M,
g_stStoredPairingInfo.u8EkhKM)
!= RET_COMPARE_PASS) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
g_stHdcpHandler.bStoredKm = bStored;
g_stHdcpHandler.bRecvMsg = false;
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
g_stHdcpHandler.bStoredKm ?
HDCP2_MSG_AKE_STORED_KM :
HDCP2_MSG_AKE_NO_STORED_KM);
break;
case HDCP2_MSG_AKE_NO_STORED_KM:
DPTXMSG("4. Get Km, derive Ekpub(km)\n");
tee_encRsaesOaep(rhdcp_tx.Ekpub_km);
//prepare Ekpub_km to send
if (!HDCPTx_WriteMsg(mtk_dp,
HDCP2_MSG_AKE_NO_STORED_KM)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_AKE_SEND_H_PRIME);
u16TimeoutValue = HDCP2_AKESENDHPRIME_NO_STORED_WDT;
g_stHdcpHandler.bRecvMsg = false;
g_u32PreTime = getSystemTime();
break;
case HDCP2_MSG_AKE_STORED_KM:
//prepare Ekh_km & M to send
if (!HDCPTx_WriteMsg(mtk_dp, HDCP2_MSG_AKE_STORED_KM)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
enErrCode = HDCP_ERR_NONE;
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_AKE_SEND_H_PRIME);
u16TimeoutValue = HDCP2_AKESENDHPRIME_STORED_WDT;
g_stHdcpHandler.bRecvMsg = false;
g_u32PreTime = getSystemTime();
break;
case HDCP2_MSG_AKE_SEND_H_PRIME:
if (mtk_dp->info.hdcp2_info.bReadHprime)
HDCPTx_ReadMsg(mtk_dp,
HDCP2_MSG_AKE_SEND_H_PRIME);
if (getTimeDiff(g_u32PreTime) > u16TimeoutValue) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!g_stHdcpHandler.bRecvMsg)
break;
if (tee_akeHPrime(rhdcp_tx.rtx,
rhdcp_rx.rrx,
rhdcp_rx.rxCaps,
rhdcp_tx.txCaps,
rhdcp_rx.HPrime,
HDCP2_HPRIME_SIZE) != RET_COMPARE_PASS) {
if (g_stHdcpHandler.bStoredKm)
tee_clearParing();
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (g_stHdcpHandler.bStoredKm)
HDCPTx_Hdcp2SetState(HDCP2_MS_A2F2,
HDCP2_MSG_LC_INIT);
else
HDCPTx_Hdcp2SetState(HDCP2_MS_A1F1,
HDCP2_MSG_AKE_SEND_PAIRING_INFO);
g_u32PreTime = getSystemTime();
g_stHdcpHandler.bRecvMsg = false;
break;
case HDCP2_MSG_AKE_SEND_PAIRING_INFO:
if (mtk_dp->info.hdcp2_info.bReadPairing
&& !g_stHdcpHandler.bStoredKm)
HDCPTx_ReadMsg(mtk_dp,
HDCP2_MSG_AKE_SEND_PAIRING_INFO);
if (getTimeDiff(g_u32PreTime) >
HDCP2_AKESENDPAIRINGINFO_WDT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!g_stHdcpHandler.bRecvMsg)
break;
// ... store m,km,Ekh(km)
tee_akeParing(rhdcp_rx.Ekh_km);
g_stHdcpHandler.bSendPair = true;
g_stHdcpHandler.bRecvMsg = false;
HDCPTx_Hdcp2SetState(HDCP2_MS_A2F2, HDCP2_MSG_LC_INIT);
g_u32PreTime = getSystemTime();
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A2F2:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_LC_INIT:
//prepare Rn to send
if (!HDCPTx_WriteMsg(mtk_dp, HDCP2_MSG_LC_INIT)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
g_stHdcpHandler.bSendLCInit = true;
HDCPTx_Hdcp2SetState(HDCP2_MS_A2F2,
HDCP2_MSG_LC_SEND_L_PRIME);
g_u32PreTime = getSystemTime();
break;
case HDCP2_MSG_LC_SEND_L_PRIME:
if (mtk_dp->info.hdcp2_info.bReadLprime)
HDCPTx_ReadMsg(mtk_dp,
HDCP2_MSG_LC_SEND_L_PRIME);
if (getTimeDiff(g_u32PreTime)
> HDCP2_LCSENDLPRIME_WDT) {
if (g_stHdcpHandler.u8RetryCnt
> HDCP2_TX_LC_RETRY_CNT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
} else {
g_stHdcpHandler.u8RetryCnt++;
HDCPTx_Hdcp2SetState(HDCP2_MS_A2F2,
HDCP2_MSG_LC_INIT);
}
break;
}
if (!g_stHdcpHandler.bRecvMsg)
break;
if (tee_lcLPrime(rhdcp_tx.rn,
rhdcp_rx.LPrime,
HDCP2_LPRIME_SIZE) != RET_COMPARE_PASS) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
DPTXMSG("L' is PASS!!\n");
g_stHdcpHandler.bRecvMsg = false;
HDCPTx_Hdcp2SetState(HDCP2_MS_A3F3, HDCP2_MSG_ZERO);
g_u32PreTime = getSystemTime();
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A3F3:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
tee_skeEncKs(rhdcp_tx.riv, rhdcp_tx.Eks);
if (!HDCPTx_WriteMsg(mtk_dp, HDCP2_MSG_SKE_SEND_EKS)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
HDCPTx_Hdcp2SetState(HDCP2_MS_A3F3,
HDCP2_MSG_SKE_SEND_EKS);
g_u32PreTime = getSystemTime();
break;
case HDCP2_MSG_SKE_SEND_EKS:
if (getTimeDiff(g_u32PreTime) >= HDCP2_ENC_EN_TIMER) {
HDCPTx_Hdcp2SetState(HDCP2_MS_A4F4,
HDCP2_MSG_ZERO);
//HDCPTx_Hdcp2EnableAuth(mtk_dp, true);
}
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A4F4:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
if (!mtk_dp->info.hdcp2_info.bRepeater)
HDCPTx_Hdcp2SetState(HDCP2_MS_A5F5,
HDCP2_MSG_AUTH_DONE);
else {
HDCPTx_Hdcp2SetState(HDCP2_MS_A6F6,
HDCP2_MSG_REPAUTH_SEND_RECVID_LIST);
g_stHdcpHandler.bRecvMsg = false;
g_u32PreTime = getSystemTime();
}
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A5F5:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_ZERO:
break;
case HDCP2_MSG_AUTH_DONE:
DPTXMSG("HDCP2.x Authentication done.\n");
mtk_dp->info.bAuthStatus = AUTH_PASS;
mtk_dp->info.hdcp2_info.uRetryCount = 0;
HDCPTx_Hdcp2SetState(HDCP2_MS_A5F5, HDCP2_MSG_ZERO);
HDCPTx_Hdcp2EnableAuth(mtk_dp, true);
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A6F6:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_REPAUTH_SEND_RECVID_LIST:
if (mtk_dp->info.hdcp2_info.bReadVprime)
HDCPTx_ReadMsg(mtk_dp,
HDCP2_MSG_REPAUTH_SEND_RECVID_LIST);
if (getTimeDiff(g_u32PreTime)
> HDCP2_REPAUTHSENDRECVID_WDT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!g_stHdcpHandler.bRecvMsg)
break;
g_u32PreTime = getSystemTime();
g_stHdcpHandler.bRecvMsg = false;
HDCPTx_Hdcp2SetState(HDCP2_MS_A7F7,
HDCP2_MSG_REPAUTH_VERIFY_RECVID_LIST);
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A7F7:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_REPAUTH_VERIFY_RECVID_LIST:
if ((rhdcp_rx.rxInfo[1] & (BIT2 | BIT3)) != 0) {
DPTXERR("DEVS_EXCEEDED or CASCADE_EXCEDDED!\n");
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
//check seqNumV here;
if (!HDCPTx_Hdcp2CheckSeqNumV(mtk_dp)) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!HDCPTx_Hdcp2RecvRepAuthSendRecvIDList(mtk_dp)) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
HDCPTx_Hdcp2SetState(HDCP2_MS_A8F8,
HDCP2_MSG_REPAUTH_SEND_ACK);
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A8F8:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_REPAUTH_SEND_ACK:
if (!HDCPTx_WriteMsg(mtk_dp,
HDCP2_MSG_REPAUTH_SEND_ACK)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (getTimeDiff(g_u32PreTime) > HDCP2_REP_SEND_ACK) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
HDCPTx_Hdcp2SetState(HDCP2_MS_A9F9,
HDCP2_MSG_REPAUTH_STREAM_MANAGE);
g_stHdcpHandler.u8RetryCnt = 0;
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
case HDCP2_MS_A9F9:
switch (g_stHdcpHandler.u8SubState) {
case HDCP2_MSG_REPAUTH_STREAM_MANAGE:
if (!HDCPTx_Hdcp2ProcessRepAuthStreamManage(mtk_dp)) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
if (!HDCPTx_WriteMsg(mtk_dp,
HDCP2_MSG_REPAUTH_STREAM_MANAGE)) {
enErrCode = HDCP_ERR_SEND_MSG_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
g_u32PreTime = getSystemTime();
g_stHdcpHandler.bRecvMsg = false;
HDCPTx_Hdcp2SetState(HDCP2_MS_A9F9,
HDCP2_MSG_REPAUTH_STREAM_READY);
break;
case HDCP2_MSG_REPAUTH_STREAM_READY:
if (getTimeDiff(g_u32PreTime)
> HDCP2_REPAUTHSTREAMRDY_WDT/2)
HDCPTx_ReadMsg(mtk_dp,
HDCP2_MSG_REPAUTH_STREAM_READY);
else
break;
if (getTimeDiff(g_u32PreTime)
> HDCP2_REPAUTHSTREAMRDY_WDT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
} else if (!g_stHdcpHandler.bRecvMsg) {
if (g_stHdcpHandler.u8RetryCnt
>= HDCP2_STREAM_MANAGE_RETRY_CNT) {
enErrCode = HDCP_ERR_RESPONSE_TIMEROUT;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
} else
g_stHdcpHandler.u8RetryCnt++;
HDCPTx_Hdcp2SetState(HDCP2_MS_A9F9,
HDCP2_MSG_REPAUTH_STREAM_READY);
break;
}
if (!HDCPTx_Hdcp2RecvRepAuthStreamReady(mtk_dp)) {
enErrCode = HDCP_ERR_PROCESS_FAIL;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
HDCPTx_Hdcp2SetState(HDCP2_MS_A5F5,
HDCP2_MSG_AUTH_DONE);
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
break;
default:
enErrCode = HDCP_ERR_UNKNOWN_STATE;
HDCPTx_ERRHandle(enErrCode, __LINE__);
break;
}
return enErrCode;
}
void mdrv_DPTx_HDCP2_SetStartAuth(struct mtk_dp *mtk_dp, bool bEnable)
{
mtk_dp->info.hdcp2_info.bEnable = bEnable;
if (bEnable) {
mtk_dp->info.bAuthStatus = AUTH_INIT;
HDCPTx_Hdcp2SetState(HDCP2_MS_A0F0, HDCP2_MSG_ZERO);
} else {
mtk_dp->info.bAuthStatus = AUTH_ZERO;
HDCPTx_Hdcp2SetState(HDCP2_MS_H1P1, HDCP2_MSG_ZERO);
HDCPTx_Hdcp2EnableAuth(mtk_dp, false);
}
mtk_dp->info.hdcp2_info.uRetryCount = 0;
}
bool mdrv_DPTx_HDCP2_Support(struct mtk_dp *mtk_dp)
{
uint8_t bTempBuffer[3];
if (mtk_dp->info.bForceHDCP1x) {
DPTXMSG("Force HDCP1x, not support HDCP2x");
return false;
}
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_6921D, bTempBuffer, 0x3);
if ((bTempBuffer[2] & BIT1) && (bTempBuffer[0] == 0x02)) {
mtk_dp->info.hdcp2_info.bEnable = true;
mtk_dp->info.hdcp2_info.bRepeater = bTempBuffer[2] & BIT0;
} else
mtk_dp->info.hdcp2_info.bEnable = false;
DPTXMSG("HDCP.2x CAPABLE: %d, Reapeater: %d\n",
mtk_dp->info.hdcp2_info.bEnable,
mtk_dp->info.hdcp2_info.bRepeater);
if (!mtk_dp->info.hdcp2_info.bEnable)
return false;
if (tee_addDevice(HDCP_VERSION_2X) != RET_SUCCESS) {
DPTXERR("HDCP TA has some error\n");
mtk_dp->info.hdcp2_info.bEnable = false;
}
return mtk_dp->info.hdcp2_info.bEnable;
}
bool mdrv_DPTx_HDCP2_irq(struct mtk_dp *mtk_dp)
{
BYTE RxStatus = 0;
BYTE ClearCpirq = BIT2;
drm_dp_dpcd_read(&mtk_dp->aux, DPCD_69493, &RxStatus,
HDCP2_RXSTATUS_SIZE);
DPTXMSG("HDCP2x RxStatus = 0x%x\n", RxStatus);
if (RxStatus & BIT0) {
DPTXMSG("READY_BIT0 Ready!\n");
mtk_dp->info.hdcp2_info.bReadVprime = true;
}
if (RxStatus & BIT1) {
DPTXMSG("H'_AVAILABLE Ready!\n");
mtk_dp->info.hdcp2_info.bReadHprime = true;
}
if (RxStatus & BIT2) {
DPTXMSG("PAIRING_AVAILABLE Ready!\n");
mtk_dp->info.hdcp2_info.bReadPairing = true;
}
if (RxStatus & BIT4 || RxStatus & BIT3) {
DPTXMSG("Re-Auth HDCP2X!\n");
mdrv_DPTx_HDCP2_SetStartAuth(mtk_dp, true);
mdrv_DPTx_reAuthentication(mtk_dp);
}
drm_dp_dpcd_write(&mtk_dp->aux, DPCD_00201, &ClearCpirq, 0x1);
return true;
}
#endif