Commit 0a068b68 authored by Jake Wang's avatar Jake Wang Committed by Alex Deucher

drm/amd/display: Added HPO HW control shutdown support

[Why]
HPO is only used for DP2.0. HPO HW control should be
disable when not being used to save power.

[How]
Shutdown HPO HW control during init hw.
Shutdown HPO HW control during stream disable.
Enable HPO HW control during stream enable if DP2.0.
Acked-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarJake Wang <haonan.wang2@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent edcf52ca
...@@ -675,6 +675,7 @@ struct dc_debug_options { ...@@ -675,6 +675,7 @@ struct dc_debug_options {
#endif #endif
union mem_low_power_enable_options enable_mem_low_power; union mem_low_power_enable_options enable_mem_low_power;
union root_clock_optimization_options root_clock_optimization; union root_clock_optimization_options root_clock_optimization;
bool hpo_optimization;
bool force_vblank_alignment; bool force_vblank_alignment;
/* Enable dmub aux for legacy ddc */ /* Enable dmub aux for legacy ddc */
......
...@@ -671,6 +671,7 @@ struct dce_hwseq_registers { ...@@ -671,6 +671,7 @@ struct dce_hwseq_registers {
uint32_t MC_VM_FB_LOCATION_BASE; uint32_t MC_VM_FB_LOCATION_BASE;
uint32_t MC_VM_FB_LOCATION_TOP; uint32_t MC_VM_FB_LOCATION_TOP;
uint32_t MC_VM_FB_OFFSET; uint32_t MC_VM_FB_OFFSET;
uint32_t HPO_TOP_HW_CONTROL;
}; };
/* set field name */ /* set field name */
#define HWS_SF(blk_name, reg_name, field_name, post_fix)\ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\
...@@ -1152,7 +1153,8 @@ struct dce_hwseq_registers { ...@@ -1152,7 +1153,8 @@ struct dce_hwseq_registers {
type DOMAIN_PGFSM_PWR_STATUS;\ type DOMAIN_PGFSM_PWR_STATUS;\
type HPO_HDMISTREAMCLK_G_GATE_DIS;\ type HPO_HDMISTREAMCLK_G_GATE_DIS;\
type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;\ type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;\
type I2C_LIGHT_SLEEP_FORCE; type I2C_LIGHT_SLEEP_FORCE;\
type HPO_IO_EN;
struct dce_hwseq_shift { struct dce_hwseq_shift {
HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_REG_FIELD_LIST(uint8_t)
......
...@@ -1244,6 +1244,12 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -1244,6 +1244,12 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
#endif #endif
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc->hwseq->funcs.setup_hpo_hw_control && is_dp_128b_132b_signal(pipe_ctx))
dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, false);
#endif
} }
void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
......
...@@ -2397,6 +2397,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2397,6 +2397,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
* BY this, it is logic clean to separate stream and link * BY this, it is logic clean to separate stream and link
*/ */
if (is_dp_128b_132b_signal(pipe_ctx)) { if (is_dp_128b_132b_signal(pipe_ctx)) {
if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control)
pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control(
pipe_ctx->stream->ctx->dc->hwseq, true);
setup_dp_hpo_stream(pipe_ctx, true); setup_dp_hpo_stream(pipe_ctx, true);
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream( pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream(
pipe_ctx->stream_res.hpo_dp_stream_enc); pipe_ctx->stream_res.hpo_dp_stream_enc);
......
...@@ -264,6 +264,9 @@ void dcn31_init_hw(struct dc *dc) ...@@ -264,6 +264,9 @@ void dcn31_init_hw(struct dc *dc)
if (dc->debug.enable_mem_low_power.bits.i2c) if (dc->debug.enable_mem_low_power.bits.i2c)
REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1); REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
if (hws->funcs.setup_hpo_hw_control)
hws->funcs.setup_hpo_hw_control(hws, false);
if (!dc->debug.disable_clock_gate) { if (!dc->debug.disable_clock_gate) {
/* enable all DCN clock gating */ /* enable all DCN clock gating */
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
...@@ -597,3 +600,9 @@ void dcn31_reset_hw_ctx_wrap( ...@@ -597,3 +600,9 @@ void dcn31_reset_hw_ctx_wrap(
/* New dc_state in the process of being applied to hardware. */ /* New dc_state in the process of being applied to hardware. */
dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT; dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT;
} }
void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
{
if (hws->ctx->dc->debug.hpo_optimization)
REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, !!enable);
}
...@@ -54,5 +54,6 @@ void dcn31_reset_hw_ctx_wrap( ...@@ -54,5 +54,6 @@ void dcn31_reset_hw_ctx_wrap(
bool dcn31_is_abm_supported(struct dc *dc, bool dcn31_is_abm_supported(struct dc *dc,
struct dc_state *context, struct dc_stream_state *stream); struct dc_state *context, struct dc_stream_state *stream);
void dcn31_init_pipes(struct dc *dc, struct dc_state *context); void dcn31_init_pipes(struct dc *dc, struct dc_state *context);
void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable);
#endif /* __DC_HWSS_DCN31_H__ */ #endif /* __DC_HWSS_DCN31_H__ */
...@@ -137,6 +137,7 @@ static const struct hwseq_private_funcs dcn31_private_funcs = { ...@@ -137,6 +137,7 @@ static const struct hwseq_private_funcs dcn31_private_funcs = {
.dccg_init = dcn20_dccg_init, .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut, .set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut, .set_shaper_3dlut = dcn20_set_shaper_3dlut,
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
}; };
void dcn31_hw_sequencer_construct(struct dc *dc) void dcn31_hw_sequencer_construct(struct dc *dc)
......
...@@ -860,7 +860,8 @@ static const struct dccg_mask dccg_mask = { ...@@ -860,7 +860,8 @@ static const struct dccg_mask dccg_mask = {
SR(D6VGA_CONTROL), \ SR(D6VGA_CONTROL), \
SR(DC_IP_REQUEST_CNTL), \ SR(DC_IP_REQUEST_CNTL), \
SR(AZALIA_AUDIO_DTO), \ SR(AZALIA_AUDIO_DTO), \
SR(AZALIA_CONTROLLER_CLOCK_GATING) SR(AZALIA_CONTROLLER_CLOCK_GATING), \
SR(HPO_TOP_HW_CONTROL)
static const struct dce_hwseq_registers hwseq_reg = { static const struct dce_hwseq_registers hwseq_reg = {
HWSEQ_DCN31_REG_LIST() HWSEQ_DCN31_REG_LIST()
...@@ -898,7 +899,8 @@ static const struct dce_hwseq_registers hwseq_reg = { ...@@ -898,7 +899,8 @@ static const struct dce_hwseq_registers hwseq_reg = {
HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh) HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \
HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh)
static const struct dce_hwseq_shift hwseq_shift = { static const struct dce_hwseq_shift hwseq_shift = {
HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) HWSEQ_DCN31_MASK_SH_LIST(__SHIFT)
......
...@@ -143,6 +143,7 @@ struct hwseq_private_funcs { ...@@ -143,6 +143,7 @@ struct hwseq_private_funcs {
const struct dc_plane_state *plane_state); const struct dc_plane_state *plane_state);
void (*PLAT_58856_wa)(struct dc_state *context, void (*PLAT_58856_wa)(struct dc_state *context,
struct pipe_ctx *pipe_ctx); struct pipe_ctx *pipe_ctx);
void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable);
}; };
struct dce_hwseq { struct dce_hwseq {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment