Loading drivers/misc/hdcp.c +9 −2 Original line number Diff line number Diff line Loading @@ -332,6 +332,7 @@ struct hdcp_lib_handle { uint32_t msglen; uint32_t tz_ctxhandle; uint32_t hdcp_timeout; uint32_t timeout_left; bool no_stored_km_flag; bool feature_supported; void *client_ctx; Loading Loading @@ -842,7 +843,11 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) mutex_lock(&handle->wakeup_mutex); handle->wakeup_cmd = data->cmd; pr_debug("%s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); handle->timeout_left = data->timeout; pr_debug("%s, timeout left: %dms\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd), handle->timeout_left); rc = hdcp_lib_check_valid_state(handle); if (rc) Loading Loading @@ -874,6 +879,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->last_msg_sent = 0; handle->hdcp_timeout = 0; handle->timeout_left = 0; atomic_set(&handle->hdcp_off, 0); handle->hdcp_state = HDCP_STATE_INIT; Loading Loading @@ -949,7 +956,7 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; cdata.timeout = handle->hdcp_timeout; cdata.timeout = handle->timeout_left; } mutex_unlock(&handle->hdcp_lock); Loading drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +87 −34 Original line number Diff line number Diff line Loading @@ -34,11 +34,12 @@ #define HDCP_SINK_DDC_HDCP2_RXSTATUS 0x70 /* RxStatus, 2 bytes */ #define HDCP_SINK_DDC_HDCP2_READ_MESSAGE 0x80 /* HDCP Tx reads here */ #define HDCP2P2_LINK_CHECK_TIME_MS 500 /* link check within 1 sec */ #define HDCP2P2_LINK_CHECK_TIME_MS 900 /* link check within 1 sec */ #define HDCP2P2_SEC_TO_US 1000000 #define HDCP2P2_MS_TO_US 1000 #define HDCP2P2_KHZ_TO_HZ 1000 #define HDCP2P2_DEFAULT_TIMEOUT 500 /* * HDCP 2.2 encryption requires the data encryption block that is present in Loading Loading @@ -66,6 +67,7 @@ struct hdmi_hdcp2p2_ctrl { char *send_msg_buf; uint32_t send_msg_len; uint32_t timeout; uint32_t timeout_left; struct task_struct *thread; struct kthread_worker worker; Loading @@ -78,6 +80,45 @@ struct hdmi_hdcp2p2_ctrl { struct delayed_work link_check_work; }; static inline bool hdmi_hdcp2p2_is_valid_state(struct hdmi_hdcp2p2_ctrl *ctrl) { if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_AUTHENTICATE) return true; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) return true; return false; } static int hdmi_hdcp2p2_copy_buf(struct hdmi_hdcp2p2_ctrl *ctrl, struct hdmi_hdcp_wakeup_data *data) { mutex_lock(&ctrl->msg_lock); if (!data->send_msg_len) { mutex_unlock(&ctrl->msg_lock); return 0; } ctrl->send_msg_len = data->send_msg_len; kzfree(ctrl->send_msg_buf); ctrl->send_msg_buf = kzalloc(data->send_msg_len, GFP_KERNEL); if (!ctrl->send_msg_buf) { mutex_unlock(&ctrl->msg_lock); return -ENOMEM; } memcpy(ctrl->send_msg_buf, data->send_msg_buf, ctrl->send_msg_len); mutex_unlock(&ctrl->msg_lock); return 0; } static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) { struct hdmi_hdcp2p2_ctrl *ctrl; Loading @@ -95,42 +136,34 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) mutex_lock(&ctrl->wakeup_mutex); pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); pr_debug("cmd: %s, timeout %dms\n", hdmi_hdcp_cmd_to_str(data->cmd), data->timeout); ctrl->wakeup_cmd = data->cmd; ctrl->timeout = data->timeout; mutex_lock(&ctrl->msg_lock); if (data->send_msg_len) { ctrl->send_msg_len = data->send_msg_len; kzfree(ctrl->send_msg_buf); ctrl->send_msg_buf = kzalloc( data->send_msg_len, GFP_KERNEL); if (data->timeout) ctrl->timeout = data->timeout; else ctrl->timeout = HDCP2P2_DEFAULT_TIMEOUT; if (!ctrl->send_msg_buf) { mutex_unlock(&ctrl->msg_lock); if (!hdmi_hdcp2p2_is_valid_state(ctrl)) { pr_err("invalid state\n"); goto exit; } memcpy(ctrl->send_msg_buf, data->send_msg_buf, ctrl->send_msg_len); } mutex_unlock(&ctrl->msg_lock); if (hdmi_hdcp2p2_copy_buf(ctrl, data)) goto exit; switch (ctrl->wakeup_cmd) { case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->send_msg); break; case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); break; case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: Loading Loading @@ -366,6 +399,7 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, pr_err("hdcp is off\n"); return -EINVAL; } memset(&ddc_data, 0, sizeof(ddc_data)); ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR; ddc_data.offset = HDCP_SINK_DDC_HDCP2_READ_MESSAGE; Loading @@ -378,9 +412,14 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; pr_debug("read msg timeout %dms\n", timeout); rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot read HDCP message register\n"); ctrl->timeout_left = ctrl->init_data.ddc_ctrl->ddc_data.timeout_left; return rc; } Loading @@ -396,6 +435,7 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.data_buf = buf; ddc_data.data_len = size; ddc_data.retry = 1; ddc_data.hard_timeout = ctrl->timeout; ddc_data.what = "HDCP2WriteMessage"; ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; Loading @@ -403,6 +443,9 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot write HDCP message register\n"); ctrl->timeout_left = ctrl->init_data.ddc_ctrl->ddc_data.timeout_left; return rc; } Loading Loading @@ -545,6 +588,7 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED; } else { cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS; cdata.timeout = ctrl->timeout_left; } exit: kzfree(msg); Loading Loading @@ -605,10 +649,13 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) lines_needed_for_given_time = (ctrl->timeout * HDCP2P2_MS_TO_US) / time_taken_by_one_line_us; pr_debug("timeout for rxstatus %d\n", lines_needed_for_given_time); pr_debug("timeout for rxstatus %dms, %d hsyncs\n", ctrl->timeout, lines_needed_for_given_time); ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->timer_delay_lines = lines_needed_for_given_time; ddc_data->timeout_ms = ctrl->timeout; ddc_data->timeout_hsync = lines_needed_for_given_time; ddc_data->periodic_timer_hsync = lines_needed_for_given_time / 20; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, true); Loading @@ -617,26 +664,30 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) goto exit; } ctrl->timeout_left = ddc_data->timeout_left; pr_debug("timeout left after rxstatus %dms, msg size %d\n", ctrl->timeout_left, ddc_data->message_size); if (!ddc_data->message_size) { pr_err("recvd invalid message size\n"); rc = -EINVAL; goto exit; } pr_debug("rxstatus msg size %d\n", ddc_data->message_size); recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL); if (!recvd_msg_buf) goto exit; rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf, ddc_data->message_size, ctrl->timeout); ddc_data->message_size, ctrl->timeout_left); if (rc) pr_err("error reading message %d\n", rc); cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; cdata.recvd_msg_buf = recvd_msg_buf; cdata.recvd_msg_len = ddc_data->message_size; cdata.timeout = ctrl->timeout_left; exit: if (rc == -ETIMEDOUT) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT; Loading Loading @@ -672,14 +723,16 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) fps = timing->refresh_rate / HDCP2P2_KHZ_TO_HZ; v_total = hdmi_tx_get_v_total(timing); time_taken_by_one_line_us = HDCP2P2_SEC_TO_US / (v_total * fps); lines_needed_for_given_time = (jiffies_to_msecs(HZ / 2) * lines_needed_for_given_time = (jiffies_to_msecs((HZ / 2) + (HZ / 4)) * HDCP2P2_MS_TO_US) / time_taken_by_one_line_us; pr_debug("timeout for rxstatus %d\n", lines_needed_for_given_time); pr_debug("timeout for rxstatus %d hsyncs\n", lines_needed_for_given_time); ddc_data->intr_mask = RXSTATUS_READY | RXSTATUS_MESSAGE_SIZE | RXSTATUS_REAUTH_REQ; ddc_data->timer_delay_lines = lines_needed_for_given_time; ddc_data->timeout_hsync = lines_needed_for_given_time; ddc_data->periodic_timer_hsync = lines_needed_for_given_time; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, false); Loading Loading @@ -788,7 +841,7 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) } rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf, ddc_data->message_size, ctrl->timeout); ddc_data->message_size, HDCP2P2_DEFAULT_TIMEOUT); if (rc) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; pr_err("error reading message %d\n", rc); Loading drivers/video/msm/mdss/mdss_hdmi_util.c +43 −22 Original line number Diff line number Diff line Loading @@ -515,23 +515,22 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, return -EINVAL; } /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); /* wait until DDC HW is free */ timeout = 100; do { --timeout; ddc_status = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_HW_STATUS); in_use = ddc_status & (in_use_by_sw | in_use_by_hw); if (in_use) { pr_debug("ddc is in use by %s\n", ddc_status & in_use_by_sw ? "sw" : "hw"); msleep(20); udelay(100); } } while (in_use && timeout); /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); } while (in_use && --timeout); if (!timeout) { pr_err("%s: timedout\n", what); Loading Loading @@ -652,10 +651,14 @@ again: &ddc_ctrl->ddc_sw_done, wait_time); pr_debug("ddc read done at %dms\n", jiffies_to_msecs(jiffies)); ddc_data->timeout_left = jiffies_to_msecs(time_out_count); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1)); if (!time_out_count) { if (ddc_data->retry-- > 0) { pr_debug("failed timout, retry=%d\n", ddc_data->retry); if (!ddc_data->hard_timeout) goto again; } status = -ETIMEDOUT; Loading Loading @@ -809,8 +812,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) intr2 = DSS_REG_R(io, HDMI_HDCP_INT_CTRL2); intr0 = DSS_REG_R(io, HDMI_DDC_INT_CTRL0); pr_debug("INT_CTRL0 :0x%x\n", intr0); pr_debug("INT_CTRL2 :0x%x\n", intr2); pr_debug("ctl0: 0x%x, ctl1: 0x%x\n", intr0, intr2); /* check for encryption ready interrupt */ if (intr2 & BIT(2)) { Loading Loading @@ -1204,6 +1206,7 @@ int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl) int status = 0, retry = 10; u32 time_out_count; struct hdmi_tx_ddc_data *ddc_data; u32 wait_time; if (!ddc_ctrl || !ddc_ctrl->io) { pr_err("invalid input\n"); Loading Loading @@ -1286,8 +1289,19 @@ again: reinit_completion(&ddc_ctrl->ddc_sw_done); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0)); if (ddc_data->hard_timeout) { pr_debug("using hard_timeout %dms\n", ddc_data->hard_timeout); wait_time = msecs_to_jiffies(ddc_data->hard_timeout); } else { wait_time = HZ/2; } pr_debug("timeout for ddc write %d jiffies\n", wait_time); time_out_count = wait_for_completion_timeout( &ddc_ctrl->ddc_sw_done, HZ/2); &ddc_ctrl->ddc_sw_done, wait_time); ddc_data->timeout_left = jiffies_to_msecs(time_out_count); pr_debug("DDC write done at %dms\n", jiffies_to_msecs(jiffies)); Loading @@ -1297,6 +1311,8 @@ again: if (retry-- > 0) { pr_debug("%s: failed timout, retry=%d\n", ddc_data->what, retry); if (!ddc_data->hard_timeout) goto again; } status = -ETIMEDOUT; Loading Loading @@ -1635,6 +1651,7 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) u32 reg_val; u32 intr_en_mask; u32 timeout; u32 timer; int rc = 0; struct hdmi_tx_hdcp2p2_ddc_data *data; Loading Loading @@ -1674,9 +1691,11 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) * 3. DDC_TIMEOUT_TIMER: Timeout in hsyncs which starts counting when * a request is made and stops when it is accepted by DDC arbiter */ timeout = data->timer_delay_lines; pr_debug("timeout: %d\n", timeout); DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timeout); timeout = data->timeout_hsync; timer = data->periodic_timer_hsync; pr_debug("timeout: %d hsyncs, timer %d hsync\n", timeout, timer); DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timer); /* Set both urgent and hw-timeout fields to the same value */ DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL2, Loading Loading @@ -1711,8 +1730,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL); reg_val &= ~(BIT(1) | BIT(0)); pr_debug("data->read_method %d\n", data->read_method); if (data->read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER) reg_val |= BIT(1) | BIT(0); else Loading @@ -1725,16 +1742,20 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1); if (wait) { u32 wait_timeout; reinit_completion(&ctrl->rxstatus_completion); /* max timeout as per hdcp 2.2 std is 1 sec */ timeout = wait_for_completion_timeout( wait_timeout = wait_for_completion_timeout( &ctrl->rxstatus_completion, msecs_to_jiffies(HDMI_SEC_TO_MS)); if (!timeout) { msecs_to_jiffies(data->timeout_ms)); if (!wait_timeout) { pr_err("sw ddc rxstatus timeout\n"); rc = -ETIMEDOUT; } data->timeout_left = jiffies_to_msecs(wait_timeout); rc = hdmi_ddc_check_status(ctrl); hdmi_hdcp2p2_ddc_disable(ctrl); Loading drivers/video/msm/mdss/mdss_hdmi_util.h +5 −1 Original line number Diff line number Diff line Loading @@ -405,6 +405,7 @@ struct hdmi_tx_ddc_data { u32 request_len; u32 no_align; u32 hard_timeout; u32 timeout_left; int retry; }; Loading @@ -416,7 +417,10 @@ enum hdmi_tx_hdcp2p2_rxstatus_intr_mask { struct hdmi_tx_hdcp2p2_ddc_data { enum hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask; u32 timer_delay_lines; u32 timeout_ms; u32 timeout_hsync; u32 periodic_timer_hsync; u32 timeout_left; u32 read_method; u32 message_size; bool encryption_ready; Loading Loading
drivers/misc/hdcp.c +9 −2 Original line number Diff line number Diff line Loading @@ -332,6 +332,7 @@ struct hdcp_lib_handle { uint32_t msglen; uint32_t tz_ctxhandle; uint32_t hdcp_timeout; uint32_t timeout_left; bool no_stored_km_flag; bool feature_supported; void *client_ctx; Loading Loading @@ -842,7 +843,11 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) mutex_lock(&handle->wakeup_mutex); handle->wakeup_cmd = data->cmd; pr_debug("%s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); handle->timeout_left = data->timeout; pr_debug("%s, timeout left: %dms\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd), handle->timeout_left); rc = hdcp_lib_check_valid_state(handle); if (rc) Loading Loading @@ -874,6 +879,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->last_msg_sent = 0; handle->hdcp_timeout = 0; handle->timeout_left = 0; atomic_set(&handle->hdcp_off, 0); handle->hdcp_state = HDCP_STATE_INIT; Loading Loading @@ -949,7 +956,7 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; cdata.timeout = handle->hdcp_timeout; cdata.timeout = handle->timeout_left; } mutex_unlock(&handle->hdcp_lock); Loading
drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +87 −34 Original line number Diff line number Diff line Loading @@ -34,11 +34,12 @@ #define HDCP_SINK_DDC_HDCP2_RXSTATUS 0x70 /* RxStatus, 2 bytes */ #define HDCP_SINK_DDC_HDCP2_READ_MESSAGE 0x80 /* HDCP Tx reads here */ #define HDCP2P2_LINK_CHECK_TIME_MS 500 /* link check within 1 sec */ #define HDCP2P2_LINK_CHECK_TIME_MS 900 /* link check within 1 sec */ #define HDCP2P2_SEC_TO_US 1000000 #define HDCP2P2_MS_TO_US 1000 #define HDCP2P2_KHZ_TO_HZ 1000 #define HDCP2P2_DEFAULT_TIMEOUT 500 /* * HDCP 2.2 encryption requires the data encryption block that is present in Loading Loading @@ -66,6 +67,7 @@ struct hdmi_hdcp2p2_ctrl { char *send_msg_buf; uint32_t send_msg_len; uint32_t timeout; uint32_t timeout_left; struct task_struct *thread; struct kthread_worker worker; Loading @@ -78,6 +80,45 @@ struct hdmi_hdcp2p2_ctrl { struct delayed_work link_check_work; }; static inline bool hdmi_hdcp2p2_is_valid_state(struct hdmi_hdcp2p2_ctrl *ctrl) { if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_AUTHENTICATE) return true; if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) return true; return false; } static int hdmi_hdcp2p2_copy_buf(struct hdmi_hdcp2p2_ctrl *ctrl, struct hdmi_hdcp_wakeup_data *data) { mutex_lock(&ctrl->msg_lock); if (!data->send_msg_len) { mutex_unlock(&ctrl->msg_lock); return 0; } ctrl->send_msg_len = data->send_msg_len; kzfree(ctrl->send_msg_buf); ctrl->send_msg_buf = kzalloc(data->send_msg_len, GFP_KERNEL); if (!ctrl->send_msg_buf) { mutex_unlock(&ctrl->msg_lock); return -ENOMEM; } memcpy(ctrl->send_msg_buf, data->send_msg_buf, ctrl->send_msg_len); mutex_unlock(&ctrl->msg_lock); return 0; } static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) { struct hdmi_hdcp2p2_ctrl *ctrl; Loading @@ -95,42 +136,34 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) mutex_lock(&ctrl->wakeup_mutex); pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); pr_debug("cmd: %s, timeout %dms\n", hdmi_hdcp_cmd_to_str(data->cmd), data->timeout); ctrl->wakeup_cmd = data->cmd; ctrl->timeout = data->timeout; mutex_lock(&ctrl->msg_lock); if (data->send_msg_len) { ctrl->send_msg_len = data->send_msg_len; kzfree(ctrl->send_msg_buf); ctrl->send_msg_buf = kzalloc( data->send_msg_len, GFP_KERNEL); if (data->timeout) ctrl->timeout = data->timeout; else ctrl->timeout = HDCP2P2_DEFAULT_TIMEOUT; if (!ctrl->send_msg_buf) { mutex_unlock(&ctrl->msg_lock); if (!hdmi_hdcp2p2_is_valid_state(ctrl)) { pr_err("invalid state\n"); goto exit; } memcpy(ctrl->send_msg_buf, data->send_msg_buf, ctrl->send_msg_len); } mutex_unlock(&ctrl->msg_lock); if (hdmi_hdcp2p2_copy_buf(ctrl, data)) goto exit; switch (ctrl->wakeup_cmd) { case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->send_msg); break; case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->recv_msg); break; case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: Loading Loading @@ -366,6 +399,7 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, pr_err("hdcp is off\n"); return -EINVAL; } memset(&ddc_data, 0, sizeof(ddc_data)); ddc_data.dev_addr = HDCP_SINK_DDC_SLAVE_ADDR; ddc_data.offset = HDCP_SINK_DDC_HDCP2_READ_MESSAGE; Loading @@ -378,9 +412,14 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; pr_debug("read msg timeout %dms\n", timeout); rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot read HDCP message register\n"); ctrl->timeout_left = ctrl->init_data.ddc_ctrl->ddc_data.timeout_left; return rc; } Loading @@ -396,6 +435,7 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.data_buf = buf; ddc_data.data_len = size; ddc_data.retry = 1; ddc_data.hard_timeout = ctrl->timeout; ddc_data.what = "HDCP2WriteMessage"; ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; Loading @@ -403,6 +443,9 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot write HDCP message register\n"); ctrl->timeout_left = ctrl->init_data.ddc_ctrl->ddc_data.timeout_left; return rc; } Loading Loading @@ -545,6 +588,7 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED; } else { cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS; cdata.timeout = ctrl->timeout_left; } exit: kzfree(msg); Loading Loading @@ -605,10 +649,13 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) lines_needed_for_given_time = (ctrl->timeout * HDCP2P2_MS_TO_US) / time_taken_by_one_line_us; pr_debug("timeout for rxstatus %d\n", lines_needed_for_given_time); pr_debug("timeout for rxstatus %dms, %d hsyncs\n", ctrl->timeout, lines_needed_for_given_time); ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->timer_delay_lines = lines_needed_for_given_time; ddc_data->timeout_ms = ctrl->timeout; ddc_data->timeout_hsync = lines_needed_for_given_time; ddc_data->periodic_timer_hsync = lines_needed_for_given_time / 20; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, true); Loading @@ -617,26 +664,30 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) goto exit; } ctrl->timeout_left = ddc_data->timeout_left; pr_debug("timeout left after rxstatus %dms, msg size %d\n", ctrl->timeout_left, ddc_data->message_size); if (!ddc_data->message_size) { pr_err("recvd invalid message size\n"); rc = -EINVAL; goto exit; } pr_debug("rxstatus msg size %d\n", ddc_data->message_size); recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL); if (!recvd_msg_buf) goto exit; rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf, ddc_data->message_size, ctrl->timeout); ddc_data->message_size, ctrl->timeout_left); if (rc) pr_err("error reading message %d\n", rc); cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; cdata.recvd_msg_buf = recvd_msg_buf; cdata.recvd_msg_len = ddc_data->message_size; cdata.timeout = ctrl->timeout_left; exit: if (rc == -ETIMEDOUT) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT; Loading Loading @@ -672,14 +723,16 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) fps = timing->refresh_rate / HDCP2P2_KHZ_TO_HZ; v_total = hdmi_tx_get_v_total(timing); time_taken_by_one_line_us = HDCP2P2_SEC_TO_US / (v_total * fps); lines_needed_for_given_time = (jiffies_to_msecs(HZ / 2) * lines_needed_for_given_time = (jiffies_to_msecs((HZ / 2) + (HZ / 4)) * HDCP2P2_MS_TO_US) / time_taken_by_one_line_us; pr_debug("timeout for rxstatus %d\n", lines_needed_for_given_time); pr_debug("timeout for rxstatus %d hsyncs\n", lines_needed_for_given_time); ddc_data->intr_mask = RXSTATUS_READY | RXSTATUS_MESSAGE_SIZE | RXSTATUS_REAUTH_REQ; ddc_data->timer_delay_lines = lines_needed_for_given_time; ddc_data->timeout_hsync = lines_needed_for_given_time; ddc_data->periodic_timer_hsync = lines_needed_for_given_time; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl, false); Loading Loading @@ -788,7 +841,7 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) } rc = hdmi_hdcp2p2_ddc_read_message(ctrl, recvd_msg_buf, ddc_data->message_size, ctrl->timeout); ddc_data->message_size, HDCP2P2_DEFAULT_TIMEOUT); if (rc) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; pr_err("error reading message %d\n", rc); Loading
drivers/video/msm/mdss/mdss_hdmi_util.c +43 −22 Original line number Diff line number Diff line Loading @@ -515,23 +515,22 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, return -EINVAL; } /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); /* wait until DDC HW is free */ timeout = 100; do { --timeout; ddc_status = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_HW_STATUS); in_use = ddc_status & (in_use_by_sw | in_use_by_hw); if (in_use) { pr_debug("ddc is in use by %s\n", ddc_status & in_use_by_sw ? "sw" : "hw"); msleep(20); udelay(100); } } while (in_use && timeout); /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); } while (in_use && --timeout); if (!timeout) { pr_err("%s: timedout\n", what); Loading Loading @@ -652,10 +651,14 @@ again: &ddc_ctrl->ddc_sw_done, wait_time); pr_debug("ddc read done at %dms\n", jiffies_to_msecs(jiffies)); ddc_data->timeout_left = jiffies_to_msecs(time_out_count); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1)); if (!time_out_count) { if (ddc_data->retry-- > 0) { pr_debug("failed timout, retry=%d\n", ddc_data->retry); if (!ddc_data->hard_timeout) goto again; } status = -ETIMEDOUT; Loading Loading @@ -809,8 +812,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) intr2 = DSS_REG_R(io, HDMI_HDCP_INT_CTRL2); intr0 = DSS_REG_R(io, HDMI_DDC_INT_CTRL0); pr_debug("INT_CTRL0 :0x%x\n", intr0); pr_debug("INT_CTRL2 :0x%x\n", intr2); pr_debug("ctl0: 0x%x, ctl1: 0x%x\n", intr0, intr2); /* check for encryption ready interrupt */ if (intr2 & BIT(2)) { Loading Loading @@ -1204,6 +1206,7 @@ int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl) int status = 0, retry = 10; u32 time_out_count; struct hdmi_tx_ddc_data *ddc_data; u32 wait_time; if (!ddc_ctrl || !ddc_ctrl->io) { pr_err("invalid input\n"); Loading Loading @@ -1286,8 +1289,19 @@ again: reinit_completion(&ddc_ctrl->ddc_sw_done); DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0)); if (ddc_data->hard_timeout) { pr_debug("using hard_timeout %dms\n", ddc_data->hard_timeout); wait_time = msecs_to_jiffies(ddc_data->hard_timeout); } else { wait_time = HZ/2; } pr_debug("timeout for ddc write %d jiffies\n", wait_time); time_out_count = wait_for_completion_timeout( &ddc_ctrl->ddc_sw_done, HZ/2); &ddc_ctrl->ddc_sw_done, wait_time); ddc_data->timeout_left = jiffies_to_msecs(time_out_count); pr_debug("DDC write done at %dms\n", jiffies_to_msecs(jiffies)); Loading @@ -1297,6 +1311,8 @@ again: if (retry-- > 0) { pr_debug("%s: failed timout, retry=%d\n", ddc_data->what, retry); if (!ddc_data->hard_timeout) goto again; } status = -ETIMEDOUT; Loading Loading @@ -1635,6 +1651,7 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) u32 reg_val; u32 intr_en_mask; u32 timeout; u32 timer; int rc = 0; struct hdmi_tx_hdcp2p2_ddc_data *data; Loading Loading @@ -1674,9 +1691,11 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) * 3. DDC_TIMEOUT_TIMER: Timeout in hsyncs which starts counting when * a request is made and stops when it is accepted by DDC arbiter */ timeout = data->timer_delay_lines; pr_debug("timeout: %d\n", timeout); DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timeout); timeout = data->timeout_hsync; timer = data->periodic_timer_hsync; pr_debug("timeout: %d hsyncs, timer %d hsync\n", timeout, timer); DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL, timer); /* Set both urgent and hw-timeout fields to the same value */ DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_TIMER_CTRL2, Loading Loading @@ -1711,8 +1730,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) reg_val = DSS_REG_R(ctrl->io, HDMI_HW_DDC_CTRL); reg_val &= ~(BIT(1) | BIT(0)); pr_debug("data->read_method %d\n", data->read_method); if (data->read_method == HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER) reg_val |= BIT(1) | BIT(0); else Loading @@ -1725,16 +1742,20 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl, bool wait) DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_SW_TRIGGER, 1); if (wait) { u32 wait_timeout; reinit_completion(&ctrl->rxstatus_completion); /* max timeout as per hdcp 2.2 std is 1 sec */ timeout = wait_for_completion_timeout( wait_timeout = wait_for_completion_timeout( &ctrl->rxstatus_completion, msecs_to_jiffies(HDMI_SEC_TO_MS)); if (!timeout) { msecs_to_jiffies(data->timeout_ms)); if (!wait_timeout) { pr_err("sw ddc rxstatus timeout\n"); rc = -ETIMEDOUT; } data->timeout_left = jiffies_to_msecs(wait_timeout); rc = hdmi_ddc_check_status(ctrl); hdmi_hdcp2p2_ddc_disable(ctrl); Loading
drivers/video/msm/mdss/mdss_hdmi_util.h +5 −1 Original line number Diff line number Diff line Loading @@ -405,6 +405,7 @@ struct hdmi_tx_ddc_data { u32 request_len; u32 no_align; u32 hard_timeout; u32 timeout_left; int retry; }; Loading @@ -416,7 +417,10 @@ enum hdmi_tx_hdcp2p2_rxstatus_intr_mask { struct hdmi_tx_hdcp2p2_ddc_data { enum hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask; u32 timer_delay_lines; u32 timeout_ms; u32 timeout_hsync; u32 periodic_timer_hsync; u32 timeout_left; u32 read_method; u32 message_size; bool encryption_ready; Loading