drm/radeon/kms: fix up dce4/5 display watermark calc for dpm
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 13 Mar 2012 20:25:11 +0000 (16:25 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jun 2013 14:49:22 +0000 (10:49 -0400)
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>
drivers/gpu/drm/radeon/evergreen.c

index b9f64f0e003ddc1f435fc9929ad523001b520795..63a1e6ec7f5a3aa072774edbbd8ee6171ca46cbe 100644 (file)
@@ -2122,7 +2122,8 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
                                         u32 lb_size, u32 num_heads)
 {
        struct drm_display_mode *mode = &radeon_crtc->base.mode;
-       struct evergreen_wm_params wm;
+       struct evergreen_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;
@@ -2138,39 +2139,81 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
                line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
+               dram_channels = evergreen_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.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;
+               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.interlaced = true;
-               wm.vsc = radeon_crtc->vsc;
-               wm.vtaps = 1;
+                       wm_high.interlaced = true;
+               wm_high.vsc = radeon_crtc->vsc;
+               wm_high.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;
-               wm.dram_channels = evergreen_get_number_of_dram_channels(rdev);
-               wm.num_heads = num_heads;
+                       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(evergreen_latency_watermark(&wm), (u32)65535);
+               latency_watermark_a = min(evergreen_latency_watermark(&wm_high), (u32)65535);
                /* set for low clocks */
-               /* wm.yclk = low clk; wm.sclk = low clk */
-               latency_watermark_b = min(evergreen_latency_watermark(&wm), (u32)65535);
+               latency_watermark_b = min(evergreen_latency_watermark(&wm_low), (u32)65535);
 
                /* possibly force display priority to high */
                /* should really do this at mode validation time... */
-               if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm) ||
-                   !evergreen_average_bandwidth_vs_available_bandwidth(&wm) ||
-                   !evergreen_check_latency_hiding(&wm) ||
+               if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
+                   !evergreen_average_bandwidth_vs_available_bandwidth(&wm_high) ||
+                   !evergreen_check_latency_hiding(&wm_high) ||
                    (rdev->disp_priority == 2)) {
-                       DRM_DEBUG_KMS("force priority to high\n");
+                       DRM_DEBUG_KMS("force priority to high\n");
                        priority_a_cnt |= PRIORITY_ALWAYS_ON;
+               }
+               if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
+                   !evergreen_average_bandwidth_vs_available_bandwidth(&wm_low) ||
+                   !evergreen_check_latency_hiding(&wm_low) ||
+                   (rdev->disp_priority == 2)) {
+                       DRM_DEBUG_KMS("force priority b to high\n");
                        priority_b_cnt |= PRIORITY_ALWAYS_ON;
                }