From f332076dfd0466a6eb42180fd27e06d70b79dcad Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Thu, 11 Apr 2024 11:03:08 +0800 Subject: [PATCH] drm/rockchip: dw-dp: support resume/suspend in mst mode When a mst capable immediate downstream device connected, some workqueue is used to help build and menage the topology, write/read sidband message. To avoid some access aux issue happen. we config phy power on when mst capable immediate downstream device connected and config phy power off when it becom disconnected. When a mst capable immediate downstream device connected and enter to suspend state, it need config phy power off. And it need config phy power on when it enter to resume state. This operation to guarantee phy can really power off when suspend and really power on when resume. Change-Id: I50e9c800c7b07ea2dd00d8728e08e9abc687378f Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/dw-dp.c | 59 +++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index d993e3c194cc..b43c8119ba84 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -5532,7 +5532,7 @@ static int dw_dp_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused dw_dp_runtime_suspend(struct device *dev) +static int dw_dp_runtime_suspend(struct device *dev) { struct dw_dp *dp = dev_get_drvdata(dev); @@ -5543,7 +5543,7 @@ static int __maybe_unused dw_dp_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused dw_dp_runtime_resume(struct device *dev) +static int dw_dp_runtime_resume(struct device *dev) { struct dw_dp *dp = dev_get_drvdata(dev); @@ -5556,10 +5556,61 @@ static int __maybe_unused dw_dp_runtime_resume(struct device *dev) return 0; } +static int dw_dp_suspend_noirq(struct device *dev) +{ + struct dw_dp *dp = dev_get_drvdata(dev); + + pm_runtime_force_suspend(dev); + if (dp->is_mst) + phy_power_off(dp->phy); + + return 0; +} + +static int dw_dp_resume_noirq(struct device *dev) +{ + struct dw_dp *dp = dev_get_drvdata(dev); + + pm_runtime_force_resume(dev); + if (dp->is_mst) + phy_power_on(dp->phy); + + return 0; +} + +static int dw_dp_suspend(struct device *dev) +{ + struct dw_dp *dp = dev_get_drvdata(dev); + + if (dp->is_mst) + drm_dp_mst_topology_mgr_suspend(&dp->mst_mgr); + + return 0; +} + +static int dw_dp_resume(struct device *dev) +{ + struct dw_dp *dp = dev_get_drvdata(dev); + int ret; + + if (!dp->support_mst) + return 0; + + ret = drm_dp_mst_topology_mgr_resume(&dp->mst_mgr, true); + if (ret) { + if (dp->is_mst) + phy_power_off(dp->phy); + dp->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&dp->mst_mgr, false); + } + + return 0; +} + static const struct dev_pm_ops dw_dp_pm_ops = { SET_RUNTIME_PM_OPS(dw_dp_runtime_suspend, dw_dp_runtime_resume, NULL) - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dw_dp_suspend_noirq, dw_dp_resume_noirq) + SET_SYSTEM_SLEEP_PM_OPS(dw_dp_suspend, dw_dp_resume) }; static const struct dw_dp_chip_data rk3588_dp[] = {