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

Commit 74f9934c authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: dp: improve interop experience for fast hotplug scenarios"

parents b19b9e43 7454e062
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -2277,6 +2277,37 @@ static int dp_debug_init_feature_toggle(struct dp_debug_private *debug,
	return rc;
}

static int dp_debug_init_configs(struct dp_debug_private *debug,
		struct dentry *dir)
{
	int rc = 0;
	struct dentry *file;

	file = debugfs_create_ulong("connect_notification_delay_ms", 0644, dir,
		&debug->dp_debug.connect_notification_delay_ms);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		DP_ERR("[%s] debugfs connect_notification_delay_ms failed, rc=%d\n",
		       DEBUG_NAME, rc);
		return rc;
	}
	debug->dp_debug.connect_notification_delay_ms =
		DEFAULT_CONNECT_NOTIFICATION_DELAY_MS;

	file = debugfs_create_u32("disconnect_delay_ms", 0644, dir,
		&debug->dp_debug.disconnect_delay_ms);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		DP_ERR("[%s] debugfs disconnect_delay_ms failed, rc=%d\n",
		       DEBUG_NAME, rc);
		return rc;
	}
	debug->dp_debug.disconnect_delay_ms = DEFAULT_DISCONNECT_DELAY_MS;

	return rc;

}

static int dp_debug_init(struct dp_debug *dp_debug)
{
	int rc = 0;
@@ -2343,6 +2374,10 @@ static int dp_debug_init(struct dp_debug *dp_debug)
	if (rc)
		goto error_remove_dir;

	rc = dp_debug_init_configs(debug, dir);
	if (rc)
		goto error_remove_dir;

	return 0;

error_remove_dir:
+12 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@
	pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__,   \
		       current->pid, ##__VA_ARGS__)

#define DEFAULT_DISCONNECT_DELAY_MS 0
#define MAX_DISCONNECT_DELAY_MS 10000
#define DEFAULT_CONNECT_NOTIFICATION_DELAY_MS 150
#define MAX_CONNECT_NOTIFICATION_DELAY_MS 5000

/**
 * struct dp_debug
 * @debug_en: specifies whether debug mode enabled
@@ -63,6 +68,10 @@
 * @mst_sim_remove_con: specifies whether sim connector is to be removed
 * @mst_sim_remove_con_id: specifies id of sim connector to be removed
 * @mst_port_cnt: number of mst ports to be added during hpd
 * @connect_notification_delay_ms: time (in ms) to wait for any attention
 *              messages before sending the connect notification uevent
 * @disconnect_delay_ms: time (in ms) to wait before turning off the mainlink
 *              in response to HPD low of cable disconnect event
 */
struct dp_debug {
	bool debug_en;
@@ -85,6 +94,9 @@ struct dp_debug {
	bool mst_sim_remove_con;
	int mst_sim_remove_con_id;
	u32 mst_port_cnt;
	unsigned long connect_notification_delay_ms;
	u32 disconnect_delay_ms;

	struct dp_mst_connector mst_connector_cache;
	u8 *(*get_edid)(struct dp_debug *dp_debug);
	void (*abort)(struct dp_debug *dp_debug);
+35 −3
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/of_irq.h>
#include <linux/soc/qcom/fsa4480-i2c.h>
#include <linux/usb/phy.h>
#include <linux/jiffies.h>

#include "sde_connector.h"

@@ -158,6 +159,7 @@ struct dp_display_private {
	struct device_node *aux_switch_node;
	struct dentry *root;
	struct completion notification_comp;
	struct completion attention_comp;

	struct dp_hpd     *hpd;
	struct dp_parser  *parser;
@@ -1026,6 +1028,8 @@ static void dp_display_host_deinit(struct dp_display_private *dp)
static int dp_display_process_hpd_high(struct dp_display_private *dp)
{
	int rc = -EINVAL;
	unsigned long wait_timeout_ms;
	unsigned long t;

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state);
	mutex_lock(&dp->session_lock);
@@ -1101,7 +1105,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
	 * Delay the HPD connect notification to see if sink generates any
	 * IRQ HPDs immediately after the HPD high.
	 */
	usleep_range(10000, 10100);
	reinit_completion(&dp->attention_comp);
	wait_timeout_ms = min_t(unsigned long,
			dp->debug->connect_notification_delay_ms,
			(unsigned long) MAX_CONNECT_NOTIFICATION_DELAY_MS);
	t = wait_for_completion_timeout(&dp->attention_comp,
		msecs_to_jiffies(wait_timeout_ms));
	DP_DEBUG("wait_timeout=%lu ms, time_waited=%u ms\n", wait_timeout_ms,
		jiffies_to_msecs(t));

	/*
	 * If an IRQ HPD is pending, then do not send a connect notification.
@@ -1118,7 +1129,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
	 */
	if (!dp->mst.mst_active &&
		(work_busy(&dp->attention_work) == WORK_BUSY_PENDING)) {
		SDE_EVT32_EXTERNAL(dp->state, 99);
		SDE_EVT32_EXTERNAL(dp->state, 99, jiffies_to_msecs(t));
		DP_DEBUG("Attention pending, skip HPD notification\n");
		goto skip_notify;
	}
@@ -1127,7 +1138,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
		dp_display_send_hpd_notification(dp);

skip_notify:
	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, rc);
	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state,
		wait_timeout_ms, rc);
	return rc;
}

@@ -1333,6 +1345,9 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp)

static void dp_display_disconnect_sync(struct dp_display_private *dp)
{
	int disconnect_delay_ms;

	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state);
	/* cancel any pending request */
	dp_display_state_add(DP_STATE_ABORTED);

@@ -1344,7 +1359,22 @@ static void dp_display_disconnect_sync(struct dp_display_private *dp)
	cancel_work_sync(&dp->attention_work);
	flush_workqueue(dp->wq);

	/*
	 * Delay the teardown of the mainlink for better interop experience.
	 * It is possible that certain sinks can issue an HPD high immediately
	 * following an HPD low as soon as they detect the mainlink being
	 * turned off. This can sometimes result in the HPD low pulse getting
	 * lost with certain cable. This issue is commonly seen when running
	 * DP LL CTS test 4.2.1.3.
	 */
	disconnect_delay_ms = min_t(u32, dp->debug->disconnect_delay_ms,
			(u32) MAX_DISCONNECT_DELAY_MS);
	DP_DEBUG("disconnect delay = %d ms\n", disconnect_delay_ms);
	msleep(disconnect_delay_ms);

	dp_display_handle_disconnect(dp);
	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state,
		disconnect_delay_ms);
}

static int dp_display_usbpd_disconnect_cb(struct device *dev)
@@ -1572,6 +1602,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
	} else if ((dp->hpd->hpd_irq && dp_display_state_is(DP_STATE_READY)) ||
			dp->debug->mst_hpd_sim) {
		queue_work(dp->wq, &dp->attention_work);
		complete_all(&dp->attention_comp);
	} else if (dp->process_hpd_connect ||
			 !dp_display_state_is(DP_STATE_CONNECTED)) {
		dp_display_state_remove(DP_STATE_ABORTED);
@@ -3384,6 +3415,7 @@ static int dp_display_probe(struct platform_device *pdev)
	}

	init_completion(&dp->notification_comp);
	init_completion(&dp->attention_comp);

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