Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Jake Wang <haonan.wang2@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jake Wang and committed by
Alex Deucher
0a068b68 edcf52ca

+29 -3
+1
drivers/gpu/drm/amd/display/dc/dc.h
··· 675 675 #endif 676 676 union mem_low_power_enable_options enable_mem_low_power; 677 677 union root_clock_optimization_options root_clock_optimization; 678 + bool hpo_optimization; 678 679 bool force_vblank_alignment; 679 680 680 681 /* Enable dmub aux for legacy ddc */
+3 -1
drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
··· 671 671 uint32_t MC_VM_FB_LOCATION_BASE; 672 672 uint32_t MC_VM_FB_LOCATION_TOP; 673 673 uint32_t MC_VM_FB_OFFSET; 674 + uint32_t HPO_TOP_HW_CONTROL; 674 675 }; 675 676 /* set field name */ 676 677 #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ ··· 1153 1152 type DOMAIN_PGFSM_PWR_STATUS;\ 1154 1153 type HPO_HDMISTREAMCLK_G_GATE_DIS;\ 1155 1154 type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;\ 1156 - type I2C_LIGHT_SLEEP_FORCE; 1155 + type I2C_LIGHT_SLEEP_FORCE;\ 1156 + type HPO_IO_EN; 1157 1157 1158 1158 struct dce_hwseq_shift { 1159 1159 HWSEQ_REG_FIELD_LIST(uint8_t)
+6
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
··· 1244 1244 #endif 1245 1245 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1246 1246 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); 1247 + 1248 + #if defined(CONFIG_DRM_AMD_DC_DCN) 1249 + if (dc->hwseq->funcs.setup_hpo_hw_control && is_dp_128b_132b_signal(pipe_ctx)) 1250 + dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, false); 1251 + #endif 1252 + 1247 1253 } 1248 1254 1249 1255 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
+3
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
··· 2397 2397 * BY this, it is logic clean to separate stream and link 2398 2398 */ 2399 2399 if (is_dp_128b_132b_signal(pipe_ctx)) { 2400 + if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control) 2401 + pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control( 2402 + pipe_ctx->stream->ctx->dc->hwseq, true); 2400 2403 setup_dp_hpo_stream(pipe_ctx, true); 2401 2404 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream( 2402 2405 pipe_ctx->stream_res.hpo_dp_stream_enc);
+9
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
··· 264 264 if (dc->debug.enable_mem_low_power.bits.i2c) 265 265 REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1); 266 266 267 + if (hws->funcs.setup_hpo_hw_control) 268 + hws->funcs.setup_hpo_hw_control(hws, false); 269 + 267 270 if (!dc->debug.disable_clock_gate) { 268 271 /* enable all DCN clock gating */ 269 272 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); ··· 599 596 600 597 /* New dc_state in the process of being applied to hardware. */ 601 598 dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT; 599 + } 600 + 601 + void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable) 602 + { 603 + if (hws->ctx->dc->debug.hpo_optimization) 604 + REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, !!enable); 602 605 }
+1
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
··· 54 54 bool dcn31_is_abm_supported(struct dc *dc, 55 55 struct dc_state *context, struct dc_stream_state *stream); 56 56 void dcn31_init_pipes(struct dc *dc, struct dc_state *context); 57 + void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable); 57 58 58 59 #endif /* __DC_HWSS_DCN31_H__ */
+1
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
··· 137 137 .dccg_init = dcn20_dccg_init, 138 138 .set_blend_lut = dcn30_set_blend_lut, 139 139 .set_shaper_3dlut = dcn20_set_shaper_3dlut, 140 + .setup_hpo_hw_control = dcn31_setup_hpo_hw_control, 140 141 }; 141 142 142 143 void dcn31_hw_sequencer_construct(struct dc *dc)
+4 -2
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
··· 860 860 SR(D6VGA_CONTROL), \ 861 861 SR(DC_IP_REQUEST_CNTL), \ 862 862 SR(AZALIA_AUDIO_DTO), \ 863 - SR(AZALIA_CONTROLLER_CLOCK_GATING) 863 + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ 864 + SR(HPO_TOP_HW_CONTROL) 864 865 865 866 static const struct dce_hwseq_registers hwseq_reg = { 866 867 HWSEQ_DCN31_REG_LIST() ··· 899 898 HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ 900 899 HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ 901 900 HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ 902 - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh) 901 + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ 902 + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) 903 903 904 904 static const struct dce_hwseq_shift hwseq_shift = { 905 905 HWSEQ_DCN31_MASK_SH_LIST(__SHIFT)
+1
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
··· 143 143 const struct dc_plane_state *plane_state); 144 144 void (*PLAT_58856_wa)(struct dc_state *context, 145 145 struct pipe_ctx *pipe_ctx); 146 + void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable); 146 147 }; 147 148 148 149 struct dce_hwseq {