mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
drm/radeon/kms: fix up dce6 display watermark calc for dpm
Calculate the low and high watermarks based on the low and high clocks for the current power state. The dynamic pm hw will select the appropriate watermark based on the internal dpm state. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
cf0cfdd7a7
commit
c696e53f78
1 changed files with 71 additions and 25 deletions
|
@ -1792,7 +1792,8 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
|
|||
u32 lb_size, u32 num_heads)
|
||||
{
|
||||
struct drm_display_mode *mode = &radeon_crtc->base.mode;
|
||||
struct dce6_wm_params wm;
|
||||
struct dce6_wm_params wm_low, wm_high;
|
||||
u32 dram_channels;
|
||||
u32 pixel_period;
|
||||
u32 line_time = 0;
|
||||
u32 latency_watermark_a = 0, latency_watermark_b = 0;
|
||||
|
@ -1808,38 +1809,83 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
|
|||
priority_a_cnt = 0;
|
||||
priority_b_cnt = 0;
|
||||
|
||||
wm.yclk = rdev->pm.current_mclk * 10;
|
||||
wm.sclk = rdev->pm.current_sclk * 10;
|
||||
wm.disp_clk = mode->clock;
|
||||
wm.src_width = mode->crtc_hdisplay;
|
||||
wm.active_time = mode->crtc_hdisplay * pixel_period;
|
||||
wm.blank_time = line_time - wm.active_time;
|
||||
wm.interlaced = false;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
wm.interlaced = true;
|
||||
wm.vsc = radeon_crtc->vsc;
|
||||
wm.vtaps = 1;
|
||||
if (radeon_crtc->rmx_type != RMX_OFF)
|
||||
wm.vtaps = 2;
|
||||
wm.bytes_per_pixel = 4; /* XXX: get this from fb config */
|
||||
wm.lb_size = lb_size;
|
||||
if (rdev->family == CHIP_ARUBA)
|
||||
wm.dram_channels = evergreen_get_number_of_dram_channels(rdev);
|
||||
dram_channels = evergreen_get_number_of_dram_channels(rdev);
|
||||
else
|
||||
wm.dram_channels = si_get_number_of_dram_channels(rdev);
|
||||
wm.num_heads = num_heads;
|
||||
dram_channels = si_get_number_of_dram_channels(rdev);
|
||||
|
||||
/* watermark for high clocks */
|
||||
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
|
||||
wm_high.yclk =
|
||||
radeon_dpm_get_mclk(rdev, false) * 10;
|
||||
wm_high.sclk =
|
||||
radeon_dpm_get_sclk(rdev, false) * 10;
|
||||
} else {
|
||||
wm_high.yclk = rdev->pm.current_mclk * 10;
|
||||
wm_high.sclk = rdev->pm.current_sclk * 10;
|
||||
}
|
||||
|
||||
wm_high.disp_clk = mode->clock;
|
||||
wm_high.src_width = mode->crtc_hdisplay;
|
||||
wm_high.active_time = mode->crtc_hdisplay * pixel_period;
|
||||
wm_high.blank_time = line_time - wm_high.active_time;
|
||||
wm_high.interlaced = false;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
wm_high.interlaced = true;
|
||||
wm_high.vsc = radeon_crtc->vsc;
|
||||
wm_high.vtaps = 1;
|
||||
if (radeon_crtc->rmx_type != RMX_OFF)
|
||||
wm_high.vtaps = 2;
|
||||
wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */
|
||||
wm_high.lb_size = lb_size;
|
||||
wm_high.dram_channels = dram_channels;
|
||||
wm_high.num_heads = num_heads;
|
||||
|
||||
/* watermark for low clocks */
|
||||
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
|
||||
wm_low.yclk =
|
||||
radeon_dpm_get_mclk(rdev, true) * 10;
|
||||
wm_low.sclk =
|
||||
radeon_dpm_get_sclk(rdev, true) * 10;
|
||||
} else {
|
||||
wm_low.yclk = rdev->pm.current_mclk * 10;
|
||||
wm_low.sclk = rdev->pm.current_sclk * 10;
|
||||
}
|
||||
|
||||
wm_low.disp_clk = mode->clock;
|
||||
wm_low.src_width = mode->crtc_hdisplay;
|
||||
wm_low.active_time = mode->crtc_hdisplay * pixel_period;
|
||||
wm_low.blank_time = line_time - wm_low.active_time;
|
||||
wm_low.interlaced = false;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
wm_low.interlaced = true;
|
||||
wm_low.vsc = radeon_crtc->vsc;
|
||||
wm_low.vtaps = 1;
|
||||
if (radeon_crtc->rmx_type != RMX_OFF)
|
||||
wm_low.vtaps = 2;
|
||||
wm_low.bytes_per_pixel = 4; /* XXX: get this from fb config */
|
||||
wm_low.lb_size = lb_size;
|
||||
wm_low.dram_channels = dram_channels;
|
||||
wm_low.num_heads = num_heads;
|
||||
|
||||
/* set for high clocks */
|
||||
latency_watermark_a = min(dce6_latency_watermark(&wm), (u32)65535);
|
||||
latency_watermark_a = min(dce6_latency_watermark(&wm_high), (u32)65535);
|
||||
/* set for low clocks */
|
||||
/* wm.yclk = low clk; wm.sclk = low clk */
|
||||
latency_watermark_b = min(dce6_latency_watermark(&wm), (u32)65535);
|
||||
latency_watermark_b = min(dce6_latency_watermark(&wm_low), (u32)65535);
|
||||
|
||||
/* possibly force display priority to high */
|
||||
/* should really do this at mode validation time... */
|
||||
if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm) ||
|
||||
!dce6_average_bandwidth_vs_available_bandwidth(&wm) ||
|
||||
!dce6_check_latency_hiding(&wm) ||
|
||||
if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
|
||||
!dce6_average_bandwidth_vs_available_bandwidth(&wm_high) ||
|
||||
!dce6_check_latency_hiding(&wm_high) ||
|
||||
(rdev->disp_priority == 2)) {
|
||||
DRM_DEBUG_KMS("force priority to high\n");
|
||||
priority_a_cnt |= PRIORITY_ALWAYS_ON;
|
||||
priority_b_cnt |= PRIORITY_ALWAYS_ON;
|
||||
}
|
||||
if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
|
||||
!dce6_average_bandwidth_vs_available_bandwidth(&wm_low) ||
|
||||
!dce6_check_latency_hiding(&wm_low) ||
|
||||
(rdev->disp_priority == 2)) {
|
||||
DRM_DEBUG_KMS("force priority to high\n");
|
||||
priority_a_cnt |= PRIORITY_ALWAYS_ON;
|
||||
|
|
Loading…
Reference in a new issue