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

Commit 20bd9b08 authored by Fuad Hossain's avatar Fuad Hossain Committed by Gerrit - the friendly Code Review server
Browse files

drm/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: I67facef3f453d67f63814f96647e51e0b0fafd45
Signed-off-by: default avatarFuad Hossain <fhossain@codeaurora.org>
parent 5ffa8544
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -2543,6 +2543,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;
@@ -2615,6 +2637,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
Original line number Diff line number Diff line
@@ -125,6 +125,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);
};

int dp_display_get_num_of_displays(void);
+3 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -63,6 +63,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;
@@ -78,6 +79,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
Original line number Diff line number Diff line
@@ -595,6 +595,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;
	}
@@ -678,8 +681,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);

+18 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -505,6 +505,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;
@@ -548,6 +564,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: