Applied the series. Thanks! Alex
On Tue, Sep 9, 2025 at 10:18 AM Timur Kristóf <timur.kris...@gmail.com> wrote: > > This commit is necessary for DC to function well with chips > that use the legacy power management code, ie. SI and KV. > Communicate display information from DC to the legacy PM code. > > Currently DC uses pm_display_cfg to communicate power management > requirements from the display code to the DPM code. > However, the legacy (non-DC) code path used different fields > and therefore could not take into account anything from DC. > > Change the legacy display code to fill the same pm_display_cfg > struct as DC and use the same in the legacy DPM code. > > To ease review and reduce churn, this commit does not yet > delete the now unneeded code, that is done in the next commit. > > v2: > Rebase. > Fix single_display in amdgpu_dpm_pick_power_state. > > Signed-off-by: Timur Kristóf <timur.kris...@gmail.com> > --- > drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c | 67 +++++++++++++++++++ > .../gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h | 2 + > drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 4 +- > .../gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c | 5 +- > drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 65 ++++++------------ > .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 11 +-- > 6 files changed, 97 insertions(+), 57 deletions(-) > > diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c > b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c > index 2d2d2d5e6763..9ef965e4a92e 100644 > --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c > +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c > @@ -100,3 +100,70 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) > > return vrefresh; > } > + > +void amdgpu_dpm_get_display_cfg(struct amdgpu_device *adev) > +{ > + struct drm_device *ddev = adev_to_drm(adev); > + struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg; > + struct single_display_configuration *display_cfg; > + struct drm_crtc *crtc; > + struct amdgpu_crtc *amdgpu_crtc; > + struct amdgpu_connector *conn; > + int num_crtcs = 0; > + int vrefresh; > + u32 vblank_in_pixels, vblank_time_us; > + > + cfg->min_vblank_time = 0xffffffff; /* if the displays are off, vblank > time is max */ > + > + if (adev->mode_info.num_crtc && > adev->mode_info.mode_config_initialized) { > + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) > { > + amdgpu_crtc = to_amdgpu_crtc(crtc); > + > + /* The array should only contain active displays. */ > + if (!amdgpu_crtc->enabled) > + continue; > + > + conn = to_amdgpu_connector(amdgpu_crtc->connector); > + display_cfg = > &adev->pm.pm_display_cfg.displays[num_crtcs++]; > + > + if (amdgpu_crtc->hw_mode.clock) { > + vrefresh = > drm_mode_vrefresh(&amdgpu_crtc->hw_mode); > + > + vblank_in_pixels = > + amdgpu_crtc->hw_mode.crtc_htotal * > + (amdgpu_crtc->hw_mode.crtc_vblank_end > - > + amdgpu_crtc->hw_mode.crtc_vdisplay + > + (amdgpu_crtc->v_border * 2)); > + > + vblank_time_us = > + vblank_in_pixels * 1000 / > amdgpu_crtc->hw_mode.clock; > + > + /* The legacy (non-DC) code has issues with > mclk switching > + * with refresh rates over 120 Hz. Disable > mclk switching. > + */ > + if (vrefresh > 120) > + vblank_time_us = 0; > + > + /* Find minimum vblank time. */ > + if (vblank_time_us < cfg->min_vblank_time) > + cfg->min_vblank_time = vblank_time_us; > + > + /* Find vertical refresh rate of first active > display. */ > + if (!cfg->vrefresh) > + cfg->vrefresh = vrefresh; > + } > + > + if (amdgpu_crtc->crtc_id < cfg->crtc_index) { > + /* Find first active CRTC and its line time. > */ > + cfg->crtc_index = amdgpu_crtc->crtc_id; > + cfg->line_time_in_us = amdgpu_crtc->line_time; > + } > + > + display_cfg->controller_id = amdgpu_crtc->crtc_id; > + display_cfg->pixel_clock = > conn->pixelclock_for_modeset; > + } > + } > + > + cfg->display_clk = adev->clock.default_dispclk; > + cfg->num_display = num_crtcs; > +} > diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h > b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h > index 5c2a89f0d5d5..8be11510cd92 100644 > --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h > +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h > @@ -29,4 +29,6 @@ u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); > > u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev); > > +void amdgpu_dpm_get_display_cfg(struct amdgpu_device *adev); > + > #endif > diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c > b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c > index 307ebf7e3226..33eb85dd68e9 100644 > --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c > +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c > @@ -2299,7 +2299,7 @@ static void kv_apply_state_adjust_rules(struct > amdgpu_device *adev, > > if (pi->sys_info.nb_dpm_enable) { > force_high = (mclk >= > pi->sys_info.nbp_memory_clock[3]) || > - pi->video_start || > (adev->pm.dpm.new_active_crtc_count >= 3) || > + pi->video_start || > (adev->pm.pm_display_cfg.num_display >= 3) || > pi->disable_nb_ps3_in_battery; > ps->dpm0_pg_nb_ps_lo = force_high ? 0x2 : 0x3; > ps->dpm0_pg_nb_ps_hi = 0x2; > @@ -2358,7 +2358,7 @@ static int kv_calculate_nbps_level_settings(struct > amdgpu_device *adev) > return 0; > > force_high = ((mclk >= pi->sys_info.nbp_memory_clock[3]) || > - (adev->pm.dpm.new_active_crtc_count >= 3) || > pi->video_start); > + (adev->pm.pm_display_cfg.num_display >= 3) || > pi->video_start); > > if (force_high) { > for (i = pi->lowest_valid; i <= pi->highest_valid; > i++) > diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c > b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c > index 52dbf6d0469d..6ebe3d0f5b87 100644 > --- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c > +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c > @@ -771,7 +771,7 @@ static struct amdgpu_ps > *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, > int i; > struct amdgpu_ps *ps; > u32 ui_class; > - bool single_display = adev->pm.dpm.new_active_crtc_count < 2; > + bool single_display = adev->pm.pm_display_cfg.num_display < 2; > > /* check if the vblank period is too short to adjust the mclk */ > if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { > @@ -967,7 +967,8 @@ void amdgpu_legacy_dpm_compute_clocks(void *handle) > { > struct amdgpu_device *adev = (struct amdgpu_device *)handle; > > - amdgpu_dpm_get_active_displays(adev); > + if (!adev->dc_enabled) > + amdgpu_dpm_get_display_cfg(adev); > > amdgpu_dpm_change_power_state_locked(adev); > } > diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c > b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c > index 6595a611ce6e..cf9932e68055 100644 > --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c > +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c > @@ -3081,7 +3081,7 @@ static int si_get_vce_clock_voltage(struct > amdgpu_device *adev, > static bool si_dpm_vblank_too_short(void *handle) > { > struct amdgpu_device *adev = (struct amdgpu_device *)handle; > - u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); > + u32 vblank_time = adev->pm.pm_display_cfg.min_vblank_time; > /* we never hit the non-gddr5 limit so disable it */ > u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? > 450 : 0; > > @@ -3447,9 +3447,10 @@ static void rv770_get_engine_memory_ss(struct > amdgpu_device *adev) > static void si_apply_state_adjust_rules(struct amdgpu_device *adev, > struct amdgpu_ps *rps) > { > + const struct amd_pp_display_configuration *display_cfg = > + &adev->pm.pm_display_cfg; > struct si_ps *ps = si_get_ps(rps); > struct amdgpu_clock_and_voltage_limits *max_limits; > - struct amdgpu_connector *conn; > bool disable_mclk_switching = false; > bool disable_sclk_switching = false; > u32 mclk, sclk; > @@ -3488,14 +3489,9 @@ static void si_apply_state_adjust_rules(struct > amdgpu_device *adev, > * For example, 4K 60Hz and 1080p 144Hz fall into this category. > * Find number of such displays connected. > */ > - for (i = 0; i < adev->mode_info.num_crtc; i++) { > - if (!(adev->pm.dpm.new_active_crtcs & (1 << i)) || > - !adev->mode_info.crtcs[i]->enabled) > - continue; > - > - conn = > to_amdgpu_connector(adev->mode_info.crtcs[i]->connector); > - > - if (conn->pixelclock_for_modeset > 297000) > + for (i = 0; i < display_cfg->num_display; i++) { > + /* The array only contains active displays. */ > + if (display_cfg->displays[i].pixel_clock > 297000) > high_pixelclock_count++; > } > > @@ -3523,7 +3519,7 @@ static void si_apply_state_adjust_rules(struct > amdgpu_device *adev, > rps->ecclk = 0; > } > > - if ((adev->pm.dpm.new_active_crtc_count > 1) || > + if ((adev->pm.pm_display_cfg.num_display > 1) || > si_dpm_vblank_too_short(adev)) > disable_mclk_switching = true; > > @@ -3671,7 +3667,7 @@ static void si_apply_state_adjust_rules(struct > amdgpu_device *adev, > > ps->performance_levels[i].mclk, > max_limits->vddc, > &ps->performance_levels[i].vddc); > > btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, > - > adev->clock.current_dispclk, > + display_cfg->display_clk, > max_limits->vddc, > &ps->performance_levels[i].vddc); > } > > @@ -4196,16 +4192,16 @@ static void si_program_ds_registers(struct > amdgpu_device *adev) > > static void si_program_display_gap(struct amdgpu_device *adev) > { > + const struct amd_pp_display_configuration *cfg = > &adev->pm.pm_display_cfg; > u32 tmp, pipe; > - int i; > > tmp = RREG32(mmCG_DISPLAY_GAP_CNTL) & > ~(CG_DISPLAY_GAP_CNTL__DISP1_GAP_MASK | CG_DISPLAY_GAP_CNTL__DISP2_GAP_MASK); > - if (adev->pm.dpm.new_active_crtc_count > 0) > + if (cfg->num_display > 0) > tmp |= R600_PM_DISPLAY_GAP_VBLANK_OR_WM << > CG_DISPLAY_GAP_CNTL__DISP1_GAP__SHIFT; > else > tmp |= R600_PM_DISPLAY_GAP_IGNORE << > CG_DISPLAY_GAP_CNTL__DISP1_GAP__SHIFT; > > - if (adev->pm.dpm.new_active_crtc_count > 1) > + if (cfg->num_display > 1) > tmp |= R600_PM_DISPLAY_GAP_VBLANK_OR_WM << > CG_DISPLAY_GAP_CNTL__DISP2_GAP__SHIFT; > else > tmp |= R600_PM_DISPLAY_GAP_IGNORE << > CG_DISPLAY_GAP_CNTL__DISP2_GAP__SHIFT; > @@ -4215,17 +4211,8 @@ static void si_program_display_gap(struct > amdgpu_device *adev) > tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG); > pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> > DCCG_DISP1_SLOW_SELECT_SHIFT; > > - if ((adev->pm.dpm.new_active_crtc_count > 0) && > - (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) { > - /* find the first active crtc */ > - for (i = 0; i < adev->mode_info.num_crtc; i++) { > - if (adev->pm.dpm.new_active_crtcs & (1 << i)) > - break; > - } > - if (i == adev->mode_info.num_crtc) > - pipe = 0; > - else > - pipe = i; > + if (cfg->num_display > 0 && pipe != cfg->crtc_index) { > + pipe = cfg->crtc_index; > > tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK; > tmp |= DCCG_DISP1_SLOW_SELECT(pipe); > @@ -4236,7 +4223,7 @@ static void si_program_display_gap(struct amdgpu_device > *adev) > * This can be a problem on PowerXpress systems or if you want to use > the card > * for offscreen rendering or compute if there are no crtcs enabled. > */ > - si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > > 0); > + si_notify_smc_display_change(adev, cfg->num_display > 0); > } > > static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool > enable) > @@ -5545,7 +5532,7 @@ static int si_convert_power_level_to_smc(struct > amdgpu_device *adev, > (pl->mclk <= pi->mclk_stutter_mode_threshold) && > !eg_pi->uvd_enabled && > (RREG32(mmDPG_PIPE_STUTTER_CONTROL) & > DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK) && > - (adev->pm.dpm.new_active_crtc_count <= 2)) { > + (adev->pm.pm_display_cfg.num_display <= 2)) { > level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN; > } > > @@ -5694,7 +5681,7 @@ static bool si_is_state_ulv_compatible(struct > amdgpu_device *adev, > /* XXX validate against display requirements! */ > > for (i = 0; i < > adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) { > - if (adev->clock.current_dispclk <= > + if (adev->pm.pm_display_cfg.display_clk <= > > adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) { > if (ulv->pl.vddc < > > adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v) > @@ -5848,30 +5835,22 @@ static int si_upload_ulv_state(struct amdgpu_device > *adev) > > static int si_upload_smc_data(struct amdgpu_device *adev) > { > - struct amdgpu_crtc *amdgpu_crtc = NULL; > - int i; > + const struct amd_pp_display_configuration *cfg = > &adev->pm.pm_display_cfg; > u32 crtc_index = 0; > u32 mclk_change_block_cp_min = 0; > u32 mclk_change_block_cp_max = 0; > > - for (i = 0; i < adev->mode_info.num_crtc; i++) { > - if (adev->pm.dpm.new_active_crtcs & (1 << i)) { > - amdgpu_crtc = adev->mode_info.crtcs[i]; > - break; > - } > - } > - > /* When a display is plugged in, program these so that the SMC > * performs MCLK switching when it doesn't cause flickering. > * When no display is plugged in, there is no need to restrict > * MCLK switching, so program them to zero. > */ > - if (adev->pm.dpm.new_active_crtc_count && amdgpu_crtc) { > - crtc_index = amdgpu_crtc->crtc_id; > + if (cfg->num_display) { > + crtc_index = cfg->crtc_index; > > - if (amdgpu_crtc->line_time) { > - mclk_change_block_cp_min = 200 / > amdgpu_crtc->line_time; > - mclk_change_block_cp_max = 100 / > amdgpu_crtc->line_time; > + if (cfg->line_time_in_us) { > + mclk_change_block_cp_min = 200 / cfg->line_time_in_us; > + mclk_change_block_cp_max = 100 / cfg->line_time_in_us; > } > } > > diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c > b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c > index b48a031cbba0..554492dfa3c0 100644 > --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c > +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c > @@ -1554,16 +1554,7 @@ static void pp_pm_compute_clocks(void *handle) > struct amdgpu_device *adev = hwmgr->adev; > > if (!adev->dc_enabled) { > - amdgpu_dpm_get_active_displays(adev); > - adev->pm.pm_display_cfg.num_display = > adev->pm.dpm.new_active_crtc_count; > - adev->pm.pm_display_cfg.vrefresh = > amdgpu_dpm_get_vrefresh(adev); > - adev->pm.pm_display_cfg.min_vblank_time = > amdgpu_dpm_get_vblank_time(adev); > - /* we have issues with mclk switching with > - * refresh rates over 120 hz on the non-DC code. > - */ > - if (adev->pm.pm_display_cfg.vrefresh > 120) > - adev->pm.pm_display_cfg.min_vblank_time = 0; > - > + amdgpu_dpm_get_display_cfg(adev); > pp_display_configuration_change(handle, > &adev->pm.pm_display_cfg); > } > -- > 2.51.0 >