Loading drivers/misc/hdcp.c +48 −7 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -354,6 +354,7 @@ struct hdcp_lib_handle { enum hdcp_state hdcp_state; enum hdcp_lib_wakeup_cmd wakeup_cmd; bool repeater_flag; bool update_stream; bool tethered; struct qseecom_handle *qseecom_handle; int last_msg_sent; Loading Loading @@ -703,11 +704,17 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle) struct hdcp_query_stream_type_req *req_buf; struct hdcp_query_stream_type_rsp *rsp_buf; if (!handle) { if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } /* send command to TZ */ req_buf = (struct hdcp_query_stream_type_req *)handle-> qseecom_handle->sbuf; Loading Loading @@ -837,12 +844,12 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle) } } else { if (atomic_read(&handle->hdcp_off)) { pr_warn("hdcp2.2 session tearing down\n"); pr_debug("hdcp2.2 session tearing down\n"); goto exit; } if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_warn("hdcp 2.2 app not loaded\n"); pr_debug("hdcp 2.2 app not loaded\n"); goto exit; } } Loading Loading @@ -921,7 +928,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) switch (handle->wakeup_cmd) { case HDCP_LIB_WKUP_CMD_START: handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->repeater_flag = false; handle->update_stream = false; handle->last_msg_sent = 0; handle->hdcp_timeout = 0; handle->timeout_left = 0; Loading Loading @@ -983,6 +991,10 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) if (!hdcp_lib_enable_encryption(handle)) { cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; hdcp_lib_wakeup_client(handle, &cdata); /* poll for link check */ cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; } else { if (!atomic_read(&handle->hdcp_off)) HDCP_LIB_EXECUTE(clean); Loading @@ -990,6 +1002,13 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) break; case REPEATER_AUTH_SEND_ACK_MESSAGE_ID: pr_debug("Repeater authentication successful\n"); if (handle->update_stream) { HDCP_LIB_EXECUTE(stream); handle->update_stream = false; } else { cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; } break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; Loading Loading @@ -1060,6 +1079,17 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) return; } if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_debug("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } req_buf = (struct hdcp_send_timeout_req *) (handle->qseecom_handle->sbuf); req_buf->commandid = HDCP_TXMTR_SEND_MESSAGE_TIMEOUT; Loading Loading @@ -1105,6 +1135,8 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) hdcp_lib_send_message(handle); } } return; error: if (!atomic_read(&handle->hdcp_off)) HDCP_LIB_EXECUTE(clean); Loading Loading @@ -1157,11 +1189,17 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) uint32_t msglen; char *msg; if (!handle) { if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } cdata.context = handle->client_ctx; mutex_lock(&handle->msg_lock); Loading Loading @@ -1222,6 +1260,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) if ((msg[0] == REPEATER_AUTH_STREAM_READY_MESSAGE_ID) && (rc == 0) && (rsp_buf->status == 0)) { pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n"); cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; goto exit; } Loading Loading @@ -1252,7 +1292,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) if ((rsp_buf->flag == HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) && (rsp_buf->timeout > 0)) handle->repeater_flag = 1; handle->repeater_flag = true; handle->update_stream = true; } memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); Loading drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +56 −36 Original line number Diff line number Diff line /* Copyright (c) 2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -34,8 +34,6 @@ #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 900 /* link check within 1 sec */ #define HDCP2P2_DEFAULT_TIMEOUT 500 /* Loading Loading @@ -74,12 +72,14 @@ struct hdmi_hdcp2p2_ctrl { struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct kthread_work poll; }; static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_send_msg(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl); static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl); static inline bool hdmi_hdcp2p2_is_valid_state(struct hdmi_hdcp2p2_ctrl *ctrl) { Loading Loading @@ -144,7 +144,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) ctrl->wakeup_cmd = data->cmd; if (data->timeout) ctrl->timeout = data->timeout; ctrl->timeout = data->timeout * 2; else ctrl->timeout = HDCP2P2_DEFAULT_TIMEOUT; Loading @@ -170,6 +170,9 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_LINK_POLL: queue_kthread_work(&ctrl->worker, &ctrl->poll); break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: queue_kthread_work(&ctrl->worker, &ctrl->auth); break; Loading @@ -186,9 +189,6 @@ static inline int hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl, { int rc = 0; if (ctrl) ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; if (ctrl && ctrl->lib && ctrl->lib->wakeup && data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) { rc = ctrl->lib->wakeup(data); Loading @@ -210,16 +210,20 @@ static void hdmi_hdcp2p2_run(struct hdmi_hdcp2p2_ctrl *ctrl) while (1) { switch (ctrl->wakeup_cmd) { case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; hdmi_hdcp2p2_send_msg(ctrl); break; case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; hdmi_hdcp2p2_recv_msg(ctrl); break; case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: hdmi_hdcp2p2_auth_status(ctrl); goto exit; case HDMI_HDCP_WKUP_CMD_LINK_POLL: hdmi_hdcp2p2_link_check(ctrl); goto exit; default: goto exit; } Loading Loading @@ -726,6 +730,19 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) hdmi_hdcp2p2_send_msg(ctrl); } static void hdmi_hdcp2p2_link_cb(void *data) { struct hdmi_hdcp2p2_ctrl *ctrl = data; if (!ctrl) { pr_debug("invalid input\n"); return; } if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) { int rc, timeout_hsync; Loading Loading @@ -770,7 +787,7 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) pr_debug("timeout for rxstatus %dms, %d hsync\n", ctrl->timeout, timeout_hsync); ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE | RXSTATUS_REAUTH_REQ; ddc_data->timeout_ms = ctrl->timeout; ddc_data->timeout_hsync = timeout_hsync; ddc_data->periodic_timer_hsync = timeout_hsync / 20; Loading @@ -783,6 +800,14 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) goto exit; } if (ddc_data->reauth_req) { ddc_data->reauth_req = false; pr_debug("reauth triggered by sink\n"); rc = -EINVAL; goto exit; } ctrl->timeout_left = ddc_data->timeout_left; pr_debug("timeout left after rxstatus %dms, msg size %d\n", Loading Loading @@ -817,7 +842,6 @@ exit: else if (rc) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED; hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); kfree(recvd_msg_buf); } Loading @@ -830,19 +854,6 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) hdmi_hdcp2p2_recv_msg(ctrl); } static void hdmi_hdcp2p2_link_cb(void *data) { struct hdmi_hdcp2p2_ctrl *ctrl = data; if (!ctrl) { pr_err("invalid input\n"); return; } if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) { struct hdmi_tx_ddc_ctrl *ddc_ctrl; Loading @@ -860,8 +871,7 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) memset(ddc_data, 0, sizeof(*ddc_data)); timeout_hsync = hdmi_utils_get_timeout_in_hysnc( ctrl->init_data.timing, jiffies_to_msecs((HZ / 2) + (HZ / 4))); ctrl->init_data.timing, jiffies_to_msecs(HZ / 2)); if (timeout_hsync <= 0) { pr_err("err in timeout hsync calc\n"); Loading @@ -880,6 +890,14 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); } static void hdmi_hdcp2p2_poll_work(struct kthread_work *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, poll); hdmi_hdcp2p2_link_check(ctrl); } static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl) { if (!ctrl) { Loading @@ -898,6 +916,9 @@ static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl) ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTHENTICATED); atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); if (ctrl->tethered) hdmi_hdcp2p2_link_check(ctrl); } } Loading Loading @@ -934,16 +955,12 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) goto exit; } rc = hdmi_hdcp2p2_ddc_check_status(ddc_ctrl); if (rc) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; goto exit; } ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; if (ddc_data->reauth_req) { pr_debug("sync reported loss of synchronization, reauth\n"); pr_debug("reauth triggered by sink\n"); ddc_data->reauth_req = false; rc = -ENOLINK; cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; goto exit; Loading @@ -953,6 +970,8 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) pr_debug("topology changed. rxstatus msg size %d\n", ddc_data->message_size); ddc_data->ready = false; recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL); if (!recvd_msg_buf) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; Loading @@ -968,9 +987,9 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; cdata.recvd_msg_buf = recvd_msg_buf; cdata.recvd_msg_len = ddc_data->message_size; hdmi_hdcp2p2_link_check(ctrl); } ddc_data->message_size = 0; } exit: hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); Loading Loading @@ -1117,6 +1136,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) init_kthread_work(&ctrl->recv_msg, hdmi_hdcp2p2_recv_msg_work); init_kthread_work(&ctrl->status, hdmi_hdcp2p2_auth_status_work); init_kthread_work(&ctrl->link, hdmi_hdcp2p2_link_work); init_kthread_work(&ctrl->poll, hdmi_hdcp2p2_poll_work); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "hdmi_hdcp2p2"); Loading drivers/video/msm/mdss/mdss_hdmi_util.c +11 −29 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -65,8 +65,6 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 ddc_int_ctrl, ddc_status, in_use, timeout; u32 sw_done_mask = BIT(2); u32 sw_done_ack = BIT(1); u32 hw_done_mask = BIT(6); u32 hw_done_ack = BIT(5); u32 in_use_by_sw = BIT(0); u32 in_use_by_hw = BIT(1); Loading @@ -76,7 +74,7 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, } /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; ddc_int_ctrl = sw_done_mask | sw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); Loading Loading @@ -871,46 +869,39 @@ void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl) DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (19 << 0)); } /* hdmi_ddc_config */ int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl) static void hdmi_hdcp2p2_ddc_clear_status(struct hdmi_tx_ddc_ctrl *ctrl) { int rc = 0; u32 reg_val; if (!ctrl) { pr_err("invalid ddc ctrl\n"); return -EINVAL; return; } /* check for errors and clear status */ reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_STATUS); if (reg_val & BIT(4)) { pr_err("ddc aborted\n"); pr_debug("ddc aborted\n"); reg_val |= BIT(5); rc = -ECONNABORTED; } if (reg_val & BIT(8)) { pr_err("timed out\n"); pr_debug("timed out\n"); reg_val |= BIT(9); rc = -ETIMEDOUT; } if (reg_val & BIT(12)) { pr_err("NACK0\n"); pr_debug("NACK0\n"); reg_val |= BIT(13); rc = -EIO; } if (reg_val & BIT(14)) { pr_err("NACK1\n"); pr_debug("NACK1\n"); reg_val |= BIT(15); rc = -EIO; } DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_STATUS, reg_val); return rc; } static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) Loading Loading @@ -987,15 +978,6 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) data->ready = true; } /* check and disable not ready interrupt */ if (intr0 & BIT(15)) { /* ack ready/not ready interrupt */ intr0 |= BIT(17); intr0 &= ~BIT(19); data->ready = false; } /* check for reauth req interrupt */ if (intr0 & BIT(12)) { /* ack and disable reauth req interrupt */ Loading Loading @@ -1053,6 +1035,8 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) } } hdmi_hdcp2p2_ddc_clear_status(ddc_ctrl); return rc; } Loading Loading @@ -1641,7 +1625,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) intr_en_mask = data->intr_mask; intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK); intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_DONE); /* Disable short read for now, sinks don't support it */ reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_CTRL); Loading Loading @@ -1675,7 +1658,7 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) /* Clear interrupt status bits */ reg_val |= intr_en_mask >> 1; pr_debug("writng HDMI_DDC_INT_CTRL0 0x%x\n", reg_val); pr_debug("writing HDMI_DDC_INT_CTRL0 0x%x\n", reg_val); DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val); reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL5); Loading Loading @@ -1730,7 +1713,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) rc = -ETIMEDOUT; } rc = hdmi_hdcp2p2_ddc_check_status(ctrl); hdmi_hdcp2p2_ddc_disable(ctrl); } Loading drivers/video/msm/mdss/mdss_hdmi_util.h +1 −2 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -504,7 +504,6 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl, u32 type, u32 to_in_num_lines); void hdmi_scrambler_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl); void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing, u32 timeout_ms); Loading include/linux/hdcp_qseecom.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -32,6 +32,7 @@ enum hdmi_hdcp_wakeup_cmd { HDMI_HDCP_WKUP_CMD_RECV_MESSAGE, HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS, HDMI_HDCP_WKUP_CMD_STATUS_FAILED, HDMI_HDCP_WKUP_CMD_LINK_POLL, HDMI_HDCP_WKUP_CMD_AUTHENTICATE }; Loading Loading @@ -62,6 +63,8 @@ static inline char *hdmi_hdcp_cmd_to_str(uint32_t cmd) return "HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS"; case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: return "HDMI_HDCP_WKUP_CMD_STATUS_FAIL"; case HDMI_HDCP_WKUP_CMD_LINK_POLL: return "HDMI_HDCP_WKUP_CMD_LINK_POLL"; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: return "HDMI_HDCP_WKUP_CMD_AUTHENTICATE"; default: Loading Loading
drivers/misc/hdcp.c +48 −7 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -354,6 +354,7 @@ struct hdcp_lib_handle { enum hdcp_state hdcp_state; enum hdcp_lib_wakeup_cmd wakeup_cmd; bool repeater_flag; bool update_stream; bool tethered; struct qseecom_handle *qseecom_handle; int last_msg_sent; Loading Loading @@ -703,11 +704,17 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle) struct hdcp_query_stream_type_req *req_buf; struct hdcp_query_stream_type_rsp *rsp_buf; if (!handle) { if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } /* send command to TZ */ req_buf = (struct hdcp_query_stream_type_req *)handle-> qseecom_handle->sbuf; Loading Loading @@ -837,12 +844,12 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle) } } else { if (atomic_read(&handle->hdcp_off)) { pr_warn("hdcp2.2 session tearing down\n"); pr_debug("hdcp2.2 session tearing down\n"); goto exit; } if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_warn("hdcp 2.2 app not loaded\n"); pr_debug("hdcp 2.2 app not loaded\n"); goto exit; } } Loading Loading @@ -921,7 +928,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) switch (handle->wakeup_cmd) { case HDCP_LIB_WKUP_CMD_START: handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->repeater_flag = false; handle->update_stream = false; handle->last_msg_sent = 0; handle->hdcp_timeout = 0; handle->timeout_left = 0; Loading Loading @@ -983,6 +991,10 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) if (!hdcp_lib_enable_encryption(handle)) { cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; hdcp_lib_wakeup_client(handle, &cdata); /* poll for link check */ cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; } else { if (!atomic_read(&handle->hdcp_off)) HDCP_LIB_EXECUTE(clean); Loading @@ -990,6 +1002,13 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) break; case REPEATER_AUTH_SEND_ACK_MESSAGE_ID: pr_debug("Repeater authentication successful\n"); if (handle->update_stream) { HDCP_LIB_EXECUTE(stream); handle->update_stream = false; } else { cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; } break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; Loading Loading @@ -1060,6 +1079,17 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) return; } if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_debug("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } req_buf = (struct hdcp_send_timeout_req *) (handle->qseecom_handle->sbuf); req_buf->commandid = HDCP_TXMTR_SEND_MESSAGE_TIMEOUT; Loading Loading @@ -1105,6 +1135,8 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) hdcp_lib_send_message(handle); } } return; error: if (!atomic_read(&handle->hdcp_off)) HDCP_LIB_EXECUTE(clean); Loading Loading @@ -1157,11 +1189,17 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) uint32_t msglen; char *msg; if (!handle) { if (!handle && !handle->qseecom_handle && !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } if (atomic_read(&handle->hdcp_off)) { pr_debug("invalid state, hdcp off\n"); return; } cdata.context = handle->client_ctx; mutex_lock(&handle->msg_lock); Loading Loading @@ -1222,6 +1260,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) if ((msg[0] == REPEATER_AUTH_STREAM_READY_MESSAGE_ID) && (rc == 0) && (rsp_buf->status == 0)) { pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n"); cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; goto exit; } Loading Loading @@ -1252,7 +1292,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) if ((rsp_buf->flag == HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) && (rsp_buf->timeout > 0)) handle->repeater_flag = 1; handle->repeater_flag = true; handle->update_stream = true; } memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); Loading
drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +56 −36 Original line number Diff line number Diff line /* Copyright (c) 2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -34,8 +34,6 @@ #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 900 /* link check within 1 sec */ #define HDCP2P2_DEFAULT_TIMEOUT 500 /* Loading Loading @@ -74,12 +72,14 @@ struct hdmi_hdcp2p2_ctrl { struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct kthread_work poll; }; static int hdmi_hdcp2p2_auth(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_send_msg(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl); static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl); static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl); static inline bool hdmi_hdcp2p2_is_valid_state(struct hdmi_hdcp2p2_ctrl *ctrl) { Loading Loading @@ -144,7 +144,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) ctrl->wakeup_cmd = data->cmd; if (data->timeout) ctrl->timeout = data->timeout; ctrl->timeout = data->timeout * 2; else ctrl->timeout = HDCP2P2_DEFAULT_TIMEOUT; Loading @@ -170,6 +170,9 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_LINK_POLL: queue_kthread_work(&ctrl->worker, &ctrl->poll); break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: queue_kthread_work(&ctrl->worker, &ctrl->auth); break; Loading @@ -186,9 +189,6 @@ static inline int hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl, { int rc = 0; if (ctrl) ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; if (ctrl && ctrl->lib && ctrl->lib->wakeup && data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) { rc = ctrl->lib->wakeup(data); Loading @@ -210,16 +210,20 @@ static void hdmi_hdcp2p2_run(struct hdmi_hdcp2p2_ctrl *ctrl) while (1) { switch (ctrl->wakeup_cmd) { case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; hdmi_hdcp2p2_send_msg(ctrl); break; case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: ctrl->wakeup_cmd = HDMI_HDCP_WKUP_CMD_INVALID; hdmi_hdcp2p2_recv_msg(ctrl); break; case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: hdmi_hdcp2p2_auth_status(ctrl); goto exit; case HDMI_HDCP_WKUP_CMD_LINK_POLL: hdmi_hdcp2p2_link_check(ctrl); goto exit; default: goto exit; } Loading Loading @@ -726,6 +730,19 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work) hdmi_hdcp2p2_send_msg(ctrl); } static void hdmi_hdcp2p2_link_cb(void *data) { struct hdmi_hdcp2p2_ctrl *ctrl = data; if (!ctrl) { pr_debug("invalid input\n"); return; } if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) { int rc, timeout_hsync; Loading Loading @@ -770,7 +787,7 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) pr_debug("timeout for rxstatus %dms, %d hsync\n", ctrl->timeout, timeout_hsync); ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE | RXSTATUS_REAUTH_REQ; ddc_data->timeout_ms = ctrl->timeout; ddc_data->timeout_hsync = timeout_hsync; ddc_data->periodic_timer_hsync = timeout_hsync / 20; Loading @@ -783,6 +800,14 @@ static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl) goto exit; } if (ddc_data->reauth_req) { ddc_data->reauth_req = false; pr_debug("reauth triggered by sink\n"); rc = -EINVAL; goto exit; } ctrl->timeout_left = ddc_data->timeout_left; pr_debug("timeout left after rxstatus %dms, msg size %d\n", Loading Loading @@ -817,7 +842,6 @@ exit: else if (rc) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED; hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); kfree(recvd_msg_buf); } Loading @@ -830,19 +854,6 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) hdmi_hdcp2p2_recv_msg(ctrl); } static void hdmi_hdcp2p2_link_cb(void *data) { struct hdmi_hdcp2p2_ctrl *ctrl = data; if (!ctrl) { pr_err("invalid input\n"); return; } if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) { struct hdmi_tx_ddc_ctrl *ddc_ctrl; Loading @@ -860,8 +871,7 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) memset(ddc_data, 0, sizeof(*ddc_data)); timeout_hsync = hdmi_utils_get_timeout_in_hysnc( ctrl->init_data.timing, jiffies_to_msecs((HZ / 2) + (HZ / 4))); ctrl->init_data.timing, jiffies_to_msecs(HZ / 2)); if (timeout_hsync <= 0) { pr_err("err in timeout hsync calc\n"); Loading @@ -880,6 +890,14 @@ static int hdmi_hdcp2p2_link_check(struct hdmi_hdcp2p2_ctrl *ctrl) return hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); } static void hdmi_hdcp2p2_poll_work(struct kthread_work *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, poll); hdmi_hdcp2p2_link_check(ctrl); } static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl) { if (!ctrl) { Loading @@ -898,6 +916,9 @@ static void hdmi_hdcp2p2_auth_status(struct hdmi_hdcp2p2_ctrl *ctrl) ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTHENTICATED); atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); if (ctrl->tethered) hdmi_hdcp2p2_link_check(ctrl); } } Loading Loading @@ -934,16 +955,12 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) goto exit; } rc = hdmi_hdcp2p2_ddc_check_status(ddc_ctrl); if (rc) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; goto exit; } ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; if (ddc_data->reauth_req) { pr_debug("sync reported loss of synchronization, reauth\n"); pr_debug("reauth triggered by sink\n"); ddc_data->reauth_req = false; rc = -ENOLINK; cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; goto exit; Loading @@ -953,6 +970,8 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) pr_debug("topology changed. rxstatus msg size %d\n", ddc_data->message_size); ddc_data->ready = false; recvd_msg_buf = kzalloc(ddc_data->message_size, GFP_KERNEL); if (!recvd_msg_buf) { cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; Loading @@ -968,9 +987,9 @@ static void hdmi_hdcp2p2_link_work(struct kthread_work *work) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS; cdata.recvd_msg_buf = recvd_msg_buf; cdata.recvd_msg_len = ddc_data->message_size; hdmi_hdcp2p2_link_check(ctrl); } ddc_data->message_size = 0; } exit: hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); Loading Loading @@ -1117,6 +1136,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) init_kthread_work(&ctrl->recv_msg, hdmi_hdcp2p2_recv_msg_work); init_kthread_work(&ctrl->status, hdmi_hdcp2p2_auth_status_work); init_kthread_work(&ctrl->link, hdmi_hdcp2p2_link_work); init_kthread_work(&ctrl->poll, hdmi_hdcp2p2_poll_work); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "hdmi_hdcp2p2"); Loading
drivers/video/msm/mdss/mdss_hdmi_util.c +11 −29 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -65,8 +65,6 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, u32 ddc_int_ctrl, ddc_status, in_use, timeout; u32 sw_done_mask = BIT(2); u32 sw_done_ack = BIT(1); u32 hw_done_mask = BIT(6); u32 hw_done_ack = BIT(5); u32 in_use_by_sw = BIT(0); u32 in_use_by_hw = BIT(1); Loading @@ -76,7 +74,7 @@ static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl, } /* clear and enable interrutps */ ddc_int_ctrl = sw_done_mask | sw_done_ack | hw_done_mask | hw_done_ack; ddc_int_ctrl = sw_done_mask | sw_done_ack; DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, ddc_int_ctrl); Loading Loading @@ -871,46 +869,39 @@ void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl) DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (19 << 0)); } /* hdmi_ddc_config */ int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl) static void hdmi_hdcp2p2_ddc_clear_status(struct hdmi_tx_ddc_ctrl *ctrl) { int rc = 0; u32 reg_val; if (!ctrl) { pr_err("invalid ddc ctrl\n"); return -EINVAL; return; } /* check for errors and clear status */ reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_STATUS); if (reg_val & BIT(4)) { pr_err("ddc aborted\n"); pr_debug("ddc aborted\n"); reg_val |= BIT(5); rc = -ECONNABORTED; } if (reg_val & BIT(8)) { pr_err("timed out\n"); pr_debug("timed out\n"); reg_val |= BIT(9); rc = -ETIMEDOUT; } if (reg_val & BIT(12)) { pr_err("NACK0\n"); pr_debug("NACK0\n"); reg_val |= BIT(13); rc = -EIO; } if (reg_val & BIT(14)) { pr_err("NACK1\n"); pr_debug("NACK1\n"); reg_val |= BIT(15); rc = -EIO; } DSS_REG_W(ctrl->io, HDMI_HDCP2P2_DDC_STATUS, reg_val); return rc; } static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) Loading Loading @@ -987,15 +978,6 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) data->ready = true; } /* check and disable not ready interrupt */ if (intr0 & BIT(15)) { /* ack ready/not ready interrupt */ intr0 |= BIT(17); intr0 &= ~BIT(19); data->ready = false; } /* check for reauth req interrupt */ if (intr0 & BIT(12)) { /* ack and disable reauth req interrupt */ Loading Loading @@ -1053,6 +1035,8 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) } } hdmi_hdcp2p2_ddc_clear_status(ddc_ctrl); return rc; } Loading Loading @@ -1641,7 +1625,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) intr_en_mask = data->intr_mask; intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_FAILED_INTR_MASK); intr_en_mask |= BIT(HDCP2P2_RXSTATUS_DDC_DONE); /* Disable short read for now, sinks don't support it */ reg_val = DSS_REG_R(ctrl->io, HDMI_HDCP2P2_DDC_CTRL); Loading Loading @@ -1675,7 +1658,7 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) /* Clear interrupt status bits */ reg_val |= intr_en_mask >> 1; pr_debug("writng HDMI_DDC_INT_CTRL0 0x%x\n", reg_val); pr_debug("writing HDMI_DDC_INT_CTRL0 0x%x\n", reg_val); DSS_REG_W(ctrl->io, HDMI_DDC_INT_CTRL0, reg_val); reg_val = DSS_REG_R(ctrl->io, HDMI_DDC_INT_CTRL5); Loading Loading @@ -1730,7 +1713,6 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl) rc = -ETIMEDOUT; } rc = hdmi_hdcp2p2_ddc_check_status(ctrl); hdmi_hdcp2p2_ddc_disable(ctrl); } Loading
drivers/video/msm/mdss/mdss_hdmi_util.h +1 −2 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -504,7 +504,6 @@ int hdmi_setup_ddc_timers(struct hdmi_tx_ddc_ctrl *ctrl, u32 type, u32 to_in_num_lines); void hdmi_scrambler_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl); void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_hdcp2p2_ddc_check_status(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl); int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing, u32 timeout_ms); Loading
include/linux/hdcp_qseecom.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -32,6 +32,7 @@ enum hdmi_hdcp_wakeup_cmd { HDMI_HDCP_WKUP_CMD_RECV_MESSAGE, HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS, HDMI_HDCP_WKUP_CMD_STATUS_FAILED, HDMI_HDCP_WKUP_CMD_LINK_POLL, HDMI_HDCP_WKUP_CMD_AUTHENTICATE }; Loading Loading @@ -62,6 +63,8 @@ static inline char *hdmi_hdcp_cmd_to_str(uint32_t cmd) return "HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS"; case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: return "HDMI_HDCP_WKUP_CMD_STATUS_FAIL"; case HDMI_HDCP_WKUP_CMD_LINK_POLL: return "HDMI_HDCP_WKUP_CMD_LINK_POLL"; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: return "HDMI_HDCP_WKUP_CMD_AUTHENTICATE"; default: Loading