@@ -569,6 +569,7 @@ struct drm_i915_display_funcs {
struct drm_crtc *crtc,
uint32_t sprite_width, uint32_t sprite_height,
int pixel_size, bool enable, bool scaled);
+ void (*program_watermarks)(struct drm_i915_private *dev_priv);
void (*modeset_global_resources)(struct drm_atomic_state *state);
/* Returns the active state of the crtc, and if the crtc is active,
* fills out the pipe-config with the hw state. */ @@ -2494,6 +2495,12 @@ struct drm_i915_cmd_table { #define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
+/*
+ * FIXME: Only some platforms have been transitioned to atomic
+watermark
+ * updates so far.
+ */
+#define HAS_ATOMIC_WM(dev_priv) (dev_priv->display.program_watermarks
+!= NULL)
+
#define GT_FREQUENCY_MULTIPLIER 50
#define GEN9_FREQ_SCALER 3
@@ -13209,6 +13209,24 @@ intel_disable_primary_plane(struct drm_plane *plane,
dev_priv->display.update_primary_plane(crtc, NULL, 0, 0); }
+static void
+do_update_watermarks(struct intel_crtc *intel_crtc,
+ void *data,
+ bool early,
+ u32 seq)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+
+ /*
+ * If we fired early because the CRTC is turning off, there's no
+ * need to actually program watermarks.
+ */
+ if (early)
+ return;
+
+ dev_priv->display.program_watermarks(dev_priv);
+}
+
static void intel_begin_crtc_commit(struct drm_crtc *crtc) {
struct drm_device *dev = crtc->dev;
@@ -13251,7 +13269,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
if (intel_crtc->atomic.pre_disable_primary)
intel_pre_disable_primary(crtc);
- if (intel_crtc->atomic.update_wm)
+ if (!HAS_ATOMIC_WM(dev_priv) && intel_crtc->atomic.update_wm)
intel_update_watermarks(crtc);
intel_runtime_pm_get(dev_priv);
@@ -13270,6 +13288,15 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_plane *p;
+ /*
+ * If this platform supports atomic watermarks, schedule a job to
+ * update watermarks when the next vblank occurs. Otherwise, just
+ * update watermarks the old-fashioned way.
+ */
+ if (HAS_ATOMIC_WM(dev_priv))
+ intel_schedule_vblank_job(intel_crtc, do_update_watermarks,
+ NULL, dev_priv->wq, 1);
+
if (intel_crtc->atomic.evade)
intel_pipe_update_end(intel_crtc,
intel_crtc->atomic.start_vbl_count);
@@ -13290,10 +13317,11 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc)
if (intel_crtc->atomic.post_enable_primary)
intel_post_enable_primary(crtc);
- drm_for_each_legacy_plane(p, &dev->mode_config.plane_list)
- if (intel_crtc->atomic.update_sprite_watermarks &
- (1 << drm_plane_index(p)))
- intel_update_sprite_watermarks(p, crtc);
+ if (!HAS_ATOMIC_WM(dev_priv))
+ drm_for_each_legacy_plane(p, &dev->mode_config.plane_list)
+ if (intel_crtc->atomic.update_sprite_watermarks &
+ (1 << drm_plane_index(p)))
+ intel_update_sprite_watermarks(p, crtc);
memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic)); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 27337fe..7f0a0c1 100644
@@ -6626,6 +6626,7 @@ void intel_init_pm(struct drm_device *dev)
dev_priv->display.update_wm = ilk_update_wm;
dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
+ dev_priv->display.program_watermarks = ilk_program_watermarks;
} else {
DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n");