Bladeren bron

disp: msm: dp: perform mst phy operations during suspend resume

Perform mst phy operations during suspend/resume
to allow sinks to be in a correct state. A usbpd
api must also be called before and after the phy
operations to allow the system to go into deep
suspend and resume in a timely manner.

CRs-Fixed: 2363921
Change-Id: Ie21ef9b1caf2044e598466373a6059d2a1e5e58c
Signed-off-by: Fuad Hossain <[email protected]>
Fuad Hossain 6 jaren geleden
bovenliggende
commit
ac1149d273
5 gewijzigde bestanden met toevoegingen van 53 en 1 verwijderingen
  1. 24 0
      msm/dp/dp_display.c
  2. 2 0
      msm/dp/dp_display.h
  3. 2 0
      msm/dp/dp_hpd.h
  4. 8 1
      msm/dp/dp_mst_drm.c
  5. 17 0
      msm/dp/dp_usbpd.c

+ 24 - 0
msm/dp/dp_display.c

@@ -2494,6 +2494,28 @@ static int dp_display_get_mst_caps(struct dp_display *dp_display,
 	return rc;
 }
 
+static void dp_display_wakeup_phy_layer(struct dp_display *dp_display,
+		bool wakeup)
+{
+	struct dp_display_private *dp;
+	struct dp_hpd *hpd;
+
+	if (!dp_display) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	dp = container_of(dp_display, struct dp_display_private, dp_display);
+	if (!dp->mst.drm_registered) {
+		pr_debug("drm mst not registered\n");
+		return;
+	}
+
+	hpd = dp->hpd;
+	if (hpd && hpd->wakeup_phy)
+		hpd->wakeup_phy(hpd, wakeup);
+}
+
 static int dp_display_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -2566,6 +2588,8 @@ static int dp_display_probe(struct platform_device *pdev)
 					dp_display_mst_get_connector_info;
 	g_dp_display->mst_get_fixed_topology_port =
 					dp_display_mst_get_fixed_topology_port;
+	g_dp_display->wakeup_phy_layer =
+					dp_display_wakeup_phy_layer;
 
 	rc = component_add(&pdev->dev, &dp_display_comp_ops);
 	if (rc) {

+ 2 - 0
msm/dp/dp_display.h

@@ -117,6 +117,8 @@ struct dp_display {
 			struct dp_display_mode *dp_mode);
 	int (*update_pps)(struct dp_display *dp_display,
 			struct drm_connector *connector, char *pps_cmd);
+	void (*wakeup_phy_layer)(struct dp_display *dp_display,
+			bool wakeup);
 };
 
 #ifdef CONFIG_DRM_MSM_DP

+ 2 - 0
msm/dp/dp_hpd.h

@@ -54,6 +54,7 @@ struct dp_hpd_cb {
  * @host_deinit: source or host side de-initializations
  * @simulate_connect: simulate disconnect or connect for debug mode
  * @simulate_attention: simulate attention messages for debug mode
+ * @wakeup_phy: wakeup USBPD phy layer
  */
 struct dp_hpd {
 	enum dp_hpd_type type;
@@ -69,6 +70,7 @@ struct dp_hpd {
 	void (*host_deinit)(struct dp_hpd *hpd, struct dp_catalog_hpd *catalog);
 	int (*simulate_connect)(struct dp_hpd *dp_hpd, bool hpd);
 	int (*simulate_attention)(struct dp_hpd *dp_hpd, int vdo);
+	void (*wakeup_phy)(struct dp_hpd *dp_hpd, bool wakeup);
 };
 
 /**

+ 8 - 1
msm/dp/dp_mst_drm.c

@@ -608,6 +608,9 @@ static void _dp_mst_bridge_pre_enable_part1(struct dp_mst_bridge *dp_bridge)
 
 	/* skip mst specific disable operations during suspend */
 	if (mst->state == PM_SUSPEND) {
+		dp_display->wakeup_phy_layer(dp_display, true);
+		drm_dp_send_power_updown_phy(&mst->mst_mgr, port, true);
+		dp_display->wakeup_phy_layer(dp_display, false);
 		_dp_mst_update_single_timeslot(mst, dp_bridge);
 		return;
 	}
@@ -691,8 +694,12 @@ static void _dp_mst_bridge_pre_disable_part2(struct dp_mst_bridge *dp_bridge)
 	DP_MST_DEBUG("enter\n");
 
 	/* skip mst specific disable operations during suspend */
-	if (mst->state == PM_SUSPEND)
+	if (mst->state == PM_SUSPEND) {
+		dp_display->wakeup_phy_layer(dp_display, true);
+		drm_dp_send_power_updown_phy(&mst->mst_mgr, port, false);
+		dp_display->wakeup_phy_layer(dp_display, false);
 		return;
+	}
 
 	mst->mst_fw_cbs->check_act_status(&mst->mst_mgr);
 

+ 17 - 0
msm/dp/dp_usbpd.c

@@ -497,6 +497,22 @@ int dp_usbpd_register(struct dp_hpd *dp_hpd)
 	return rc;
 }
 
+static void dp_usbpd_wakeup_phy(struct dp_hpd *dp_hpd, bool wakeup)
+{
+	struct dp_usbpd *dp_usbpd;
+	struct dp_usbpd_private *usbpd;
+
+	dp_usbpd = container_of(dp_hpd, struct dp_usbpd, base);
+	usbpd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd);
+
+	if (!usbpd->pd) {
+		pr_err("usbpd pointer invalid");
+		return;
+	}
+
+	usbpd_vdm_in_suspend(usbpd->pd, wakeup);
+}
+
 struct dp_hpd *dp_usbpd_get(struct device *dev, struct dp_hpd_cb *cb)
 {
 	int rc = 0;
@@ -540,6 +556,7 @@ struct dp_hpd *dp_usbpd_get(struct device *dev, struct dp_hpd_cb *cb)
 	dp_usbpd->base.simulate_connect = dp_usbpd_simulate_connect;
 	dp_usbpd->base.simulate_attention = dp_usbpd_simulate_attention;
 	dp_usbpd->base.register_hpd = dp_usbpd_register;
+	dp_usbpd->base.wakeup_phy = dp_usbpd_wakeup_phy;
 
 	return &dp_usbpd->base;
 error: