drm/radeon/kms: fix up dce8 display watermark calc for dpm
authorAlex Deucher <alexander.deucher@amd.com>
Thu, 24 Jan 2013 15:03:39 +0000 (10:03 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 30 Aug 2013 20:30:02 +0000 (16:30 -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/cik.c

index 8928bd109c1647b684293cb49ed91198419eb33c..42b143e75d429f8930c6eb2789bc247d2da88840 100644 (file)
@@ -6826,7 +6826,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
                                    u32 lb_size, u32 num_heads)
 {
        struct drm_display_mode *mode = &radeon_crtc->base.mode;
-       struct dce8_wm_params wm;
+       struct dce8_wm_params wm_low, wm_high;
        u32 pixel_period;
        u32 line_time = 0;
        u32 latency_watermark_a = 0, latency_watermark_b = 0;
@@ -6836,35 +6836,82 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
                pixel_period = 1000000 / (u32)mode->clock;
                line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
 
-               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;
+               /* 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.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 = cik_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 = cik_get_number_of_dram_channels(rdev);
+               wm_high.num_heads = num_heads;
 
                /* set for high clocks */
-               latency_watermark_a = min(dce8_latency_watermark(&wm), (u32)65535);
+               latency_watermark_a = min(dce8_latency_watermark(&wm_high), (u32)65535);
+
+               /* possibly force display priority to high */
+               /* should really do this at mode validation time... */
+               if (!dce8_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
+                   !dce8_average_bandwidth_vs_available_bandwidth(&wm_high) ||
+                   !dce8_check_latency_hiding(&wm_high) ||
+                   (rdev->disp_priority == 2)) {
+                       DRM_DEBUG_KMS("force priority to high\n");
+               }
+
+               /* 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 = cik_get_number_of_dram_channels(rdev);
+               wm_low.num_heads = num_heads;
+
                /* set for low clocks */
-               /* wm.yclk = low clk; wm.sclk = low clk */
-               latency_watermark_b = min(dce8_latency_watermark(&wm), (u32)65535);
+               latency_watermark_b = min(dce8_latency_watermark(&wm_low), (u32)65535);
 
                /* possibly force display priority to high */
                /* should really do this at mode validation time... */
-               if (!dce8_average_bandwidth_vs_dram_bandwidth_for_display(&wm) ||
-                   !dce8_average_bandwidth_vs_available_bandwidth(&wm) ||
-                   !dce8_check_latency_hiding(&wm) ||
+               if (!dce8_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
+                   !dce8_average_bandwidth_vs_available_bandwidth(&wm_low) ||
+                   !dce8_check_latency_hiding(&wm_low) ||
                    (rdev->disp_priority == 2)) {
                        DRM_DEBUG_KMS("force priority to high\n");
                }
@@ -6889,6 +6936,11 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
                LATENCY_HIGH_WATERMARK(line_time)));
        /* restore original selection */
        WREG32(DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset, wm_mask);
+
+       /* save values for DPM */
+       radeon_crtc->line_time = line_time;
+       radeon_crtc->wm_high = latency_watermark_a;
+       radeon_crtc->wm_low = latency_watermark_b;
 }
 
 /**