From 7963ee24855344e5ad6b1b3b2830b000c2a8fbb6 Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Thu, 27 Oct 2016 11:39:22 -0700 Subject: [PATCH] msm: mdss: hdcp1x: fix hdcp 1x registration and reset Keep the correct hdcp1x data after hdcp1x registration to avoid issues with invalid data access. Also, increase the re-authenticate timeout to give sink and source reasonable time to reset the hdcp engines. Fix the reset bit before hdcp off and re-authentication. Change-Id: Ie1d1540a87e96a33d3e5521cf933399a60d467ab Signed-off-by: Ajay Singh Parmar --- drivers/video/fbdev/msm/mdss_dp.c | 8 ++++---- drivers/video/fbdev/msm/mdss_hdcp_1x.c | 24 ++++++++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 391d4c24eb7f..22d3d45ccea3 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1743,19 +1743,19 @@ static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata) hdcp_init_data.sec_access = true; hdcp_init_data.client_id = HDCP_CLIENT_DP; - dp_drv->hdcp.data = hdcp_1x_init(&hdcp_init_data); - if (IS_ERR_OR_NULL(dp_drv->hdcp.data)) { + dp_drv->hdcp.hdcp1 = hdcp_1x_init(&hdcp_init_data); + if (IS_ERR_OR_NULL(dp_drv->hdcp.hdcp1)) { pr_err("Error hdcp init\n"); rc = -EINVAL; goto error; } - dp_drv->panel_data.panel_info.hdcp_1x_data = dp_drv->hdcp.data; + dp_drv->panel_data.panel_info.hdcp_1x_data = dp_drv->hdcp.hdcp1; pr_debug("HDCP 1.3 initialized\n"); dp_drv->hdcp.hdcp2 = dp_hdcp2p2_init(&hdcp_init_data); - if (!IS_ERR_OR_NULL(dp_drv->hdcp.data)) + if (!IS_ERR_OR_NULL(dp_drv->hdcp.hdcp2)) pr_debug("HDCP 2.2 initialized\n"); dp_drv->hdcp.feature_enabled = true; diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c index 1e502cf750a6..1e0ad986afb1 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c +++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c @@ -153,6 +153,7 @@ struct hdcp_reg_set { u32 sec_data12; u32 reset; + u32 reset_bit; }; #define HDCP_REG_SET_CLIENT_HDMI \ @@ -175,7 +176,7 @@ struct hdcp_reg_set { HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \ - HDMI_HDCP_RESET} + HDMI_HDCP_RESET, BIT(0)} #define HDCP_REG_SET_CLIENT_DP \ {DP_HDCP_STATUS, 16, 14, 13, DP_HDCP_CTRL, \ @@ -193,7 +194,8 @@ struct hdcp_reg_set { HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, \ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \ - HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, 0} + HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \ + DP_SW_RESET, BIT(1)} #define HDCP_HDMI_SINK_ADDR_MAP \ {{"bcaps", 0x40, 1}, {"bksv", 0x00, 5}, {"r0'", 0x08, 2}, \ @@ -1431,7 +1433,7 @@ int hdcp_1x_reauthenticate(void *input) struct hdcp_reg_set *reg_set; struct hdcp_int_set *isr; u32 hdmi_hw_version; - u32 ret = 0; + u32 ret = 0, reg; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) { DEV_ERR("%s: invalid input\n", __func__); @@ -1462,15 +1464,17 @@ int hdcp_1x_reauthenticate(void *input) /* Disable HDCP interrupts */ DSS_REG_W(io, isr->int_reg, DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN); - if (reg_set->reset) - DSS_REG_W(io, reg_set->reset, BIT(0)); + reg = DSS_REG_R(io, reg_set->reset); + DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit); /* Disable encryption and disable the HDCP block */ DSS_REG_W(io, reg_set->ctrl, 0); + DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit); + if (!hdcp_1x_load_keys(input)) queue_delayed_work(hdcp_ctrl->init_data.workq, - &hdcp_ctrl->hdcp_auth_work, HZ/2); + &hdcp_ctrl->hdcp_auth_work, HZ); else queue_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_int_work); @@ -1485,6 +1489,7 @@ void hdcp_1x_off(void *input) struct hdcp_reg_set *reg_set; struct hdcp_int_set *isr; int rc = 0; + u32 reg; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) { DEV_ERR("%s: invalid input\n", __func__); @@ -1527,12 +1532,15 @@ void hdcp_1x_off(void *input) DEV_DBG("%s: %s: Deleted hdcp int work\n", __func__, HDCP_STATE_NAME); - if (reg_set->reset) - DSS_REG_W(io, reg_set->reset, BIT(0)); + + reg = DSS_REG_R(io, reg_set->reset); + DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit); /* Disable encryption and disable the HDCP block */ DSS_REG_W(io, reg_set->ctrl, 0); + DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit); + DEV_DBG("%s: %s: HDCP: Off\n", __func__, HDCP_STATE_NAME); } /* hdcp_1x_off */