aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2015-07-14 15:58:28 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-07-14 17:18:51 +0200
commit5c1e34261907736dc3b3a7219b2f48f353f10a93 (patch)
treef6513b487a375143479b6177bfba93ecd146c7d0
parentdrm/i915: Calculate vblank timestamping constants before enabling vblank. (diff)
downloadlinux-dev-5c1e34261907736dc3b3a7219b2f48f353f10a93.tar.xz
linux-dev-5c1e34261907736dc3b3a7219b2f48f353f10a93.zip
drm/i915: Readout initial hw mode.
drm/i915: Readout initial hw mode, v2. Atomic requires a mode blob when crtc_state->enable is true, or you get a huge warn_on. With a few tweaks the mode we read out from hardware could be used as the real mode without a modeset, but this requires too much testing, so for now force a modeset the first time the mode blob's updated. This preserves the old behavior, because previously we never set the initial mode, which always meant that a modeset happened when the mode was first set. Changes since v1: - Add a description in intel_modeset_readout_hw_state of how the recalculation is done. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c62
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c11
2 files changed, 44 insertions, 29 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1b8a17c67ff5..a1341cbd40e0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13146,7 +13146,7 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc_state);
- bool modeset, recalc;
+ bool modeset, recalc = false;
if (!crtc_state->enable) {
if (needs_modeset(crtc_state))
@@ -13155,7 +13155,10 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
}
modeset = needs_modeset(crtc_state);
- recalc = pipe_config->quirks & PIPE_CONFIG_QUIRK_INHERITED_MODE;
+ /* see comment in intel_modeset_readout_hw_state */
+ if (!modeset && crtc_state->mode_blob != crtc->state->mode_blob &&
+ pipe_config->quirks & PIPE_CONFIG_QUIRK_INHERITED_MODE)
+ recalc = true;
if (!modeset && !recalc)
continue;
@@ -13170,9 +13173,10 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
if (ret)
return ret;
- if (recalc && !intel_pipe_config_compare(state->dev,
+ if (recalc && (!i915.fastboot ||
+ !intel_pipe_config_compare(state->dev,
to_intel_crtc_state(crtc->state),
- pipe_config, true)) {
+ pipe_config, true))) {
modeset = crtc_state->mode_changed = true;
ret = drm_atomic_add_affected_planes(state, crtc);
@@ -15451,11 +15455,42 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->active = dev_priv->display.get_pipe_config(crtc,
crtc->config);
- crtc->base.state->enable = crtc->active;
crtc->base.state->active = crtc->active;
crtc->base.enabled = crtc->active;
- crtc->base.hwmode = crtc->config->base.adjusted_mode;
+ memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+ if (crtc->base.state->active) {
+ intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+ intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
+ WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+
+ /*
+ * The initial mode needs to be set in order to keep
+ * the atomic core happy. It wants a valid mode if the
+ * crtc's enabled, so we do the above call.
+ *
+ * At this point some state updated by the connectors
+ * in their ->detect() callback has not run yet, so
+ * no recalculation can be done yet.
+ *
+ * Even if we could do a recalculation and modeset
+ * right now it would cause a double modeset if
+ * fbdev or userspace chooses a different initial mode.
+ *
+ * So to prevent the double modeset, fail the memcmp
+ * test in drm_atomic_set_mode_for_crtc to get a new
+ * mode blob, and compare if the mode blob changed
+ * when the PIPE_CONFIG_QUIRK_INHERITED_MODE quirk is
+ * set.
+ *
+ * If that happens, someone indicated they wanted a
+ * mode change, which means it's safe to do a full
+ * recalculation.
+ */
+ crtc->base.state->mode.private_flags = ~0;
+ }
+
+ crtc->base.hwmode = crtc->config->base.adjusted_mode;
readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
@@ -15532,21 +15567,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
intel_modeset_readout_hw_state(dev);
- /*
- * Now that we have the config, copy it to each CRTC struct
- * Note that this could go away if we move to using crtc_config
- * checking everywhere.
- */
- for_each_intel_crtc(dev, crtc) {
- if (crtc->active && i915.fastboot) {
- intel_mode_from_pipe_config(&crtc->base.mode,
- crtc->config);
- DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
- crtc->base.base.id);
- drm_mode_debug_printmodeline(&crtc->base.mode);
- }
- }
-
/* HW state is read out, now we need to sanitize this mess. */
for_each_intel_encoder(dev, encoder) {
intel_sanitize_encoder(encoder);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index b791f2374f3b..7eff33ff84f6 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -483,18 +483,13 @@ retry:
* IMPORTANT: We want to use the adjusted mode (i.e.
* after the panel fitter upscaling) as the initial
* config, not the input mode, which is what crtc->mode
- * usually contains. But since our current fastboot
+ * usually contains. But since our current
* code puts a mode derived from the post-pfit timings
- * into crtc->mode this works out correctly. We don't
- * use hwmode anywhere right now, so use it for this
- * since the fb helper layer wants a pointer to
- * something we own.
+ * into crtc->mode this works out correctly.
*/
DRM_DEBUG_KMS("looking for current mode on connector %s\n",
connector->name);
- intel_mode_from_pipe_config(&encoder->crtc->hwmode,
- to_intel_crtc(encoder->crtc)->config);
- modes[i] = &encoder->crtc->hwmode;
+ modes[i] = &encoder->crtc->mode;
}
crtcs[i] = new_crtc;