[Intel-gfx] [RFC 3/3] drm/i915: Update modeset programming to use intermediate state
Matt Roper
matthew.d.roper at intel.com
Fri Aug 28 16:57:29 PDT 2015
As suggested by Ville, the general flow should now roughly follow:
// whatever the user wanted
compute_final_atomic_state()
// include all crtcs in the intermediate state which are
// getting disabled (even temporarily to perform a modeset)
compute_intermediate_atomic_state()
ret = check_state_change(old, intermediate)
ret = check_state_change(intermediate, new)
// commit all planes in one go to make them pop out as
// atomically as possible
for_each_crtc_in(intermediate) {
commit_planes()
}
for_each_crtc_in(intermediate) {
disable_crtc()
}
for_each_crtc_in(new) {
if (!currently_active)
crtc_enable()
}
// commit all planes in one go to make them pop in as atomically
// as possible
for_each_crtc_in(new) {
commit_planes()
}
Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
Ville, is this what you had in mind for the intermediate states for modeset? I
think there might still be a bug or two here that I need to track down, but
figured I should post this now to make sure this matches what you were asking for.
drivers/gpu/drm/i915/intel_display.c | 63 +++++++++++++++++++++++++-----------
1 file changed, 44 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 76f3727..cbc2c69 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4747,10 +4747,11 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
hsw_disable_ips(intel_crtc);
}
-static void intel_post_plane_update(struct intel_crtc *crtc)
+static void intel_post_plane_update(struct drm_crtc_state *s)
{
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->base.state);
- struct drm_device *dev = crtc->base.dev;
+ struct intel_crtc_state *cstate = to_intel_crtc_state(s);
+ struct intel_crtc *crtc = to_intel_crtc(s->crtc);
+ struct drm_device *dev = s->crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_plane *plane;
@@ -4776,10 +4777,11 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
0, 0, 0, false, false);
}
-static void intel_pre_plane_update(struct intel_crtc *crtc)
+static void intel_pre_plane_update(struct drm_crtc_state *s)
{
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->base.state);
- struct drm_device *dev = crtc->base.dev;
+ struct intel_crtc_state *cstate = to_intel_crtc_state(s);
+ struct intel_crtc *crtc = to_intel_crtc(s->crtc);
+ struct drm_device *dev = s->crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_plane *p;
@@ -13076,8 +13078,9 @@ static int intel_atomic_commit(struct drm_device *dev,
bool async)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_atomic_state *istate = to_intel_atomic_state(state);
struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
+ struct drm_crtc_state *old_crtc_state;
int ret = 0;
int i;
bool any_ms = false;
@@ -13091,19 +13094,36 @@ static int intel_atomic_commit(struct drm_device *dev,
if (ret)
return ret;
+ /*
+ * Commit final state to the underlying crtc/plane objects; the final
+ * state should now be accessed via crtc->state, plane->state, etc.
+ * However the intermediate state continues to reside in the top-level
+ * state structure (istate->int_{crtc,plane}_states[]).
+ */
drm_atomic_helper_swap_state(dev, state);
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ /*
+ * Commit all planes in one go to make them pop out as atomically
+ * as possible.
+ */
+ for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+ struct drm_crtc_state *int_cstate;
if (!needs_modeset(crtc->state))
continue;
+ if (WARN_ON(!(int_cstate = istate->int_crtc_states[i])))
+ continue;
any_ms = true;
- intel_pre_plane_update(intel_crtc);
+ intel_pre_plane_update(int_cstate);
+ drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
+ intel_post_plane_update(int_cstate);
+ }
- if (crtc_state->active) {
- intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
+ for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ if (needs_modeset(crtc->state) && old_crtc_state->active) {
dev_priv->display.crtc_disable(crtc);
intel_crtc->active = false;
intel_disable_shared_dpll(intel_crtc);
@@ -13121,21 +13141,26 @@ static int intel_atomic_commit(struct drm_device *dev,
modeset_update_crtc_power_domains(state);
}
- /* Now enable the clocks, plane, pipe, and connectors that we set up. */
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ /* Now enable the clocks, pipe, and connectors that we set up. */
+ for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
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(intel_crtc);
+ /*
+ * Commit all planes in one go to make them pop in as atomically as
+ * possible.
+ */
+ for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+ old_crtc_state = istate->int_crtc_states[i] ?: old_crtc_state;
- drm_atomic_helper_commit_planes_on_crtc(crtc_state);
- intel_post_plane_update(intel_crtc);
+ intel_pre_plane_update(crtc->state);
+ drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
+ intel_post_plane_update(crtc->state);
}
/* FIXME: add subpixel order */
--
2.1.4
More information about the Intel-gfx
mailing list