Loading drivers/misc/hdcp.c +108 −56 Original line number Diff line number Diff line Loading @@ -333,9 +333,11 @@ struct hdcp_lib_handle { uint32_t tz_ctxhandle; uint32_t hdcp_timeout; bool no_stored_km_flag; bool feature_supported; void *client_ctx; struct hdcp_client_ops *client_ops; struct mutex hdcp_lock; struct mutex wakeup_mutex; enum hdcp_state hdcp_state; enum hdcp_lib_wakeup_cmd wakeup_cmd; bool repeater_flag; Loading @@ -343,9 +345,10 @@ struct hdcp_lib_handle { int last_msg_sent; char *last_msg_recvd_buf; uint32_t last_msg_recvd_len; atomic_t hdcp_off_pending; atomic_t hdcp_off; struct task_struct *thread; struct completion topo_wait; struct kthread_worker worker; struct kthread_work init; Loading @@ -353,6 +356,8 @@ struct hdcp_lib_handle { struct kthread_work msg_recvd; struct kthread_work timeout; struct kthread_work clean; struct kthread_work topology; struct kthread_work stream; }; struct hdcp_lib_message_map { Loading Loading @@ -456,7 +461,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) pr_debug("success\n"); return 0; error: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); return rc; Loading Loading @@ -668,30 +673,20 @@ exit: return rc; } static int hdcp_lib_query_stream_type(void *phdcpcontext) static void hdcp_lib_query_stream_type_work(struct kthread_work *work) { int rc = 0; struct hdcp_query_stream_type_req *req_buf; struct hdcp_query_stream_type_rsp *rsp_buf; struct hdcp_lib_handle *handle = phdcpcontext; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, stream); if (!handle) { pr_err("invalid input\n"); return -EINVAL; } if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_debug("hdcp library not loaded\n"); goto exit; } if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) { pr_err("txmtr is not initialized\n"); rc = -EINVAL; goto exit; pr_err("invalid handle\n"); return; } flush_kthread_worker(&handle->worker); mutex_lock(&handle->hdcp_lock); /* send command to TZ */ req_buf = (struct hdcp_query_stream_type_req *)handle-> Loading @@ -715,7 +710,7 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext) goto exit; } pr_debug("message received is %s\n", pr_debug("message received from TZ: %s\n", hdcp_lib_message_name((int)rsp_buf->msg[0])); memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); Loading @@ -723,15 +718,11 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext) rsp_buf->msglen); handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; exit: mutex_unlock(&handle->hdcp_lock); if (!atomic_read(&handle->hdcp_off_pending)) if (!rc && !atomic_read(&handle->hdcp_off)) hdcp_lib_send_message(handle); else goto exit; pr_debug("success\n"); exit: return rc; } static bool hdcp_lib_client_feature_supported(void *phdcpcontext) Loading @@ -745,9 +736,15 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext) goto exit; } if (handle->feature_supported) { supported = true; goto exit; } rc = hdcp_lib_library_load(handle); if (!rc) { pr_debug("HDCP2p2 supported\n"); handle->feature_supported = true; hdcp_lib_library_unload(handle); supported = true; } Loading @@ -767,9 +764,11 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) if (!handle) return -EINVAL; mutex_lock(&handle->wakeup_mutex); handle->wakeup_cmd = data->cmd; pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); if (data->recvd_msg_len) { handle->last_msg_recvd_len = data->recvd_msg_len; Loading @@ -785,42 +784,51 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) data->recvd_msg_len); } if (!completion_done(&handle->topo_wait)) complete_all(&handle->topo_wait); switch (handle->wakeup_cmd) { case HDCP_LIB_WKUP_CMD_START: handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->last_msg_sent = 0; atomic_set(&handle->hdcp_off, 0); handle->hdcp_state = HDCP_STATE_INIT; if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->init); break; case HDCP_LIB_WKUP_CMD_STOP: atomic_set(&handle->hdcp_off_pending, 1); atomic_set(&handle->hdcp_off, 1); queue_kthread_work(&handle->worker, &handle->clean); break; case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS: handle->last_msg_sent = handle->listener_buf[0]; if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->msg_sent); break; case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED: case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); break; case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->msg_recvd); break; case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->timeout); break; case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE: if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->stream); break; default: pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); } exit: mutex_unlock(&handle->wakeup_mutex); return 0; } Loading @@ -835,28 +843,41 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) return; } if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); return; } mutex_lock(&handle->hdcp_lock); cdata.context = handle->client_ctx; if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { if (handle->last_msg_sent == SKE_SEND_EKS_MESSAGE_ID) { switch (handle->last_msg_sent) { case SKE_SEND_EKS_MESSAGE_ID: if (handle->repeater_flag) { if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->topology); } if (!hdcp_lib_enable_encryption(handle)) cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; else cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED; } else { if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); break; case REPEATER_AUTH_SEND_ACK_MESSAGE_ID: pr_debug("Repeater authentication successful\n"); break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; cdata.timeout = handle->hdcp_timeout; } } else { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); } mutex_unlock(&handle->hdcp_lock); hdcp_lib_wakeup_client(handle, &cdata); return; } static void hdcp_lib_init_work(struct kthread_work *work) Loading Loading @@ -900,7 +921,7 @@ exit: if (send_msg) hdcp_lib_send_message(handle); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); return; } Loading Loading @@ -954,7 +975,7 @@ static void hdcp_lib_manage_timeout_work(struct kthread_work *work) if ((rsp_buf->commandid == HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) && ((int)rsp_buf->message[0] == LC_INIT_MESSAGE_ID) && (rsp_buf->msglen == LC_INIT_MESSAGE_SIZE)) { if (!atomic_read(&handle->hdcp_off_pending)) { if (!atomic_read(&handle->hdcp_off)) { /* keep local copy of TZ response */ memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, Loading @@ -972,7 +993,7 @@ error: if (send_msg) hdcp_lib_send_message(handle); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } Loading @@ -997,10 +1018,10 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work) mutex_unlock(&handle->hdcp_lock); if (atomic_read(&handle->hdcp_off_pending)) atomic_set(&handle->hdcp_off_pending, 0); else if (!atomic_read(&handle->hdcp_off)) hdcp_lib_wakeup_client(handle, &cdata); atomic_set(&handle->hdcp_off, 1); } static void hdcp_lib_msg_recvd_work(struct kthread_work *work) Loading Loading @@ -1108,7 +1129,7 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; if (!atomic_read(&handle->hdcp_off_pending)) { if (!atomic_read(&handle->hdcp_off)) { cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE; cdata.send_msg_buf = handle->listener_buf; cdata.send_msg_len = handle->msglen; Loading @@ -1121,10 +1142,36 @@ exit: hdcp_lib_wakeup_client(handle, &cdata); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } static void hdcp_lib_topology_work(struct kthread_work *work) { u32 timeout; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, topology); struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; if (!handle) { pr_err("invalid input\n"); return; } cdata.context = handle->client_ctx; cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; hdcp_lib_wakeup_client(handle, &cdata); reinit_completion(&handle->topo_wait); timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3); if (!timeout) { pr_err("topology receiver id list timeout\n"); if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } } /* APIs exposed to all clients */ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) { Loading Loading @@ -1204,7 +1251,6 @@ int hdcp_library_register(void **pphdcpcontext, /* populate ops to be called by client */ txmtr_ops->feature_supported = hdcp_lib_client_feature_supported; txmtr_ops->wakeup = hdcp_lib_wakeup; txmtr_ops->hdcp_query_stream_type = hdcp_lib_query_stream_type; handle = kzalloc(sizeof(*handle), GFP_KERNEL); if (!handle) { Loading @@ -1215,9 +1261,10 @@ int hdcp_library_register(void **pphdcpcontext, handle->client_ctx = client_ctx; handle->client_ops = client_ops; atomic_set(&handle->hdcp_off_pending, 0); atomic_set(&handle->hdcp_off, 0); mutex_init(&handle->hdcp_lock); mutex_init(&handle->wakeup_mutex); init_kthread_worker(&handle->worker); Loading @@ -1226,6 +1273,10 @@ int hdcp_library_register(void **pphdcpcontext, init_kthread_work(&handle->msg_recvd, hdcp_lib_msg_recvd_work); init_kthread_work(&handle->timeout, hdcp_lib_manage_timeout_work); init_kthread_work(&handle->clean, hdcp_lib_cleanup_work); init_kthread_work(&handle->topology, hdcp_lib_topology_work); init_kthread_work(&handle->stream, hdcp_lib_query_stream_type_work); init_completion(&handle->topo_wait); handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL); if (!(handle->listener_buf)) { Loading Loading @@ -1267,6 +1318,7 @@ void hdcp_library_deregister(void *phdcpcontext) kzfree(handle->qseecom_handle); mutex_destroy(&handle->hdcp_lock); mutex_destroy(&handle->wakeup_mutex); kzfree(handle->listener_buf); kzfree(handle); Loading drivers/video/msm/mdss/mdss_hdmi_hdcp.c +32 −9 Original line number Diff line number Diff line Loading @@ -366,7 +366,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -529,7 +532,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.data_buf = an; ddc_data.data_len = 8; ddc_data.what = "An"; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME); goto error; Loading @@ -542,7 +547,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.data_buf = aksv; ddc_data.data_len = 5; ddc_data.what = "Aksv"; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: AKSV write failed\n", __func__, HDCP_STATE_NAME); Loading @@ -561,7 +568,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bksv"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BKSV read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -633,7 +643,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "R0'"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME); goto error; Loading Loading @@ -684,7 +697,8 @@ do { \ ddc_data.offset = (off); \ memset(what, 0, sizeof(what)); \ snprintf(what, sizeof(what), (name)); \ rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); \ hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; \ rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); \ if (rc) { \ DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \ what); \ Loading Loading @@ -868,7 +882,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; ddc_data.no_align = false; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, HDCP_STATE_NAME); Loading @@ -887,7 +904,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bstatuss"; ddc_data.no_align = false; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BSTATUS read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -979,9 +999,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "KSV FIFO"; ddc_data.no_align = true; hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; cnt = 0; do { rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__, HDCP_STATE_NAME); Loading drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +138 −103 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #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 */ /* * HDCP 2.2 encryption requires the data encryption block that is present in * HDMI controller version 4.0.0 and above Loading Loading @@ -67,6 +69,9 @@ struct hdmi_hdcp2p2_ctrl { struct kthread_work auth; struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct delayed_work link_check_work; }; static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) Loading @@ -86,7 +91,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) mutex_lock(&ctrl->wakeup_mutex); pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); ctrl->wakeup_cmd = data->cmd; ctrl->timeout = data->timeout; Loading Loading @@ -275,7 +280,8 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev, { struct hdmi_hdcp2p2_ctrl *ctrl = hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2); int res; struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE}; if (!ctrl) { pr_err("invalid input\n"); Loading @@ -283,8 +289,9 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev, } pr_debug("notification of minimum level change received\n"); res = ctrl->lib-> hdcp_query_stream_type(ctrl->lib_ctx); cdata.context = ctrl->lib_ctx; hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); return count; } Loading @@ -299,8 +306,7 @@ static void hdmi_hdcp2p2_auth_failed(struct hdmi_hdcp2p2_ctrl *ctrl) atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); /* notify hdmi tx about HDCP failure */ ctrl->init_data.notify_status( ctrl->init_data.cb_data, ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTH_FAIL); } Loading @@ -310,6 +316,10 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, struct hdmi_tx_ddc_data ddc_data; int rc; if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { 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 @@ -320,7 +330,9 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.hard_timeout = timeout; ddc_data.what = "HDCP2ReadMessage"; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot read HDCP message register\n"); return rc; Loading @@ -340,24 +352,14 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; ddc_data.what = "HDCP2WriteMessage"; rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot write HDCP message register"); return rc; } static void hdmi_hdcp2p2_ddc_abort(struct hdmi_hdcp2p2_ctrl *ctrl) { /* Abort any ongoing DDC transactions */ struct hdmi_tx_ddc_data ddc_data; memset(&ddc_data, 0, sizeof(ddc_data)); ddc_data.retry = 1; ddc_data.what = "HDCPAbortTransaction"; hdmi_ddc_abort_transaction(ctrl->init_data.ddc_ctrl, &ddc_data); } static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl, u8 *hdcp2version) { Loading @@ -373,7 +375,9 @@ static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; ddc_data.what = "HDCP2Version"; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) { pr_err("Cannot read HDCP2Version register"); return rc; Loading Loading @@ -424,44 +428,6 @@ static struct attribute_group hdmi_hdcp2p2_fs_attr_group = { .attrs = hdmi_hdcp2p2_fs_attrs, }; static int hdmi_hdcp2p2_isr(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = input; u32 reg_val; if (!ctrl) { pr_err("invalid input\n"); return -EINVAL; } pr_debug("INT_CTRL0 is 0x%x\n", DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0)); reg_val = DSS_REG_R(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2); if (reg_val & BIT(0)) { pr_debug("HDCP 2.2 Encryption is enabled\n"); reg_val |= BIT(1); DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2, reg_val); } reg_val = DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0); if (reg_val & HDCP2P2_RXSTATUS_MESSAGE_SIZE_MASK) { DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0, reg_val & ~(BIT(31))); if (!completion_done(&ctrl->rxstatus_completion)) complete_all(&ctrl->rxstatus_completion); } else if (reg_val & BIT(8)) { DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0, reg_val & ~(BIT(9) | BIT(10))); if (!completion_done(&ctrl->rxstatus_completion)) complete_all(&ctrl->rxstatus_completion); } return 0; } static bool hdmi_hdcp2p2_feature_supported(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = input; Loading Loading @@ -525,12 +491,12 @@ exit: static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) { int rc = 0, msg_size = 0, retries = 5; int rc = 0; u64 mult; char *recvd_msg_buf = NULL; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, recv_msg); struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data; struct hdmi_tx_hdcp2p2_ddc_data *ddc_data; struct hdmi_tx_ddc_ctrl *ddc_ctrl; struct msm_hdmi_mode_timing_info *timing; struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; Loading @@ -550,59 +516,47 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) } ddc_ctrl = ctrl->init_data.ddc_ctrl; if (!ddc_ctrl) goto exit; do { timing = ctrl->init_data.timing; hdmi_ddc_config(ddc_ctrl); mult = hdmi_tx_get_v_total(timing) / 20; memset(&hdcp2p2_ddc_data, 0, sizeof(hdcp2p2_ddc_data)); hdcp2p2_ddc_data.ddc_data.what = "HDCP2RxStatus"; hdcp2p2_ddc_data.ddc_data.data_buf = (u8 *)&msg_size; hdcp2p2_ddc_data.ddc_data.data_len = sizeof(msg_size); hdcp2p2_ddc_data.rxstatus_field = RXSTATUS_MESSAGE_SIZE; hdcp2p2_ddc_data.timer_delay_lines = (u32)mult; hdcp2p2_ddc_data.irq_wait_count = 100; hdcp2p2_ddc_data.poll_sink = false; ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; hdmi_ddc_config(ddc_ctrl); pr_debug("Reading rxstatus, timer delay %u\n", (u32)mult); memset(ddc_data, 0, sizeof(*ddc_data)); rc = hdmi_hdcp2p2_ddc_read_rxstatus( ddc_ctrl, &hdcp2p2_ddc_data, &ctrl->rxstatus_completion); timing = ctrl->init_data.timing; mult = hdmi_tx_get_v_total(timing) / 20; ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->timer_delay_lines = (u32)mult; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); if (rc) { pr_err("Could not read rxstatus from sink\n"); continue; pr_err("error reading rxstatus %d\n", rc); goto exit; } if (!msg_size) { if (!ddc_data->message_size) { pr_err("recvd invalid message size\n"); rc = -EINVAL; continue; } } while (rc && (retries-- > 0)); if (rc) { pr_err("error reading valid rxstatus data\n"); goto exit; } recvd_msg_buf = kzalloc(msg_size, GFP_KERNEL); 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, msg_size, ctrl->timeout); ddc_data->message_size, ctrl->timeout); if (rc) pr_err("ERROR reading message from sink\n"); hdmi_hdcp2p2_ddc_abort(ctrl); hdmi_hdcp2p2_ddc_reset(ddc_ctrl); hdmi_hdcp2p2_ddc_disable(ddc_ctrl); 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 = msg_size; cdata.recvd_msg_len = ddc_data->message_size; exit: if (rc == -ETIMEDOUT) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT; Loading Loading @@ -646,14 +600,92 @@ static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work) DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2, regval); ctrl->init_data.notify_status( ctrl->init_data.cb_data, ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTHENTICATED); /* recheck within 1sec as per hdcp 2.2 standard */ schedule_delayed_work(&ctrl->link_check_work, msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS)); } exit: mutex_unlock(&ctrl->mutex); } static void hdmi_hdcp2p2_link_schedule_work(struct work_struct *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(to_delayed_work(work), struct hdmi_hdcp2p2_ctrl, link_check_work); if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static void hdmi_hdcp2p2_link_work(struct kthread_work *work) { int rc = 0; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, link); struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_STOP}; struct hdmi_tx_ddc_ctrl *ddc_ctrl; struct hdmi_tx_hdcp2p2_ddc_data *ddc_data; u64 mult; struct msm_hdmi_mode_timing_info *timing; if (!ctrl) { pr_err("invalid input\n"); return; } mutex_lock(&ctrl->mutex); cdata.context = ctrl->lib_ctx; ddc_ctrl = ctrl->init_data.ddc_ctrl; if (!ddc_ctrl) { rc = -EINVAL; goto exit; } hdmi_ddc_config(ddc_ctrl); ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; memset(ddc_data, 0, sizeof(*ddc_data)); timing = ctrl->init_data.timing; mult = hdmi_tx_get_v_total(timing) / 20; ddc_data->intr_mask = RXSTATUS_REAUTH_REQ; ddc_data->timer_delay_lines = (u32)mult; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); if (rc) { pr_err("error reading rxstatus %d\n", rc); goto exit; } if (ddc_data->reauth_req) { pr_debug("sync reported loss of synchronization, reauth\n"); rc = -ENOLINK; } exit: mutex_unlock(&ctrl->mutex); if (rc) { /* notify hdcp lib to stop auth */ hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); /* notify hdmi tx about auth failure */ hdmi_hdcp2p2_auth_failed(ctrl); return; } /* recheck within 1sec as per hdcp 2.2 standard */ schedule_delayed_work(&ctrl->link_check_work, msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS)); } static void hdmi_hdcp2p2_auth_work(struct kthread_work *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, Loading Loading @@ -707,7 +739,6 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) struct hdmi_hdcp2p2_ctrl *ctrl; int rc; static struct hdmi_hdcp_ops ops = { .hdmi_hdcp_isr = hdmi_hdcp2p2_isr, .hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate, .hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate, .feature_supported = hdmi_hdcp2p2_feature_supported, Loading Loading @@ -771,10 +802,14 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) init_kthread_work(&ctrl->send_msg, hdmi_hdcp2p2_send_msg_work); 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); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "hdmi_hdcp2p2"); INIT_DELAYED_WORK(&ctrl->link_check_work, hdmi_hdcp2p2_link_schedule_work); if (IS_ERR(ctrl->thread)) { pr_err("unable to start hdcp2p2 thread\n"); rc = PTR_ERR(ctrl->thread); Loading drivers/video/msm/mdss/mdss_hdmi_tx.c +15 −6 Original line number Diff line number Diff line Loading @@ -1291,11 +1291,13 @@ static u32 hdmi_tx_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl, ddc_data.what = "EDID"; ddc_data.no_align = false; ddc_ctrl->ddc_data = ddc_data; /* Read EDID twice with 32bit alighnment too */ if (block < 2) status = hdmi_ddc_read(ddc_ctrl, &ddc_data); status = hdmi_ddc_read(ddc_ctrl); else status = hdmi_ddc_read_seg(ddc_ctrl, &ddc_data); status = hdmi_ddc_read_seg(ddc_ctrl); if (status) break; Loading Loading @@ -3777,10 +3779,14 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data) if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC])) DEV_ERR("%s: hdmi_cec_isr failed\n", __func__); if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) { if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) { if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr( hdmi_ctrl->hdcp_feature_data)) DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__); DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__); } } end: return IRQ_HANDLED; } /* hdmi_tx_isr */ Loading Loading @@ -3865,6 +3871,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO]; init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done); init_completion(&hdmi_ctrl->ddc_ctrl.rxstatus_completion); hdmi_ctrl->panel_power_on = false; hdmi_ctrl->panel_suspend = false; Loading Loading @@ -4080,6 +4087,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, hdmi_ctrl->hdcp_ops->hdmi_hdcp_off( hdmi_ctrl->hdcp_feature_data); hdmi_ctrl->hdcp_ops = NULL; rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false); if (rc) Loading drivers/video/msm/mdss/mdss_hdmi_util.c +315 −215 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
drivers/misc/hdcp.c +108 −56 Original line number Diff line number Diff line Loading @@ -333,9 +333,11 @@ struct hdcp_lib_handle { uint32_t tz_ctxhandle; uint32_t hdcp_timeout; bool no_stored_km_flag; bool feature_supported; void *client_ctx; struct hdcp_client_ops *client_ops; struct mutex hdcp_lock; struct mutex wakeup_mutex; enum hdcp_state hdcp_state; enum hdcp_lib_wakeup_cmd wakeup_cmd; bool repeater_flag; Loading @@ -343,9 +345,10 @@ struct hdcp_lib_handle { int last_msg_sent; char *last_msg_recvd_buf; uint32_t last_msg_recvd_len; atomic_t hdcp_off_pending; atomic_t hdcp_off; struct task_struct *thread; struct completion topo_wait; struct kthread_worker worker; struct kthread_work init; Loading @@ -353,6 +356,8 @@ struct hdcp_lib_handle { struct kthread_work msg_recvd; struct kthread_work timeout; struct kthread_work clean; struct kthread_work topology; struct kthread_work stream; }; struct hdcp_lib_message_map { Loading Loading @@ -456,7 +461,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) pr_debug("success\n"); return 0; error: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); return rc; Loading Loading @@ -668,30 +673,20 @@ exit: return rc; } static int hdcp_lib_query_stream_type(void *phdcpcontext) static void hdcp_lib_query_stream_type_work(struct kthread_work *work) { int rc = 0; struct hdcp_query_stream_type_req *req_buf; struct hdcp_query_stream_type_rsp *rsp_buf; struct hdcp_lib_handle *handle = phdcpcontext; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, stream); if (!handle) { pr_err("invalid input\n"); return -EINVAL; } if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_debug("hdcp library not loaded\n"); goto exit; } if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) { pr_err("txmtr is not initialized\n"); rc = -EINVAL; goto exit; pr_err("invalid handle\n"); return; } flush_kthread_worker(&handle->worker); mutex_lock(&handle->hdcp_lock); /* send command to TZ */ req_buf = (struct hdcp_query_stream_type_req *)handle-> Loading @@ -715,7 +710,7 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext) goto exit; } pr_debug("message received is %s\n", pr_debug("message received from TZ: %s\n", hdcp_lib_message_name((int)rsp_buf->msg[0])); memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); Loading @@ -723,15 +718,11 @@ static int hdcp_lib_query_stream_type(void *phdcpcontext) rsp_buf->msglen); handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; exit: mutex_unlock(&handle->hdcp_lock); if (!atomic_read(&handle->hdcp_off_pending)) if (!rc && !atomic_read(&handle->hdcp_off)) hdcp_lib_send_message(handle); else goto exit; pr_debug("success\n"); exit: return rc; } static bool hdcp_lib_client_feature_supported(void *phdcpcontext) Loading @@ -745,9 +736,15 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext) goto exit; } if (handle->feature_supported) { supported = true; goto exit; } rc = hdcp_lib_library_load(handle); if (!rc) { pr_debug("HDCP2p2 supported\n"); handle->feature_supported = true; hdcp_lib_library_unload(handle); supported = true; } Loading @@ -767,9 +764,11 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) if (!handle) return -EINVAL; mutex_lock(&handle->wakeup_mutex); handle->wakeup_cmd = data->cmd; pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd)); if (data->recvd_msg_len) { handle->last_msg_recvd_len = data->recvd_msg_len; Loading @@ -785,42 +784,51 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) data->recvd_msg_len); } if (!completion_done(&handle->topo_wait)) complete_all(&handle->topo_wait); switch (handle->wakeup_cmd) { case HDCP_LIB_WKUP_CMD_START: handle->no_stored_km_flag = 0; handle->repeater_flag = 0; handle->last_msg_sent = 0; atomic_set(&handle->hdcp_off, 0); handle->hdcp_state = HDCP_STATE_INIT; if (!atomic_read(&handle->hdcp_off_pending)) queue_kthread_work(&handle->worker, &handle->init); break; case HDCP_LIB_WKUP_CMD_STOP: atomic_set(&handle->hdcp_off_pending, 1); atomic_set(&handle->hdcp_off, 1); queue_kthread_work(&handle->worker, &handle->clean); break; case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS: handle->last_msg_sent = handle->listener_buf[0]; if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->msg_sent); break; case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED: case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); break; case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->msg_recvd); break; case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT: if (!atomic_read(&handle->hdcp_off_pending)) if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->timeout); break; case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE: if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->stream); break; default: pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); } exit: mutex_unlock(&handle->wakeup_mutex); return 0; } Loading @@ -835,28 +843,41 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work) return; } if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); return; } mutex_lock(&handle->hdcp_lock); cdata.context = handle->client_ctx; if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { if (handle->last_msg_sent == SKE_SEND_EKS_MESSAGE_ID) { switch (handle->last_msg_sent) { case SKE_SEND_EKS_MESSAGE_ID: if (handle->repeater_flag) { if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->topology); } if (!hdcp_lib_enable_encryption(handle)) cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; else cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED; } else { if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); break; case REPEATER_AUTH_SEND_ACK_MESSAGE_ID: pr_debug("Repeater authentication successful\n"); break; default: cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; cdata.timeout = handle->hdcp_timeout; } } else { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); } mutex_unlock(&handle->hdcp_lock); hdcp_lib_wakeup_client(handle, &cdata); return; } static void hdcp_lib_init_work(struct kthread_work *work) Loading Loading @@ -900,7 +921,7 @@ exit: if (send_msg) hdcp_lib_send_message(handle); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); return; } Loading Loading @@ -954,7 +975,7 @@ static void hdcp_lib_manage_timeout_work(struct kthread_work *work) if ((rsp_buf->commandid == HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) && ((int)rsp_buf->message[0] == LC_INIT_MESSAGE_ID) && (rsp_buf->msglen == LC_INIT_MESSAGE_SIZE)) { if (!atomic_read(&handle->hdcp_off_pending)) { if (!atomic_read(&handle->hdcp_off)) { /* keep local copy of TZ response */ memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, Loading @@ -972,7 +993,7 @@ error: if (send_msg) hdcp_lib_send_message(handle); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } Loading @@ -997,10 +1018,10 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work) mutex_unlock(&handle->hdcp_lock); if (atomic_read(&handle->hdcp_off_pending)) atomic_set(&handle->hdcp_off_pending, 0); else if (!atomic_read(&handle->hdcp_off)) hdcp_lib_wakeup_client(handle, &cdata); atomic_set(&handle->hdcp_off, 1); } static void hdcp_lib_msg_recvd_work(struct kthread_work *work) Loading Loading @@ -1108,7 +1129,7 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work) handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; if (!atomic_read(&handle->hdcp_off_pending)) { if (!atomic_read(&handle->hdcp_off)) { cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE; cdata.send_msg_buf = handle->listener_buf; cdata.send_msg_len = handle->msglen; Loading @@ -1121,10 +1142,36 @@ exit: hdcp_lib_wakeup_client(handle, &cdata); if (rc && !atomic_read(&handle->hdcp_off_pending)) if (rc && !atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } static void hdcp_lib_topology_work(struct kthread_work *work) { u32 timeout; struct hdcp_lib_handle *handle = container_of(work, struct hdcp_lib_handle, topology); struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; if (!handle) { pr_err("invalid input\n"); return; } cdata.context = handle->client_ctx; cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; hdcp_lib_wakeup_client(handle, &cdata); reinit_completion(&handle->topo_wait); timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3); if (!timeout) { pr_err("topology receiver id list timeout\n"); if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, &handle->clean); } } /* APIs exposed to all clients */ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) { Loading Loading @@ -1204,7 +1251,6 @@ int hdcp_library_register(void **pphdcpcontext, /* populate ops to be called by client */ txmtr_ops->feature_supported = hdcp_lib_client_feature_supported; txmtr_ops->wakeup = hdcp_lib_wakeup; txmtr_ops->hdcp_query_stream_type = hdcp_lib_query_stream_type; handle = kzalloc(sizeof(*handle), GFP_KERNEL); if (!handle) { Loading @@ -1215,9 +1261,10 @@ int hdcp_library_register(void **pphdcpcontext, handle->client_ctx = client_ctx; handle->client_ops = client_ops; atomic_set(&handle->hdcp_off_pending, 0); atomic_set(&handle->hdcp_off, 0); mutex_init(&handle->hdcp_lock); mutex_init(&handle->wakeup_mutex); init_kthread_worker(&handle->worker); Loading @@ -1226,6 +1273,10 @@ int hdcp_library_register(void **pphdcpcontext, init_kthread_work(&handle->msg_recvd, hdcp_lib_msg_recvd_work); init_kthread_work(&handle->timeout, hdcp_lib_manage_timeout_work); init_kthread_work(&handle->clean, hdcp_lib_cleanup_work); init_kthread_work(&handle->topology, hdcp_lib_topology_work); init_kthread_work(&handle->stream, hdcp_lib_query_stream_type_work); init_completion(&handle->topo_wait); handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL); if (!(handle->listener_buf)) { Loading Loading @@ -1267,6 +1318,7 @@ void hdcp_library_deregister(void *phdcpcontext) kzfree(handle->qseecom_handle); mutex_destroy(&handle->hdcp_lock); mutex_destroy(&handle->wakeup_mutex); kzfree(handle->listener_buf); kzfree(handle); Loading
drivers/video/msm/mdss/mdss_hdmi_hdcp.c +32 −9 Original line number Diff line number Diff line Loading @@ -366,7 +366,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -529,7 +532,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.data_buf = an; ddc_data.data_len = 8; ddc_data.what = "An"; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME); goto error; Loading @@ -542,7 +547,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.data_buf = aksv; ddc_data.data_len = 5; ddc_data.what = "Aksv"; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: AKSV write failed\n", __func__, HDCP_STATE_NAME); Loading @@ -561,7 +568,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bksv"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BKSV read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -633,7 +643,10 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "R0'"; ddc_data.no_align = true; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME); goto error; Loading Loading @@ -684,7 +697,8 @@ do { \ ddc_data.offset = (off); \ memset(what, 0, sizeof(what)); \ snprintf(what, sizeof(what), (name)); \ rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); \ hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; \ rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); \ if (rc) { \ DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \ what); \ Loading Loading @@ -868,7 +882,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bcaps"; ddc_data.no_align = false; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BCAPS read failed\n", __func__, HDCP_STATE_NAME); Loading @@ -887,7 +904,10 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "Bstatuss"; ddc_data.no_align = false; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: BSTATUS read failed\n", __func__, HDCP_STATE_NAME); Loading Loading @@ -979,9 +999,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) ddc_data.retry = 5; ddc_data.what = "KSV FIFO"; ddc_data.no_align = true; hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; cnt = 0; do { rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl, &ddc_data); rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); if (rc) { DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__, HDCP_STATE_NAME); Loading
drivers/video/msm/mdss/mdss_hdmi_hdcp2p2.c +138 −103 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #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 */ /* * HDCP 2.2 encryption requires the data encryption block that is present in * HDMI controller version 4.0.0 and above Loading Loading @@ -67,6 +69,9 @@ struct hdmi_hdcp2p2_ctrl { struct kthread_work auth; struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; struct delayed_work link_check_work; }; static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) Loading @@ -86,7 +91,7 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) mutex_lock(&ctrl->wakeup_mutex); pr_debug("wakeup_cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); pr_debug("cmd: %s\n", hdmi_hdcp_cmd_to_str(data->cmd)); ctrl->wakeup_cmd = data->cmd; ctrl->timeout = data->timeout; Loading Loading @@ -275,7 +280,8 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev, { struct hdmi_hdcp2p2_ctrl *ctrl = hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP2P2); int res; struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE}; if (!ctrl) { pr_err("invalid input\n"); Loading @@ -283,8 +289,9 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev, } pr_debug("notification of minimum level change received\n"); res = ctrl->lib-> hdcp_query_stream_type(ctrl->lib_ctx); cdata.context = ctrl->lib_ctx; hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); return count; } Loading @@ -299,8 +306,7 @@ static void hdmi_hdcp2p2_auth_failed(struct hdmi_hdcp2p2_ctrl *ctrl) atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); /* notify hdmi tx about HDCP failure */ ctrl->init_data.notify_status( ctrl->init_data.cb_data, ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTH_FAIL); } Loading @@ -310,6 +316,10 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, struct hdmi_tx_ddc_data ddc_data; int rc; if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { 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 @@ -320,7 +330,9 @@ static int hdmi_hdcp2p2_ddc_read_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.hard_timeout = timeout; ddc_data.what = "HDCP2ReadMessage"; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot read HDCP message register\n"); return rc; Loading @@ -340,24 +352,14 @@ static int hdmi_hdcp2p2_ddc_write_message(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; ddc_data.what = "HDCP2WriteMessage"; rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(ctrl->init_data.ddc_ctrl); if (rc) pr_err("Cannot write HDCP message register"); return rc; } static void hdmi_hdcp2p2_ddc_abort(struct hdmi_hdcp2p2_ctrl *ctrl) { /* Abort any ongoing DDC transactions */ struct hdmi_tx_ddc_data ddc_data; memset(&ddc_data, 0, sizeof(ddc_data)); ddc_data.retry = 1; ddc_data.what = "HDCPAbortTransaction"; hdmi_ddc_abort_transaction(ctrl->init_data.ddc_ctrl, &ddc_data); } static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl, u8 *hdcp2version) { Loading @@ -373,7 +375,9 @@ static int hdmi_hdcp2p2_read_version(struct hdmi_hdcp2p2_ctrl *ctrl, ddc_data.retry = 1; ddc_data.what = "HDCP2Version"; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl, &ddc_data); ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_read(ctrl->init_data.ddc_ctrl); if (rc) { pr_err("Cannot read HDCP2Version register"); return rc; Loading Loading @@ -424,44 +428,6 @@ static struct attribute_group hdmi_hdcp2p2_fs_attr_group = { .attrs = hdmi_hdcp2p2_fs_attrs, }; static int hdmi_hdcp2p2_isr(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = input; u32 reg_val; if (!ctrl) { pr_err("invalid input\n"); return -EINVAL; } pr_debug("INT_CTRL0 is 0x%x\n", DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0)); reg_val = DSS_REG_R(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2); if (reg_val & BIT(0)) { pr_debug("HDCP 2.2 Encryption is enabled\n"); reg_val |= BIT(1); DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2, reg_val); } reg_val = DSS_REG_R(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0); if (reg_val & HDCP2P2_RXSTATUS_MESSAGE_SIZE_MASK) { DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0, reg_val & ~(BIT(31))); if (!completion_done(&ctrl->rxstatus_completion)) complete_all(&ctrl->rxstatus_completion); } else if (reg_val & BIT(8)) { DSS_REG_W(ctrl->init_data.core_io, HDMI_DDC_INT_CTRL0, reg_val & ~(BIT(9) | BIT(10))); if (!completion_done(&ctrl->rxstatus_completion)) complete_all(&ctrl->rxstatus_completion); } return 0; } static bool hdmi_hdcp2p2_feature_supported(void *input) { struct hdmi_hdcp2p2_ctrl *ctrl = input; Loading Loading @@ -525,12 +491,12 @@ exit: static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) { int rc = 0, msg_size = 0, retries = 5; int rc = 0; u64 mult; char *recvd_msg_buf = NULL; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, recv_msg); struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data; struct hdmi_tx_hdcp2p2_ddc_data *ddc_data; struct hdmi_tx_ddc_ctrl *ddc_ctrl; struct msm_hdmi_mode_timing_info *timing; struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; Loading @@ -550,59 +516,47 @@ static void hdmi_hdcp2p2_recv_msg_work(struct kthread_work *work) } ddc_ctrl = ctrl->init_data.ddc_ctrl; if (!ddc_ctrl) goto exit; do { timing = ctrl->init_data.timing; hdmi_ddc_config(ddc_ctrl); mult = hdmi_tx_get_v_total(timing) / 20; memset(&hdcp2p2_ddc_data, 0, sizeof(hdcp2p2_ddc_data)); hdcp2p2_ddc_data.ddc_data.what = "HDCP2RxStatus"; hdcp2p2_ddc_data.ddc_data.data_buf = (u8 *)&msg_size; hdcp2p2_ddc_data.ddc_data.data_len = sizeof(msg_size); hdcp2p2_ddc_data.rxstatus_field = RXSTATUS_MESSAGE_SIZE; hdcp2p2_ddc_data.timer_delay_lines = (u32)mult; hdcp2p2_ddc_data.irq_wait_count = 100; hdcp2p2_ddc_data.poll_sink = false; ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; hdmi_ddc_config(ddc_ctrl); pr_debug("Reading rxstatus, timer delay %u\n", (u32)mult); memset(ddc_data, 0, sizeof(*ddc_data)); rc = hdmi_hdcp2p2_ddc_read_rxstatus( ddc_ctrl, &hdcp2p2_ddc_data, &ctrl->rxstatus_completion); timing = ctrl->init_data.timing; mult = hdmi_tx_get_v_total(timing) / 20; ddc_data->intr_mask = RXSTATUS_MESSAGE_SIZE; ddc_data->timer_delay_lines = (u32)mult; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); if (rc) { pr_err("Could not read rxstatus from sink\n"); continue; pr_err("error reading rxstatus %d\n", rc); goto exit; } if (!msg_size) { if (!ddc_data->message_size) { pr_err("recvd invalid message size\n"); rc = -EINVAL; continue; } } while (rc && (retries-- > 0)); if (rc) { pr_err("error reading valid rxstatus data\n"); goto exit; } recvd_msg_buf = kzalloc(msg_size, GFP_KERNEL); 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, msg_size, ctrl->timeout); ddc_data->message_size, ctrl->timeout); if (rc) pr_err("ERROR reading message from sink\n"); hdmi_hdcp2p2_ddc_abort(ctrl); hdmi_hdcp2p2_ddc_reset(ddc_ctrl); hdmi_hdcp2p2_ddc_disable(ddc_ctrl); 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 = msg_size; cdata.recvd_msg_len = ddc_data->message_size; exit: if (rc == -ETIMEDOUT) cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT; Loading Loading @@ -646,14 +600,92 @@ static void hdmi_hdcp2p2_auth_status_work(struct kthread_work *work) DSS_REG_W(ctrl->init_data.core_io, HDMI_HDCP_INT_CTRL2, regval); ctrl->init_data.notify_status( ctrl->init_data.cb_data, ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTHENTICATED); /* recheck within 1sec as per hdcp 2.2 standard */ schedule_delayed_work(&ctrl->link_check_work, msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS)); } exit: mutex_unlock(&ctrl->mutex); } static void hdmi_hdcp2p2_link_schedule_work(struct work_struct *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(to_delayed_work(work), struct hdmi_hdcp2p2_ctrl, link_check_work); if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) queue_kthread_work(&ctrl->worker, &ctrl->link); } static void hdmi_hdcp2p2_link_work(struct kthread_work *work) { int rc = 0; struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, struct hdmi_hdcp2p2_ctrl, link); struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_STOP}; struct hdmi_tx_ddc_ctrl *ddc_ctrl; struct hdmi_tx_hdcp2p2_ddc_data *ddc_data; u64 mult; struct msm_hdmi_mode_timing_info *timing; if (!ctrl) { pr_err("invalid input\n"); return; } mutex_lock(&ctrl->mutex); cdata.context = ctrl->lib_ctx; ddc_ctrl = ctrl->init_data.ddc_ctrl; if (!ddc_ctrl) { rc = -EINVAL; goto exit; } hdmi_ddc_config(ddc_ctrl); ddc_data = &ddc_ctrl->hdcp2p2_ddc_data; memset(ddc_data, 0, sizeof(*ddc_data)); timing = ctrl->init_data.timing; mult = hdmi_tx_get_v_total(timing) / 20; ddc_data->intr_mask = RXSTATUS_REAUTH_REQ; ddc_data->timer_delay_lines = (u32)mult; ddc_data->read_method = HDCP2P2_RXSTATUS_HW_DDC_SW_TRIGGER; rc = hdmi_hdcp2p2_ddc_read_rxstatus(ddc_ctrl); if (rc) { pr_err("error reading rxstatus %d\n", rc); goto exit; } if (ddc_data->reauth_req) { pr_debug("sync reported loss of synchronization, reauth\n"); rc = -ENOLINK; } exit: mutex_unlock(&ctrl->mutex); if (rc) { /* notify hdcp lib to stop auth */ hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata); /* notify hdmi tx about auth failure */ hdmi_hdcp2p2_auth_failed(ctrl); return; } /* recheck within 1sec as per hdcp 2.2 standard */ schedule_delayed_work(&ctrl->link_check_work, msecs_to_jiffies(HDCP2P2_LINK_CHECK_TIME_MS)); } static void hdmi_hdcp2p2_auth_work(struct kthread_work *work) { struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work, Loading Loading @@ -707,7 +739,6 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) struct hdmi_hdcp2p2_ctrl *ctrl; int rc; static struct hdmi_hdcp_ops ops = { .hdmi_hdcp_isr = hdmi_hdcp2p2_isr, .hdmi_hdcp_reauthenticate = hdmi_hdcp2p2_reauthenticate, .hdmi_hdcp_authenticate = hdmi_hdcp2p2_authenticate, .feature_supported = hdmi_hdcp2p2_feature_supported, Loading Loading @@ -771,10 +802,14 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data) init_kthread_work(&ctrl->send_msg, hdmi_hdcp2p2_send_msg_work); 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); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "hdmi_hdcp2p2"); INIT_DELAYED_WORK(&ctrl->link_check_work, hdmi_hdcp2p2_link_schedule_work); if (IS_ERR(ctrl->thread)) { pr_err("unable to start hdcp2p2 thread\n"); rc = PTR_ERR(ctrl->thread); Loading
drivers/video/msm/mdss/mdss_hdmi_tx.c +15 −6 Original line number Diff line number Diff line Loading @@ -1291,11 +1291,13 @@ static u32 hdmi_tx_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl, ddc_data.what = "EDID"; ddc_data.no_align = false; ddc_ctrl->ddc_data = ddc_data; /* Read EDID twice with 32bit alighnment too */ if (block < 2) status = hdmi_ddc_read(ddc_ctrl, &ddc_data); status = hdmi_ddc_read(ddc_ctrl); else status = hdmi_ddc_read_seg(ddc_ctrl, &ddc_data); status = hdmi_ddc_read_seg(ddc_ctrl); if (status) break; Loading Loading @@ -3777,10 +3779,14 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data) if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC])) DEV_ERR("%s: hdmi_cec_isr failed\n", __func__); if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) { if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) { if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr( hdmi_ctrl->hdcp_feature_data)) DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__); DEV_ERR("%s: hdmi_hdcp_isr failed\n", __func__); } } end: return IRQ_HANDLED; } /* hdmi_tx_isr */ Loading Loading @@ -3865,6 +3871,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO]; init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done); init_completion(&hdmi_ctrl->ddc_ctrl.rxstatus_completion); hdmi_ctrl->panel_power_on = false; hdmi_ctrl->panel_suspend = false; Loading Loading @@ -4080,6 +4087,8 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, hdmi_ctrl->hdcp_ops->hdmi_hdcp_off( hdmi_ctrl->hdcp_feature_data); hdmi_ctrl->hdcp_ops = NULL; rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false); if (rc) Loading
drivers/video/msm/mdss/mdss_hdmi_util.c +315 −215 File changed.Preview size limit exceeded, changes collapsed. Show changes