aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-07-10 04:42:52 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-09-06 02:21:29 -0400
commitea9d758d6ddb9f4bb9639619100743e8f5fa85a0 (patch)
tree9d68d3b5294e551e8f1768daeaa70c9375c80f5f
parentfc303101dc9bfe2b079798c948f6ad4245c51e57 (diff)
drm/i915: push commit_output_state past the crtc/encoder preparing
With this change we can (finally!) rip out a few of the temporary hacks and clean up a few other things: - Kill intel_crtc_prepare_encoders, now unused. - Kill the hacks in the crtc_disable/enable functions to always call the encoder callbacks, we now always call the crtc functions with the right encoder -> crtc links. - Also push down the crtc->enable, encoder and connector dpms state updates. Unfortunately we can't add a WARN in the crtc_disable callbacks to ensure that the crtc is always still enabled when disabling an output pipe - the crtc sanitizer of the hw readout path can hit this when it needs to disable an active pipe without any enabled outputs. - Only call crtc->disable if the pipe is already enabled - again avoids running afoul of the new WARN. v2: Copy&paste our own version of crtc_in_use, too. v3: We need to update the dpms an encoder->connectors_active states, too. v4: I've forgotten to kill the unconditional encoder->disable calls in the crtc_disable functions. v5: Rip out leftover debug printk. v6: Properly clear intel_encoder->connectors_active. This wasn't properly cleared when disabling an encoder because it was no longer on the new connector list, but the crtc was still enabled (i.e. switching the encoder of an active crtc). Reported by Jani Nikula. v7: Don't clobber the encoder->connectors_active state of untouched encoders. Since X likes to first disable all outputs with dpms off before setting a new framebuffer, this hit a few warnings. Reported by Paulo Zanoni. v8: Kill the now stale comment warning that intel_crtc->active is not always updated at the right times. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c108
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
2 files changed, 70 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e3d3abff670c..2a393cbe6173 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3221,10 +3221,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
3221 3221
3222 WARN_ON(!crtc->enabled); 3222 WARN_ON(!crtc->enabled);
3223 3223
3224 /* XXX: For compatability with the crtc helper code, call the encoder's
3225 * enable function unconditionally for now. */
3226 if (intel_crtc->active) 3224 if (intel_crtc->active)
3227 goto encoders; 3225 return;
3228 3226
3229 intel_crtc->active = true; 3227 intel_crtc->active = true;
3230 intel_update_watermarks(dev); 3228 intel_update_watermarks(dev);
@@ -3272,7 +3270,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
3272 3270
3273 intel_crtc_update_cursor(crtc, true); 3271 intel_crtc_update_cursor(crtc, true);
3274 3272
3275encoders:
3276 for_each_encoder_on_crtc(dev, crtc, encoder) 3273 for_each_encoder_on_crtc(dev, crtc, encoder)
3277 encoder->enable(encoder); 3274 encoder->enable(encoder);
3278 3275
@@ -3290,14 +3287,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
3290 int plane = intel_crtc->plane; 3287 int plane = intel_crtc->plane;
3291 u32 reg, temp; 3288 u32 reg, temp;
3292 3289
3293 /* XXX: For compatability with the crtc helper code, call the encoder's
3294 * disable function unconditionally for now. */
3295 for_each_encoder_on_crtc(dev, crtc, encoder)
3296 encoder->disable(encoder);
3297 3290
3298 if (!intel_crtc->active) 3291 if (!intel_crtc->active)
3299 return; 3292 return;
3300 3293
3294 for_each_encoder_on_crtc(dev, crtc, encoder)
3295 encoder->disable(encoder);
3296
3301 intel_crtc_wait_for_pending_flips(crtc); 3297 intel_crtc_wait_for_pending_flips(crtc);
3302 drm_vblank_off(dev, pipe); 3298 drm_vblank_off(dev, pipe);
3303 intel_crtc_update_cursor(crtc, false); 3299 intel_crtc_update_cursor(crtc, false);
@@ -3399,10 +3395,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
3399 3395
3400 WARN_ON(!crtc->enabled); 3396 WARN_ON(!crtc->enabled);
3401 3397
3402 /* XXX: For compatability with the crtc helper code, call the encoder's
3403 * enable function unconditionally for now. */
3404 if (intel_crtc->active) 3398 if (intel_crtc->active)
3405 goto encoders; 3399 return;
3406 3400
3407 intel_crtc->active = true; 3401 intel_crtc->active = true;
3408 intel_update_watermarks(dev); 3402 intel_update_watermarks(dev);
@@ -3418,7 +3412,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
3418 intel_crtc_dpms_overlay(intel_crtc, true); 3412 intel_crtc_dpms_overlay(intel_crtc, true);
3419 intel_crtc_update_cursor(crtc, true); 3413 intel_crtc_update_cursor(crtc, true);
3420 3414
3421encoders:
3422 for_each_encoder_on_crtc(dev, crtc, encoder) 3415 for_each_encoder_on_crtc(dev, crtc, encoder)
3423 encoder->enable(encoder); 3416 encoder->enable(encoder);
3424} 3417}
@@ -3432,14 +3425,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
3432 int pipe = intel_crtc->pipe; 3425 int pipe = intel_crtc->pipe;
3433 int plane = intel_crtc->plane; 3426 int plane = intel_crtc->plane;
3434 3427
3435 /* XXX: For compatability with the crtc helper code, call the encoder's
3436 * disable function unconditionally for now. */
3437 for_each_encoder_on_crtc(dev, crtc, encoder)
3438 encoder->disable(encoder);
3439 3428
3440 if (!intel_crtc->active) 3429 if (!intel_crtc->active)
3441 return; 3430 return;
3442 3431
3432 for_each_encoder_on_crtc(dev, crtc, encoder)
3433 encoder->disable(encoder);
3434
3443 /* Give the overlay scaler a chance to disable if it's on this pipe */ 3435 /* Give the overlay scaler a chance to disable if it's on this pipe */
3444 intel_crtc_wait_for_pending_flips(crtc); 3436 intel_crtc_wait_for_pending_flips(crtc);
3445 drm_vblank_off(dev, pipe); 3437 drm_vblank_off(dev, pipe);
@@ -6631,18 +6623,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
6631 return false; 6623 return false;
6632} 6624}
6633 6625
6634static void
6635intel_crtc_prepare_encoders(struct drm_device *dev)
6636{
6637 struct intel_encoder *encoder;
6638
6639 list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
6640 /* Disable unused encoders */
6641 if (encoder->base.crtc == NULL)
6642 encoder->disable(encoder);
6643 }
6644}
6645
6646/** 6626/**
6647 * intel_modeset_update_staged_output_state 6627 * intel_modeset_update_staged_output_state
6648 * 6628 *
@@ -6822,6 +6802,60 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
6822 *prepare_pipes &= ~(*disable_pipes); 6802 *prepare_pipes &= ~(*disable_pipes);
6823} 6803}
6824 6804
6805static bool intel_crtc_in_use(struct drm_crtc *crtc)
6806{
6807 struct drm_encoder *encoder;
6808 struct drm_device *dev = crtc->dev;
6809
6810 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
6811 if (encoder->crtc == crtc)
6812 return true;
6813
6814 return false;
6815}
6816
6817static void
6818intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
6819{
6820 struct intel_encoder *intel_encoder;
6821 struct intel_crtc *intel_crtc;
6822 struct drm_connector *connector;
6823
6824 list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
6825 base.head) {
6826 if (!intel_encoder->base.crtc)
6827 continue;
6828
6829 intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
6830
6831 if (prepare_pipes & (1 << intel_crtc->pipe))
6832 intel_encoder->connectors_active = false;
6833 }
6834
6835 intel_modeset_commit_output_state(dev);
6836
6837 /* Update computed state. */
6838 list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
6839 base.head) {
6840 intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
6841 }
6842
6843 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
6844 if (!connector->encoder || !connector->encoder->crtc)
6845 continue;
6846
6847 intel_crtc = to_intel_crtc(connector->encoder->crtc);
6848
6849 if (prepare_pipes & (1 << intel_crtc->pipe)) {
6850 connector->dpms = DRM_MODE_DPMS_ON;
6851
6852 intel_encoder = to_intel_encoder(connector->encoder);
6853 intel_encoder->connectors_active = true;
6854 }
6855 }
6856
6857}
6858
6825#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \ 6859#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
6826 list_for_each_entry((intel_crtc), \ 6860 list_for_each_entry((intel_crtc), \
6827 &(dev)->mode_config.crtc_list, \ 6861 &(dev)->mode_config.crtc_list, \
@@ -6850,12 +6884,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
6850 for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) 6884 for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
6851 intel_crtc_disable(&intel_crtc->base); 6885 intel_crtc_disable(&intel_crtc->base);
6852 6886
6853 intel_modeset_commit_output_state(dev);
6854
6855 list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
6856 base.head)
6857 intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
6858
6859 saved_hwmode = crtc->hwmode; 6887 saved_hwmode = crtc->hwmode;
6860 saved_mode = crtc->mode; 6888 saved_mode = crtc->mode;
6861 6889
@@ -6870,12 +6898,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
6870 if (IS_ERR(adjusted_mode)) { 6898 if (IS_ERR(adjusted_mode)) {
6871 return false; 6899 return false;
6872 } 6900 }
6873
6874 intel_crtc_prepare_encoders(dev);
6875 } 6901 }
6876 6902
6877 for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) 6903 for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
6878 dev_priv->display.crtc_disable(&intel_crtc->base); 6904 if (intel_crtc->base.enabled)
6905 dev_priv->display.crtc_disable(&intel_crtc->base);
6906 }
6879 6907
6880 if (modeset_pipes) { 6908 if (modeset_pipes) {
6881 crtc->mode = *mode; 6909 crtc->mode = *mode;
@@ -6883,6 +6911,10 @@ bool intel_set_mode(struct drm_crtc *crtc,
6883 crtc->y = y; 6911 crtc->y = y;
6884 } 6912 }
6885 6913
6914 /* Only after disabling all output pipelines that will be changed can we
6915 * update the the output configuration. */
6916 intel_modeset_update_state(dev, prepare_pipes);
6917
6886 /* Set up the DPLL and any encoders state that needs to adjust or depend 6918 /* Set up the DPLL and any encoders state that needs to adjust or depend
6887 * on the DPLL. 6919 * on the DPLL.
6888 */ 6920 */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5137f9bef13e..d03e77752157 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -184,9 +184,6 @@ struct intel_crtc {
184 * Whether the crtc and the connected output pipeline is active. Implies 184 * Whether the crtc and the connected output pipeline is active. Implies
185 * that crtc->enabled is set, i.e. the current mode configuration has 185 * that crtc->enabled is set, i.e. the current mode configuration has
186 * some outputs connected to this crtc. 186 * some outputs connected to this crtc.
187 *
188 * Atm crtc->enabled is unconditionally updated _before_ the hw state is
189 * changed, hence we can only check this when enabling the crtc.
190 */ 187 */
191 bool active; 188 bool active;
192 bool primary_disabled; /* is the crtc obscured by a plane? */ 189 bool primary_disabled; /* is the crtc obscured by a plane? */