|
@@ -1811,8 +1811,110 @@ static void sandybridge_update_wm(struct drm_device *dev)
|
|
|
enabled |= 2;
|
|
|
}
|
|
|
|
|
|
- if ((dev_priv->num_pipe == 3) &&
|
|
|
- g4x_compute_wm0(dev, 2,
|
|
|
+ /*
|
|
|
+ * Calculate and update the self-refresh watermark only when one
|
|
|
+ * display plane is used.
|
|
|
+ *
|
|
|
+ * SNB support 3 levels of watermark.
|
|
|
+ *
|
|
|
+ * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
|
|
|
+ * and disabled in the descending order
|
|
|
+ *
|
|
|
+ */
|
|
|
+ I915_WRITE(WM3_LP_ILK, 0);
|
|
|
+ I915_WRITE(WM2_LP_ILK, 0);
|
|
|
+ I915_WRITE(WM1_LP_ILK, 0);
|
|
|
+
|
|
|
+ if (!single_plane_enabled(enabled) ||
|
|
|
+ dev_priv->sprite_scaling_enabled)
|
|
|
+ return;
|
|
|
+ enabled = ffs(enabled) - 1;
|
|
|
+
|
|
|
+ /* WM1 */
|
|
|
+ if (!ironlake_compute_srwm(dev, 1, enabled,
|
|
|
+ SNB_READ_WM1_LATENCY() * 500,
|
|
|
+ &sandybridge_display_srwm_info,
|
|
|
+ &sandybridge_cursor_srwm_info,
|
|
|
+ &fbc_wm, &plane_wm, &cursor_wm))
|
|
|
+ return;
|
|
|
+
|
|
|
+ I915_WRITE(WM1_LP_ILK,
|
|
|
+ WM1_LP_SR_EN |
|
|
|
+ (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
|
|
|
+ (fbc_wm << WM1_LP_FBC_SHIFT) |
|
|
|
+ (plane_wm << WM1_LP_SR_SHIFT) |
|
|
|
+ cursor_wm);
|
|
|
+
|
|
|
+ /* WM2 */
|
|
|
+ if (!ironlake_compute_srwm(dev, 2, enabled,
|
|
|
+ SNB_READ_WM2_LATENCY() * 500,
|
|
|
+ &sandybridge_display_srwm_info,
|
|
|
+ &sandybridge_cursor_srwm_info,
|
|
|
+ &fbc_wm, &plane_wm, &cursor_wm))
|
|
|
+ return;
|
|
|
+
|
|
|
+ I915_WRITE(WM2_LP_ILK,
|
|
|
+ WM2_LP_EN |
|
|
|
+ (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
|
|
|
+ (fbc_wm << WM1_LP_FBC_SHIFT) |
|
|
|
+ (plane_wm << WM1_LP_SR_SHIFT) |
|
|
|
+ cursor_wm);
|
|
|
+
|
|
|
+ /* WM3 */
|
|
|
+ if (!ironlake_compute_srwm(dev, 3, enabled,
|
|
|
+ SNB_READ_WM3_LATENCY() * 500,
|
|
|
+ &sandybridge_display_srwm_info,
|
|
|
+ &sandybridge_cursor_srwm_info,
|
|
|
+ &fbc_wm, &plane_wm, &cursor_wm))
|
|
|
+ return;
|
|
|
+
|
|
|
+ I915_WRITE(WM3_LP_ILK,
|
|
|
+ WM3_LP_EN |
|
|
|
+ (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
|
|
|
+ (fbc_wm << WM1_LP_FBC_SHIFT) |
|
|
|
+ (plane_wm << WM1_LP_SR_SHIFT) |
|
|
|
+ cursor_wm);
|
|
|
+}
|
|
|
+
|
|
|
+static void ivybridge_update_wm(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */
|
|
|
+ u32 val;
|
|
|
+ int fbc_wm, plane_wm, cursor_wm;
|
|
|
+ int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
|
|
|
+ unsigned int enabled;
|
|
|
+
|
|
|
+ enabled = 0;
|
|
|
+ if (g4x_compute_wm0(dev, 0,
|
|
|
+ &sandybridge_display_wm_info, latency,
|
|
|
+ &sandybridge_cursor_wm_info, latency,
|
|
|
+ &plane_wm, &cursor_wm)) {
|
|
|
+ val = I915_READ(WM0_PIPEA_ILK);
|
|
|
+ val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
|
|
|
+ I915_WRITE(WM0_PIPEA_ILK, val |
|
|
|
+ ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
|
|
|
+ DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
|
|
|
+ " plane %d, " "cursor: %d\n",
|
|
|
+ plane_wm, cursor_wm);
|
|
|
+ enabled |= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (g4x_compute_wm0(dev, 1,
|
|
|
+ &sandybridge_display_wm_info, latency,
|
|
|
+ &sandybridge_cursor_wm_info, latency,
|
|
|
+ &plane_wm, &cursor_wm)) {
|
|
|
+ val = I915_READ(WM0_PIPEB_ILK);
|
|
|
+ val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
|
|
|
+ I915_WRITE(WM0_PIPEB_ILK, val |
|
|
|
+ ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
|
|
|
+ DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
|
|
|
+ " plane %d, cursor: %d\n",
|
|
|
+ plane_wm, cursor_wm);
|
|
|
+ enabled |= 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (g4x_compute_wm0(dev, 2,
|
|
|
&sandybridge_display_wm_info, latency,
|
|
|
&sandybridge_cursor_wm_info, latency,
|
|
|
&plane_wm, &cursor_wm)) {
|
|
@@ -1875,12 +1977,17 @@ static void sandybridge_update_wm(struct drm_device *dev)
|
|
|
(plane_wm << WM1_LP_SR_SHIFT) |
|
|
|
cursor_wm);
|
|
|
|
|
|
- /* WM3 */
|
|
|
+ /* WM3, note we have to correct the cursor latency */
|
|
|
if (!ironlake_compute_srwm(dev, 3, enabled,
|
|
|
SNB_READ_WM3_LATENCY() * 500,
|
|
|
&sandybridge_display_srwm_info,
|
|
|
&sandybridge_cursor_srwm_info,
|
|
|
- &fbc_wm, &plane_wm, &cursor_wm))
|
|
|
+ &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
|
|
|
+ !ironlake_compute_srwm(dev, 3, enabled,
|
|
|
+ 2 * SNB_READ_WM3_LATENCY() * 500,
|
|
|
+ &sandybridge_display_srwm_info,
|
|
|
+ &sandybridge_cursor_srwm_info,
|
|
|
+ &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
|
|
|
return;
|
|
|
|
|
|
I915_WRITE(WM3_LP_ILK,
|
|
@@ -4005,7 +4112,7 @@ void intel_init_pm(struct drm_device *dev)
|
|
|
} else if (IS_IVYBRIDGE(dev)) {
|
|
|
/* FIXME: detect B0+ stepping and use auto training */
|
|
|
if (SNB_READ_WM0_LATENCY()) {
|
|
|
- dev_priv->display.update_wm = sandybridge_update_wm;
|
|
|
+ dev_priv->display.update_wm = ivybridge_update_wm;
|
|
|
dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
|
|
|
} else {
|
|
|
DRM_DEBUG_KMS("Failed to read display plane latency. "
|