Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 753e42eb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: add SRM support for HDCP 2.2"

parents b23666a9 271ec6b3
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -665,6 +665,15 @@ static void sde_hdmi_tx_hdcp_cb_work(struct work_struct *work)
					 __func__);
		}

		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;
+36 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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
+106 −2
Original line number Diff line number Diff line
@@ -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
@@ -138,6 +139,7 @@
#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
};

+1 −0
Original line number Diff line number Diff line
@@ -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 {