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 <johnliu@nvidia.com>
Change-Id: Iadb0b1f960ca8b9c80094d1769a2d90496263124
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2948452
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Johnny Liu
2023-08-04 05:41:32 +00:00
committed by mobile promotions
parent 61af983ca4
commit 69d9f479a4
4 changed files with 82 additions and 43 deletions

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,