Re: [PATCH v2 2/3] Subject: [PATCH] drm/mediatek/dp: Add HDCP2.x feature for DisplayPort

CK Hu (胡俊光)
2024-02-19T09:34:05Z

Hi, Mac:

On Mon, 2024-02-05 at 13:50 +0800, mac.shen wrote:
> Add HDCP2.x feature for DisplayPort.
> When userspace request the kernel protect future content communicated
> over the link with Content_Protection property, the feature will do
> HDCP2.x authentication if the sink support HDCP2.X.
>
> Changes in v2:
> - remove switch case, and refine code to make more clear
> - remove some definitions, and use the definitions in
> include/drm/drm_hdcp.h
> - use the struct which defined in include/drm/drm_hdcp.h
> - do HDCP2.x authentication when userspace request the
> kernel protect future content communicated
> per suggestion from the previous thread:
> https://lore.kernel.org/all/8fff59b5567449d8201dd1138c8fa
> 9218a545c46.camel@mediatek.com/
>
> Signed-off-by: mac.shen <mac.shen@mediatek.com>
> ---

[snip]

> +
> +int dp_tx_hdcp2_fsm(struct mtk_hdcp_info *hdcp_info)
> +{
> + static u32 timeout_value;
> + static u8 pre_main;
> + static u8 pre_sub;
> + static u32 pre_time;
> + int err_code = HDCP_ERR_NONE;
> + bool stored = false;
> + u32 time;
> + int ret = 0;
> + bool tmp = false;
> +
> + if (pre_main != hdcp_info->hdcp2_info.hdcp_handler.main_state
> ||
> + hdcp_info->hdcp2_info.hdcp_handler.sub_state != pre_sub) {
> + DPTXHDCPMSG("2.x: Port(M : S)= (%d, %d)",
> + hdcp_info-
> >hdcp2_info.hdcp_handler.main_state,
> + hdcp_info-
> >hdcp2_info.hdcp_handler.sub_state);
> + pre_main = hdcp_info-
> >hdcp2_info.hdcp_handler.main_state;
> + pre_sub = hdcp_info->hdcp2_info.hdcp_handler.sub_state;
> + }
> +
> + switch (hdcp_info->hdcp2_info.hdcp_handler.main_state) {
> + case HDCP2_MS_H1P1:
> + /* HDCP2_MS_H1P1 */
> + /* HDCP_2_2_AUTH_FAIL */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AUTH_FAIL) {
> + pr_err("2.x: Authentication Fail!\n");
> + dp_tx_hdcp2_enable_auth(hdcp_info, false);
> + hdcp_info->auth_status = AUTH_FAIL;
> + }
> + break;
> +
> + case HDCP2_MS_A0F0:
> + /* HDCP2_MS_A0F0 */
> + /* HDCP_2_2_NULL_MSG */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_NULL_MSG) {

Could you refer to intel driver to get rid of this state machine? It
seams this flow does not need state machine. Just step forward. If
error happen, break the flow. If your implement is like intel driver,
it's easier for me to compare and easier to review.

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/i915/display/intel_hdcp.c?h=v6.8-rc5#n1868

Regards,
CK

> + if (!hdcp_info->hdcp2_info.enable) {
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_H1P1, HDCP_2_2_AUTH_FAIL);
> + DPTXHDCPMSG("2.x: Sink Doesn't Support
> Hdcp2x!\n");
> + break;
> + }
> +
> + dp_tx_hdcp2_init(hdcp_info);
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> HDCP_2_2_NULL_MSG);
> + DPTXHDCPMSG("2.x: Sink Support Hdcp2x!\n");
> + }
> + break;
> +
> + case HDCP2_MS_A1F1:
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_NULL_MSG */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_NULL_MSG) {
> + if (hdcp_info->hdcp2_info.retry_count >=
> HDCP2_TX_RETRY_CNT) {
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_H1P1, HDCP_2_2_AUTH_FAIL);
> + pr_err("2.x: Try Max Count\n");
> + break;
> + }
> +
> + hdcp_info->hdcp2_info.retry_count++;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> HDCP_2_2_AKE_INIT);
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_INIT */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AKE_INIT) {
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_AKE_INIT);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> + dp_tx_hdcp2_rest_variable(hdcp_info);
> + hdcp_info->hdcp2_info.read_certrx = true;
> +
> + hdcp_info-
> >hdcp2_info.hdcp_handler.send_ake_init = true;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> HDCP_2_2_AKE_SEND_CERT);
> + pre_time = mtk_dp_get_system_time();
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_SEND_CERT */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AKE_SEND_CERT) {
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time < HDCP_2_2_CERT_TIMEOUT_MS) {
> + msleep(20);
> + break;
> + }
> + if (hdcp_info->hdcp2_info.read_certrx)
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_AKE_SEND_CERT);
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg)
> + break;
> +
> + ret = tee_ake_certificate(hdcp_info,
> + (u8 *)&hdcp_info-
> >hdcp2_info.hdcp_rx.cert_rx,
> + &stored,
> + hdcp_info-
> >hdcp2_info.ake_stored_km.e_kh_km_m +
> + HDCP_2_2_E_KH_KM_LEN,
> + hdcp_info-
> >hdcp2_info.ake_stored_km.e_kh_km_m);
> +
> + if (ret != RET_COMPARE_PASS) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + hdcp_info->hdcp2_info.hdcp_handler.stored_km =
> stored;
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> + hdcp_info-
> >hdcp2_info.hdcp_handler.stored_km ?
> + HDCP_2_2_AKE_STORED_KM :
> + HDCP_2_2_AKE_NO_STORED_KM);
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_NO_STORED_KM */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AKE_NO_STORED_KM) {
> + DPTXHDCPMSG("2.x: Get Km, derive Ekpub(km)\n");
> +
> + tee_enc_rsaes_oaep(hdcp_info,
> + hdcp_info-
> >hdcp2_info.hdcp_tx.no_stored_km.e_kpub_km);
> + /* Prepare e_kpub_km to send */
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_AKE_NO_STORED_KM);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> HDCP_2_2_AKE_SEND_HPRIME);
> + timeout_value =
> HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS;
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + pre_time = mtk_dp_get_system_time();
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_STORED_KM */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AKE_STORED_KM) {
> + /* Prepare ekh_km & M to send */
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_AKE_STORED_KM);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + err_code = HDCP_ERR_NONE;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A1F1,
> HDCP_2_2_AKE_SEND_HPRIME);
> + timeout_value =
> HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS;
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + pre_time = mtk_dp_get_system_time();
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_SEND_HPRIME */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AKE_SEND_HPRIME) {
> + if (hdcp_info->hdcp2_info.read_h_prime)
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_AKE_SEND_HPRIME);
> +
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time > timeout_value) {
> + err_code = HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg)
> + break;
> +
> + ret = tee_ake_h_prime(hdcp_info,
> + hdcp_info-
> >hdcp2_info.hdcp_tx.ake_init.r_tx,
> + hdcp_info-
> >hdcp2_info.hdcp_rx.send_cert.r_rx,
> + hdcp_info-
> >hdcp2_info.hdcp_rx.send_cert.rx_caps,
> + (u8 *)&hdcp_info-
> >hdcp2_info.hdcp_tx.tx_caps,
> + hdcp_info-
> >hdcp2_info.hdcp_rx.send_hprime.h_prime,
> + HDCP_2_2_H_PRIME_LEN);
> + if (ret != RET_COMPARE_PASS) {
> + if (hdcp_info-
> >hdcp2_info.hdcp_handler.stored_km)
> + tee_clear_paring(hdcp_info);
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (hdcp_info-
> >hdcp2_info.hdcp_handler.stored_km)
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_A2F2, HDCP_2_2_LC_INIT);
> + else
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_A1F1,
> + HDCP_2_2_AKE_SEND
> _PAIRING_INFO);
> +
> + pre_time = mtk_dp_get_system_time();
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + }
> +
> + /* HDCP2_MS_A1F1 */
> + /* HDCP_2_2_AKE_SEND_PAIRING_INFO */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> + HDCP_2_2_AKE_SEND_PAIRING_INFO) {
> + if (hdcp_info->hdcp2_info.read_pairing)
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_AKE_SEND_PAIRING_INFO);
> +
> + /* Ekh_Km must be available less than 200ms,
> Give mode time for some Rx */
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time > HDCP_2_2_PAIRING_TIMEOUT_MS *
> 2) {
> + err_code = HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg)
> + break;
> +
> + /* Store m, km, Ekh(km) */
> + tee_ake_paring(hdcp_info,
> + hdcp_info-
> >hdcp2_info.hdcp_rx.pairing_info.e_kh_km);
> +
> + hdcp_info->hdcp2_info.hdcp_handler.send_pair =
> true;
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A2F2,
> HDCP_2_2_LC_INIT);
> + pre_time = mtk_dp_get_system_time();
> + }
> + break;
> +
> + case HDCP2_MS_A2F2:
> + /* HDCP2_MS_A2F2 */
> + /* HDCP_2_2_LC_INIT */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_LC_INIT) {
> + /* prepare Rn to send */
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_LC_INIT);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> + hdcp_info->hdcp2_info.hdcp_handler.send_lc_init
> = true;
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A2F2,
> HDCP_2_2_LC_SEND_LPRIME);
> + pre_time = mtk_dp_get_system_time();
> + }
> +
> + /* HDCP2_MS_A2F2 */
> + /* HDCP_2_2_LC_SEND_LPRIME */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_LC_SEND_LPRIME) {
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time < HDCP_2_2_DP_HPRIME_READ_TIMEOUT_MS)
> + break;
> +
> + if (hdcp_info->hdcp2_info.read_l_prime)
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_LC_SEND_LPRIME);
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg)
> + break;
> +
> + ret = tee_lc_l_prime(hdcp_info, hdcp_info-
> >hdcp2_info.hdcp_tx.lc_init.r_n,
> + hdcp_info-
> >hdcp2_info.hdcp_rx.send_lprime.l_prime,
> + HDCP_2_2_L_PRIME_LEN);
> + if (ret != RET_COMPARE_PASS) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + DPTXHDCPMSG("2.x: L' is PASS!!\n");
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A3F3,
> HDCP_2_2_NULL_MSG);
> + pre_time = mtk_dp_get_system_time();
> + }
> + break;
> +
> + case HDCP2_MS_A3F3:
> + /* HDCP2_MS_A3F3 */
> + /* HDCP_2_2_NULL_MSG */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_NULL_MSG) {
> + tee_ske_enc_ks(hdcp_info, hdcp_info-
> >hdcp2_info.hdcp_tx.send_eks.riv,
> + hdcp_info-
> >hdcp2_info.hdcp_tx.send_eks.e_dkey_ks);
> +
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_SKE_SEND_EKS);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (!hdcp_info->hdcp2_info.repeater)
> + dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_STREAM_TYPE);
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A3F3,
> HDCP_2_2_SKE_SEND_EKS);
> + pre_time = mtk_dp_get_system_time();
> + }
> +
> + /* HDCP2_MS_A3F3 */
> + /* HDCP_2_2_SKE_SEND_EKS */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_SKE_SEND_EKS) {
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time >=
> HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN)
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_A4F4, HDCP_2_2_NULL_MSG);
> + }
> + break;
> +
> + case HDCP2_MS_A4F4:
> + /* HDCP2_MS_A4F4 */
> + /* HDCP_2_2_NULL_MSG */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_NULL_MSG) {
> + if (!hdcp_info->hdcp2_info.repeater) {
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_A5F5, HDCP_2_2_AUTH_DONE);
> + break;
> + }
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A6F6,
> + HDCP_2_2_REP_SEND_RECVID_
> LIST);
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + pre_time = mtk_dp_get_system_time();
> + }
> + break;
> +
> + case HDCP2_MS_A5F5:
> + /* HDCP2_MS_A5F5 */
> + /* HDCP_2_2_AUTH_DONE */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_AUTH_DONE) {
> + DPTXHDCPMSG("2.x: Authentication done!\n");
> + hdcp_info->auth_status = AUTH_PASS;
> + hdcp_info->hdcp2_info.retry_count = 0;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A5F5,
> HDCP_2_2_NULL_MSG);
> + dp_tx_hdcp2_enable_auth(hdcp_info, true);
> + }
> + break;
> +
> + case HDCP2_MS_A6F6:
> + /* HDCP2_MS_A6F6 */
> + /* HDCP_2_2_REP_SEND_RECVID_LIST */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> + HDCP_2_2_REP_SEND_RECVID_LIST) {
> + if (hdcp_info->hdcp2_info.read_v_prime)
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_REP_SEND_RECVID_LIST);
> +
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time > HDCP_2_2_RECVID_LIST_TIMEOUT_MS) {
> + err_code = HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg)
> + break;
> +
> + pre_time = mtk_dp_get_system_time();
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A7F7,
> + HDCP_2_2_REP_VERIFY_RECVI
> D_LIST);
> + }
> + break;
> +
> + case HDCP2_MS_A7F7:
> + /* HDCP2_MS_A7F7 */
> + /* HDCP_2_2_REP_VERIFY_RECVID_LIST */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> + HDCP_2_2_REP_VERIFY_RECVID_LIST) {
> + if ((hdcp_info-
> >hdcp2_info.hdcp_rx.receiverid_list.rx_info[1]
> + & (BIT(2) | BIT(3))) != 0) {
> + pr_err("2.x: DEVS_EXCEEDED or
> CASCADE_EXCEDDED!\n");
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + /* check seqNumV here */
> + tmp = dp_tx_hdcp2_check_seq_num_v(hdcp_info);
> + if (!tmp) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + tmp =
> dp_tx_hdcp2_recv_rep_auth_send_recv_id_list(hdcp_info);
> + if (!tmp) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A8F8,
> HDCP_2_2_REP_SEND_ACK);
> + }
> + break;
> +
> + case HDCP2_MS_A8F8:
> + /* HDCP2_MS_A8F8 */
> + /* HDCP_2_2_REP_SEND_ACK */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_REP_SEND_ACK) {
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_REP_SEND_ACK);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time > HDCP2_REP_SEND_ACK) {
> + err_code = HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A9F9,
> HDCP_2_2_REP_STREAM_MANAGE);
> + hdcp_info->hdcp2_info.hdcp_handler.retry_cnt =
> 0;
> + }
> + break;
> +
> + case HDCP2_MS_A9F9:
> + /* HDCP2_MS_A9F9 */
> + /* HDCP_2_2_REP_STREAM_MANAGE */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_REP_STREAM_MANAGE) {
> + tmp =
> dp_tx_hdcp2_process_rep_auth_stream_manage(hdcp_info);
> + if (!tmp) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + tmp = dp_tx_hdcp2_write_msg(hdcp_info,
> HDCP_2_2_REP_STREAM_MANAGE);
> + if (!tmp) {
> + err_code = HDCP_ERR_SEND_MSG_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + pre_time = mtk_dp_get_system_time();
> + hdcp_info->hdcp2_info.hdcp_handler.recv_msg =
> false;
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A9F9,
> + HDCP_2_2_REP_STREAM_READY
> );
> + }
> +
> + /* HDCP2_MS_A9F9 */
> + /* HDCP_2_2_REP_STREAM_READY */
> + if (hdcp_info->hdcp2_info.hdcp_handler.sub_state ==
> HDCP_2_2_REP_STREAM_READY) {
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time <= HDCP_2_2_STREAM_READY_TIMEOUT_MS /
> 2)
> + break;
> +
> + dp_tx_hdcp2_read_msg(hdcp_info,
> HDCP_2_2_REP_STREAM_READY);
> +
> + time = mtk_dp_get_time_diff(pre_time);
> + if (time > HDCP_2_2_STREAM_READY_TIMEOUT_MS) {
> + err_code = HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + if (!hdcp_info-
> >hdcp2_info.hdcp_handler.recv_msg) {
> + if (hdcp_info-
> >hdcp2_info.hdcp_handler.retry_cnt
> + >=
> HDCP2_STREAM_MANAGE_RETRY_CNT) {
> + err_code =
> HDCP_ERR_RESPONSE_TIMEROUT;
> + dp_tx_hdcp2_err_handle(hdcp_inf
> o, err_code, __LINE__);
> + break;
> + }
> +
> + hdcp_info-
> >hdcp2_info.hdcp_handler.retry_cnt++;
> +
> + dp_tx_hdcp2_set_state(hdcp_info,
> HDCP2_MS_A9F9,
> + HDCP_2_2_REP_STRE
> AM_READY);
> + break;
> + }
> +
> + tmp =
> dp_tx_hdcp2_recv_rep_auth_stream_ready(hdcp_info);
> + if (!tmp) {
> + err_code = HDCP_ERR_PROCESS_FAIL;
> + dp_tx_hdcp2_err_handle(hdcp_info,
> err_code, __LINE__);
> + break;
> + }
> +
> + dp_tx_hdcp2_set_state(hdcp_info, HDCP2_MS_A5F5,
> HDCP_2_2_AUTH_DONE);
> + }
> + break;
> +
> + default:
> + err_code = HDCP_ERR_UNKNOWN_STATE;
> + dp_tx_hdcp2_err_handle(hdcp_info, err_code, __LINE__);
> + break;
> + }
> +
> + return err_code;
> +}
> +