From: Wayne Lin <Wayne.Lin@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Roman Li <roman.li@amd.com>, Wayne Lin <wayne.lin@amd.com>,
Tom Chung <chiahsuan.chung@amd.com>,
"Fangzhi Zuo" <jerry.zuo@amd.com>,
Dan Wheeler <daniel.wheeler@amd.com>, Ray Wu <Ray.Wu@amd.com>,
Ivan Lipski <ivan.lipski@amd.com>, Alex Hung <alex.hung@amd.com>,
James Lin <PingLei.Lin@amd.com>,
Chenyu Chen <Chen-Yu.Chen@amd.com>,
Rafal Ostrowski <rafal.ostrowski@amd.com>,
Alvin Lee <alvin.lee2@amd.com>
Subject: [PATCH 67/74] drm/amd/display: Make DPP_PG_CONTROL and HUBP_PG_CONTROL BLS compliant
Date: Wed, 11 Nov 2026 09:29:13 +0800 [thread overview]
Message-ID: <20261111014100.3596072-68-Wayne.Lin@amd.com> (raw)
In-Reply-To: <20261111014100.3596072-1-Wayne.Lin@amd.com>
From: Rafal Ostrowski <rafal.ostrowski@amd.com>
[Why]
- The DCN401 builders read IP_REQUEST_EN from HW to decide whether to
emit DC_IP_REQUEST_CNTL, so the sequence depended on HW state at build
time.
- The PG hooks read the PG policy from dc->debug at execute time.
- The DCN20 and DCN314 cursor workarounds found the DPP by indexing
res_pool->dpps[] with dpp_inst instead of using the DPP being gated.
[How]
- Add DC_IP_REQUEST_STATUS. The DCN401 status hook reads IP_REQUEST_EN
at execute time and keeps it in hws->ip_request_already_enabled. When
it was already 1, dcn401_dc_ip_request_cntl writes nothing for the
pair, as in the direct path, and the closing call clears the flag.
Both executors only dispatch.
- Emit the status step and the pair only when
dcn401_pg_needs_ip_request() is true: both hooks exist and a PG hook
can gate (DPP PG enabled, or HUBP PG enabled and ignore_pg clear).
- The DC2 commit builder asks the same check through the new
hws->funcs.pg_needs_ip_request hook, bound on DCN401. It is built
without CONFIG_DRM_AMD_DC_FP, so it must not call dcn401_hwseq.c, and
its include of dcn401_hwseq.h is dropped.
- Pass disable_power_gate and ignore_pg to the PG hooks, and the DPP
handle to dpp_pg_control instead of dpp_inst.
- Adders validate their arguments and hooks; executors only program.
Cc: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Wayne Lin <wayne.lin@amd.com>
---
.../bls_builder/bls_builder_private_types.h | 2 +
.../bls_builder/dcn401_non_seamless_builder.c | 11 +--
.../dc/bls_builder/dcn401_seamless_builder.c | 20 +++-
.../display/dc/bls_executor/bls_executor.c | 12 ++-
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 62 +++++++++++--
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 44 ++++++---
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.h | 9 +-
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 31 ++++---
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.h | 9 +-
.../amd/display/dc/hwss/dcn302/dcn302_hwseq.c | 15 ++-
.../amd/display/dc/hwss/dcn302/dcn302_hwseq.h | 6 +-
.../amd/display/dc/hwss/dcn303/dcn303_hwseq.c | 11 ++-
.../amd/display/dc/hwss/dcn303/dcn303_hwseq.h | 6 +-
.../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 8 +-
.../amd/display/dc/hwss/dcn31/dcn31_hwseq.h | 3 +-
.../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 15 +--
.../amd/display/dc/hwss/dcn314/dcn314_hwseq.h | 3 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 7 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.h | 3 +-
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 92 ++++++++++++++-----
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 2 +
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 2 +
.../drm/amd/display/dc/hwss/hw_sequencer.h | 25 ++++-
.../display/dc/hwss/hw_sequencer_private.h | 14 ++-
24 files changed, 303 insertions(+), 109 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/bls_builder/bls_builder_private_types.h b/drivers/gpu/drm/amd/display/dc/bls_builder/bls_builder_private_types.h
index 784a3cb4d311..cc301a02c494 100644
--- a/drivers/gpu/drm/amd/display/dc/bls_builder/bls_builder_private_types.h
+++ b/drivers/gpu/drm/amd/display/dc/bls_builder/bls_builder_private_types.h
@@ -126,6 +126,8 @@ struct dcn401_commit_step_meta {
* so a plane add always programs the scaler and viewport.
*/
bool scaling_unchanged;
+ /* funcs.pg_needs_ip_request() is false: no PG hook can gate. */
+ bool no_ip_request;
} skip_if;
};
diff --git a/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_non_seamless_builder.c b/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_non_seamless_builder.c
index d28e162a6632..965004f6e49b 100644
--- a/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_non_seamless_builder.c
+++ b/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_non_seamless_builder.c
@@ -231,15 +231,14 @@ static const struct dcn401_commit_step
{ .func = HUBP_SET_FLIP_CONTROL_GSL },
{ .func = HUBP_CLK_CNTL },
{ .func = DPP_DPPCLK_CONTROL },
- /*
- * dcn10_plane_atomic_power_down sets IP_REQUEST_EN only when it
- * reads 0. Every writer clears it again, so it always reads 0 here.
- */
- { .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = true },
+ { .func = DC_IP_REQUEST_STATUS, .meta.skip_if.no_ip_request = true },
+ { .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = true,
+ .meta.skip_if.no_ip_request = true },
{ .func = HUBP_PG_CONTROL },
{ .func = HUBP_RESET },
{ .func = DPP_RESET },
- { .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = false },
+ { .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = false,
+ .meta.skip_if.no_ip_request = true },
};
static const struct dcn401_commit_step
diff --git a/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_seamless_builder.c b/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_seamless_builder.c
index 8a563386d725..863919e0967e 100644
--- a/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_seamless_builder.c
+++ b/drivers/gpu/drm/amd/display/dc/bls_builder/dcn401_seamless_builder.c
@@ -14,6 +14,7 @@
#include "dc_dmub_srv.h"
#include "custom_float.h"
#include "dcn32/dcn32_resource.h"
+#include "dce/dce_hwseq.h"
#include "bls_builder/bls_builder_internal.h"
#include "bls_builder/dcn401_init_builder.h"
#include "bls_builder/bls_builder_private_types.h"
@@ -1001,12 +1002,17 @@ static const struct dcn401_commit_step bls_update_head_new_stream[] = {
/* enable_plane, then the watermark propagate and the DET segments. */
static const struct dcn401_commit_step bls_update_head_new_enable_plane[] = {
+ { .func = DC_IP_REQUEST_STATUS,
+ .meta.skip_if.hubp_dpp_already_enabled = true,
+ .meta.skip_if.no_ip_request = true },
{ .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = true,
- .meta.skip_if.hubp_dpp_already_enabled = true },
+ .meta.skip_if.hubp_dpp_already_enabled = true,
+ .meta.skip_if.no_ip_request = true },
{ .func = HUBP_PG_CONTROL, .meta.hubp_pg_control.power_on = true,
.meta.skip_if.hubp_dpp_already_enabled = true },
{ .func = DC_IP_REQUEST_CNTL, .meta.dc_ip_request_cntl.enable = false,
- .meta.skip_if.hubp_dpp_already_enabled = true },
+ .meta.skip_if.hubp_dpp_already_enabled = true,
+ .meta.skip_if.no_ip_request = true },
{ .func = HUBP_CLK_CNTL, .meta.hubp_clk_cntl.enable = true,
.meta.skip_if.hubp_dpp_already_enabled = true },
{ .func = HUBP_INIT,
@@ -1690,6 +1696,9 @@ static void dcn401_add_step(struct block_sequence_state *sequence,
p->dpp_dppclk_control_params.enable =
m->dpp_dppclk_control.enable;
break;
+ case DC_IP_REQUEST_STATUS:
+ p->dc_ip_request_status_params.hws = dc->hwseq;
+ break;
case DC_IP_REQUEST_CNTL:
p->dc_ip_request_cntl_params.hws = dc->hwseq;
p->dc_ip_request_cntl_params.enable =
@@ -1701,6 +1710,9 @@ static void dcn401_add_step(struct block_sequence_state *sequence,
pipe->plane_res.hubp->inst;
p->hubp_pg_control_params.power_on =
m->hubp_pg_control.power_on;
+ p->hubp_pg_control_params.disable_power_gate =
+ dc->debug.disable_hubp_power_gate;
+ p->hubp_pg_control_params.ignore_pg = dc->debug.ignore_pg;
break;
case HUBP_RESET:
p->hubp_reset_params.hubp = pipe->plane_res.hubp;
@@ -1967,6 +1979,10 @@ static bool dcn401_skip_step(const struct dcn401_commit_step_args *args,
!args->pipe->plane_state->update_bits.position_change &&
!args->pipe->stream->update_flags.bits.scaling)
return true;
+ if (step->meta.skip_if.no_ip_request &&
+ (!args->dc->hwseq->funcs.pg_needs_ip_request ||
+ !args->dc->hwseq->funcs.pg_needs_ip_request(args->dc)))
+ return true;
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bls_executor/bls_executor.c b/drivers/gpu/drm/amd/display/dc/bls_executor/bls_executor.c
index 6a875add72e2..47c7137eeeaf 100644
--- a/drivers/gpu/drm/amd/display/dc/bls_executor/bls_executor.c
+++ b/drivers/gpu/drm/amd/display/dc/bls_executor/bls_executor.c
@@ -453,6 +453,9 @@ static noinline_for_stack bool dc2_bls_step_supported(const struct dc2 *dc2,
case HUBP_PG_CONTROL:
hws = step->params.hubp_pg_control_params.hws;
return hws && hws->funcs.hubp_pg_control;
+ case DC_IP_REQUEST_STATUS:
+ hws = step->params.dc_ip_request_status_params.hws;
+ return hws && hws->funcs.dc_ip_request_status;
case DC_IP_REQUEST_CNTL:
hws = step->params.dc_ip_request_cntl_params.hws;
return hws && hws->funcs.dc_ip_request_cntl;
@@ -1415,7 +1418,14 @@ enum dc2_bls_exec_result dc2_bls_execute(
&entry->params.hubp_pg_control_params;
p->hws->funcs.hubp_pg_control(p->hws, p->hubp_inst,
- p->power_on);
+ p->power_on, p->disable_power_gate, p->ignore_pg);
+ break;
+ }
+ case DC_IP_REQUEST_STATUS: {
+ struct dce_hwseq *hws =
+ entry->params.dc_ip_request_status_params.hws;
+
+ hws->funcs.dc_ip_request_status(hws);
break;
}
case DC_IP_REQUEST_CNTL: {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 82ac4ca4a13b..ecf90e3a770c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -2094,6 +2094,9 @@ void hwss_execute_sequence(struct dc *dc,
case DPP_ROOT_CLOCK_CONTROL:
hwss_dpp_root_clock_control(params);
break;
+ case DC_IP_REQUEST_STATUS:
+ hwss_dc_ip_request_status(params);
+ break;
case DC_IP_REQUEST_CNTL:
hwss_dc_ip_request_cntl(params);
break;
@@ -4066,11 +4069,11 @@ void hwss_dccg_set_ref_dscclk(union block_sequence_params *params)
void hwss_dpp_pg_control(union block_sequence_params *params)
{
struct dce_hwseq *hws = params->dpp_pg_control_params.hws;
- unsigned int dpp_inst = params->dpp_pg_control_params.dpp_inst;
+ struct dpp *dpp = params->dpp_pg_control_params.dpp;
bool power_on = params->dpp_pg_control_params.power_on;
+ bool disable_power_gate = params->dpp_pg_control_params.disable_power_gate;
- if (hws->funcs.dpp_pg_control)
- hws->funcs.dpp_pg_control(hws, dpp_inst, power_on);
+ hws->funcs.dpp_pg_control(hws, dpp, power_on, disable_power_gate);
}
void hwss_hubp_pg_control(union block_sequence_params *params)
@@ -4078,9 +4081,10 @@ void hwss_hubp_pg_control(union block_sequence_params *params)
struct dce_hwseq *hws = params->hubp_pg_control_params.hws;
unsigned int hubp_inst = params->hubp_pg_control_params.hubp_inst;
bool power_on = params->hubp_pg_control_params.power_on;
+ bool disable_power_gate = params->hubp_pg_control_params.disable_power_gate;
+ bool ignore_pg = params->hubp_pg_control_params.ignore_pg;
- if (hws->funcs.hubp_pg_control)
- hws->funcs.hubp_pg_control(hws, hubp_inst, power_on);
+ hws->funcs.hubp_pg_control(hws, hubp_inst, power_on, disable_power_gate, ignore_pg);
}
void hwss_hubp_reset(union block_sequence_params *params)
@@ -4109,6 +4113,13 @@ void hwss_dpp_root_clock_control(union block_sequence_params *params)
dccg->funcs->dpp_root_clock_control(dccg, dpp_inst, clock_on, root_clock_optimization_dpp);
}
+void hwss_dc_ip_request_status(union block_sequence_params *params)
+{
+ struct dce_hwseq *hws = params->dc_ip_request_status_params.hws;
+
+ hws->funcs.dc_ip_request_status(hws);
+}
+
void hwss_dc_ip_request_cntl(union block_sequence_params *params)
{
struct dce_hwseq *hws = params->dc_ip_request_cntl_params.hws;
@@ -5018,6 +5029,23 @@ void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state,
}
}
+bool hwss_add_dc_ip_request_status(struct block_sequence_state *seq_state,
+ struct dce_hwseq *hws)
+{
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps ||
+ !hws || !hws->funcs.dc_ip_request_status)
+ return false;
+
+ if (*seq_state->num_steps >= MAX_HWSS_BLOCK_SEQUENCE_SIZE)
+ return false;
+
+ seq_state->steps[*seq_state->num_steps].func = DC_IP_REQUEST_STATUS;
+ seq_state->steps[*seq_state->num_steps].params.dc_ip_request_status_params.hws = hws;
+ (*seq_state->num_steps)++;
+
+ return true;
+}
+
void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state,
struct dc *dc,
bool enable)
@@ -5561,14 +5589,21 @@ void hwss_add_dpp_root_clock_control(struct block_sequence_state *seq_state,
void hwss_add_dpp_pg_control(struct block_sequence_state *seq_state,
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on)
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate)
{
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps || !hws ||
+ !hws->funcs.dpp_pg_control || !dpp)
+ return;
+
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].func = DPP_PG_CONTROL;
seq_state->steps[*seq_state->num_steps].params.dpp_pg_control_params.hws = hws;
- seq_state->steps[*seq_state->num_steps].params.dpp_pg_control_params.dpp_inst = dpp_inst;
+ seq_state->steps[*seq_state->num_steps].params.dpp_pg_control_params.dpp = dpp;
seq_state->steps[*seq_state->num_steps].params.dpp_pg_control_params.power_on = power_on;
+ seq_state->steps[*seq_state->num_steps].params.dpp_pg_control_params.disable_power_gate =
+ disable_power_gate;
(*seq_state->num_steps)++;
}
}
@@ -5576,13 +5611,22 @@ void hwss_add_dpp_pg_control(struct block_sequence_state *seq_state,
void hwss_add_hubp_pg_control(struct block_sequence_state *seq_state,
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on)
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg)
{
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps || !hws ||
+ !hws->funcs.hubp_pg_control)
+ return;
+
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].func = HUBP_PG_CONTROL;
seq_state->steps[*seq_state->num_steps].params.hubp_pg_control_params.hws = hws;
seq_state->steps[*seq_state->num_steps].params.hubp_pg_control_params.hubp_inst = hubp_inst;
seq_state->steps[*seq_state->num_steps].params.hubp_pg_control_params.power_on = power_on;
+ seq_state->steps[*seq_state->num_steps].params.hubp_pg_control_params.disable_power_gate =
+ disable_power_gate;
+ seq_state->steps[*seq_state->num_steps].params.hubp_pg_control_params.ignore_pg = ignore_pg;
(*seq_state->num_steps)++;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 79c0f55d11e8..08fff8d42cbd 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -935,25 +935,27 @@ void dcn10_disable_vga(
* dcn10_dpp_pg_control - DPP power gate control.
*
* @hws: dce_hwseq reference.
- * @dpp_inst: DPP instance reference.
+ * @dpp: DPP instance reference.
* @power_on: true if we want to enable power gate, false otherwise.
+ * @disable_power_gate: true if DPP power gating is disabled by debug policy.
*
* Enable or disable power gate in the specific DPP instance.
*/
void dcn10_dpp_pg_control(
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on)
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
- if (hws->ctx->dc->debug.disable_dpp_power_gate)
+ if (disable_power_gate)
return;
if (REG(DOMAIN1_PG_CONFIG) == 0)
return;
- switch (dpp_inst) {
+ switch (dpp->inst) {
case 0: /* DPP0 */
REG_UPDATE(DOMAIN1_PG_CONFIG,
DOMAIN1_POWER_GATE, power_gate);
@@ -998,18 +1000,24 @@ void dcn10_dpp_pg_control(
* @hws: dce_hwseq reference.
* @hubp_inst: DPP instance reference.
* @power_on: true if we want to enable power gate, false otherwise.
+ * @disable_power_gate: true if HUBP power gating is disabled by debug policy.
+ * @ignore_pg: unused on DCN10.
*
* Enable or disable power gate in the specific HUBP instance.
*/
void dcn10_hubp_pg_control(
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on)
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
+ (void)ignore_pg;
+
+ if (disable_power_gate)
return;
if (REG(DOMAIN0_PG_CONFIG) == 0)
return;
@@ -1055,8 +1063,11 @@ void dcn10_hubp_pg_control(
static void power_on_plane_resources(
struct dce_hwseq *hws,
+ struct dpp *dpp,
int plane_id)
{
+ struct dc *dc = hws->ctx->dc;
+
DC_LOGGER_INIT(hws->ctx);
if (hws->funcs.dpp_root_clock_control &&
@@ -1068,10 +1079,12 @@ static void power_on_plane_resources(
IP_REQUEST_EN, 1);
if (hws->funcs.dpp_pg_control)
- hws->funcs.dpp_pg_control(hws, plane_id, true);
+ hws->funcs.dpp_pg_control(hws, dpp, true,
+ dc->debug.disable_dpp_power_gate);
if (hws->funcs.hubp_pg_control)
- hws->funcs.hubp_pg_control(hws, plane_id, true);
+ hws->funcs.hubp_pg_control(hws, plane_id, true,
+ dc->debug.disable_hubp_power_gate, dc->debug.ignore_pg);
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0);
@@ -1093,7 +1106,8 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1);
- hws->funcs.hubp_pg_control(hws, 0, false);
+ hws->funcs.hubp_pg_control(hws, 0, false, dc->debug.disable_hubp_power_gate,
+ dc->debug.ignore_pg);
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0);
@@ -1122,7 +1136,8 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1);
- hws->funcs.hubp_pg_control(hws, 0, true);
+ hws->funcs.hubp_pg_control(hws, 0, true, dc->debug.disable_hubp_power_gate,
+ dc->debug.ignore_pg);
REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0);
@@ -1546,10 +1561,12 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
IP_REQUEST_EN, 1);
if (hws->funcs.dpp_pg_control)
- hws->funcs.dpp_pg_control(hws, dpp->inst, false);
+ hws->funcs.dpp_pg_control(hws, dpp, false,
+ dc->debug.disable_dpp_power_gate);
if (hws->funcs.hubp_pg_control)
- hws->funcs.hubp_pg_control(hws, hubp->inst, false);
+ hws->funcs.hubp_pg_control(hws, hubp->inst, false,
+ dc->debug.disable_hubp_power_gate, dc->debug.ignore_pg);
hubp->funcs->hubp_reset(hubp);
dpp->funcs->dpp_reset(dpp);
@@ -2806,6 +2823,7 @@ static void dcn10_enable_plane(
undo_DEGVIDCN10_253_wa(dc);
power_on_plane_resources(dc->hwseq,
+ pipe_ctx->plane_res.dpp,
pipe_ctx->plane_res.hubp->inst);
/* enable DCFCLK current DCHUB */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
index 383998531503..c62a32115e11 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
@@ -90,11 +90,14 @@ void dcn10_post_unlock_program_front_end(
void dcn10_hubp_pg_control(
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on);
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg);
void dcn10_dpp_pg_control(
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on);
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate);
void dcn10_enable_power_gating_plane(
struct dce_hwseq *hws,
bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 696c0d5b8132..356ca90bf9bb 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -556,18 +556,19 @@ void dcn20_dsc_pg_control(
void dcn20_dpp_pg_control(
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on)
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_dpp_power_gate)
+ if (disable_power_gate)
return;
if (REG(DOMAIN1_PG_CONFIG) == 0)
return;
- switch (dpp_inst) {
+ switch (dpp->inst) {
case 0: /* DPP0 */
REG_UPDATE(DOMAIN1_PG_CONFIG,
DOMAIN1_POWER_GATE, power_gate);
@@ -622,11 +623,8 @@ void dcn20_dpp_pg_control(
*/
/* Force disable cursor on plane powerdown on DPP 5 using dpp_force_disable_cursor */
- if (!power_on) {
- struct dpp *dpp5 = hws->ctx->dc->res_pool->dpps[dpp_inst];
- if (dpp5 && dpp5->funcs->dpp_force_disable_cursor)
- dpp5->funcs->dpp_force_disable_cursor(dpp5);
- }
+ if (!power_on && dpp->funcs->dpp_force_disable_cursor)
+ dpp->funcs->dpp_force_disable_cursor(dpp);
break;
default:
@@ -639,12 +637,16 @@ void dcn20_dpp_pg_control(
void dcn20_hubp_pg_control(
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on)
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
+ (void)ignore_pg;
+
+ if (disable_power_gate)
return;
if (REG(DOMAIN0_PG_CONFIG) == 0)
return;
@@ -1321,10 +1323,13 @@ static void dcn20_power_on_plane_resources(
IP_REQUEST_EN, 1);
if (hws->funcs.dpp_pg_control)
- hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
+ hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp, true,
+ hws->ctx->dc->debug.disable_dpp_power_gate);
if (hws->funcs.hubp_pg_control)
- hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
+ hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true,
+ hws->ctx->dc->debug.disable_hubp_power_gate,
+ hws->ctx->dc->debug.ignore_pg);
if (org_ip_request_cntl == 0)
REG_SET(DC_IP_REQUEST_CNTL, 0,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
index 9a5addaa9a03..e2f65c3748de 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
@@ -107,12 +107,15 @@ void dcn20_enable_power_gating_plane(
bool enable);
void dcn20_dpp_pg_control(
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on);
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate);
void dcn20_hubp_pg_control(
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on);
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg);
void dcn20_program_triple_buffer(
struct hubp *hubp,
bool enable_triple_buffer);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.c
index 0a6d58dd8f6d..ba4b1492825f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.c
@@ -29,6 +29,7 @@
#include "reg_helper.h"
#include "dc.h"
+#include "core_types.h"
#define DC_LOGGER_INIT(logger)
@@ -42,17 +43,18 @@
hws->shifts->field_name, hws->masks->field_name
-void dcn302_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on)
+void dcn302_dpp_pg_control(struct dce_hwseq *hws, struct dpp *dpp, bool power_on,
+ bool disable_power_gate)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_dpp_power_gate)
+ if (disable_power_gate)
return;
if (REG(DOMAIN1_PG_CONFIG) == 0)
return;
- switch (dpp_inst) {
+ switch (dpp->inst) {
case 0: /* DPP0 */
REG_UPDATE(DOMAIN1_PG_CONFIG,
DOMAIN1_POWER_GATE, power_gate);
@@ -99,12 +101,15 @@ void dcn302_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool po
}
}
-void dcn302_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
+void dcn302_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
+ (void)ignore_pg;
+
+ if (disable_power_gate)
return;
if (REG(DOMAIN0_PG_CONFIG) == 0)
return;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.h
index 1e5126a0e695..2c4268970a2d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_hwseq.h
@@ -28,8 +28,10 @@
#include "hw_sequencer_private.h"
-void dcn302_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
-void dcn302_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
+void dcn302_dpp_pg_control(struct dce_hwseq *hws, struct dpp *dpp, bool power_on,
+ bool disable_power_gate);
+void dcn302_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg);
void dcn302_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on);
#endif /* __DC_HWSS_DCN302_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
index 6e1877a8682d..ecc70952aabb 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
@@ -43,19 +43,24 @@
hws->shifts->field_name, hws->masks->field_name
-void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on)
+void dcn303_dpp_pg_control(struct dce_hwseq *hws, struct dpp *dpp, bool power_on,
+ bool disable_power_gate)
{
- (void)dpp_inst;
+ (void)dpp;
(void)hws;
(void)power_on;
+ (void)disable_power_gate;
/*DCN303 removes PG registers*/
}
-void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
+void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg)
{
(void)hubp_inst;
(void)hws;
(void)power_on;
+ (void)disable_power_gate;
+ (void)ignore_pg;
/*DCN303 removes PG registers*/
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.h
index 7fdfc4175f80..494ad66f68d6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.h
@@ -29,8 +29,10 @@
#include "hw_sequencer_private.h"
-void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
-void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
+void dcn303_dpp_pg_control(struct dce_hwseq *hws, struct dpp *dpp, bool power_on,
+ bool disable_power_gate);
+void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg);
void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on);
void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index b6f3c0480ab6..7acf6af7e472 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -459,12 +459,16 @@ void dcn31_z10_restore(const struct dc *dc)
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
-void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
+void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
uint32_t org_ip_request_cntl;
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
+
+ (void)ignore_pg;
+
+ if (disable_power_gate)
return;
if (REG(DOMAIN0_PG_CONFIG) == 0)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
index 0d09aa8cfb65..5aebb31fe2ec 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
@@ -46,7 +46,8 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx);
void dcn31_z10_restore(const struct dc *dc);
void dcn31_z10_save_init(struct dc *dc);
-void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
+void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg);
int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config);
void dcn31_reset_hw_ctx_wrap(
struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index de7dde2b036b..8af325a21267 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -550,28 +550,29 @@ void dcn314_disable_link_output(struct dc_link *link,
* dcn314_dpp_pg_control - DPP power gate control.
*
* @hws: dce_hwseq reference.
- * @dpp_inst: DPP instance reference.
+ * @dpp: DPP instance reference.
* @power_on: true if we want to enable power gate, false otherwise.
+ * @disable_power_gate: true if DPP power gating is disabled by debug policy.
*
* Enable or disable power gate in the specific DPP instance.
* If power gating is disabled, will force disable cursor in the DPP instance.
*/
void dcn314_dpp_pg_control(
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on)
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_dpp_power_gate) {
+ if (disable_power_gate) {
/* Workaround for DCN314 with disabled power gating */
if (!power_on) {
/* Force disable cursor if power gating is disabled */
- struct dpp *dpp = hws->ctx->dc->res_pool->dpps[dpp_inst];
- if (dpp && dpp->funcs->dpp_force_disable_cursor)
+ if (dpp->funcs->dpp_force_disable_cursor)
dpp->funcs->dpp_force_disable_cursor(dpp);
}
return;
@@ -579,7 +580,7 @@ void dcn314_dpp_pg_control(
if (REG(DOMAIN1_PG_CONFIG) == 0)
return;
- switch (dpp_inst) {
+ switch (dpp->inst) {
case 0: /* DPP0 */
REG_UPDATE(DOMAIN1_PG_CONFIG,
DOMAIN1_POWER_GATE, power_gate);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
index e33237fb74be..a631aa7c56d5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
@@ -49,6 +49,7 @@ bool dcn314_is_dpp_root_clock_control_supported(bool root_clock_optimization_dpp
void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);
-void dcn314_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
+void dcn314_dpp_pg_control(struct dce_hwseq *hws, struct dpp *dpp, bool power_on,
+ bool disable_power_gate);
#endif /* __DC_HWSS_DCN314_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 9135b01fe388..b78041ba94e9 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -164,15 +164,16 @@ void dcn32_enable_power_gating_plane(
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
}
-void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
+void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg)
{
uint32_t power_gate = power_on ? 0 : 1;
uint32_t pwr_status = power_on ? 0 : 2;
- if (hws->ctx->dc->debug.disable_hubp_power_gate)
+ if (disable_power_gate)
return;
- if (hws->ctx->dc->debug.ignore_pg)
+ if (ignore_pg)
return;
if (REG(DOMAIN0_PG_CONFIG) == 0)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
index 734727015b3f..3db34bff3847 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
@@ -39,7 +39,8 @@ void dcn32_enable_power_gating_plane(
struct dce_hwseq *hws,
bool enable);
-void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
+void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on,
+ bool disable_power_gate, bool ignore_pg);
bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index bac9c5e18e6a..c39189deb244 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -3191,10 +3191,11 @@ void dcn401_plane_atomic_power_down(struct dc *dc,
}
if (hws->funcs.dpp_pg_control)
- hws->funcs.dpp_pg_control(hws, dpp->inst, false);
+ hws->funcs.dpp_pg_control(hws, dpp, false, dc->debug.disable_dpp_power_gate);
if (hws->funcs.hubp_pg_control)
- hws->funcs.hubp_pg_control(hws, hubp->inst, false);
+ hws->funcs.hubp_pg_control(hws, hubp->inst, false,
+ dc->debug.disable_hubp_power_gate, dc->debug.ignore_pg);
hubp->funcs->hubp_reset(hubp);
dpp->funcs->dpp_reset(dpp);
@@ -3261,26 +3262,41 @@ void dcn401_update_cursor_offload_pipe(struct dmub_srv *dmub, uint32_t stream_id
cs->offload_streams[stream_idx].payloads[payload_idx].pipe_mask |= (1u << pipe_idx);
}
+bool dcn401_pg_needs_ip_request(const struct dc *dc)
+{
+ const struct dce_hwseq *hws = dc->hwseq;
+
+ /* The status step and the pair need both hooks. */
+ ASSERT(!hws->funcs.dc_ip_request_cntl == !hws->funcs.dc_ip_request_status);
+ if (!hws->funcs.dc_ip_request_cntl || !hws->funcs.dc_ip_request_status)
+ return false;
+
+ /* dcn32_hubp_pg_control, bound on DCN401, also honors ignore_pg. */
+ return (hws->funcs.dpp_pg_control && !dc->debug.disable_dpp_power_gate) ||
+ (hws->funcs.hubp_pg_control && !dc->debug.disable_hubp_power_gate &&
+ !dc->debug.ignore_pg);
+}
+
void dcn401_plane_atomic_power_down_sequence(struct dc *dc,
struct dpp *dpp,
struct hubp *hubp,
struct block_sequence_state *seq_state)
{
struct dce_hwseq *hws = dc->hwseq;
- uint32_t org_ip_request_cntl = 0;
+ bool ip_request = false;
- /* Check and set DC_IP_REQUEST_CNTL if needed */
- if (REG(DC_IP_REQUEST_CNTL)) {
- REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
- if (org_ip_request_cntl == 0)
- hwss_add_dc_ip_request_cntl(seq_state, dc, true);
- }
+ if (dcn401_pg_needs_ip_request(dc))
+ ip_request = hwss_add_dc_ip_request_status(seq_state, hws);
+
+ if (ip_request)
+ hwss_add_dc_ip_request_cntl(seq_state, dc, true);
/* DPP power gating control */
- hwss_add_dpp_pg_control(seq_state, hws, dpp->inst, false);
+ hwss_add_dpp_pg_control(seq_state, hws, dpp, false, dc->debug.disable_dpp_power_gate);
/* HUBP power gating control */
- hwss_add_hubp_pg_control(seq_state, hws, hubp->inst, false);
+ hwss_add_hubp_pg_control(seq_state, hws, hubp->inst, false,
+ dc->debug.disable_hubp_power_gate, dc->debug.ignore_pg);
/* HUBP reset */
hwss_add_hubp_reset(seq_state, hubp);
@@ -3288,8 +3304,7 @@ void dcn401_plane_atomic_power_down_sequence(struct dc *dc,
/* DPP reset */
hwss_add_dpp_reset(seq_state, dpp);
- /* Restore DC_IP_REQUEST_CNTL if it was originally 0 */
- if (org_ip_request_cntl == 0 && REG(DC_IP_REQUEST_CNTL))
+ if (ip_request)
hwss_add_dc_ip_request_cntl(seq_state, dc, false);
DC_LOG_DEBUG("Power gated front end %d\n", hubp->inst);
@@ -3672,12 +3687,39 @@ void dcn401_post_unlock_reset_opp_sequence(
}
}
+/*
+ * Called in pairs after dcn401_dc_ip_request_status(). Writes nothing when
+ * IP_REQUEST_EN was already 1; the disable call clears that status.
+ */
void dcn401_dc_ip_request_cntl(struct dce_hwseq *hws, bool enable)
{
+ bool already_enabled;
+
if (!hws || !hws->ctx || !hws->regs || !hws->shifts || !hws->masks)
return;
+
+ already_enabled = hws->ip_request_already_enabled;
+
+ if (!enable)
+ hws->ip_request_already_enabled = false;
+
+ if (already_enabled || !REG(DC_IP_REQUEST_CNTL))
+ return;
+
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, enable ? 1 : 0);
+}
+
+void dcn401_dc_ip_request_status(struct dce_hwseq *hws)
+{
+ uint32_t ip_request_en = 0;
+
+ if (!hws || !hws->ctx || !hws->regs || !hws->shifts || !hws->masks)
+ return;
+
if (REG(DC_IP_REQUEST_CNTL))
- REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, enable ? 1 : 0);
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &ip_request_en);
+
+ hws->ip_request_already_enabled = ip_request_en != 0;
}
void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx,
@@ -3686,32 +3728,32 @@ void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx,
{
(void)context;
struct dce_hwseq *hws = dc->hwseq;
- uint32_t org_ip_request_cntl = 0;
+ bool ip_request = false;
if (!pipe_ctx->plane_res.dpp || !pipe_ctx->plane_res.hubp || !pipe_ctx->stream_res.opp)
return;
- if (REG(DC_IP_REQUEST_CNTL))
- REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
-
/* Step 1: DPP root clock control - enable clock */
if (hws->funcs.dpp_root_clock_control)
hwss_add_dpp_root_clock_control(seq_state, hws, pipe_ctx->plane_res.dpp->inst, true);
/* Step 2: Enable DC IP request (if needed) */
- if (hws->funcs.dc_ip_request_cntl)
+ if (dcn401_pg_needs_ip_request(dc))
+ ip_request = hwss_add_dc_ip_request_status(seq_state, hws);
+
+ if (ip_request)
hwss_add_dc_ip_request_cntl(seq_state, dc, true);
/* Step 3: DPP power gating control - power on */
- if (REG(DC_IP_REQUEST_CNTL) && hws->funcs.dpp_pg_control)
- hwss_add_dpp_pg_control(seq_state, hws, pipe_ctx->plane_res.dpp->inst, true);
+ hwss_add_dpp_pg_control(seq_state, hws, pipe_ctx->plane_res.dpp, true,
+ dc->debug.disable_dpp_power_gate);
/* Step 4: HUBP power gating control - power on */
- if (REG(DC_IP_REQUEST_CNTL) && hws->funcs.hubp_pg_control)
- hwss_add_hubp_pg_control(seq_state, hws, pipe_ctx->plane_res.hubp->inst, true);
+ hwss_add_hubp_pg_control(seq_state, hws, pipe_ctx->plane_res.hubp->inst, true,
+ dc->debug.disable_hubp_power_gate, dc->debug.ignore_pg);
- /* Step 5: Disable DC IP request (restore state) */
- if (org_ip_request_cntl == 0 && hws->funcs.dc_ip_request_cntl)
+ /* Step 5: Disable DC IP request */
+ if (ip_request)
hwss_add_dc_ip_request_cntl(seq_state, dc, false);
/* Step 6: HUBP clock control - enable DCFCLK */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
index fef0dd59a81f..c95d929b453c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
@@ -191,6 +191,8 @@ void dcn401_post_unlock_reset_opp_sequence(
struct block_sequence_state *seq_state);
void dcn401_dc_ip_request_cntl(struct dce_hwseq *hws, bool enable);
+void dcn401_dc_ip_request_status(struct dce_hwseq *hws);
+bool dcn401_pg_needs_ip_request(const struct dc *dc);
void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index 1e79b4945801..09737dddce3e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -176,6 +176,8 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
.perform_3dlut_wa_unlock = dcn401_perform_3dlut_wa_unlock,
.program_pipe_sequence = dcn401_program_pipe_sequence,
.dc_ip_request_cntl = dcn401_dc_ip_request_cntl,
+ .dc_ip_request_status = dcn401_dc_ip_request_status,
+ .pg_needs_ip_request = dcn401_pg_needs_ip_request,
.wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed,
.set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe,
};
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index c4f3ec532572..bfe9afb434af 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -1005,14 +1005,17 @@ struct disable_phantom_crtc_params {
struct dpp_pg_control_params {
struct dce_hwseq *hws;
- unsigned int dpp_inst;
+ struct dpp *dpp;
bool power_on;
+ bool disable_power_gate;
};
struct hubp_pg_control_params {
struct dce_hwseq *hws;
unsigned int hubp_inst;
bool power_on;
+ bool disable_power_gate;
+ bool ignore_pg;
};
struct hubp_reset_params {
@@ -1030,6 +1033,10 @@ struct dpp_root_clock_control_params {
bool root_clock_optimization_dpp;
};
+struct dc_ip_request_status_params {
+ struct dce_hwseq *hws;
+};
+
struct dc_ip_request_cntl_params {
struct dce_hwseq *hws;
bool enable;
@@ -1461,6 +1468,7 @@ union block_sequence_params {
struct hubp_reset_params hubp_reset_params;
struct dpp_reset_params dpp_reset_params;
struct dpp_root_clock_control_params dpp_root_clock_control_params;
+ struct dc_ip_request_status_params dc_ip_request_status_params;
struct dc_ip_request_cntl_params dc_ip_request_cntl_params;
struct dsc_pg_status_params dsc_pg_status_params;
struct dsc_wait_disconnect_pending_clear_params dsc_wait_disconnect_pending_clear_params;
@@ -1699,6 +1707,7 @@ enum block_sequence_func {
HUBP_RESET,
DPP_RESET,
DPP_ROOT_CLOCK_CONTROL,
+ DC_IP_REQUEST_STATUS,
DC_IP_REQUEST_CNTL,
DCCG_UPDATE_DPP_DTO,
HUBP_VTG_SEL,
@@ -2547,6 +2556,8 @@ void hwss_dpp_reset(union block_sequence_params *params);
void hwss_dpp_root_clock_control(union block_sequence_params *params);
+void hwss_dc_ip_request_status(union block_sequence_params *params);
+
void hwss_dc_ip_request_cntl(union block_sequence_params *params);
void hwss_dccg_update_dpp_dto(union block_sequence_params *params);
@@ -2786,6 +2797,9 @@ void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state,
struct cm_hist_control cm_hist_control,
enum dc_color_space color_space);
+bool hwss_add_dc_ip_request_status(struct block_sequence_state *seq_state,
+ struct dce_hwseq *hws);
+
void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state,
struct dc *dc,
bool enable);
@@ -2938,13 +2952,16 @@ void hwss_add_dpp_root_clock_control(struct block_sequence_state *seq_state,
void hwss_add_dpp_pg_control(struct block_sequence_state *seq_state,
struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on);
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate);
void hwss_add_hubp_pg_control(struct block_sequence_state *seq_state,
struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on);
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg);
void hwss_add_hubp_set_blank(struct block_sequence_state *seq_state,
struct hubp *hubp,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
index 91a84fb50b59..e4001656a330 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
@@ -150,11 +150,14 @@ struct hwseq_private_funcs {
unsigned int phy_inst,
bool clock_on);
void (*dpp_pg_control)(struct dce_hwseq *hws,
- unsigned int dpp_inst,
- bool power_on);
+ struct dpp *dpp,
+ bool power_on,
+ bool disable_power_gate);
void (*hubp_pg_control)(struct dce_hwseq *hws,
unsigned int hubp_inst,
- bool power_on);
+ bool power_on,
+ bool disable_power_gate,
+ bool ignore_pg);
void (*dsc_pg_control)(struct dce_hwseq *hws,
unsigned int dsc_inst,
bool power_on);
@@ -237,6 +240,8 @@ struct hwseq_private_funcs {
void (*wait_for_pipe_update_if_needed)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only);
void (*set_wait_for_update_needed_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx);
void (*dc_ip_request_cntl)(struct dce_hwseq *hws, bool enable);
+ void (*dc_ip_request_status)(struct dce_hwseq *hws);
+ bool (*pg_needs_ip_request)(const struct dc *dc);
void (*program_cm_hist)(struct dc *dc,
struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state);
@@ -254,6 +259,9 @@ struct dce_hwseq {
struct hwseq_wa_state wa_state;
struct hwseq_private_funcs funcs;
+ /* Set by dc_ip_request_status(), cleared by the closing dc_ip_request_cntl(). */
+ bool ip_request_already_enabled;
+
PHYSICAL_ADDRESS_LOC fb_base;
PHYSICAL_ADDRESS_LOC fb_top;
PHYSICAL_ADDRESS_LOC fb_offset;
--
2.43.0
next prev parent reply other threads:[~2026-11-11 1:45 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 1:28 [PATCH 00/74] DC Patches November 16, 2026 Wayne Lin
2026-11-11 1:28 ` [PATCH 01/74] drm/amd/display: Fix elapsed time indentation Wayne Lin
2026-11-11 1:28 ` [PATCH 02/74] drm/amd/display: Correct the forced YCbCr420 comment Wayne Lin
2026-11-11 1:28 ` [PATCH 03/74] drm/amd/display: Remove duplicate block sequence leftovers Wayne Lin
2026-11-11 1:28 ` [PATCH 04/74] drm/amd/display: Skip UPSP programming when UPSP regs are absent Wayne Lin
2026-11-11 1:28 ` [PATCH 05/74] drm/amd/display: Dispatch commit_state_hw through dc2_funcs Wayne Lin
2026-11-11 1:28 ` [PATCH 06/74] drm/amd/display: Add leaf BLS entries for a virtual commit Wayne Lin
2026-11-11 1:28 ` [PATCH 07/74] drm/amd/display: Build the dcn401 virtual commit natively Wayne Lin
2026-11-11 1:28 ` [PATCH 08/74] drm/amd/display: Move HDMI FRL Polling Outside dc_lock Wayne Lin
2026-11-11 1:28 ` [PATCH 09/74] drm/amd/display: Extend the IOMMU mismatch workaround to DCN42B Wayne Lin
2026-11-11 1:28 ` [PATCH 10/74] drm/amd/display: Stop HDMI FRL status polling on fini Wayne Lin
2026-11-12 8:51 ` Eren Özen
2026-11-11 1:28 ` [PATCH 11/74] drm/amd/display: Relax stutter constraints for DRR streams Wayne Lin
2026-11-11 1:28 ` [PATCH 12/74] drm/amd/display: Include Ramless Idle in stutter relaxation Wayne Lin
2026-11-11 1:28 ` [PATCH 13/74] drm/amd/display: Initialize DMUB LSDMA ring buffer Wayne Lin
2026-11-11 1:28 ` [PATCH 14/74] drm/amd/display: Fix FFE test automation link rate change Wayne Lin
2026-11-11 1:28 ` [PATCH 15/74] drm/amd/display: Update indicate pstate enable sequence Wayne Lin
2026-11-11 1:28 ` [PATCH 16/74] drm/amd/display: HWSS Refactor - Watermarks Wayne Lin
2026-11-11 1:28 ` [PATCH 17/74] drm/amd/display: Resolve clk_mgr DPP DTO targets when the sequence is built Wayne Lin
2026-11-11 1:28 ` [PATCH 18/74] drm/amd/display: Resolve clk_mgr DTBCLK " Wayne Lin
2026-11-11 1:28 ` [PATCH 19/74] drm/amd/display: Resolve the DCN401 DENTIST divider " Wayne Lin
2026-11-11 1:28 ` [PATCH 20/74] drm/amd/display: Update default VCO frequency Wayne Lin
2026-11-11 1:28 ` [PATCH 21/74] drm/amd/display: commit validated target when minimal transition cannot be built Wayne Lin
2026-11-11 1:28 ` [PATCH 22/74] drm/amd/display: Update DP HPO to use correct APG instance Wayne Lin
2026-11-11 1:28 ` [PATCH 23/74] drm/amd/display: cleanup tiling and address formats Wayne Lin
2026-11-11 1:28 ` [PATCH 24/74] drm/amd/display: Enable SST PCON FRL DSC passthrough Wayne Lin
2026-11-11 1:28 ` [PATCH 25/74] drm/amd/display: Don't let HPD IRQ handler take dc_lock in reset Wayne Lin
2026-11-11 1:28 ` [PATCH 26/74] drm/amd/display: Skip visual confirm color programming when FW owns it Wayne Lin
2026-11-11 1:28 ` [PATCH 27/74] drm/amd/display: Fix Stage Optimizer Parameter Naming Wayne Lin
2026-11-11 1:28 ` [PATCH 28/74] drm/amd/display: Build the dcn401 seamless update in DC2 Wayne Lin
2026-11-11 1:28 ` [PATCH 29/74] drm/amd/display: Read accelerated mode through a query builder Wayne Lin
2026-11-11 1:28 ` [PATCH 30/74] drm/amd/display: Ensure exit IPS before checking flip status Wayne Lin
2026-11-11 1:28 ` [PATCH 31/74] drm/amd/display: Updating missing assignments for DCN6 Wayne Lin
2026-11-11 1:28 ` [PATCH 32/74] drm/amd/display: update dcn42b based on dcn42 Wayne Lin
2026-11-11 1:28 ` [PATCH 33/74] drm/amd/display: Build the kept-plane surface update in DC2 Wayne Lin
2026-11-11 1:28 ` [PATCH 34/74] drm/amd/display: Skip first-enable steps on a kept plane Wayne Lin
2026-11-11 1:28 ` [PATCH 35/74] drm/amd/display: Enable DRR stutter constraint relaxation on DCN42 Wayne Lin
2026-11-11 1:28 ` [PATCH 36/74] drm/amd/display: detect static screen state and propagate Wayne Lin
2026-11-11 1:28 ` [PATCH 37/74] drm/amd/display: Allow DC_PSR_MASK to enable PSR without DMUB PSR cap Wayne Lin
2026-11-11 1:28 ` [PATCH 38/74] drm/amd/display: Fix DSC teardown gating in post-unlock BLS sequence Wayne Lin
2026-11-11 1:28 ` [PATCH 39/74] drm/amd/display: Enable HDCP on DCN6 Wayne Lin
2026-11-11 1:28 ` [PATCH 40/74] drm/amd/display: enable DF C-state vote on DCN42B Wayne Lin
2026-11-11 1:28 ` [PATCH 41/74] drm/amd/display: Increase the DCN42 DDR5 stutter latency Wayne Lin
2026-11-11 1:28 ` [PATCH 42/74] drm/amd/display: [FW Promotion] Release 0.1.83.0 Wayne Lin
2026-11-11 1:28 ` [PATCH 43/74] drm/amd/display: Promote DC to 3.2.406 Wayne Lin
2026-11-11 1:28 ` [PATCH 44/74] drm/amd/display: Fix KUnit tiled EDID size Wayne Lin
2026-11-12 7:17 ` Eren Özen
2026-11-11 1:28 ` [PATCH 45/74] drm/amd/display: fix hubbub read state logging Wayne Lin
2026-11-11 1:28 ` [PATCH 46/74] drm/amd/display: Keep panel power across link-loss retrain Wayne Lin
2026-11-11 1:28 ` [PATCH 47/74] drm/amd/display: Don't shrink zero-area recout in full viewport visual confirm Wayne Lin
2026-11-11 1:28 ` [PATCH 48/74] drm/amd/display: Keep patched HDMI panels on FRL across detect Wayne Lin
2026-11-11 1:28 ` [PATCH 49/74] drm/amd/display: Use expanded DMUB-provided SoC BB and IP caps Wayne Lin
2026-11-11 1:28 ` [PATCH 50/74] drm/amd/display: Only force P-State on first plane if TTU is below WM Wayne Lin
2026-11-11 1:28 ` [PATCH 51/74] drm/amd/display: Program the kept-plane scaler in DC2 Wayne Lin
2026-11-11 1:28 ` [PATCH 52/74] drm/amd/display: Add and remove two MPO planes " Wayne Lin
2026-11-11 1:28 ` [PATCH 53/74] drm/amd/display: Add DC2 state facts and split the builders Wayne Lin
2026-11-11 1:29 ` [PATCH 54/74] drm/amd/display: Program DC2 commit stereo once Wayne Lin
2026-11-11 1:29 ` [PATCH 55/74] drm/amd/display: Read DCN6 SOP constraints from the idle row Wayne Lin
2026-11-11 1:29 ` [PATCH 56/74] drm/amd/display: Use soc_bb hostvm fraction instead of hardcoded value Wayne Lin
2026-11-11 1:29 ` [PATCH 57/74] drm/amd/display: Increase state if dcfclk deep sleep needed exceeds dcfclk Wayne Lin
2026-11-11 1:29 ` [PATCH 58/74] drm/amd/display: Flip dml2_core_utils_get_segment_horizontal_contiguous() Inputs Wayne Lin
2026-11-11 1:29 ` [PATCH 59/74] drm/amd/display: Update DCN6 Calcs Wayne Lin
2026-11-11 1:29 ` [PATCH 60/74] drm/amd/display: Add effective_number_of_dpp parameter Wayne Lin
2026-11-11 1:29 ` [PATCH 61/74] drm/amd/display: Read DRAM channel width from SMU init table Wayne Lin
2026-11-11 1:29 ` [PATCH 62/74] drm/amd/display: Update DCN42B stutter latency to match DCN42 Wayne Lin
2026-11-11 1:29 ` [PATCH 63/74] drm/amd/display: Expect VRAM|GTT for the DMUB framebuffer Wayne Lin
2026-11-12 7:17 ` Eren Özen
2026-11-11 1:29 ` [PATCH 64/74] drm/amd/display: Report QoS latency bounds and request Wayne Lin
2026-11-11 1:29 ` [PATCH 65/74] drm/amd/display: Bypass chroma upsampling without the DPP cap Wayne Lin
2026-11-11 1:29 ` [PATCH 66/74] drm/amd/display: Limit VRAM aperture retrieval to DCN6 Wayne Lin
2026-11-11 1:29 ` Wayne Lin [this message]
2026-11-11 1:29 ` [PATCH 68/74] drm/amd/display: Seed boot clocks to avoid lowering pre-OS display clocks Wayne Lin
2026-11-11 1:29 ` [PATCH 69/74] drm/amd/display: Account for split pipe overlap in alt channel copy size Wayne Lin
2026-11-11 1:29 ` [PATCH 70/74] drm/amd/display: Get OPP heads and DPP pipes by stream in dc_resource Wayne Lin
2026-11-11 1:29 ` [PATCH 71/74] drm/amd/display: Program ODM 2:1 and 3:1 on one stream in DC2 Wayne Lin
2026-11-11 1:29 ` [PATCH 72/74] drm/amd/display: Enable Replay timing sync by default Wayne Lin
2026-11-11 1:29 ` [PATCH 73/74] drm/amd/display: [FW Promotion] Release 0.1.84.0 Wayne Lin
2026-11-11 1:29 ` [PATCH 74/74] drm/amd/display: Promote DC to 3.2.407 Wayne Lin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261111014100.3596072-68-Wayne.Lin@amd.com \
--to=wayne.lin@amd.com \
--cc=Chen-Yu.Chen@amd.com \
--cc=PingLei.Lin@amd.com \
--cc=Ray.Wu@amd.com \
--cc=alex.hung@amd.com \
--cc=alvin.lee2@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=chiahsuan.chung@amd.com \
--cc=daniel.wheeler@amd.com \
--cc=harry.wentland@amd.com \
--cc=ivan.lipski@amd.com \
--cc=jerry.zuo@amd.com \
--cc=rafal.ostrowski@amd.com \
--cc=roman.li@amd.com \
--cc=sunpeng.li@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.