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

Commit e06c83bc authored by Xiaowen Wu's avatar Xiaowen Wu Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/dp: use dp_msm_sim for dp-mst simulation



Revert changes in dp mst topology manager and use dp_msm_sim bridge
at aux layer to implement dp-mst simulation.

Change-Id: I863649f901ac918f65c9078e6a2f1b6931d19e3a
Signed-off-by: default avatarXiaowen Wu <wxiaowen@codeaurora.org>
parent 48bc7e31
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ struct dp_aux_private {
	struct drm_dp_aux drm_aux;

	struct msm_dp_aux_bridge *aux_bridge;
	struct msm_dp_aux_bridge *sim_bridge;
	bool bridge_in_transfer;

	bool cmd_busy;
@@ -480,6 +481,12 @@ static int dp_aux_transfer_ready(struct dp_aux_private *aux,
	return ret;
}

static inline bool dp_aux_is_sideband_msg(u32 address, size_t size)
{
	return (address >= 0x1000 && address + size < 0x1800) ||
			(address >= 0x2000 && address + size < 0x2200);
}

static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
		struct drm_dp_aux_msg *msg)
{
@@ -501,7 +508,8 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
		goto end;
	}

	if ((msg->address + msg->size) > SZ_4K) {
	if ((msg->address + msg->size) > SZ_4K &&
		!dp_aux_is_sideband_msg(msg->address, msg->size)) {
		pr_debug("invalid dpcd access: addr=0x%x, size=0x%lx\n",
				msg->address, msg->size);
		goto address_error;
@@ -514,7 +522,17 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,

		reinit_completion(&aux->comp);

		if (aux->read) {
		if (dp_aux_is_sideband_msg(msg->address, msg->size)) {
			if (!aux->sim_bridge || !aux->sim_bridge->transfer) {
				pr_err("no mst bridge available\n");
				atomic_set(&aux->aborted, 1);
				ret = -ETIMEDOUT;
				goto end;
			}

			ret = aux->sim_bridge->transfer(aux->sim_bridge,
				drm_aux, msg);
		} else if (aux->read) {
			timeout = wait_for_completion_timeout(&aux->comp, HZ);
			if (!timeout) {
				pr_err("read timeout 0x%x\n", msg->address);
@@ -765,7 +783,7 @@ static void dp_aux_dpcd_updated(struct dp_aux *dp_aux)
}

static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en,
		u8 *edid, u8 *dpcd)
		u8 *edid, u8 *dpcd, struct msm_dp_aux_bridge *sim_bridge)
{
	struct dp_aux_private *aux;

@@ -780,6 +798,7 @@ static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en,

	aux->edid = edid;
	aux->dpcd = dpcd;
	aux->sim_bridge = sim_bridge;

	if (en) {
		atomic_set(&aux->aborted, 0);
+2 −1
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ struct dp_aux {
	void (*reconfig)(struct dp_aux *aux);
	void (*abort)(struct dp_aux *aux, bool reset);
	void (*dpcd_updated)(struct dp_aux *aux);
	void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd);
	void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd,
		struct msm_dp_aux_bridge *sim_bridge);
	int (*aux_switch)(struct dp_aux *aux, bool enable, int orientation);
};

+82 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "drm_connector.h"
#include "sde_connector.h"
#include "dp_display.h"
#include <soc/qcom/msm_dp_mst_sim_helper.h>

#define DEBUG_NAME "drm_dp"

@@ -53,8 +54,73 @@ struct dp_debug_private {
	struct dp_ctrl *ctrl;
	struct dp_power *power;
	struct mutex lock;
	struct msm_dp_aux_bridge *sim_bridge;
};

static int dp_debug_sim_hpd_cb(void *arg, bool hpd, bool hpd_irq)
{
	struct dp_debug_private *debug = arg;

	if (hpd_irq)
		return debug->hpd->simulate_attention(debug->hpd, 0);
	else
		return debug->hpd->simulate_connect(debug->hpd, hpd);
}

static int dp_debug_configure_mst_bridge(struct dp_debug_private *debug)
{
	struct device_node *bridge_node;
	struct msm_dp_mst_sim_port *ports;
	int i, ret;

	static const struct msm_dp_mst_sim_port output_port = {
		false, false, true, 3, false, 0x12,
		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
		0, 0, 2520, 2520, NULL, 0
	};

	if (!debug->sim_bridge) {
		bridge_node = of_parse_phandle(debug->dev->of_node,
			"qcom,dp-aux-bridge-sim", 0);
		if (!bridge_node)
			return 0;
		debug->sim_bridge = of_msm_dp_aux_find_bridge(bridge_node);
	}

	if (!debug->sim_bridge)
		return -EINVAL;

	if (debug->sim_bridge->register_hpd) {
		ret = debug->sim_bridge->register_hpd(debug->sim_bridge,
			dp_debug_sim_hpd_cb, debug);
		if (ret)
			return ret;
	}

	if (!debug->dp_debug.mst_port_cnt || !debug->sim_bridge->mst_ctx)
		return 0;

	ports = kcalloc(debug->dp_debug.mst_port_cnt,
		sizeof(*ports), GFP_KERNEL);
	if (!ports)
		return -ENOMEM;

	for (i = 0; i < debug->dp_debug.mst_port_cnt; i++) {
		memcpy(&ports[i], &output_port, sizeof(*ports));
		ports[i].peer_guid[0] = i;
		ports[i].edid = debug->edid;
		ports[i].edid_size = debug->edid_size;
	}

	ret = msm_dp_mst_sim_update(debug->sim_bridge->mst_ctx,
		debug->dp_debug.mst_port_cnt, ports);

	kfree(ports);

	return ret;
}

static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
{
	int rc = 0;
@@ -141,7 +207,8 @@ static ssize_t dp_debug_write_edid(struct file *file,

			debug->aux->set_sim_mode(debug->aux,
					debug->dp_debug.sim_mode,
					debug->edid, debug->dpcd);
					debug->edid, debug->dpcd,
					debug->sim_bridge);
		}
	}

@@ -175,6 +242,9 @@ static ssize_t dp_debug_write_edid(struct file *file,
	 */
	pr_info("[%s]\n", edid ? "SET" : "CLEAR");

	if (dp_debug_configure_mst_bridge(debug))
		pr_err("failed to config mst bridge\n");

	mutex_unlock(&debug->lock);
	return rc;
}
@@ -699,10 +769,13 @@ static ssize_t dp_debug_mst_sideband_mode_write(struct file *file,
		return -EINVAL;
	}

	debug->parser->has_mst_sideband = mst_sideband_mode ? true : false;
	debug->dp_debug.mst_port_cnt = mst_port_cnt;
	pr_debug("mst_sideband_mode: %d port_cnt:%d\n",
			mst_sideband_mode, mst_port_cnt);

	if (dp_debug_configure_mst_bridge(debug))
		pr_err("failed to config mst bridge\n");

	return count;
}

@@ -1483,10 +1556,14 @@ static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim)
			return;
		}

		if (dp_debug_configure_mst_bridge(debug))
			pr_err("failed to config mst bridge\n");

		debug->dp_debug.mst_hpd_sim = true;
		debug->dp_debug.sim_mode = true;
		debug->power->sim_mode = true;
		debug->aux->set_sim_mode(debug->aux, true,
			debug->edid, debug->dpcd);
			debug->edid, debug->dpcd, debug->sim_bridge);
	} else {

		if (debug->hotplug) {
@@ -1498,9 +1575,10 @@ static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim)
		debug->aux->abort(debug->aux, false);
		debug->ctrl->abort(debug->ctrl, false);

		debug->aux->set_sim_mode(debug->aux, false, NULL, NULL);
		debug->aux->set_sim_mode(debug->aux, false, NULL, NULL, NULL);
		debug->power->sim_mode = false;
		debug->dp_debug.sim_mode = false;
		debug->dp_debug.mst_hpd_sim = false;

		debug->panel->set_edid(debug->panel, 0);
		if (debug->edid) {
+6 −19
Original line number Diff line number Diff line
@@ -673,7 +673,6 @@ static void dp_display_process_mst_hpd_high(struct dp_display_private *dp,
						bool mst_probe)
{
	bool is_mst_receiver;
	struct dp_mst_hpd_info info;
	const int clear_mstm_ctrl_timeout = 100000;
	u8 old_mstm_ctrl;
	int ret;
@@ -716,12 +715,8 @@ static void dp_display_process_mst_hpd_high(struct dp_display_private *dp,

		dp_display_update_mst_state(dp, true);
	} else if (dp->mst.mst_active && mst_probe) {
		info.mst_protocol = dp->parser->has_mst_sideband;
		info.mst_port_cnt = dp->debug->mst_port_cnt;
		info.edid = dp->debug->get_edid(dp->debug);

		if (dp->mst.cbs.hpd)
			dp->mst.cbs.hpd(&dp->dp_display, true, &info);
			dp->mst.cbs.hpd(&dp->dp_display, true);
	}

	DP_MST_DEBUG("mst_hpd_high. mst_active:%d\n", dp->mst.mst_active);
@@ -839,15 +834,12 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)

static void dp_display_process_mst_hpd_low(struct dp_display_private *dp)
{
	struct dp_mst_hpd_info info = {0};

	if (dp->mst.mst_active) {
		DP_MST_DEBUG("mst_hpd_low work\n");

		if (dp->mst.cbs.hpd) {
			info.mst_protocol = dp->parser->has_mst_sideband;
			dp->mst.cbs.hpd(&dp->dp_display, false, &info);
		}
		if (dp->mst.cbs.hpd)
			dp->mst.cbs.hpd(&dp->dp_display, false);

		dp_display_update_mst_state(dp, false);
	}

@@ -1102,13 +1094,8 @@ static int dp_display_stream_enable(struct dp_display_private *dp,

static void dp_display_mst_attention(struct dp_display_private *dp)
{
	struct dp_mst_hpd_info hpd_irq = {0};

	if (dp->mst.mst_active && dp->mst.cbs.hpd_irq) {
		hpd_irq.mst_hpd_sim = dp->debug->mst_hpd_sim;
		dp->mst.cbs.hpd_irq(&dp->dp_display, &hpd_irq);
		dp->debug->mst_hpd_sim = false;
	}
	if (dp->mst.mst_active && dp->mst.cbs.hpd_irq)
		dp->mst.cbs.hpd_irq(&dp->dp_display);

	DP_MST_DEBUG("mst_attention_work. mst_active:%d\n", dp->mst.mst_active);
}
+2 −10
Original line number Diff line number Diff line
@@ -28,17 +28,9 @@ enum dp_drv_state {
	PM_SUSPEND,
};

struct dp_mst_hpd_info {
	bool mst_protocol;
	bool mst_hpd_sim;
	u32 mst_port_cnt;
	u8 *edid;
};

struct dp_mst_drm_cbs {
	void (*hpd)(void *display, bool hpd_status,
			struct dp_mst_hpd_info *info);
	void (*hpd_irq)(void *display, struct dp_mst_hpd_info *info);
	void (*hpd)(void *display, bool hpd_status);
	void (*hpd_irq)(void *display);
	void (*set_drv_state)(void *dp_display,
			enum dp_drv_state mst_state);
};
Loading