[PATCH 21/26] drm/i915: Allow async modeset enable.
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Thu May 12 20:50:26 UTC 2016
Transitioning from enable -> disable or enable -> enable is not yet
allowed. This cannot be run async yet.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 105 ++++++++++++++++++-----------------
1 file changed, 55 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b9f1712569c1..a6edfea5da27 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10938,6 +10938,45 @@ void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+static void update_scanline_offset(struct intel_crtc *crtc,
+ struct intel_crtc_state *pipe_config)
+{
+ struct drm_device *dev = crtc->base.dev;
+
+ /*
+ * The scanline counter increments at the leading edge of hsync.
+ *
+ * On most platforms it starts counting from vtotal-1 on the
+ * first active line. That means the scanline counter value is
+ * always one less than what we would expect. Ie. just after
+ * start of vblank, which also occurs at start of hsync (on the
+ * last active line), the scanline counter will read vblank_start-1.
+ *
+ * On gen2 the scanline counter starts counting from 1 instead
+ * of vtotal-1, so we have to subtract one (or rather add vtotal-1
+ * to keep the value positive), instead of adding one.
+ *
+ * On HSW+ the behaviour of the scanline counter depends on the output
+ * type. For DP ports it behaves like most other platforms, but on HDMI
+ * there's an extra 1 line difference. So we need to add two instead of
+ * one to the value.
+ */
+ if (IS_GEN2(dev)) {
+ const struct drm_display_mode *mode = &pipe_config->base.adjusted_mode;
+ int vtotal;
+
+ vtotal = mode->crtc_vtotal;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ vtotal /= 2;
+
+ crtc->scanline_offset = vtotal - 1;
+ } else if (HAS_DDI(dev) &&
+ intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+ crtc->scanline_offset = 2;
+ } else
+ crtc->scanline_offset = 1;
+}
+
static void intel_mmio_flip_work_func(struct work_struct *w)
{
struct intel_flip_work *work =
@@ -10970,6 +11009,11 @@ static void intel_mmio_flip_work_func(struct work_struct *w)
&dev_priv->rps.mmioflips));
}
+ if (needs_modeset(&crtc_state->base)) {
+ update_scanline_offset(intel_crtc, crtc_state);
+ dev_priv->display.crtc_enable(crtc);
+ }
+
ret = drm_crtc_vblank_get(crtc);
I915_STATE_WARN(ret < 0, "enabling vblank failed with %i\n", ret);
@@ -12347,44 +12391,6 @@ intel_modeset_verify_disabled(struct drm_device *dev)
verify_disabled_dpll_state(dev);
}
-static void update_scanline_offset(struct intel_crtc *crtc)
-{
- struct drm_device *dev = crtc->base.dev;
-
- /*
- * The scanline counter increments at the leading edge of hsync.
- *
- * On most platforms it starts counting from vtotal-1 on the
- * first active line. That means the scanline counter value is
- * always one less than what we would expect. Ie. just after
- * start of vblank, which also occurs at start of hsync (on the
- * last active line), the scanline counter will read vblank_start-1.
- *
- * On gen2 the scanline counter starts counting from 1 instead
- * of vtotal-1, so we have to subtract one (or rather add vtotal-1
- * to keep the value positive), instead of adding one.
- *
- * On HSW+ the behaviour of the scanline counter depends on the output
- * type. For DP ports it behaves like most other platforms, but on HDMI
- * there's an extra 1 line difference. So we need to add two instead of
- * one to the value.
- */
- if (IS_GEN2(dev)) {
- const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
- int vtotal;
-
- vtotal = adjusted_mode->crtc_vtotal;
- if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
- vtotal /= 2;
-
- crtc->scanline_offset = vtotal - 1;
- } else if (HAS_DDI(dev) &&
- intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
- crtc->scanline_offset = 2;
- } else
- crtc->scanline_offset = 1;
-}
-
static void intel_modeset_clear_plls(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
@@ -12722,7 +12728,7 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
struct drm_crtc_state *crtc_state;
struct drm_plane *plane;
struct drm_crtc *crtc;
- int i, ret;
+ int i, ret, num_ms_disable = 0;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -12736,10 +12742,12 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
flush_workqueue(dev_priv->wq);
}
- /* test if we need to update something */
if (!needs_work(crtc_state))
continue;
+ if (needs_modeset(crtc_state) && crtc->state->active)
+ num_ms_disable++;
+
intel_state->work[i] =
kzalloc(sizeof(**intel_state->work), GFP_KERNEL);
@@ -12747,8 +12755,8 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
return -ENOMEM;
}
- if (intel_state->modeset && nonblock) {
- DRM_DEBUG_ATOMIC("Nonblock modesets are not yet supported!\n");
+ if (nonblock && num_ms_disable) {
+ DRM_DEBUG_ATOMIC("Nonblocking modeset disable/toggling is not yet supported!\n");
return -EINVAL;
}
@@ -13019,11 +13027,6 @@ static int intel_atomic_commit(struct drm_device *dev,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
bool modeset = needs_modeset(crtc->state);
- if (modeset && crtc->state->active) {
- update_scanline_offset(to_intel_crtc(crtc));
- dev_priv->display.crtc_enable(crtc);
- }
-
if (!modeset)
intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
@@ -15188,7 +15191,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
- update_scanline_offset(crtc);
+ update_scanline_offset(crtc, crtc->config);
}
intel_pipe_config_sanity_check(dev_priv, crtc->config);
@@ -15246,8 +15249,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
unsigned long put_domains;
put_domains = modeset_get_crtc_power_domains(&crtc->base, crtc->config);
- if (WARN_ON(put_domains))
- modeset_put_power_domains(dev_priv, put_domains);
+
+ WARN_ON(put_domains);
+
+ modeset_put_power_domains(dev_priv, put_domains);
}
intel_display_set_init_power(dev_priv, false);
--
2.5.5
More information about the Intel-gfx-trybot
mailing list