OSDN Git Service

drm/msm: add SRM support for HDCP 2.2
authorAbhinav Kumar <abhinavk@codeaurora.org>
Thu, 28 Sep 2017 03:23:53 +0000 (20:23 -0700)
committerAbhinav Kumar <abhinavk@codeaurora.org>
Fri, 20 Oct 2017 02:32:56 +0000 (19:32 -0700)
Add support for clients to notify SRM update
to HDCP driver.

This shall also notify all the clients registered
with the HDCP driver to take further action on an
updated SRM list.

Change-Id: I2881e53fa15a11e4af57cdb632a71e1ad48c31b3
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c
drivers/gpu/drm/msm/sde_hdcp.h
drivers/misc/hdcp.c
include/linux/hdcp_qseecom.h

index fa111d5..0f77e35 100644 (file)
@@ -666,6 +666,15 @@ static void sde_hdmi_tx_hdcp_cb_work(struct work_struct *work)
                }
 
                break;
+               case HDCP_STATE_AUTH_FAIL_NOREAUTH:
+               if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) {
+                       if (hdmi_ctrl->auth_state && !hdmi_ctrl->hdcp22_present)
+                               hdcp1_set_enc(false);
+               }
+
+               hdmi_ctrl->auth_state = false;
+
+               break;
        case HDCP_STATE_AUTH_ENC_NONE:
                hdmi_ctrl->enc_lvl = HDCP_STATE_AUTH_ENC_NONE;
                if (sde_hdmi_tx_is_panel_on(hdmi_ctrl))
index 1e67344..51f5c8d 100644 (file)
@@ -338,6 +338,41 @@ static void sde_hdmi_hdcp2p2_auth_failed(struct sde_hdmi_hdcp2p2_ctrl *ctrl)
                HDCP_STATE_AUTH_FAIL);
 }
 
+static void sde_hdmi_hdcp2p2_fail_noreauth(struct sde_hdmi_hdcp2p2_ctrl *ctrl)
+{
+       if (!ctrl) {
+               SDE_ERROR("invalid input\n");
+               return;
+       }
+
+       atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
+
+       sde_hdmi_hdcp2p2_ddc_disable(ctrl->init_data.cb_data);
+
+       /* notify hdmi tx about HDCP failure */
+       ctrl->init_data.notify_status(ctrl->init_data.cb_data,
+               HDCP_STATE_AUTH_FAIL_NOREAUTH);
+}
+
+static void sde_hdmi_hdcp2p2_srm_cb(void *client_ctx)
+{
+       struct sde_hdmi_hdcp2p2_ctrl *ctrl =
+               (struct sde_hdmi_hdcp2p2_ctrl *)client_ctx;
+       struct hdcp_lib_wakeup_data cdata = {
+               HDCP_LIB_WKUP_CMD_INVALID};
+
+       if (!ctrl) {
+               SDE_ERROR("invalid input\n");
+               return;
+       }
+
+       cdata.context = ctrl->lib_ctx;
+       cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
+       sde_hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
+
+       sde_hdmi_hdcp2p2_fail_noreauth(ctrl);
+}
+
 static int sde_hdmi_hdcp2p2_ddc_rd_message(struct sde_hdmi_hdcp2p2_ctrl *ctrl,
        u8 *buf, int size, u32 timeout)
 {
@@ -888,6 +923,7 @@ void *sde_hdmi_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
        static struct hdcp_client_ops client_ops = {
                .wakeup = sde_hdmi_hdcp2p2_wakeup,
                .notify_lvl_change = sde_hdmi_hdcp2p2_min_level_change,
+               .srm_cb = sde_hdmi_hdcp2p2_srm_cb,
        };
 
        static struct hdcp_txmtr_ops txmtr_ops;
index 49cca93..c414f68 100644 (file)
@@ -43,6 +43,7 @@ enum sde_hdcp_states {
        HDCP_STATE_AUTHENTICATING,
        HDCP_STATE_AUTHENTICATED,
        HDCP_STATE_AUTH_FAIL,
+       HDCP_STATE_AUTH_FAIL_NOREAUTH,
        HDCP_STATE_AUTH_ENC_NONE,
        HDCP_STATE_AUTH_ENC_1X,
        HDCP_STATE_AUTH_ENC_2P2
index 687f55b..87daee7 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "qseecom_kernel.h"
 
+#define SRMAPP_NAME            "hdcpsrm"
 #define TZAPP_NAME            "hdcp2p2"
 #define HDCP1_APP_NAME        "hdcp1"
 #define QSEECOM_SBUFF_SIZE    0x1000
 #define HDCP_SESSION_INIT                     SERVICE_CREATE_CMD(16)
 #define HDCP_SESSION_DEINIT                   SERVICE_CREATE_CMD(17)
 #define HDCP_TXMTR_START_AUTHENTICATE         SERVICE_CREATE_CMD(18)
+#define HDCP_TXMTR_VALIDATE_RECEIVER_ID_LIST  SERVICE_CREATE_CMD(19)
 
 #define HCDP_TXMTR_GET_MAJOR_VERSION(v) (((v) >> 16) & 0xFF)
 #define HCDP_TXMTR_GET_MINOR_VERSION(v) (((v) >> 8) & 0xFF)
@@ -485,6 +487,15 @@ struct __attribute__ ((__packed__)) hdcp_start_auth_rsp {
        uint8_t message[MAX_TX_MESSAGE_SIZE];
 };
 
+struct __attribute__ ((__packed__)) hdcp_rcv_id_list_req {
+       uint32_t commandid;
+       uint32_t ctxHandle;
+};
+struct __attribute__ ((__packed__)) hdcp_rcv_id_list_rsp {
+       uint32_t status;
+       uint32_t commandid;
+};
+
 /*
  * struct hdcp_lib_handle - handle for hdcp client
  * @qseecom_handle - for sending commands to qseecom
@@ -575,6 +586,8 @@ static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle);
 static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle);
 
 static struct qseecom_handle *hdcp1_handle;
+static struct qseecom_handle *hdcpsrm_handle;
+
 static bool hdcp1_supported = true;
 static bool hdcp1_enc_enabled;
 static struct mutex hdcp1_ta_cmd_lock;
@@ -1044,6 +1057,15 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle)
                goto exit;
        }
 
+       if (!hdcpsrm_handle) {
+               rc = qseecom_start_app(&hdcpsrm_handle,
+                                       SRMAPP_NAME, QSEECOM_SBUFF_SIZE);
+               if (rc) {
+                       pr_err("qseecom_start_app failed for SRM TA %d\n", rc);
+                       goto exit;
+               }
+       }
+
        handle->hdcp_state |= HDCP_STATE_APP_LOADED;
        pr_debug("qseecom_start_app success\n");
 
@@ -1113,10 +1135,17 @@ static int hdcp_lib_library_unload(struct hdcp_lib_handle *handle)
                goto exit;
        }
 
-       /* deallocate the resources for qseecom handle */
+       /* deallocate the resources for qseecom hdcp2p2 handle */
        rc = qseecom_shutdown_app(&handle->qseecom_handle);
        if (rc) {
-               pr_err("qseecom_shutdown_app failed err: %d\n", rc);
+               pr_err("hdcp2p2 qseecom_shutdown_app failed err: %d\n", rc);
+               goto exit;
+       }
+
+       /* deallocate the resources for qseecom hdcpsrm handle */
+       rc = qseecom_shutdown_app(&hdcpsrm_handle);
+       if (rc) {
+               pr_err("hdcpsrm qseecom_shutdown_app failed err: %d\n", rc);
                goto exit;
        }
 
@@ -2322,6 +2351,48 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
        return 0;
 }
 
+static int hdcp_validate_recv_id(struct hdcp_lib_handle *handle)
+{
+       int rc = 0;
+       struct hdcp_rcv_id_list_req *recv_id_req;
+       struct hdcp_rcv_id_list_rsp *recv_id_rsp;
+
+       if (!handle || !handle->qseecom_handle ||
+               !handle->qseecom_handle->sbuf) {
+               pr_err("invalid handle\n");
+               return -EINVAL;
+       }
+
+       /* validate the receiver ID list against the new SRM blob */
+       recv_id_req = (struct hdcp_rcv_id_list_req *)
+                                       handle->qseecom_handle->sbuf;
+       recv_id_req->commandid = HDCP_TXMTR_VALIDATE_RECEIVER_ID_LIST;
+       recv_id_req->ctxHandle = handle->tz_ctxhandle;
+
+       recv_id_rsp = (struct hdcp_rcv_id_list_rsp *)
+               (handle->qseecom_handle->sbuf +
+               QSEECOM_ALIGN(sizeof(struct hdcp_rcv_id_list_req)));
+
+       rc = qseecom_send_command(handle->qseecom_handle,
+                       recv_id_req,
+                       QSEECOM_ALIGN(sizeof(struct hdcp_rcv_id_list_req)),
+                       recv_id_rsp,
+                       QSEECOM_ALIGN(sizeof(struct hdcp_rcv_id_list_rsp)));
+
+
+       if ((rc < 0) || (recv_id_rsp->status != HDCP_SUCCESS) ||
+               (recv_id_rsp->commandid !=
+                       HDCP_TXMTR_VALIDATE_RECEIVER_ID_LIST)) {
+               pr_err("qseecom cmd failed with err = %d status = %d\n",
+                          rc, recv_id_rsp->status);
+               rc = -EINVAL;
+               goto exit;
+       }
+
+exit:
+       return rc;
+}
+
 int hdcp1_set_enc(bool enable)
 {
        int rc = 0;
@@ -2601,12 +2672,44 @@ static ssize_t hdmi_hdcp2p2_sysfs_wta_min_level_change(struct device *dev,
        return ret;
 }
 
+static ssize_t hdmi_hdcp_srm_updated(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       int rc;
+       int srm_updated;
+       struct hdcp_lib_handle *handle;
+       ssize_t ret = count;
+
+       handle = hdcp_drv_mgr->handle;
+
+       rc = kstrtoint(buf, 10, &srm_updated);
+       if (rc) {
+               pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+               return -EINVAL;
+       }
+
+       if (srm_updated) {
+               if (hdcp_validate_recv_id(handle)) {
+                       pr_debug("SRM check FAILED\n");
+                       if (handle && handle->client_ops->srm_cb)
+                               handle->client_ops->srm_cb(handle->client_ctx);
+               } else {
+                       pr_debug("SRM check PASSED\n");
+               }
+       }
+
+       return ret;
+}
+
 static DEVICE_ATTR(tp, S_IRUGO | S_IWUSR, msm_hdcp_1x_sysfs_rda_tp,
 msm_hdcp_1x_sysfs_wta_tp);
 
 static DEVICE_ATTR(min_level_change, S_IWUSR, NULL,
 hdmi_hdcp2p2_sysfs_wta_min_level_change);
 
+static DEVICE_ATTR(srm_updated, S_IWUSR, NULL,
+hdmi_hdcp_srm_updated);
+
 void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp)
 {
        memcpy((void *)&hdcp_drv_mgr->cached_tp,
@@ -2617,6 +2720,7 @@ void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp)
 static struct attribute *msm_hdcp_fs_attrs[] = {
        &dev_attr_tp.attr,
        &dev_attr_min_level_change.attr,
+       &dev_attr_srm_updated.attr,
        NULL
 };
 
index dc513fb..8e1b853 100644 (file)
@@ -126,6 +126,7 @@ struct hdcp_txmtr_ops {
 struct hdcp_client_ops {
        int (*wakeup)(struct hdmi_hdcp_wakeup_data *data);
        void (*notify_lvl_change)(void *client_ctx, int min_lvl);
+       void (*srm_cb)(void *client_ctx);
 };
 
 enum hdcp_device_type {