Browse Source

disp: msm: dp: unify hpd event for sst and mst

Currently hpd uevent notification to usermode is triggered at different
points in the hpd handler callflow. With respect to the SST callflow,
the MST callflow has the following issues:
* the completion event object is getting reinitialized after the uevent
is sent
* The NOTIFIED states are not updated properly.
* dp_display_process_mst_hpd_high is overloaded to do two different
functions in the same flow and is controlled by the mst_probe argument.

This change cleans up the hpd callflows for MST and unifies the hpd
event notification. Also moved the mst check logic from
dp_display_process_mst_hpd_high to a separate function.

Change-Id: I8fdc92d2f9aae16d248c74643cb93688786dfbd5
Signed-off-by: Rajkumar Subbiah <[email protected]>
Rajkumar Subbiah 4 năm trước cách đây
mục cha
commit
2fc0439a46
1 tập tin đã thay đổi với 67 bổ sung69 xóa
  1. 67 69
      msm/dp/dp_display.c

+ 67 - 69
msm/dp/dp_display.c

@@ -807,7 +807,7 @@ static const struct component_ops dp_display_comp_ops = {
 	.unbind = dp_display_unbind,
 };
 
-static void dp_display_send_hpd_event(struct dp_display_private *dp)
+static bool dp_display_send_hpd_event(struct dp_display_private *dp)
 {
 	struct drm_device *dev = NULL;
 	struct drm_connector *connector;
@@ -816,24 +816,18 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)
 	char *envp[5];
 	int rc = 0;
 
-	if (dp->mst.mst_active) {
-		DP_DEBUG("skip notification for mst mode\n");
-		dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED);
-		return;
-	}
-
 	connector = dp->dp_display.base_connector;
 
 	if (!connector) {
 		DP_ERR("connector not set\n");
-		return;
+		return false;
 	}
 
 	connector->status = connector->funcs->detect(connector, false);
 	if (dp->cached_connector_status == connector->status) {
 		DP_DEBUG("connector status (%d) unchanged, skipping uevent\n",
 				dp->cached_connector_status);
-		return;
+		return false;
 	}
 
 	dp->cached_connector_status = connector->status;
@@ -842,7 +836,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)
 
 	if (dp->debug->skip_uevent) {
 		DP_INFO("skipping uevent\n");
-		goto update_state;
+		return false;
 	}
 
 	snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name);
@@ -864,14 +858,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)
 	rc = kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
 	DP_INFO("uevent %s: %d\n", rc ? "failure" : "success", rc);
 
-update_state:
-	if (connector->status == connector_status_connected) {
-		dp_display_state_add(DP_STATE_CONNECT_NOTIFIED);
-		dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED);
-	} else {
-		dp_display_state_add(DP_STATE_DISCONNECT_NOTIFIED);
-		dp_display_state_remove(DP_STATE_CONNECT_NOTIFIED);
-	}
+	return true;
 }
 
 static int dp_display_send_hpd_notification(struct dp_display_private *dp)
@@ -900,13 +887,29 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)
 
 	dp->aux->state |= DP_STATE_NOTIFICATION_SENT;
 
-	if (!dp->mst.mst_active)
+	reinit_completion(&dp->notification_comp);
+
+	if (!dp->mst.mst_active) {
 		dp->dp_display.is_sst_connected = hpd;
-	else
+
+		if (!dp_display_send_hpd_event(dp))
+			goto skip_wait;
+	} else {
 		dp->dp_display.is_sst_connected = false;
 
-	reinit_completion(&dp->notification_comp);
-	dp_display_send_hpd_event(dp);
+		if (!dp->mst.cbs.hpd)
+			goto skip_wait;
+
+		dp->mst.cbs.hpd(&dp->dp_display, true);
+	}
+
+	if (hpd) {
+		dp_display_state_add(DP_STATE_CONNECT_NOTIFIED);
+		dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED);
+	} else {
+		dp_display_state_add(DP_STATE_DISCONNECT_NOTIFIED);
+		dp_display_state_remove(DP_STATE_CONNECT_NOTIFIED);
+	}
 
 	/*
 	 * Skip the wait if TUI is active considering that the user mode will
@@ -942,11 +945,9 @@ static void dp_display_update_mst_state(struct dp_display_private *dp,
 	dp->panel->mst_state = state;
 }
 
-static void dp_display_process_mst_hpd_high(struct dp_display_private *dp,
-						bool mst_probe)
+static void dp_display_mst_init(struct dp_display_private *dp)
 {
 	bool is_mst_receiver;
-	struct dp_mst_hpd_info info;
 	const unsigned long clear_mstm_ctrl_timeout_us = 100000;
 	u8 old_mstm_ctrl;
 	int ret;
@@ -957,50 +958,53 @@ static void dp_display_process_mst_hpd_high(struct dp_display_private *dp,
 		return;
 	}
 
-	DP_MST_DEBUG("mst_hpd_high work. mst_probe:%d\n", mst_probe);
+	is_mst_receiver = dp->panel->read_mst_cap(dp->panel);
 
-	if (!dp->mst.mst_active) {
-		is_mst_receiver = dp->panel->read_mst_cap(dp->panel);
+	if (!is_mst_receiver) {
+		DP_MST_DEBUG("sink doesn't support mst\n");
+		return;
+	}
 
-		if (!is_mst_receiver) {
-			DP_MST_DEBUG("sink doesn't support mst\n");
-			return;
-		}
+	/* clear sink mst state */
+	drm_dp_dpcd_readb(dp->aux->drm_aux, DP_MSTM_CTRL, &old_mstm_ctrl);
+	drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL, 0);
 
-		/* clear sink mst state */
-		drm_dp_dpcd_readb(dp->aux->drm_aux, DP_MSTM_CTRL,
-				&old_mstm_ctrl);
-		drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL, 0);
-
-		/* add extra delay if MST state is not cleared */
-		if (old_mstm_ctrl) {
-			DP_MST_DEBUG("MSTM_CTRL is not cleared, wait %dus\n",
-					clear_mstm_ctrl_timeout_us);
-			usleep_range(clear_mstm_ctrl_timeout_us,
-				clear_mstm_ctrl_timeout_us + 1000);
-		}
+	/* add extra delay if MST state is not cleared */
+	if (old_mstm_ctrl) {
+		DP_MST_DEBUG("MSTM_CTRL is not cleared, wait %dus\n",
+				clear_mstm_ctrl_timeout_us);
+		usleep_range(clear_mstm_ctrl_timeout_us,
+			clear_mstm_ctrl_timeout_us + 1000);
+	}
 
-		ret = drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL,
-				 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
-		if (ret < 0) {
-			DP_ERR("sink mst enablement failed\n");
-			return;
-		}
+	ret = drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL,
+				DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+	if (ret < 0) {
+		DP_ERR("sink mst enablement failed\n");
+		return;
+	}
 
-		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);
+	dp_display_update_mst_state(dp, true);
+}
 
-		if (dp->mst.cbs.set_mgr_state)
-			dp->mst.cbs.set_mgr_state(&dp->dp_display, true, &info);
+static void dp_display_set_mst_mgr_state(struct dp_display_private *dp,
+					bool state)
+{
+	struct dp_mst_hpd_info info = {0};
 
-		if (dp->mst.cbs.hpd)
-			dp->mst.cbs.hpd(&dp->dp_display, true);
+	if (!dp->mst.mst_active)
+		return;
+
+	info.mst_protocol = dp->parser->has_mst_sideband;
+	if (state) {
+		info.mst_port_cnt = dp->debug->mst_port_cnt;
+		info.edid = dp->debug->get_edid(dp->debug);
 	}
 
-	DP_MST_DEBUG("mst_hpd_high. mst_active:%d\n", dp->mst.mst_active);
+	if (dp->mst.cbs.set_mgr_state)
+		dp->mst.cbs.set_mgr_state(&dp->dp_display, state, &info);
+
+	DP_MST_DEBUG("mst_mgr_state: %d\n", state);
 }
 
 static void dp_display_host_init(struct dp_display_private *dp)
@@ -1174,7 +1178,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
 	dp->link->process_request(dp->link);
 	dp->panel->handle_sink_request(dp->panel);
 
-	dp_display_process_mst_hpd_high(dp, false);
+	dp_display_mst_init(dp);
 
 	rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active,
 			dp->panel->fec_en, dp->panel->dsc_en, false);
@@ -1185,7 +1189,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
 
 	dp->process_hpd_connect = false;
 
-	dp_display_process_mst_hpd_high(dp, true);
+	dp_display_set_mst_mgr_state(dp, true);
 end:
 	mutex_unlock(&dp->session_lock);
 
@@ -1234,7 +1238,6 @@ skip_notify:
 static void dp_display_process_mst_hpd_low(struct dp_display_private *dp)
 {
 	int rc = 0;
-	struct dp_mst_hpd_info info = {0};
 
 	if (dp->mst.mst_active) {
 		DP_MST_DEBUG("mst_hpd_low work\n");
@@ -1255,12 +1258,7 @@ static void dp_display_process_mst_hpd_low(struct dp_display_private *dp)
 			rc = dp_display_send_hpd_notification(dp);
 
 		dp_display_update_mst_state(dp, false);
-
-		if (dp->mst.cbs.set_mgr_state) {
-			info.mst_protocol = dp->parser->has_mst_sideband;
-			dp->mst.cbs.set_mgr_state(&dp->dp_display, false,
-					&info);
-		}
+		dp_display_set_mst_mgr_state(dp, false);
 	}
 
 	DP_MST_DEBUG("mst_hpd_low. mst_active:%d\n", dp->mst.mst_active);