Loading drivers/video/msm/mdss/mdss_hdmi_hdcp.c +114 −135 Original line number Original line Diff line number Diff line Loading @@ -245,120 +245,148 @@ static int hdcp_scm_call(struct scm_hdcp_req *req, u32 *resp) return ret; return ret; } } static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) static int hdmi_hdcp_load_keys(void *input) { { int rc; int rc = 0; bool use_sw_keys = false; u32 reg_val; u32 reg_val; u32 qfprom_aksv_lsb, qfprom_aksv_msb; u32 link0_aksv_0, link0_aksv_1; u32 link0_bksv_0, link0_bksv_1; u32 link0_an_0, link0_an_1; u32 timeout_count; bool is_match, use_sw_keys = false; bool stale_an = false; struct dss_io_data *io; struct dss_io_data *hdcp_io; u8 aksv[5], *bksv = NULL; u8 an[8]; u8 bcaps; struct hdmi_tx_ddc_data ddc_data; u32 link0_status, an_ready, keys_state; u8 buf[0xFF]; u32 ksv_lsb_addr, ksv_msb_addr; u32 ksv_lsb_addr, ksv_msb_addr; u32 aksv_lsb, aksv_msb; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u8 aksv[5]; u32 phy_addr; struct dss_io_data *io; u32 ret = 0; struct dss_io_data *qfprom_io; u32 resp = 0; struct hdmi_hdcp_ctrl *hdcp_ctrl = input; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || !hdcp_ctrl->init_data.qfprom_io) { !hdcp_ctrl->init_data.qfprom_io) { DEV_ERR("%s: invalid input\n", __func__); DEV_ERR("%s: invalid input\n", __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } phy_addr = hdcp_ctrl->init_data.phy_addr; if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) && bksv = hdcp_ctrl->current_tp.bksv; (HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state)) { io = hdcp_ctrl->init_data.core_io; hdcp_io = hdcp_ctrl->init_data.hdcp_io; if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) { DEV_ERR("%s: %s: invalid state. returning\n", __func__, DEV_ERR("%s: %s: invalid state. returning\n", __func__, HDCP_STATE_NAME); HDCP_STATE_NAME); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } /* On compatible hardware, use SW aksv */ io = hdcp_ctrl->init_data.core_io; reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, qfprom_io = hdcp_ctrl->init_data.qfprom_io; SEC_CTRL_HW_VERSION); /* On compatible hardware, use SW keys */ reg_val = DSS_REG_R(qfprom_io, SEC_CTRL_HW_VERSION); if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) { if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) { reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, reg_val = DSS_REG_R(qfprom_io, QFPROM_RAW_FEAT_CONFIG_ROW0_MSB + QFPROM_RAW_FEAT_CONFIG_ROW0_MSB + QFPROM_RAW_VERSION_4); QFPROM_RAW_VERSION_4); if (!(reg_val & BIT(23))) if (!(reg_val & BIT(23))) use_sw_keys = true; use_sw_keys = true; } } if (use_sw_keys) { if (use_sw_keys) { if (hdcp1_set_keys(&qfprom_aksv_msb, &qfprom_aksv_lsb)) { if (hdcp1_set_keys(&aksv_msb, &aksv_lsb)) { pr_err("%s: setting of hdcp SW keys failed\n", pr_err("%s: setting hdcp SW keys failed\n", __func__); __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } } else { } else { /* Fetch aksv from QFPROM, this info should be public. */ /* Fetch aksv from QFPROM, this info should be public. */ ksv_lsb_addr = HDCP_KSV_LSB; ksv_lsb_addr = HDCP_KSV_LSB; ksv_msb_addr = HDCP_KSV_MSB; ksv_msb_addr = HDCP_KSV_MSB; if (hdcp_ctrl->hdmi_tx_ver_4) { if (hdcp_ctrl->hdmi_tx_ver_4) { ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET; } } qfprom_aksv_lsb = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, ksv_lsb_addr); aksv_lsb = DSS_REG_R(qfprom_io, ksv_lsb_addr); qfprom_aksv_msb = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, aksv_msb = DSS_REG_R(qfprom_io, ksv_msb_addr); ksv_msb_addr); } } aksv[0] = qfprom_aksv_lsb & 0xFF; DEV_DBG("%s: %s: AKSV=%02x%08x\n", __func__, HDCP_STATE_NAME, aksv[1] = (qfprom_aksv_lsb >> 8) & 0xFF; aksv_msb, aksv_lsb); aksv[2] = (qfprom_aksv_lsb >> 16) & 0xFF; aksv[3] = (qfprom_aksv_lsb >> 24) & 0xFF; aksv[0] = aksv_lsb & 0xFF; aksv[4] = qfprom_aksv_msb & 0xFF; aksv[1] = (aksv_lsb >> 8) & 0xFF; aksv[2] = (aksv_lsb >> 16) & 0xFF; aksv[3] = (aksv_lsb >> 24) & 0xFF; aksv[4] = aksv_msb & 0xFF; /* check there are 20 ones in AKSV */ /* check there are 20 ones in AKSV */ if (hdmi_hdcp_count_one(aksv, 5) != 20) { if (hdmi_hdcp_count_one(aksv, 5) != 20) { DEV_ERR("%s: %s: AKSV QFPROM doesn't have 20 1's, 20 0's\n", DEV_ERR("%s: AKSV bit count failed\n", __func__); __func__, HDCP_STATE_NAME); rc = -EINVAL; DEV_ERR("%s: %s: QFPROM AKSV chk failed (AKSV=%02x%08x)\n", goto end; __func__, HDCP_STATE_NAME, qfprom_aksv_msb, } qfprom_aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_LOWER_AKSV, aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_UPPER_AKSV, aksv_msb); /* Setup seed values for random number An */ DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF); DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); /* Disable the RngCipher state */ DSS_REG_W(io, HDMI_HDCP_DEBUG_CTRL, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL) & ~(BIT(2))); /* make sure hw is programmed */ wmb(); DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0)); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; end: return rc; } static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) { int rc; u32 link0_aksv_0, link0_aksv_1; u32 link0_bksv_0, link0_bksv_1; u32 link0_an_0, link0_an_1; u32 timeout_count; bool is_match; struct dss_io_data *io; struct dss_io_data *hdcp_io; u8 aksv[5], *bksv = NULL; u8 an[8]; u8 bcaps; struct hdmi_tx_ddc_data ddc_data; u32 link0_status, an_ready, keys_state; u8 buf[0xFF]; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u32 phy_addr; u32 ret = 0; u32 resp = 0; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || !hdcp_ctrl->init_data.qfprom_io) { DEV_ERR("%s: invalid input\n", __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto error; } } DEV_DBG("%s: %s: AKSV=%02x%08x\n", __func__, HDCP_STATE_NAME, qfprom_aksv_msb, qfprom_aksv_lsb); /* phy_addr = hdcp_ctrl->init_data.phy_addr; * Write AKSV read from QFPROM to the HDCP registers. bksv = hdcp_ctrl->current_tp.bksv; * This step is needed for HDCP authentication and must be io = hdcp_ctrl->init_data.core_io; * written before enabling HDCP. hdcp_io = hdcp_ctrl->init_data.hdcp_io; */ DSS_REG_W(io, HDMI_HDCP_SW_LOWER_AKSV, qfprom_aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_UPPER_AKSV, qfprom_aksv_msb); /* Check to see if link0_Status has stale values for An ready bit */ if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) { link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS); DEV_ERR("%s: %s: invalid state. returning\n", __func__, DEV_DBG("%s: %s: Before enabling cipher Link0_status=0x%08x\n", HDCP_STATE_NAME); __func__, HDCP_STATE_NAME, link0_status); rc = -EINVAL; if (link0_status & (BIT(8) | BIT(9))) { goto error; DEV_DBG("%s: %s: An ready even before enabling HDCP\n", __func__, HDCP_STATE_NAME); stale_an = true; } } /* Clear any DDC failures from previous tries */ reset_hdcp_ddc_failures(hdcp_ctrl); /* /* * Read BCAPS * Read BCAPS * We need to first try to read an HDCP register on the sink to see if * We need to first try to read an HDCP register on the sink to see if Loading Loading @@ -387,35 +415,6 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) hdcp_ctrl->current_tp.ds_type = hdcp_ctrl->current_tp.ds_type = (bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER; (bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER; /* * HDCP setup prior to enabling HDCP_CTRL. * Setup seed values for random number An. */ DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF); DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); /* Disable the RngCipher state */ DSS_REG_W(io, HDMI_HDCP_DEBUG_CTRL, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL) & ~(BIT(2))); DEV_DBG("%s: %s: HDCP_DEBUG_CTRL=0x%08x\n", __func__, HDCP_STATE_NAME, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL)); /* * Ensure that all register writes are completed before * enabling HDCP cipher */ wmb(); /* * Enable HDCP * This needs to be done as early as possible in order for the * hardware to make An available to read */ DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0)); /* Clear any DDC failures from previous tries */ reset_hdcp_ddc_failures(hdcp_ctrl); /* Write BCAPS to the hardware */ /* Write BCAPS to the hardware */ if (hdcp_ctrl->tz_hdcp) { if (hdcp_ctrl->tz_hdcp) { memset(scm_buf, 0x00, sizeof(scm_buf)); memset(scm_buf, 0x00, sizeof(scm_buf)); Loading @@ -437,19 +436,6 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps); DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps); } } /* * If we had stale values for the An ready bit, it should most * likely be cleared now after enabling HDCP cipher */ link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS); DEV_DBG("%s: %s: After enabling HDCP Link0_Status=0x%08x\n", __func__, HDCP_STATE_NAME, link0_status); if (!(link0_status & (BIT(8) | BIT(9)))) { DEV_DBG("%s: %s: An not ready after enabling HDCP\n", __func__, HDCP_STATE_NAME); stale_an = false; } /* Wait for HDCP keys to be checked and validated */ /* Wait for HDCP keys to be checked and validated */ timeout_count = 100; timeout_count = 100; keys_state = (link0_status >> 28) & 0x7; keys_state = (link0_status >> 28) & 0x7; Loading Loading @@ -497,15 +483,8 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) goto error; goto error; } } /* /* As per hardware recommendations, wait before reading An */ * In cases where An_ready bits had stale values, it would be msleep(20); * better to delay reading of An to avoid any potential of this * read being blocked */ if (stale_an) { msleep(200); stale_an = false; } /* Read An0 and An1 */ /* Read An0 and An1 */ link0_an_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA5); link0_an_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA5); Loading Loading @@ -1334,11 +1313,13 @@ int hdmi_hdcp_authenticate(void *input) DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__, DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__, HDCP_STATE_NAME); HDCP_STATE_NAME); mutex_lock(hdcp_ctrl->init_data.mutex); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; if (!hdmi_hdcp_load_keys(input)) mutex_unlock(hdcp_ctrl->init_data.mutex); queue_delayed_work(hdcp_ctrl->init_data.workq, queue_delayed_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_auth_work, 0); &hdcp_ctrl->hdcp_auth_work, HZ/2); else queue_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_int_work); return 0; return 0; } /* hdmi_hdcp_authenticate */ } /* hdmi_hdcp_authenticate */ Loading Loading @@ -1380,14 +1361,12 @@ int hdmi_hdcp_reauthenticate(void *input) /* Disable encryption and disable the HDCP block */ /* Disable encryption and disable the HDCP block */ DSS_REG_W(io, HDMI_HDCP_CTRL, 0); DSS_REG_W(io, HDMI_HDCP_CTRL, 0); /* Restart authentication attempt */ if (!hdmi_hdcp_load_keys(input)) DEV_DBG("%s: %s: Scheduling work to start HDCP authentication", __func__, HDCP_STATE_NAME); mutex_lock(hdcp_ctrl->init_data.mutex); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; mutex_unlock(hdcp_ctrl->init_data.mutex); queue_delayed_work(hdcp_ctrl->init_data.workq, queue_delayed_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_auth_work, HZ/2); &hdcp_ctrl->hdcp_auth_work, HZ/2); else queue_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_int_work); return ret; return ret; } /* hdmi_hdcp_reauthenticate */ } /* hdmi_hdcp_reauthenticate */ Loading Loading
drivers/video/msm/mdss/mdss_hdmi_hdcp.c +114 −135 Original line number Original line Diff line number Diff line Loading @@ -245,120 +245,148 @@ static int hdcp_scm_call(struct scm_hdcp_req *req, u32 *resp) return ret; return ret; } } static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) static int hdmi_hdcp_load_keys(void *input) { { int rc; int rc = 0; bool use_sw_keys = false; u32 reg_val; u32 reg_val; u32 qfprom_aksv_lsb, qfprom_aksv_msb; u32 link0_aksv_0, link0_aksv_1; u32 link0_bksv_0, link0_bksv_1; u32 link0_an_0, link0_an_1; u32 timeout_count; bool is_match, use_sw_keys = false; bool stale_an = false; struct dss_io_data *io; struct dss_io_data *hdcp_io; u8 aksv[5], *bksv = NULL; u8 an[8]; u8 bcaps; struct hdmi_tx_ddc_data ddc_data; u32 link0_status, an_ready, keys_state; u8 buf[0xFF]; u32 ksv_lsb_addr, ksv_msb_addr; u32 ksv_lsb_addr, ksv_msb_addr; u32 aksv_lsb, aksv_msb; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u8 aksv[5]; u32 phy_addr; struct dss_io_data *io; u32 ret = 0; struct dss_io_data *qfprom_io; u32 resp = 0; struct hdmi_hdcp_ctrl *hdcp_ctrl = input; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || !hdcp_ctrl->init_data.qfprom_io) { !hdcp_ctrl->init_data.qfprom_io) { DEV_ERR("%s: invalid input\n", __func__); DEV_ERR("%s: invalid input\n", __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } phy_addr = hdcp_ctrl->init_data.phy_addr; if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) && bksv = hdcp_ctrl->current_tp.bksv; (HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state)) { io = hdcp_ctrl->init_data.core_io; hdcp_io = hdcp_ctrl->init_data.hdcp_io; if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) { DEV_ERR("%s: %s: invalid state. returning\n", __func__, DEV_ERR("%s: %s: invalid state. returning\n", __func__, HDCP_STATE_NAME); HDCP_STATE_NAME); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } /* On compatible hardware, use SW aksv */ io = hdcp_ctrl->init_data.core_io; reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, qfprom_io = hdcp_ctrl->init_data.qfprom_io; SEC_CTRL_HW_VERSION); /* On compatible hardware, use SW keys */ reg_val = DSS_REG_R(qfprom_io, SEC_CTRL_HW_VERSION); if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) { if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) { reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, reg_val = DSS_REG_R(qfprom_io, QFPROM_RAW_FEAT_CONFIG_ROW0_MSB + QFPROM_RAW_FEAT_CONFIG_ROW0_MSB + QFPROM_RAW_VERSION_4); QFPROM_RAW_VERSION_4); if (!(reg_val & BIT(23))) if (!(reg_val & BIT(23))) use_sw_keys = true; use_sw_keys = true; } } if (use_sw_keys) { if (use_sw_keys) { if (hdcp1_set_keys(&qfprom_aksv_msb, &qfprom_aksv_lsb)) { if (hdcp1_set_keys(&aksv_msb, &aksv_lsb)) { pr_err("%s: setting of hdcp SW keys failed\n", pr_err("%s: setting hdcp SW keys failed\n", __func__); __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto end; } } } else { } else { /* Fetch aksv from QFPROM, this info should be public. */ /* Fetch aksv from QFPROM, this info should be public. */ ksv_lsb_addr = HDCP_KSV_LSB; ksv_lsb_addr = HDCP_KSV_LSB; ksv_msb_addr = HDCP_KSV_MSB; ksv_msb_addr = HDCP_KSV_MSB; if (hdcp_ctrl->hdmi_tx_ver_4) { if (hdcp_ctrl->hdmi_tx_ver_4) { ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET; ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET; } } qfprom_aksv_lsb = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, ksv_lsb_addr); aksv_lsb = DSS_REG_R(qfprom_io, ksv_lsb_addr); qfprom_aksv_msb = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io, aksv_msb = DSS_REG_R(qfprom_io, ksv_msb_addr); ksv_msb_addr); } } aksv[0] = qfprom_aksv_lsb & 0xFF; DEV_DBG("%s: %s: AKSV=%02x%08x\n", __func__, HDCP_STATE_NAME, aksv[1] = (qfprom_aksv_lsb >> 8) & 0xFF; aksv_msb, aksv_lsb); aksv[2] = (qfprom_aksv_lsb >> 16) & 0xFF; aksv[3] = (qfprom_aksv_lsb >> 24) & 0xFF; aksv[0] = aksv_lsb & 0xFF; aksv[4] = qfprom_aksv_msb & 0xFF; aksv[1] = (aksv_lsb >> 8) & 0xFF; aksv[2] = (aksv_lsb >> 16) & 0xFF; aksv[3] = (aksv_lsb >> 24) & 0xFF; aksv[4] = aksv_msb & 0xFF; /* check there are 20 ones in AKSV */ /* check there are 20 ones in AKSV */ if (hdmi_hdcp_count_one(aksv, 5) != 20) { if (hdmi_hdcp_count_one(aksv, 5) != 20) { DEV_ERR("%s: %s: AKSV QFPROM doesn't have 20 1's, 20 0's\n", DEV_ERR("%s: AKSV bit count failed\n", __func__); __func__, HDCP_STATE_NAME); rc = -EINVAL; DEV_ERR("%s: %s: QFPROM AKSV chk failed (AKSV=%02x%08x)\n", goto end; __func__, HDCP_STATE_NAME, qfprom_aksv_msb, } qfprom_aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_LOWER_AKSV, aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_UPPER_AKSV, aksv_msb); /* Setup seed values for random number An */ DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF); DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); /* Disable the RngCipher state */ DSS_REG_W(io, HDMI_HDCP_DEBUG_CTRL, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL) & ~(BIT(2))); /* make sure hw is programmed */ wmb(); DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0)); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; end: return rc; } static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) { int rc; u32 link0_aksv_0, link0_aksv_1; u32 link0_bksv_0, link0_bksv_1; u32 link0_an_0, link0_an_1; u32 timeout_count; bool is_match; struct dss_io_data *io; struct dss_io_data *hdcp_io; u8 aksv[5], *bksv = NULL; u8 an[8]; u8 bcaps; struct hdmi_tx_ddc_data ddc_data; u32 link0_status, an_ready, keys_state; u8 buf[0xFF]; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u32 phy_addr; u32 ret = 0; u32 resp = 0; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || !hdcp_ctrl->init_data.qfprom_io) { DEV_ERR("%s: invalid input\n", __func__); rc = -EINVAL; rc = -EINVAL; goto error; goto error; } } DEV_DBG("%s: %s: AKSV=%02x%08x\n", __func__, HDCP_STATE_NAME, qfprom_aksv_msb, qfprom_aksv_lsb); /* phy_addr = hdcp_ctrl->init_data.phy_addr; * Write AKSV read from QFPROM to the HDCP registers. bksv = hdcp_ctrl->current_tp.bksv; * This step is needed for HDCP authentication and must be io = hdcp_ctrl->init_data.core_io; * written before enabling HDCP. hdcp_io = hdcp_ctrl->init_data.hdcp_io; */ DSS_REG_W(io, HDMI_HDCP_SW_LOWER_AKSV, qfprom_aksv_lsb); DSS_REG_W(io, HDMI_HDCP_SW_UPPER_AKSV, qfprom_aksv_msb); /* Check to see if link0_Status has stale values for An ready bit */ if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) { link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS); DEV_ERR("%s: %s: invalid state. returning\n", __func__, DEV_DBG("%s: %s: Before enabling cipher Link0_status=0x%08x\n", HDCP_STATE_NAME); __func__, HDCP_STATE_NAME, link0_status); rc = -EINVAL; if (link0_status & (BIT(8) | BIT(9))) { goto error; DEV_DBG("%s: %s: An ready even before enabling HDCP\n", __func__, HDCP_STATE_NAME); stale_an = true; } } /* Clear any DDC failures from previous tries */ reset_hdcp_ddc_failures(hdcp_ctrl); /* /* * Read BCAPS * Read BCAPS * We need to first try to read an HDCP register on the sink to see if * We need to first try to read an HDCP register on the sink to see if Loading Loading @@ -387,35 +415,6 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) hdcp_ctrl->current_tp.ds_type = hdcp_ctrl->current_tp.ds_type = (bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER; (bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER; /* * HDCP setup prior to enabling HDCP_CTRL. * Setup seed values for random number An. */ DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF); DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); /* Disable the RngCipher state */ DSS_REG_W(io, HDMI_HDCP_DEBUG_CTRL, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL) & ~(BIT(2))); DEV_DBG("%s: %s: HDCP_DEBUG_CTRL=0x%08x\n", __func__, HDCP_STATE_NAME, DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL)); /* * Ensure that all register writes are completed before * enabling HDCP cipher */ wmb(); /* * Enable HDCP * This needs to be done as early as possible in order for the * hardware to make An available to read */ DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0)); /* Clear any DDC failures from previous tries */ reset_hdcp_ddc_failures(hdcp_ctrl); /* Write BCAPS to the hardware */ /* Write BCAPS to the hardware */ if (hdcp_ctrl->tz_hdcp) { if (hdcp_ctrl->tz_hdcp) { memset(scm_buf, 0x00, sizeof(scm_buf)); memset(scm_buf, 0x00, sizeof(scm_buf)); Loading @@ -437,19 +436,6 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps); DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps); } } /* * If we had stale values for the An ready bit, it should most * likely be cleared now after enabling HDCP cipher */ link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS); DEV_DBG("%s: %s: After enabling HDCP Link0_Status=0x%08x\n", __func__, HDCP_STATE_NAME, link0_status); if (!(link0_status & (BIT(8) | BIT(9)))) { DEV_DBG("%s: %s: An not ready after enabling HDCP\n", __func__, HDCP_STATE_NAME); stale_an = false; } /* Wait for HDCP keys to be checked and validated */ /* Wait for HDCP keys to be checked and validated */ timeout_count = 100; timeout_count = 100; keys_state = (link0_status >> 28) & 0x7; keys_state = (link0_status >> 28) & 0x7; Loading Loading @@ -497,15 +483,8 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) goto error; goto error; } } /* /* As per hardware recommendations, wait before reading An */ * In cases where An_ready bits had stale values, it would be msleep(20); * better to delay reading of An to avoid any potential of this * read being blocked */ if (stale_an) { msleep(200); stale_an = false; } /* Read An0 and An1 */ /* Read An0 and An1 */ link0_an_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA5); link0_an_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA5); Loading Loading @@ -1334,11 +1313,13 @@ int hdmi_hdcp_authenticate(void *input) DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__, DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__, HDCP_STATE_NAME); HDCP_STATE_NAME); mutex_lock(hdcp_ctrl->init_data.mutex); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; if (!hdmi_hdcp_load_keys(input)) mutex_unlock(hdcp_ctrl->init_data.mutex); queue_delayed_work(hdcp_ctrl->init_data.workq, queue_delayed_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_auth_work, 0); &hdcp_ctrl->hdcp_auth_work, HZ/2); else queue_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_int_work); return 0; return 0; } /* hdmi_hdcp_authenticate */ } /* hdmi_hdcp_authenticate */ Loading Loading @@ -1380,14 +1361,12 @@ int hdmi_hdcp_reauthenticate(void *input) /* Disable encryption and disable the HDCP block */ /* Disable encryption and disable the HDCP block */ DSS_REG_W(io, HDMI_HDCP_CTRL, 0); DSS_REG_W(io, HDMI_HDCP_CTRL, 0); /* Restart authentication attempt */ if (!hdmi_hdcp_load_keys(input)) DEV_DBG("%s: %s: Scheduling work to start HDCP authentication", __func__, HDCP_STATE_NAME); mutex_lock(hdcp_ctrl->init_data.mutex); hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; mutex_unlock(hdcp_ctrl->init_data.mutex); queue_delayed_work(hdcp_ctrl->init_data.workq, queue_delayed_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_auth_work, HZ/2); &hdcp_ctrl->hdcp_auth_work, HZ/2); else queue_work(hdcp_ctrl->init_data.workq, &hdcp_ctrl->hdcp_int_work); return ret; return ret; } /* hdmi_hdcp_reauthenticate */ } /* hdmi_hdcp_reauthenticate */ Loading