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

Commit f63dbc7a authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

drm/msm/dp: synchronize the usbpd and drm events



USBPD delivers cable connect/disconnect and other sink related
events. Based on these events, DRM framework issues enable/disable
events. Both USBPD and DRM execute in different threads and depends
on each other. Synchronize USBPD and DRM events to handle different
use cases involving cable connect/disconnect.

CRs-Fixed: 2072336
Change-Id: I88a2e1b72f3ef39438ade5b30997b18b53f07ce2
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent a4b06065
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -131,13 +131,14 @@ static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
		return -ETIMEDOUT;
	}

	pr_debug("aux status %s\n",
	if (aux->aux_error_num == DP_AUX_ERR_NONE) {
		ret = len;
	} else {
		pr_err_ratelimited("aux err: %s\n",
			dp_aux_get_error(aux->aux_error_num));

	if (aux->aux_error_num == DP_AUX_ERR_NONE)
		ret = len;
	else
		ret = -EINVAL;
	}

	return ret;
}
+14 −9
Original line number Diff line number Diff line
@@ -471,6 +471,8 @@ static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u32 cfg)
	dp_catalog_get_priv(ctrl);
	base = catalog->io->ctrl_io.base;

	pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg);

	dp_write(base + DP_CONFIGURATION_CTRL, cfg);
	dp_write(base + DP_MAINLINK_LEVELS, 0xa08);
	dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1);
@@ -507,10 +509,7 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl,
	dp_catalog_get_priv(ctrl);
	base = catalog->io->ctrl_io.base;

	mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);

	if (enable) {
		mainlink_ctrl |= BIT(0);
		dp_write(base + DP_MAINLINK_CTRL, 0x02000000);
		wmb(); /* make sure mainlink is turned off before reset */
		dp_write(base + DP_MAINLINK_CTRL, 0x02000002);
@@ -520,8 +519,9 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl,
		dp_write(base + DP_MAINLINK_CTRL, 0x02000001);
		wmb(); /* make sure mainlink turned on */
	} else {
		mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
		mainlink_ctrl &= ~BIT(0);
		dp_write(base + DP_MAINLINK_CTRL, 0x0);
		dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl);
	}
}

@@ -543,7 +543,7 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl,
	misc_val |= (tb << 5);
	misc_val |= BIT(0); /* Configure clock to synchronous mode */

	pr_debug("isc settings = 0x%x\n", misc_val);
	pr_debug("misc settings = 0x%x\n", misc_val);
	dp_write(base + DP_MISC1_MISC0, misc_val);
}

@@ -572,6 +572,8 @@ static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
	mvid = (pixel_m & 0xFFFF) * 5;
	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);

	pr_debug("rate = %d\n", rate);

	if (link_rate == rate)
		nvid *= 2;

@@ -598,7 +600,7 @@ static void dp_catalog_ctrl_set_pattern(struct dp_catalog_ctrl *ctrl,

	bit = 1;
	bit <<= (pattern - 1);
	pr_debug("bit=%d train=%d\n", bit, pattern);
	pr_debug("hw: bit=%d train=%d\n", bit, pattern);
	dp_write(base + DP_STATE_CTRL, bit);

	bit = 8;
@@ -797,7 +799,7 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl,
	base0 = catalog->io->ln_tx0_io.base;
	base1 = catalog->io->ln_tx1_io.base;

	pr_debug("v=%d p=%d\n", v_level, p_level);
	pr_debug("hw: v=%d p=%d\n", v_level, p_level);

	value0 = vm_voltage_swing[v_level][p_level];
	value1 = vm_pre_emphasis[v_level][p_level];
@@ -819,8 +821,11 @@ static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl,
		dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1);
		dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1);

		pr_debug("host PHY settings: value0=0x%x value1=0x%x",
		pr_debug("hw: vx_value=0x%x px_value=0x%x\n",
			value0, value1);
	} else {
		pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n",
			v_level, value0, p_level, value1);
	}
}

+18 −12
Original line number Diff line number Diff line
@@ -133,6 +133,10 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)

	tbd = ctrl->link->get_test_bits_depth(ctrl->link,
			ctrl->panel->pinfo.bpp);

	if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN)
		tbd = DP_TEST_BIT_DEPTH_8;

	config |= tbd << 8;

	/* Num of Lanes */
@@ -732,14 +736,12 @@ static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl,
		max_level_reached  |= BIT(5);
	}

	pr_debug("max_level_reached = 0x%x\n", max_level_reached);

	pre_emphasis_level <<= 3;

	for (i = 0; i < 4; i++)
		buf[i] = voltage_level | pre_emphasis_level | max_level_reached;

	pr_debug("p|v=0x%x\n", voltage_level | pre_emphasis_level);
	pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level);
	return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4);
}

@@ -747,8 +749,6 @@ static void dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
{
	struct dp_link *link = ctrl->link;

	pr_debug("v=%d p=%d\n", link->v_level, link->p_level);

	ctrl->catalog->update_vx_px(ctrl->catalog,
			link->v_level, link->p_level);

@@ -760,7 +760,7 @@ static void dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
{
	u8 buf[4];

	pr_debug("pattern=%x\n", pattern);
	pr_debug("sink: pattern=%x\n", pattern);

	buf[0] = pattern;
	drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1);
@@ -789,7 +789,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)
		len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
			link_status);
		if (len < DP_LINK_STATUS_SIZE) {
			pr_err("[%s]: DP link status read failed\n", __func__);
			pr_err("DP link status read failed\n");
			ret = -1;
			break;
		}
@@ -801,21 +801,25 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)
		}

		if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) {
			pr_err_ratelimited("max v_level reached\n");
			ret = -1;
			break;	/* quit */
			break;
		}

		if (old_v_level == ctrl->link->v_level) {
			tries++;
			if (tries >= maximum_retries) {
				pr_err("max tries reached\n");
				ret = -1;
				break;	/* quit */
				break;
			}
		} else {
			tries = 0;
			old_v_level = ctrl->link->v_level;
		}

		pr_debug("clock recovery not done, adjusting vx px\n");

		ctrl->link->adjust_levels(ctrl->link, link_status);
		dp_ctrl_update_vx_px(ctrl);
	}
@@ -879,7 +883,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
		len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
			link_status);
		if (len < DP_LINK_STATUS_SIZE) {
			pr_err("[%s]: DP link status read failed\n", __func__);
			pr_err("DP link status read failed\n");
			ret = -1;
			break;
		}
@@ -932,7 +936,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
		goto clear;
	}

	pr_debug("Training 1 completed successfully\n");
	/* print success info as this is a result of user initiated action */
	pr_info("Training 1 completed\n");

	dp_ctrl_state_ctrl(ctrl, 0);

@@ -953,7 +958,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
		goto clear;
	}

	pr_debug("Training 2 completed successfully\n");
	/* print success info as this is a result of user initiated action */
	pr_info("Training 2 completed\n");

	dp_ctrl_state_ctrl(ctrl, 0);
	/* Make sure to clear the current pattern before starting a new one */
+40 −35
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
 *
 */

#define pr_fmt(fmt)	"[drm-dp]: %s: " fmt, __func__
#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__

#include <linux/module.h>
#include <linux/slab.h>
@@ -45,7 +45,7 @@ struct dp_display_private {

	struct platform_device *pdev;
	struct dentry *root;
	struct mutex lock;
	struct completion notification_comp;

	struct dp_usbpd   *usbpd;
	struct dp_parser  *parser;
@@ -171,7 +171,7 @@ static int dp_display_bind(struct device *dev, struct device *master,
		pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n",
				dev, pdev, master);
		rc = -EINVAL;
		goto error;
		goto end;
	}

	drm = dev_get_drvdata(master);
@@ -180,14 +180,12 @@ static int dp_display_bind(struct device *dev, struct device *master,
		pr_err("invalid param(s), drm %pK, dp %pK\n",
				drm, dp);
		rc = -EINVAL;
		goto error;
		goto end;
	}

	dp->dp_display.drm_dev = drm;
	priv = drm->dev_private;

	mutex_lock(&dp->lock);

	rc = dp_display_debugfs_init(dp);
	if (rc) {
		pr_err("[%s]Debugfs init failed, rc=%d\n", dp->name, rc);
@@ -218,8 +216,6 @@ static int dp_display_bind(struct device *dev, struct device *master,
		goto end;
	}
end:
	mutex_unlock(&dp->lock);
error:
	return rc;
}

@@ -240,17 +236,10 @@ static void dp_display_unbind(struct device *dev, struct device *master,
		return;
	}

	mutex_lock(&dp->lock);

	(void)dp->power->power_client_deinit(dp->power);

	(void)dp->panel->sde_edid_deregister(dp->panel);

	(void)dp->aux->drm_aux_deregister(dp->aux);

	(void)dp_display_debugfs_deinit(dp);

	mutex_unlock(&dp->lock);
}

static const struct component_ops dp_display_comp_ops = {
@@ -276,8 +265,13 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
		dp->parser->max_pclk_khz);

	dp->dp_display.is_connected = true;

	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

	reinit_completion(&dp->notification_comp);
	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
		pr_warn("timeout\n");

	return rc;
}

@@ -318,6 +312,10 @@ static void dp_display_process_hpd_low(struct dp_display_private *dp)
{
	dp->dp_display.is_connected = false;
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

	reinit_completion(&dp->notification_comp);
	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
		pr_warn("timeout\n");
}

static int dp_display_usbpd_configure_cb(struct device *dev)
@@ -338,11 +336,10 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
		goto end;
	}

	mutex_lock(&dp->lock);
	dp_display_host_init(dp);

	if (dp->usbpd->hpd_high)
		dp_display_process_hpd_high(dp);
	mutex_unlock(&dp->lock);
end:
	return rc;
}
@@ -365,11 +362,13 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev)
		goto end;
	}

	mutex_lock(&dp->lock);

	dp->dp_display.is_connected = false;
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

	reinit_completion(&dp->notification_comp);
	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
		pr_warn("timeout\n");

	/*
	 * If a cable/dongle is connected to the TX device but
	 * no sink device is connected, we call host
@@ -381,8 +380,6 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev)
	 */
	if (!dp->power_on && dp->core_initialized)
		dp_display_host_deinit(dp);

	mutex_unlock(&dp->lock);
end:
	return rc;
}
@@ -403,8 +400,6 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
		return -ENODEV;
	}

	mutex_lock(&dp->lock);

	if (dp->usbpd->hpd_irq) {
		dp->hpd_irq_on = true;
		rc = dp->link->process_request(dp->link);
@@ -423,7 +418,6 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
		dp_display_process_hpd_high(dp);
	}
end:
	mutex_unlock(&dp->lock);
	return rc;
}

@@ -543,18 +537,29 @@ static int dp_display_enable(struct dp_display *dp_display)

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);
	rc = dp->ctrl->on(dp->ctrl, dp->hpd_irq_on);
	if (!rc)
		dp->power_on = true;
	mutex_unlock(&dp->lock);
error:
	return rc;
}

static int dp_display_post_enable(struct dp_display *dp)
static int dp_display_post_enable(struct dp_display *dp_display)
{
	return 0;
	int rc = 0;
	struct dp_display_private *dp;

	if (!dp_display) {
		pr_err("invalid input\n");
		rc = -EINVAL;
		goto end;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	complete_all(&dp->notification_comp);
end:
	return rc;
}

static int dp_display_pre_disable(struct dp_display *dp_display)
@@ -570,9 +575,7 @@ static int dp_display_pre_disable(struct dp_display *dp_display)

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);
	dp->ctrl->push_idle(dp->ctrl);
	mutex_unlock(&dp->lock);
error:
	return rc;
}
@@ -590,11 +593,12 @@ static int dp_display_disable(struct dp_display *dp_display)

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);
	dp->ctrl->off(dp->ctrl, dp->hpd_irq_on);
	dp_display_host_deinit(dp);

	dp->power_on = false;
	mutex_unlock(&dp->lock);

	complete_all(&dp->notification_comp);
error:
	return rc;
}
@@ -668,7 +672,8 @@ static int dp_display_probe(struct platform_device *pdev)
	if (!dp)
		return -ENOMEM;

	mutex_init(&dp->lock);
	init_completion(&dp->notification_comp);

	dp->pdev = pdev;
	dp->name = "drm_dp";

+1 −8
Original line number Diff line number Diff line
@@ -47,13 +47,6 @@ enum test_video_pattern {
	DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
};

enum test_bit_depth {
	DP_TEST_BIT_DEPTH_6 = 0x00,
	DP_TEST_BIT_DEPTH_8 = 0x01,
	DP_TEST_BIT_DEPTH_10 = 0x02,
	DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
};

enum dp_link_response {
	TEST_ACK			= 0x1,
	TEST_NACK			= 0x2,
@@ -1517,7 +1510,7 @@ static int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
		dp_link->p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
	}

	pr_debug("v_level=%d, p_level=%d\n",
	pr_debug("adjusted: v_level=%d, p_level=%d\n",
		dp_link->v_level, dp_link->p_level);

	return 0;
Loading