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

Commit 7038f0a6 authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

msm: mdss: dp: add hdcp support to display-port



Initialize the hdcp 1.x module and get hdcp operations.
On DP power, start the hdcp authentication and handle
the result in a call back. Re-authenticate in case
authentication failed. When DP is powered off, tear down
the hdcp session.

Change-Id: Ia321ab17bc9f9aeec1078d6f5199582f9b410b94
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 008f057b
Loading
Loading
Loading
Loading
+125 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include "mdss_dp.h"
#include "mdss_dp_util.h"
#include "mdss_hdmi_panel.h"
#include <linux/hdcp_qseecom.h>
#include "mdss_hdmi_hdcp.h"
#include "mdss_debug.h"

#define RGB_COMPONENTS		3
@@ -982,6 +984,8 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
	if (mdss_dp_mainlink_ready(dp_drv, BIT(0)))
		pr_debug("mainlink ready\n");

	dp_drv->power_on = true;

	mutex_unlock(&dp_drv->host_mutex);
	pr_debug("End-\n");

@@ -1031,6 +1035,7 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
	pr_debug("End--: state_ctrl=%x\n",
				dp_read(dp_drv->base + DP_STATE_CTRL));

	dp_drv->power_on = false;
	mutex_unlock(&dp_drv->train_mutex);
	return 0;
}
@@ -1214,12 +1219,105 @@ end:
	return rc;
}

static void mdss_dp_hdcp_cb(void *ptr, enum hdmi_hdcp_state status)
{
	struct mdss_dp_drv_pdata *dp = ptr;
	struct hdmi_hdcp_ops *ops;
	int rc = 0;

	if (!dp) {
		pr_debug("invalid input\n");
		return;
	}

	ops = dp->hdcp_ops;

	mutex_lock(&dp->train_mutex);

	switch (status) {
	case HDCP_STATE_AUTHENTICATED:
		pr_debug("hdcp 1.3 authenticated\n");
		break;
	case HDCP_STATE_AUTH_FAIL:
		if (dp->power_on) {
			pr_debug("Reauthenticating\n");
			if (ops && ops->hdmi_hdcp_reauthenticate) {
				rc = ops->hdmi_hdcp_reauthenticate(
					dp->hdcp_data);
				if (rc)
					pr_err("HDCP reauth failed. rc=%d\n",
						rc);
			}
		} else {
			pr_debug("not reauthenticating, cable disconnected\n");
		}

		break;
	default:
		break;
	}

	mutex_unlock(&dp->train_mutex);
}

static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata)
{
	struct hdmi_hdcp_init_data hdcp_init_data = {0};
	struct mdss_dp_drv_pdata *dp_drv = NULL;
	struct resource *res;
	int rc = 0;

	if (!pdata) {
		pr_err("Invalid input data\n");
		goto error;
	}

	dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
			panel_data);

	res = platform_get_resource_byname(dp_drv->pdev,
		IORESOURCE_MEM, "dp_ctrl");
	if (!res) {
		pr_err("Error getting dp ctrl resource\n");
		rc = -EINVAL;
		goto error;
	}

	hdcp_init_data.phy_addr      = res->start;
	hdcp_init_data.core_io       = &dp_drv->ctrl_io;
	hdcp_init_data.qfprom_io     = &dp_drv->qfprom_io;
	hdcp_init_data.hdcp_io       = &dp_drv->hdcp_io;
	hdcp_init_data.mutex         = &dp_drv->hdcp_mutex;
	hdcp_init_data.sysfs_kobj    = dp_drv->kobj;
	hdcp_init_data.workq         = dp_drv->workq;
	hdcp_init_data.notify_status = mdss_dp_hdcp_cb;
	hdcp_init_data.cb_data       = (void *)dp_drv;
	hdcp_init_data.sec_access    = true;
	hdcp_init_data.client_id     = HDCP_CLIENT_DP;

	dp_drv->hdcp_data = hdmi_hdcp_init(&hdcp_init_data);
	if (IS_ERR_OR_NULL(dp_drv->hdcp_data)) {
		pr_err("Error hdcp init\n");
		rc = -EINVAL;
		goto error;
	}

	pr_debug("HDCP 1.3 initialized\n");

	dp_drv->hdcp_ops = hdmi_hdcp_start(dp_drv->hdcp_data);

	return 0;
error:
	return rc;
}

static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
				  int event, void *arg)
{
	int rc = 0;
	struct fb_info *fbi;
	struct mdss_dp_drv_pdata *dp = NULL;
	struct hdmi_hdcp_ops *ops;

	if (!pdata) {
		pr_err("%s: Invalid input data\n", __func__);
@@ -1231,13 +1329,25 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
	dp = container_of(pdata, struct mdss_dp_drv_pdata,
				panel_data);

	ops = dp->hdcp_ops;

	switch (event) {
	case MDSS_EVENT_UNBLANK:
		rc = mdss_dp_on(pdata);
		break;
	case MDSS_EVENT_PANEL_ON:
		if (hdcp1_check_if_supported_load_app()) {
			if (ops && ops->hdmi_hdcp_authenticate)
				rc = ops->hdmi_hdcp_authenticate(dp->hdcp_data);
		}
		break;
	case MDSS_EVENT_PANEL_OFF:
		rc = mdss_dp_off(pdata);
		break;
	case MDSS_EVENT_BLANK:
		if (ops && ops->hdmi_hdcp_off)
			ops->hdmi_hdcp_off(dp->hdcp_data);
		break;
	case MDSS_EVENT_FB_REGISTERED:
		fbi = (struct fb_info *)arg;
		if (!fbi || !fbi->dev)
@@ -1246,6 +1356,7 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
		dp->kobj = &fbi->dev->kobj;
		dp->fb_node = fbi->node;
		mdss_dp_edid_init(pdata);
		mdss_dp_hdcp_init(pdata);
		mdss_dp_register_switch_event(dp);
		break;
	case MDSS_EVENT_CHECK_PARAMS:
@@ -1339,6 +1450,14 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev,
		return rc;
	}

	if (msm_dss_ioremap_byname(pdev, &dp_drv->qfprom_io,
					"qfprom_physical"))
		pr_warn("unable to remap dp qfprom resources\n");

	if (msm_dss_ioremap_byname(pdev, &dp_drv->hdcp_io,
					"hdcp_physical"))
		pr_warn("unable to remap dp hdcp resources\n");

	pr_debug("DP Driver base=%p size=%x\n",
		dp_drv->base, dp_drv->base_size);

@@ -1501,6 +1620,11 @@ irqreturn_t dp_isr(int irq, void *ptr)
			dp_aux_native_handler(dp, isr1);
	}

	if (dp->hdcp_ops && dp->hdcp_ops->hdmi_hdcp_isr) {
		if (dp->hdcp_ops->hdmi_hdcp_isr(dp->hdcp_data))
			pr_err("isr failed\n");
	}

	return IRQ_HANDLED;
}

@@ -1723,6 +1847,7 @@ static int mdss_dp_probe(struct platform_device *pdev)
	mutex_init(&dp_drv->emutex);
	mutex_init(&dp_drv->host_mutex);
	mutex_init(&dp_drv->pd_msg_mutex);
	mutex_init(&dp_drv->hdcp_mutex);
	spin_lock_init(&dp_drv->lock);

	if (mdss_dp_usbpd_setup(dp_drv)) {
+7 −0
Original line number Diff line number Diff line
@@ -345,12 +345,15 @@ struct mdss_dp_drv_pdata {
	bool core_power;
	bool core_clks_on;
	bool link_clks_on;
	bool power_on;

	/* dp specific */
	unsigned char *base;
	struct dss_io_data ctrl_io;
	struct dss_io_data phy_io;
	struct dss_io_data tcsr_reg_io;
	struct dss_io_data qfprom_io;
	struct dss_io_data hdcp_io;
	int base_size;
	unsigned char *mmss_cc_base;
	u32 mask1;
@@ -397,6 +400,7 @@ struct mdss_dp_drv_pdata {
	struct mutex train_mutex;
	struct mutex host_mutex;
	struct mutex pd_msg_mutex;
	struct mutex hdcp_mutex;
	bool cable_connected;
	u32 aux_cmd_busy;
	u32 aux_cmd_i2c;
@@ -430,6 +434,9 @@ struct mdss_dp_drv_pdata {
	u32 vic;
	u32 new_vic;
	int fb_node;

	void *hdcp_data;
	struct hdmi_hdcp_ops *hdcp_ops;
};

static inline const char *__mdss_dp_pm_name(enum dp_pm_type module)
+1 −1
Original line number Diff line number Diff line
@@ -355,7 +355,7 @@ static int dp_aux_write_buf(struct mdss_dp_drv_pdata *ep, u32 addr,
static int dp_aux_read_buf(struct mdss_dp_drv_pdata *ep, u32 addr,
				int len, int i2c)
{
	struct edp_cmd cmd;
	struct edp_cmd cmd = {0};

	cmd.read = 1;
	cmd.i2c = i2c;
+1 −0
Original line number Diff line number Diff line
@@ -1803,6 +1803,7 @@ static int hdmi_tx_init_hdcp(struct hdmi_tx_ctrl *hdmi_ctrl)
	hdcp_init_data.hdmi_tx_ver   = hdmi_ctrl->hdmi_tx_major_version;
	hdcp_init_data.sec_access    = true;
	hdcp_init_data.timing        = &hdmi_ctrl->timing;
	hdcp_init_data.client_id     = HDCP_CLIENT_HDMI;

	if (hdmi_ctrl->hdcp14_present) {
		hdcp_data = hdmi_hdcp_init(&hdcp_init_data);