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

Commit 456b02e5 authored by Casey Piper's avatar Casey Piper
Browse files

msm: mdss: hdmi: use HDCP SW keys if available



On compatible hardware, HDCP keys can be provisioned
through software instead of being hardware fused.
If HDCP keys are available in sofware, set these
keys and gather aksv through QSEECom calls. If
keys are not available, do not continue HDCP
authentication process.

Change-Id: I7a93b6e1ef958aaa53ef756393ce1f81882bedaf
Signed-off-by: default avatarCasey Piper <cpiper@codeaurora.org>
parent 598646bf
Loading
Loading
Loading
Loading
+33 −12
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <soc/qcom/scm.h>

#include <linux/hdcp_qseecom.h>
#include "mdss_hdmi_hdcp.h"
#include "video/msm_hdmi_hdcp_mgr.h"

@@ -241,12 +241,13 @@ static int hdcp_scm_call(struct scm_hdcp_req *req, u32 *resp)
static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{
	int rc;
	u32 reg_val;
	u32 qfprom_aksv_lsb, qfprom_aksv_msb;
	u32 link0_aksv_0, link0_aksv_1;
	u32 link0_bksv_0, link0_bksv_1;
	u32 link0_an_0, link0_an_1;
	u32 timeout_count;
	bool is_match;
	bool is_match, use_sw_keys = false;
	bool stale_an = false;
	struct dss_io_data *io;
	struct dss_io_data *hdcp_io;
@@ -282,6 +283,25 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
		goto error;
	}

	/* On compatible hardware, use SW aksv */
	reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io,
			SEC_CTRL_HW_VERSION);
	if (reg_val >= HDCP_SEL_MIN_SEC_VERSION) {
		reg_val = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io,
				QFPROM_RAW_FEAT_CONFIG_ROW0_MSB +
				QFPROM_RAW_VERSION_4);
		if (!(reg_val & BIT(23)))
			use_sw_keys = true;
	}

	if (use_sw_keys) {
		if (hdcp1_set_keys(&qfprom_aksv_msb, &qfprom_aksv_lsb)) {
			pr_err("%s: setting of hdcp SW keys failed\n",
						__func__);
			rc = -EINVAL;
			goto error;
		}
	} else {
		/* Fetch aksv from QFPROM, this info should be public. */
		ksv_lsb_addr = HDCP_KSV_LSB;
		ksv_msb_addr = HDCP_KSV_MSB;
@@ -293,6 +313,7 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
			ksv_lsb_addr);
		qfprom_aksv_msb = DSS_REG_R(hdcp_ctrl->init_data.qfprom_io,
			ksv_msb_addr);
	}

	aksv[0] =  qfprom_aksv_lsb        & 0xFF;
	aksv[1] = (qfprom_aksv_lsb >> 8)  & 0xFF;
+24 −7
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/types.h>
#include <linux/msm_hdmi.h>
#include <linux/hdcp_qseecom.h>

#define REG_DUMP 0

@@ -395,11 +396,24 @@ static bool hdmi_tx_is_cea_format(int mode)

static inline bool hdmi_tx_is_hdcp_enabled(struct hdmi_tx_ctrl *hdmi_ctrl)
{
	if (hdmi_ctrl->hdcp_feature_on &&
		(hdmi_ctrl->hdcp14_present || hdmi_ctrl->hdcp22_present))
		return true;
	bool ret = false;

	return false;
	if (hdmi_ctrl->hdcp_feature_on) {
		if (hdmi_ctrl->hdcp14_present) {
			/* Check to see if sw keys are available */
			if (hdmi_ctrl->hdcp14_sw_keys) {
				u32 m_aksv, l_aksv;

				ret = !hdcp1_set_keys(&m_aksv, &l_aksv);
			} else {
				ret = true;
			}
		}
		if (hdmi_ctrl->hdcp22_present)
			ret = true;
	}

	return ret;
}

static const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
@@ -1476,6 +1490,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
{
	u32 hdmi_disabled, hdcp_disabled, reg_val;
	bool sw_keys = false;
	struct dss_io_data *io = NULL;

	if (!hdmi_ctrl) {
@@ -1502,14 +1517,15 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
		hdmi_disabled = reg_val & BIT(13);
		reg_val = DSS_REG_R_ND(io, SEC_CTRL_HW_VERSION);
		/*
		 * With HDCP enabled on HDCP 2.2 capable hardware, check if HW
		 * or SW keys should be used. If using SW keys, disable HDCP 1.4
		 * With HDCP enabled on capable hardware, check if HW
		 * or SW keys should be used.
		 */
		if (!hdcp_disabled && (reg_val >= HDCP_SEL_MIN_SEC_VERSION)) {
			reg_val = DSS_REG_R_ND(io,
				QFPROM_RAW_FEAT_CONFIG_ROW0_MSB +
				QFPROM_RAW_VERSION_4);
			hdcp_disabled = !(reg_val & BIT(23));
			if (!(reg_val & BIT(23)))
				sw_keys = true;
		}
	}

@@ -1526,6 +1542,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
		DEV_WARN("%s: HDCP disabled\n", __func__);
	} else {
		hdmi_ctrl->hdcp14_present = 1;
		hdmi_ctrl->hdcp14_sw_keys = sw_keys;
		DEV_DBG("%s: Device is HDCP enabled\n", __func__);
	}

+1 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ struct hdmi_tx_ctrl {
	u32 hdcp14_present;
	bool audio_ack_enabled;
	atomic_t audio_ack_pending;
	bool hdcp14_sw_keys;

	u8 spd_vendor_name[9];
	u8 spd_product_description[17];