From 69d9f479a4228c249d8fe7fe2caa5c7b7a57d86e Mon Sep 17 00:00:00 2001 From: Johnny Liu Date: Fri, 4 Aug 2023 05:41:32 +0000 Subject: [PATCH] drm/tegra: Unify logic for suspend and resume Two main changes for the suspend and resume: 1. Set clock to Fmin/Fmax in suspend/resume cycles 2. Reorder the code in suspend and resume functions and add recovering logic when error happens in between Bug 4224081 Signed-off-by: Johnny Liu Change-Id: Iadb0b1f960ca8b9c80094d1769a2d90496263124 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2948452 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/gpu/drm/tegra/nvdec.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/tegra/nvenc.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/tegra/nvjpg.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/tegra/vic.c | 35 ++++++++++++++++++++++------------- 4 files changed, 82 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c index 645dad00..6a99d43e 100644 --- a/drivers/gpu/drm/tegra/nvdec.c +++ b/drivers/gpu/drm/tegra/nvdec.c @@ -577,12 +577,14 @@ static __maybe_unused int nvdec_runtime_resume(struct device *dev) goto disable; } + err = devfreq_resume_device(nvdec->devfreq); + if (err < 0) + goto disable; + nvdec_actmon_reg_init(nvdec); host1x_actmon_enable(&nvdec->client.base); - devfreq_resume_device(nvdec->devfreq); - return 0; disable: @@ -595,21 +597,29 @@ static __maybe_unused int nvdec_runtime_suspend(struct device *dev) struct nvdec *nvdec = dev_get_drvdata(dev); int err; - devfreq_suspend_device(nvdec->devfreq); - - host1x_actmon_disable(&nvdec->client.base); - - host1x_channel_stop(nvdec->channel); - - clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks); + err = devfreq_suspend_device(nvdec->devfreq); + if (err < 0) + return err; if (nvdec->icc_write) { err = icc_set_bw(nvdec->icc_write, 0, 0); - if (err) + if (err) { dev_warn(nvdec->dev, "failed to set icc bw: %d\n", err); + goto devfreq_resume; + } } + clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks); + + host1x_channel_stop(nvdec->channel); + + host1x_actmon_disable(&nvdec->client.base); + return 0; + +devfreq_resume: + devfreq_resume_device(nvdec->devfreq); + return err; } static int nvdec_open_channel(struct tegra_drm_client *client, diff --git a/drivers/gpu/drm/tegra/nvenc.c b/drivers/gpu/drm/tegra/nvenc.c index 049571c4..c666e74d 100644 --- a/drivers/gpu/drm/tegra/nvenc.c +++ b/drivers/gpu/drm/tegra/nvenc.c @@ -467,12 +467,14 @@ static __maybe_unused int nvenc_runtime_resume(struct device *dev) if (err < 0) goto disable; + err = devfreq_resume_device(nvenc->devfreq); + if (err < 0) + goto disable; + nvenc_actmon_reg_init(nvenc); host1x_actmon_enable(&nvenc->client.base); - devfreq_resume_device(nvenc->devfreq); - return 0; disable: @@ -485,21 +487,29 @@ static __maybe_unused int nvenc_runtime_suspend(struct device *dev) struct nvenc *nvenc = dev_get_drvdata(dev); int err; - devfreq_suspend_device(nvenc->devfreq); - - host1x_actmon_disable(&nvenc->client.base); - - host1x_channel_stop(nvenc->channel); - - clk_disable_unprepare(nvenc->clk); + err = devfreq_suspend_device(nvenc->devfreq); + if (err < 0) + return err; if (nvenc->icc_write) { err = icc_set_bw(nvenc->icc_write, 0, 0); - if (err) + if (err) { dev_warn(nvenc->dev, "failed to set icc bw: %d\n", err); + goto devfreq_resume; + } } + clk_disable_unprepare(nvenc->clk); + + host1x_channel_stop(nvenc->channel); + + host1x_actmon_disable(&nvenc->client.base); + return 0; + +devfreq_resume: + devfreq_resume_device(nvenc->devfreq); + return err; } static int nvenc_open_channel(struct tegra_drm_client *client, diff --git a/drivers/gpu/drm/tegra/nvjpg.c b/drivers/gpu/drm/tegra/nvjpg.c index a79564c1..8d40db35 100644 --- a/drivers/gpu/drm/tegra/nvjpg.c +++ b/drivers/gpu/drm/tegra/nvjpg.c @@ -466,12 +466,14 @@ static __maybe_unused int nvjpg_runtime_resume(struct device *dev) if (err < 0) goto disable; + err = devfreq_resume_device(nvjpg->devfreq); + if (err < 0) + goto disable; + nvjpg_actmon_reg_init(nvjpg); host1x_actmon_enable(&nvjpg->client.base); - devfreq_resume_device(nvjpg->devfreq); - return 0; disable: @@ -484,21 +486,29 @@ static __maybe_unused int nvjpg_runtime_suspend(struct device *dev) struct nvjpg *nvjpg = dev_get_drvdata(dev); int err; - devfreq_suspend_device(nvjpg->devfreq); - - host1x_actmon_disable(&nvjpg->client.base); - - host1x_channel_stop(nvjpg->channel); - - clk_disable_unprepare(nvjpg->clk); + err = devfreq_suspend_device(nvjpg->devfreq); + if (err < 0) + return err; if (nvjpg->icc_write) { err = icc_set_bw(nvjpg->icc_write, 0, 0); - if (err) + if (err) { dev_warn(nvjpg->dev, "failed to set icc bw: %d\n", err); + goto devfreq_resume; + } } + clk_disable_unprepare(nvjpg->clk); + + host1x_channel_stop(nvjpg->channel); + + host1x_actmon_disable(&nvjpg->client.base); + return 0; + +devfreq_resume: + devfreq_resume_device(nvjpg->devfreq); + return err; } static int nvjpg_open_channel(struct tegra_drm_client *client, diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index 1884a16b..4e990e92 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -524,18 +524,19 @@ static int __maybe_unused vic_runtime_resume(struct device *dev) if (err < 0) goto assert; + err = devfreq_resume_device(vic->devfreq); + if (err < 0) + goto assert; + vic_actmon_reg_init(vic); host1x_actmon_enable(&vic->client.base); - devfreq_resume_device(vic->devfreq); - return 0; assert: reset_control_assert(vic->rst); disable: - devfreq_suspend_device(vic->devfreq); clk_disable_unprepare(vic->clk); return err; } @@ -545,27 +546,35 @@ static int __maybe_unused vic_runtime_suspend(struct device *dev) struct vic *vic = dev_get_drvdata(dev); int err; - devfreq_suspend_device(vic->devfreq); + err = devfreq_suspend_device(vic->devfreq); + if (err < 0) + return err; - host1x_actmon_disable(&vic->client.base); - - host1x_channel_stop(vic->channel); + if (vic->icc_write) { + err = icc_set_bw(vic->icc_write, 0, 0); + if (err) { + dev_warn(vic->dev, "failed to set icc bw: %d\n", err); + goto devfreq_resume; + } + } err = reset_control_assert(vic->rst); if (err < 0) - return err; + goto devfreq_resume; usleep_range(2000, 4000); clk_disable_unprepare(vic->clk); - if (vic->icc_write) { - err = icc_set_bw(vic->icc_write, 0, 0); - if (err) - dev_warn(vic->dev, "failed to set icc bw: %d\n", err); - } + host1x_channel_stop(vic->channel); + + host1x_actmon_disable(&vic->client.base); return 0; + +devfreq_resume: + devfreq_resume_device(vic->devfreq); + return err; } static int vic_open_channel(struct tegra_drm_client *client,