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

Commit 29ba1c51 authored by Divya Sharma's avatar Divya Sharma
Browse files

Revert "drm/msm/dp: fix hdcp version check at sink"



This reverts commit 731db77a.

Change-Id: Ibff3e458e99e5efa595b3f5874cf5b68037300a2
Signed-off-by: default avatarDivya Sharma <divyash@codeaurora.org>
parent e93d470c
Loading
Loading
Loading
Loading
+0 −65
Original line number Diff line number Diff line
@@ -598,56 +598,6 @@ static ssize_t dp_debug_read_connected(struct file *file,
	return len;
}

static ssize_t dp_debug_write_hdcp(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	char buf[SZ_8];
	size_t len = 0;
	int hdcp = 0;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		return 0;

	/* Leave room for termination char */
	len = min_t(size_t, count, SZ_8 - 1);
	if (copy_from_user(buf, user_buff, len))
		goto end;

	buf[len] = '\0';

	if (kstrtoint(buf, 10, &hdcp) != 0)
		goto end;

	debug->dp_debug.hdcp_disabled = !hdcp;
end:
	return len;
}

static ssize_t dp_debug_read_hdcp(struct file *file,
		char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	u32 len = 0;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		return 0;

	len = sizeof(debug->dp_debug.hdcp_status);

	if (copy_to_user(user_buff, debug->dp_debug.hdcp_status, len))
		return -EFAULT;

	*ppos += len;
	return len;
}

static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len)
{
	if (rc >= *max_size) {
@@ -1287,12 +1237,6 @@ static const struct file_operations max_pclk_khz_fops = {
	.read = dp_debug_max_pclk_khz_read,
};

static const struct file_operations hdcp_fops = {
	.open = simple_open,
	.write = dp_debug_write_hdcp,
	.read = dp_debug_read_hdcp,
};

static int dp_debug_init(struct dp_debug *dp_debug)
{
	int rc = 0;
@@ -1468,15 +1412,6 @@ static int dp_debug_init(struct dp_debug *dp_debug)
		goto error_remove_dir;
	}

	file = debugfs_create_file("hdcp", 0644, dir,
					debug, &hdcp_fops);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs hdcp failed, rc=%d\n",
			DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	return 0;

error_remove_dir:
+0 −2
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ struct dp_debug {
	bool debug_en;
	bool sim_mode;
	bool psm_enabled;
	bool hdcp_disabled;
	int aspect_ratio;
	int vdisplay;
	int hdisplay;
@@ -42,7 +41,6 @@ struct dp_debug {
	bool tpg_state;
	u32 max_pclk_khz;
	bool force_encryption;
	char hdcp_status[SZ_128];

	u8 *(*get_edid)(struct dp_debug *dp_debug);
};
+76 −124
Original line number Diff line number Diff line
@@ -43,19 +43,14 @@
static struct dp_display *g_dp_display;
#define HPD_STRING_SIZE 30

struct dp_hdcp_dev {
	void *fd;
	struct sde_hdcp_ops *ops;
	enum sde_hdcp_version ver;
};

struct dp_hdcp {
	void *data;
	struct sde_hdcp_ops *ops;

	u32 source_cap;
	void *hdcp1;
	void *hdcp2;

	struct dp_hdcp_dev dev[HDCP_VERSION_MAX];
	bool feature_enabled;
};

struct dp_mst {
@@ -121,7 +116,8 @@ static bool dp_display_framework_ready(struct dp_display_private *dp)

static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp)
{
	return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops;
	return dp->hdcp.feature_enabled && dp->link->hdcp_status.hdcp_version
		&& dp->hdcp.ops;
}

static irqreturn_t dp_display_irq(int irq, void *dev_id)
@@ -166,83 +162,16 @@ static bool dp_display_is_ready(struct dp_display_private *dp)
		dp->hpd->alt_mode_cfg_done;
}

static void dp_display_update_hdcp_status(struct dp_display_private *dp,
					bool reset)
{
	if (reset) {
		dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE;
		dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE;
	}

	memset(dp->debug->hdcp_status, 0, sizeof(dp->debug->hdcp_status));

	snprintf(dp->debug->hdcp_status, sizeof(dp->debug->hdcp_status),
		"%s: %s\ncaps: %d\n",
		sde_hdcp_version(dp->link->hdcp_status.hdcp_version),
		sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state),
		dp->hdcp.source_cap);
}

static void dp_display_update_hdcp_info(struct dp_display_private *dp)
{
	void *fd = NULL;
	struct dp_hdcp_dev *dev = NULL;
	struct sde_hdcp_ops *ops = NULL;
	int i = HDCP_VERSION_2P2;

	dp_display_update_hdcp_status(dp, true);

	dp->hdcp.data = NULL;
	dp->hdcp.ops = NULL;

	if (dp->debug->hdcp_disabled || dp->debug->sim_mode)
		return;

	while (i) {
		dev = &dp->hdcp.dev[i];
		ops = dev->ops;
		fd = dev->fd;

		i >>= 1;

		if (!(dp->hdcp.source_cap & dev->ver))
			continue;

		if (ops->sink_support(fd)) {
			dp->hdcp.data = fd;
			dp->hdcp.ops = ops;
			dp->link->hdcp_status.hdcp_version = dev->ver;
			break;
		}
	}

	pr_debug("HDCP version supported: %s\n",
		sde_hdcp_version(dp->link->hdcp_status.hdcp_version));
}

static void dp_display_hdcp_cb_work(struct work_struct *work)
{
	struct dp_display_private *dp;
	struct delayed_work *dw = to_delayed_work(work);
	struct sde_hdcp_ops *ops;
	struct dp_link_hdcp_status *status;
	void *data;
	int rc = 0;
	u32 hdcp_auth_state;

	dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
	status = &dp->link->hdcp_status;

	if (status->hdcp_state == HDCP_STATE_INACTIVE) {
		dp_display_update_hdcp_info(dp);

		if (dp_display_is_hdcp_enabled(dp)) {
			status->hdcp_state = HDCP_STATE_AUTHENTICATING;
		} else {
			dp_display_update_hdcp_status(dp, true);
			return;
		}
	}

	rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl);
	if (rc >= 0) {
@@ -253,15 +182,14 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
	ops = dp->hdcp.ops;
	data = dp->hdcp.data;

	pr_debug("%s: %s\n", sde_hdcp_version(status->hdcp_version),
		sde_hdcp_state_name(status->hdcp_state));

	dp_display_update_hdcp_status(dp, false);
	pr_debug("%s: %s\n",
		sde_hdcp_version(dp->link->hdcp_status.hdcp_version),
		sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state));

	if (dp->debug->force_encryption && ops && ops->force_encryption)
		ops->force_encryption(data, dp->debug->force_encryption);

	switch (status->hdcp_state) {
	switch (dp->link->hdcp_status.hdcp_state) {
	case HDCP_STATE_AUTHENTICATING:
		if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
			rc = dp->hdcp.ops->authenticate(data);
@@ -298,35 +226,62 @@ static void dp_display_notify_hdcp_status_cb(void *ptr,
		queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ/4);
}

static void dp_display_check_source_hdcp_caps(struct dp_display_private *dp)
static void dp_display_update_hdcp_info(struct dp_display_private *dp)
{
	int i;
	struct dp_hdcp_dev *hdcp_dev = dp->hdcp.dev;
	void *fd = NULL;
	struct sde_hdcp_ops *ops = NULL;
	bool hdcp2_present = false, hdcp1_present = false;

	if (dp->debug->hdcp_disabled) {
		pr_debug("hdcp disabled\n");
	if (!dp) {
		pr_err("invalid input\n");
		return;
	}

	for (i = 0; i < HDCP_VERSION_MAX; i++) {
		struct dp_hdcp_dev *dev = &hdcp_dev[i];
		struct sde_hdcp_ops *ops = dev->ops;
		void *fd = dev->fd;
	dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE;
	dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE;

		if (!fd || !ops)
			continue;
	if (!dp->hdcp.feature_enabled) {
		pr_debug("feature not enabled\n");
		return;
	}

		if (ops->feature_supported(fd))
			dp->hdcp.source_cap |= dev->ver;
		else
			pr_warn("This device doesn't support %s\n",
				sde_hdcp_version(dev->ver));
	if (dp->debug->sim_mode) {
		pr_debug("skip HDCP version checks for simulation mode\n");
		return;
	}

	if (!dp->hdcp.source_cap)
		dp->debug->hdcp_disabled = true;
	fd = dp->hdcp.hdcp2;
	if (fd)
		ops = sde_dp_hdcp2p2_start(fd);

	if (ops && ops->feature_supported)
		hdcp2_present = ops->feature_supported(fd);

	if (hdcp2_present)
		dp->link->hdcp_status.hdcp_version = HDCP_VERSION_2P2;

	dp_display_update_hdcp_status(dp, false);
	if (!hdcp2_present) {
		fd = dp->hdcp.hdcp1;
		if (fd)
			ops = sde_hdcp_1x_start(fd);

		if (ops && ops->feature_supported)
			hdcp1_present = ops->feature_supported(fd);

		if (hdcp1_present)
			dp->link->hdcp_status.hdcp_version = HDCP_VERSION_1X;
	}

	if (hdcp2_present || hdcp1_present) {
		dp->hdcp.data = fd;
		dp->hdcp.ops = ops;
	} else {
		dp->hdcp.data = NULL;
		dp->hdcp.ops = NULL;
	}

	pr_debug("HDCP version supported: %s\n",
		sde_hdcp_version(dp->link->hdcp_status.hdcp_version));
}

static void dp_display_deinitialize_hdcp(struct dp_display_private *dp)
@@ -343,7 +298,6 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp)
{
	struct sde_hdcp_init_data hdcp_init_data;
	struct dp_parser *parser;
	void *fd;
	int rc = 0;

	if (!dp) {
@@ -370,35 +324,29 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp)
	hdcp_init_data.revision      = &dp->panel->link_info.revision;
	hdcp_init_data.msm_hdcp_dev  = dp->parser->msm_hdcp_dev;

	fd = sde_hdcp_1x_init(&hdcp_init_data);
	if (IS_ERR_OR_NULL(fd)) {
	dp->hdcp.hdcp1 = sde_hdcp_1x_init(&hdcp_init_data);
	if (IS_ERR_OR_NULL(dp->hdcp.hdcp1)) {
		pr_err("Error initializing HDCP 1.x\n");
		rc = -EINVAL;
		goto error;
	}

	dp->hdcp.dev[HDCP_VERSION_1X].fd = fd;
	dp->hdcp.dev[HDCP_VERSION_1X].ops = sde_hdcp_1x_get(fd);
	dp->hdcp.dev[HDCP_VERSION_1X].ver = HDCP_VERSION_1X;
	pr_debug("HDCP 1.3 initialized\n");

	fd = sde_dp_hdcp2p2_init(&hdcp_init_data);
	if (IS_ERR_OR_NULL(fd)) {
	dp->hdcp.hdcp2 = sde_dp_hdcp2p2_init(&hdcp_init_data);
	if (IS_ERR_OR_NULL(dp->hdcp.hdcp2)) {
		pr_err("Error initializing HDCP 2.x\n");
		rc = -EINVAL;
		goto error;
	}

	dp->hdcp.dev[HDCP_VERSION_2P2].fd = fd;
	dp->hdcp.dev[HDCP_VERSION_2P2].ops = sde_dp_hdcp2p2_get(fd);
	dp->hdcp.dev[HDCP_VERSION_2P2].ver = HDCP_VERSION_2P2;
	pr_debug("HDCP 2.2 initialized\n");

	dp->hdcp.feature_enabled = true;

	return 0;
error:
	dp_display_deinitialize_hdcp(dp);
	dp->debug->hdcp_disabled = true;

	return rc;
}

@@ -527,9 +475,6 @@ static void dp_display_post_open(struct dp_display *dp_display)
		return;
	}

	dp_display_update_hdcp_status(dp, true);
	dp_display_check_source_hdcp_caps(dp);

	/* if cable is already connected, send notification */
	if (dp->hpd->hpd_high)
		queue_delayed_work(dp->wq, &dp->connect_work, HZ * 10);
@@ -775,11 +720,11 @@ static void dp_display_clean(struct dp_display_private *dp)
	struct dp_panel *dp_panel;

	if (dp_display_is_hdcp_enabled(dp)) {
		dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE;

		cancel_delayed_work_sync(&dp->hdcp_cb_work);
		if (dp->hdcp.ops->off)
			dp->hdcp.ops->off(dp->hdcp.data);

		dp_display_update_hdcp_status(dp, true);
	}

	for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) {
@@ -918,7 +863,7 @@ static void dp_display_attention_work(struct work_struct *work)
			struct dp_display_private, attention_work);

	if (dp->link->process_request(dp->link))
		goto cp_irq;
		goto mst_attention;

	if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) {
		if (dp_display_is_sink_count_zero(dp)) {
@@ -954,7 +899,7 @@ static void dp_display_attention_work(struct work_struct *work)

	if (dp->link->sink_request & DP_LINK_STATUS_UPDATED)
		dp->ctrl->link_maintenance(dp->ctrl);
cp_irq:

	if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq)
		dp->hdcp.ops->cp_irq(dp->hdcp.data);
mst_attention:
@@ -1456,8 +1401,15 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
		dp_panel->audio->on(dp_panel->audio);
	}

	dp_display_update_hdcp_info(dp);

	if (dp_display_is_hdcp_enabled(dp)) {
		cancel_delayed_work_sync(&dp->hdcp_cb_work);
	queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ);

		dp->link->hdcp_status.hdcp_state = HDCP_STATE_AUTHENTICATING;
		queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2);
	}

end:
	/* clear framework event notifier */
	dp_display->post_open = NULL;
@@ -1497,11 +1449,11 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
	}

	if (dp_display_is_hdcp_enabled(dp)) {
		dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE;

		cancel_delayed_work_sync(&dp->hdcp_cb_work);
		if (dp->hdcp.ops->off)
			dp->hdcp.ops->off(dp->hdcp.data);

		dp_display_update_hdcp_status(dp, true);
	}

	if (dp_panel->audio_supported)
+31 −28
Original line number Diff line number Diff line
@@ -777,31 +777,6 @@ static int dp_hdcp2p2_isr(void *input)
	return rc;
}

static bool dp_hdcp2p2_supported(void *input)
{
	struct dp_hdcp2p2_ctrl *ctrl = input;
	u32 const rxcaps_dpcd_offset = 0x6921d;
	ssize_t bytes_read = 0;
	u8 buf[DP_HDCP_RXCAPS_LENGTH];

	pr_debug("Checking sink capability\n");

	bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
			rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH);
	if (bytes_read != DP_HDCP_RXCAPS_LENGTH) {
		pr_err("RxCaps read failed\n");
		goto error;
	}

	pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1);
	pr_debug("VERSION=%d\n", buf[0]);

	if ((buf[2] & BIT(1)) && (buf[0] == 0x2))
		return true;
error:
	return false;
}

void sde_dp_hdcp2p2_deinit(void *input)
{
	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
@@ -834,7 +809,6 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
		.authenticate = dp_hdcp2p2_authenticate,
		.feature_supported = dp_hdcp2p2_feature_supported,
		.force_encryption = dp_hdcp2p2_force_encryption,
		.sink_support = dp_hdcp2p2_supported,
		.off = dp_hdcp2p2_off,
		.cp_irq = dp_hdcp2p2_cp_irq,
	};
@@ -926,8 +900,37 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
	return ERR_PTR(rc);
}

struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input)
static bool dp_hdcp2p2_supported(struct dp_hdcp2p2_ctrl *ctrl)
{
	u32 const rxcaps_dpcd_offset = 0x6921d;
	ssize_t bytes_read = 0;
	u8 buf[DP_HDCP_RXCAPS_LENGTH];

	bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
			rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH);
	if (bytes_read != DP_HDCP_RXCAPS_LENGTH) {
		pr_err("RxCaps read failed\n");
		goto error;
	}

	pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1);
	pr_debug("VERSION=%d\n", buf[0]);

	if ((buf[2] & BIT(1)) && (buf[0] == 0x2))
		return true;

error:
	return false;
}

struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input)
{
	return ((struct dp_hdcp2p2_ctrl *)input)->ops;
	struct dp_hdcp2p2_ctrl *ctrl = input;

	pr_debug("Checking sink capability\n");
	if (dp_hdcp2p2_supported(ctrl))
		return ctrl->ops;
	else
		return NULL;
}
+4 −6
Original line number Diff line number Diff line
@@ -40,9 +40,8 @@ enum sde_hdcp_state {

enum sde_hdcp_version {
	HDCP_VERSION_NONE,
	HDCP_VERSION_1X = BIT(0),
	HDCP_VERSION_2P2 = BIT(1),
	HDCP_VERSION_MAX = BIT(2),
	HDCP_VERSION_1X,
	HDCP_VERSION_2P2
};

struct sde_hdcp_init_data {
@@ -73,7 +72,6 @@ struct sde_hdcp_ops {
	int (*authenticate)(void *hdcp_ctrl);
	bool (*feature_supported)(void *input);
	void (*force_encryption)(void *input, bool enable);
	bool (*sink_support)(void *input);
	void (*off)(void *hdcp_ctrl);
};

@@ -100,8 +98,8 @@ static inline const char *sde_hdcp_version(enum sde_hdcp_version hdcp_version)

void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data);
void sde_hdcp_1x_deinit(void *input);
struct sde_hdcp_ops *sde_hdcp_1x_get(void *input);
struct sde_hdcp_ops *sde_hdcp_1x_start(void *input);
void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data);
void sde_dp_hdcp2p2_deinit(void *input);
struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input);
struct sde_hdcp_ops *sde_dp_hdcp2p2_start(void *input);
#endif /* __SDE_HDCP_H__ */
Loading