staticint msm_hdmi_hdcp_scm_wr(struct hdmi_hdcp_ctrl *hdcp_ctrl, u32 *preg,
u32 *pdata, u32 count)
{ struct hdmi *hdmi = hdcp_ctrl->hdmi; struct qcom_scm_hdcp_req scm_buf[QCOM_SCM_HDCP_MAX_REQ_CNT];
u32 resp, phy_addr, idx = 0; int i, ret = 0;
WARN_ON(!pdata || !preg || (count == 0));
if (hdcp_ctrl->tz_hdcp) {
phy_addr = (u32)hdmi->mmio_phy_addr;
while (count) {
memset(scm_buf, 0, sizeof(scm_buf)); for (i = 0; i < count && i < QCOM_SCM_HDCP_MAX_REQ_CNT;
i++) {
scm_buf[i].addr = phy_addr + preg[idx];
scm_buf[i].val = pdata[idx];
idx++;
}
ret = qcom_scm_hdcp_req(scm_buf, i, &resp);
if (ret || resp) {
pr_err("%s: error: scm_call ret=%d resp=%u\n",
__func__, ret, resp);
ret = -EINVAL; break;
}
count -= i;
}
} else { for (i = 0; i < count; i++)
hdmi_write(hdmi, preg[i], pdata[i]);
}
/* Fetch aksv from QFPROM, this info should be public. */
hdcp_ctrl->aksv_lsb = hdmi_qfprom_read(hdmi, HDCP_KSV_LSB);
hdcp_ctrl->aksv_msb = hdmi_qfprom_read(hdmi, HDCP_KSV_MSB);
/* check there are 20 ones in AKSV */ if ((hweight32(hdcp_ctrl->aksv_lsb) + hweight32(hdcp_ctrl->aksv_msb))
!= 20) {
pr_err("%s: AKSV QFPROM doesn't have 20 1's, 20 0's\n",
__func__);
pr_err("%s: QFPROM AKSV chk failed (AKSV=%02x%08x)\n",
__func__, hdcp_ctrl->aksv_msb,
hdcp_ctrl->aksv_lsb); return -EINVAL;
}
DBG("AKSV=%02x%08x", hdcp_ctrl->aksv_msb, hdcp_ctrl->aksv_lsb);
/* Check for any DDC transfer failures */
reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS);
failure = reg_val & HDMI_HDCP_DDC_STATUS_FAILED;
nack0 = reg_val & HDMI_HDCP_DDC_STATUS_NACK0;
DBG("HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d",
reg_val, failure, nack0);
if (failure) { /* * Indicates that the last HDCP HW DDC transfer failed. * This occurs when a transfer is attempted with HDCP DDC * disabled (HDCP_DDC_DISABLE=1) or the number of retries * matches HDCP_DDC_RETRY_CNT. * Failure occurred, let's clear it.
*/
DBG("DDC failure detected");
DBG("HDCP REAUTH WORK"); /* * Disable HPD circuitry. * This is needed to reset the HDCP cipher engine so that when we * attempt a re-authentication, HW would clear the AN0_READY and * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register
*/
spin_lock_irqsave(&hdmi->reg_lock, flags);
reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
reg_val &= ~HDMI_HPD_CTRL_ENABLE;
hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val);
/* * Only retry defined times then abort current authenticating process
*/ if (++hdcp_ctrl->auth_retries == AUTH_RETRIES_TIME) {
hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE;
hdcp_ctrl->auth_retries = 0;
pr_info("%s: abort reauthentication!\n", __func__);
/* * Write AKSV read from QFPROM to the HDCP registers. * This step is needed for HDCP authentication and must be * written before enabling HDCP.
*/
hdmi_write(hdmi, REG_HDMI_HDCP_SW_LOWER_AKSV, hdcp_ctrl->aksv_lsb);
hdmi_write(hdmi, REG_HDMI_HDCP_SW_UPPER_AKSV, hdcp_ctrl->aksv_msb);
/* * HDCP setup prior to enabling HDCP_CTRL. * Setup seed values for random number An.
*/
hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF);
hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE);
/* Disable the RngCipher state */
reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL);
reg_val &= ~HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER;
hdmi_write(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, reg_val);
DBG("HDCP_DEBUG_CTRL=0x%08x",
hdmi_read(hdmi, REG_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
*/
hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, HDMI_HDCP_CTRL_ENABLE);
/* * If we had stale values for the An ready bit, it should most * likely be cleared now after enabling HDCP cipher
*/
link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS);
DBG("After enabling HDCP Link0_Status=0x%08x", link0_status); if (!(link0_status &
(HDMI_HDCP_LINK0_STATUS_AN_0_READY |
HDMI_HDCP_LINK0_STATUS_AN_1_READY)))
DBG("An not ready after enabling HDCP");
/* Clear any DDC failures from previous tries before enable HDCP*/
rc = msm_reset_hdcp_ddc_failures(hdcp_ctrl);
/* * Disable software DDC before going into part3 to make sure * there is no Arbitration between software and hardware for DDC
*/
spin_lock_irqsave(&hdmi->reg_lock, flags);
reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION);
reg_val |= HDMI_DDC_ARBITRATION_HW_ARBITRATION;
hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val);
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
/* Wait for AKSV key and An ready */
rc = msm_hdmi_hdcp_wait_key_an_ready(hdcp_ctrl); if (rc) {
pr_err("%s: wait key and an ready failed\n", __func__); return rc;
}
/* Read BCAPS and send to HDCP engine */
rc = msm_hdmi_hdcp_recv_bcaps(hdcp_ctrl); if (rc) {
pr_err("%s: read bcaps error, abort\n", __func__); return rc;
}
/* * 1.1_Features turned off by default. * No need to write AInfo since 1.1_Features is disabled.
*/
hdmi_write(hdmi, REG_HDMI_HDCP_RCVPORT_DATA4, 0);
/* Send AKSV and An to sink */
rc = msm_hdmi_hdcp_send_aksv_an(hdcp_ctrl); if (rc) {
pr_err("%s:An/Aksv write failed\n", __func__); return rc;
}
/* Read BKSV and send to HDCP engine*/
rc = msm_hdmi_hdcp_recv_bksv(hdcp_ctrl); if (rc) {
pr_err("%s:BKSV Process failed\n", __func__); return rc;
}
/* Enable HDCP interrupts and ack/clear any stale interrupts */
spin_lock_irqsave(&hdmi->reg_lock, flags);
hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL,
HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_ACK |
HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_MASK |
HDMI_HDCP_INT_CTRL_AUTH_FAIL_ACK |
HDMI_HDCP_INT_CTRL_AUTH_FAIL_MASK |
HDMI_HDCP_INT_CTRL_AUTH_FAIL_INFO_ACK);
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
return 0;
}
/* read R0' from sink and pass it to HDCP engine */ staticint msm_hdmi_hdcp_auth_part1_recv_r0(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{ struct hdmi *hdmi = hdcp_ctrl->hdmi; int rc = 0;
u8 buf[2];
/* * HDCP Compliance Test case 1A-01: * Wait here at least 100ms before reading R0'
*/
rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 125, AUTH_ABORT_EV); if (rc) return rc;
/* Write R0' to HDCP registers and check to see if it is a match */
hdmi_write(hdmi, REG_HDMI_HDCP_RCVPORT_DATA2_0,
(((u32)buf[1]) << 8) | buf[0]);
return 0;
}
/* Wait for authenticating result: R0/R0' are matched or not */ staticint msm_hdmi_hdcp_auth_part1_verify_r0(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{ struct hdmi *hdmi = hdcp_ctrl->hdmi;
u32 link0_status; int rc;
/* wait for hdcp irq, 10 sec should be long enough */
rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 10000, AUTH_RESULT_RDY_EV); if (!rc) {
pr_err("%s: Wait Auth IRQ timeout\n", __func__); return -ETIMEDOUT;
}
link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); if (!(link0_status & HDMI_HDCP_LINK0_STATUS_RI_MATCHES)) {
pr_err("%s: Authentication Part I failed\n", __func__); return -EINVAL;
}
if (down_stream_devices == 0) { /* * If no downstream devices are attached to the repeater * then part II fails. * todo: The other approach would be to continue PART II.
*/
pr_err("%s: No downstream devices\n", __func__);
rc = -EINVAL; goto error;
}
/* * HDCP Compliance 1B-05: * Check if no. of devices connected to repeater * exceed max_devices_connected from bit 7 of Bstatus.
*/ if (max_devs_exceeded) {
pr_err("%s: no. of devs connected exceeds max allowed",
__func__);
rc = -EINVAL; goto error;
}
/* * HDCP Compliance 1B-06: * Check if no. of cascade connected to repeater * exceed max_cascade_connected from bit 11 of Bstatus.
*/ if (max_cascade_exceeded) {
pr_err("%s: no. of cascade conn exceeds max allowed",
__func__);
rc = -EINVAL; goto error;
}
/* * Wait until READY bit is set in BCAPS, as per HDCP specifications * maximum permitted time to check for READY bit is five seconds.
*/
timeout_count = 100; do { /* Read BCAPS at offset 0x40 */
rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x40, &bcaps, 1); if (rc) {
pr_err("%s: BCAPS read failed\n", __func__); return rc;
}
staticint msm_hdmi_hdcp_auth_part2_recv_ksv_fifo( struct hdmi_hdcp_ctrl *hdcp_ctrl)
{ int rc;
u32 timeout_count;
/* * Read KSV FIFO over DDC * Key Selection vector FIFO Used to pull downstream KSVs * from HDCP Repeaters. * All bytes (DEVICE_COUNT * 5) must be read in a single, * auto incrementing access. * All bytes read as 0x00 for HDCP Receivers that are not * HDCP Repeaters (REPEATER == 0).
*/
timeout_count = 100; do {
rc = msm_hdmi_hdcp_recv_ksv_fifo(hdcp_ctrl); if (!rc) break;
rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 25, AUTH_ABORT_EV); if (rc) return rc;
} while (1);
rc = msm_hdmi_hdcp_transfer_v_h(hdcp_ctrl); if (rc) {
pr_err("%s: transfer V failed\n", __func__); return rc;
}
/* reset SHA engine before write ksv fifo */
rc = msm_hdmi_hdcp_reset_sha_engine(hdcp_ctrl); if (rc) {
pr_err("%s: fail to reset sha engine\n", __func__); return rc;
}
return 0;
}
/* * Write KSV FIFO to HDCP_SHA_DATA. * This is done 1 byte at time starting with the LSB. * Once 64 bytes have been written, we need to poll for * HDCP_SHA_BLOCK_DONE before writing any further * If the last byte is written, we need to poll for * HDCP_SHA_COMP_DONE to wait until HW finish
*/ staticint msm_hdmi_hdcp_write_ksv_fifo(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{ int i; struct hdmi *hdmi = hdcp_ctrl->hdmi;
u32 ksv_bytes, last_byte = 0;
u8 *ksv_fifo = NULL;
u32 reg_val, data, reg;
u32 rc = 0;
ksv_bytes = 5 * hdcp_ctrl->dev_count;
/* Check if need to wait for HW completion */ if (hdcp_ctrl->ksv_fifo_w_index) {
reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_SHA_STATUS);
DBG("HDCP_SHA_STATUS=%08x", reg_val); if (hdcp_ctrl->ksv_fifo_w_index == ksv_bytes) { /* check COMP_DONE if last write */ if (reg_val & HDMI_HDCP_SHA_STATUS_COMP_DONE) {
DBG("COMP_DONE"); return 0;
} else { return -EAGAIN;
}
} else { /* check BLOCK_DONE if not last write */ if (!(reg_val & HDMI_HDCP_SHA_STATUS_BLOCK_DONE)) return -EAGAIN;
for (i = 0; i < ksv_bytes; i++) { /* Write KSV byte and set DONE bit[0] for last byte*/
reg_val = ksv_fifo[i] << 16; if ((i == (ksv_bytes - 1)) && last_byte)
reg_val |= HDMI_HDCP_SHA_DATA_DONE;
if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) ||
(HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) {
DBG("still active or activating or no askv. returning"); return;
}
if ((HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) ||
(HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) {
DBG("hdcp inactive or no aksv. returning"); return;
}
/* * Disable HPD circuitry. * This is needed to reset the HDCP cipher engine so that when we * attempt a re-authentication, HW would clear the AN0_READY and * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register
*/
spin_lock_irqsave(&hdmi->reg_lock, flags);
reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
reg_val &= ~HDMI_HPD_CTRL_ENABLE;
hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val);
/* * Disable HDCP interrupts. * Also, need to set the state to inactive here so that any ongoing * reauth works will know that the HDCP session has been turned off.
*/
hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, 0);
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
/* * Cancel any pending auth/reauth attempts. * If one is ongoing, this will wait for it to finish. * No more reauthentication attempts will be scheduled since we * set the current state to inactive.
*/
set_bit(AUTH_ABORT_EV, &hdcp_ctrl->auth_event);
wake_up_all(&hdcp_ctrl->auth_event_queue);
cancel_work_sync(&hdcp_ctrl->hdcp_auth_work);
cancel_work_sync(&hdcp_ctrl->hdcp_reauth_work);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.