aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-07-02 14:28:59 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-09-06 01:59:24 -0400
commit24929352481f085c5f85d4d4cbc919ddf106d381 (patch)
tree03fd187328c1c0cd8526f60dab92bec3ef64ee11 /drivers
parent732ce74f4adfcdac84862fb74c6897b4a152d5e1 (diff)
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work out. To properly disable the output pipelines at the initial modeset after resume or boot up we need to have an accurate picture of which outputs are enabled and connected to which crtcs. Otherwise we risk disabling things at the wrong time, which can lead to hangs (or at least royally confused panels), both requiring a walk to the reset button to fix. Hence read out the hw state with the freshly introduce get_hw_state functions and then sanitize it afterwards. For a full modeset readout (which would allow us to avoid the initial modeset at boot up) a few things are still missing: - Reading out the mode from the pipe, especially the dotclock computation is quite some fun. - Reading out the parameters for the stolen memory framebuffer and wrapping it up. - Reading out the pch pll connections - luckily the disable code simply bails out if the crtc doesn't have a pch pll attached (even for configurations that would need one). This patch here turned up tons of smelly stuff around resume: We restore tons of register in seemingly random way (well, not quite, but we're not too careful either), which leaves the hw in a rather ill-defined state: E.g. the port registers are sometimes unconditionally restore (lvds, crt), leaving us with an active encoder/connector but no active pipe connected to it. Luckily the hw state sanitizer detects this madness and fixes things up a bit. v2: When checking whether an encoder with active connectors has a crtc wire up to it, check for both the crtc _and_ it's active state. v3: - Extract intel_sanitize_encoder. - Manually disable active encoders without an active pipe. v4: Correclty fix up the pipe<->plane mapping on machines where we switch pipes/planes. Noticed by Chris Wilson, who also provided the fixup. v5: Spelling fix in a comment, noticed by Paulo Zanoni Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c278
3 files changed, 214 insertions, 66 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 7ebb13b65133..4abac6d6c3e6 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -543,6 +543,7 @@ static int i915_drm_thaw(struct drm_device *dev)
543 mutex_unlock(&dev->struct_mutex); 543 mutex_unlock(&dev->struct_mutex);
544 544
545 intel_modeset_init_hw(dev); 545 intel_modeset_init_hw(dev);
546 intel_modeset_setup_hw_state(dev);
546 drm_mode_config_reset(dev); 547 drm_mode_config_reset(dev);
547 drm_irq_install(dev); 548 drm_irq_install(dev);
548 549
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fb46c6f356e4..9fce7820d96f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1539,6 +1539,7 @@ extern void intel_modeset_init(struct drm_device *dev);
1539extern void intel_modeset_gem_init(struct drm_device *dev); 1539extern void intel_modeset_gem_init(struct drm_device *dev);
1540extern void intel_modeset_cleanup(struct drm_device *dev); 1540extern void intel_modeset_cleanup(struct drm_device *dev);
1541extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); 1541extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
1542extern void intel_modeset_setup_hw_state(struct drm_device *dev);
1542extern bool intel_fbc_enabled(struct drm_device *dev); 1543extern bool intel_fbc_enabled(struct drm_device *dev);
1543extern void intel_disable_fbc(struct drm_device *dev); 1544extern void intel_disable_fbc(struct drm_device *dev);
1544extern bool ironlake_set_drps(struct drm_device *dev, u8 val); 1545extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e7569b68039..8c8dbc90faf1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3589,7 +3589,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
3589 * of the connector. */ 3589 * of the connector. */
3590bool intel_connector_get_hw_state(struct intel_connector *connector) 3590bool intel_connector_get_hw_state(struct intel_connector *connector)
3591{ 3591{
3592 enum pipe pipe; 3592 enum pipe pipe = 0;
3593 struct intel_encoder *encoder = connector->encoder; 3593 struct intel_encoder *encoder = connector->encoder;
3594 3594
3595 return encoder->get_hw_state(encoder, &pipe); 3595 return encoder->get_hw_state(encoder, &pipe);
@@ -6533,65 +6533,6 @@ free_work:
6533 return ret; 6533 return ret;
6534} 6534}
6535 6535
6536static void intel_sanitize_modesetting(struct drm_device *dev,
6537 int pipe, int plane)
6538{
6539 struct drm_i915_private *dev_priv = dev->dev_private;
6540 u32 reg, val;
6541 int i;
6542
6543 /* Clear any frame start delays used for debugging left by the BIOS */
6544 for_each_pipe(i) {
6545 reg = PIPECONF(i);
6546 I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
6547 }
6548
6549 if (HAS_PCH_SPLIT(dev))
6550 return;
6551
6552 /* Who knows what state these registers were left in by the BIOS or
6553 * grub?
6554 *
6555 * If we leave the registers in a conflicting state (e.g. with the
6556 * display plane reading from the other pipe than the one we intend
6557 * to use) then when we attempt to teardown the active mode, we will
6558 * not disable the pipes and planes in the correct order -- leaving
6559 * a plane reading from a disabled pipe and possibly leading to
6560 * undefined behaviour.
6561 */
6562
6563 reg = DSPCNTR(plane);
6564 val = I915_READ(reg);
6565
6566 if ((val & DISPLAY_PLANE_ENABLE) == 0)
6567 return;
6568 if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
6569 return;
6570
6571 /* This display plane is active and attached to the other CPU pipe. */
6572 pipe = !pipe;
6573
6574 /* Disable the plane and wait for it to stop reading from the pipe. */
6575 intel_disable_plane(dev_priv, plane, pipe);
6576 intel_disable_pipe(dev_priv, pipe);
6577}
6578
6579static void intel_crtc_reset(struct drm_crtc *crtc)
6580{
6581 struct drm_device *dev = crtc->dev;
6582 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
6583
6584 /* Reset flags back to the 'unknown' status so that they
6585 * will be correctly set on the initial modeset.
6586 */
6587 intel_crtc->dpms_mode = -1;
6588
6589 /* We need to fix up any BIOS configuration that conflicts with
6590 * our expectations.
6591 */
6592 intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
6593}
6594
6595static struct drm_crtc_helper_funcs intel_helper_funcs = { 6536static struct drm_crtc_helper_funcs intel_helper_funcs = {
6596 .mode_set_base_atomic = intel_pipe_set_base_atomic, 6537 .mode_set_base_atomic = intel_pipe_set_base_atomic,
6597 .load_lut = intel_crtc_load_lut, 6538 .load_lut = intel_crtc_load_lut,
@@ -7006,7 +6947,6 @@ fail:
7006} 6947}
7007 6948
7008static const struct drm_crtc_funcs intel_crtc_funcs = { 6949static const struct drm_crtc_funcs intel_crtc_funcs = {
7009 .reset = intel_crtc_reset,
7010 .cursor_set = intel_crtc_cursor_set, 6950 .cursor_set = intel_crtc_cursor_set,
7011 .cursor_move = intel_crtc_cursor_move, 6951 .cursor_move = intel_crtc_cursor_move,
7012 .gamma_set = intel_crtc_gamma_set, 6952 .gamma_set = intel_crtc_gamma_set,
@@ -7064,8 +7004,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
7064 dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; 7004 dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
7065 dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; 7005 dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
7066 7006
7067 intel_crtc_reset(&intel_crtc->base);
7068 intel_crtc->active = true; /* force the pipe off on setup_init_config */
7069 intel_crtc->bpp = 24; /* default for pre-Ironlake */ 7007 intel_crtc->bpp = 24; /* default for pre-Ironlake */
7070 7008
7071 drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); 7009 drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
@@ -7273,9 +7211,6 @@ static void intel_setup_outputs(struct drm_device *dev)
7273 intel_encoder_clones(encoder); 7211 intel_encoder_clones(encoder);
7274 } 7212 }
7275 7213
7276 /* disable all the possible outputs/crtcs before entering KMS mode */
7277 drm_helper_disable_unused_functions(dev);
7278
7279 if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) 7214 if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
7280 ironlake_init_pch_refclk(dev); 7215 ironlake_init_pch_refclk(dev);
7281} 7216}
@@ -7634,11 +7569,222 @@ void intel_modeset_init(struct drm_device *dev)
7634 intel_setup_outputs(dev); 7569 intel_setup_outputs(dev);
7635} 7570}
7636 7571
7572static void
7573intel_connector_break_all_links(struct intel_connector *connector)
7574{
7575 connector->base.dpms = DRM_MODE_DPMS_OFF;
7576 connector->base.encoder = NULL;
7577 connector->encoder->connectors_active = false;
7578 connector->encoder->base.crtc = NULL;
7579}
7580
7581static void intel_sanitize_crtc(struct intel_crtc *crtc)
7582{
7583 struct drm_device *dev = crtc->base.dev;
7584 struct drm_i915_private *dev_priv = dev->dev_private;
7585 u32 reg, val;
7586
7587 /* Clear the dpms state for compatibility with code still using that
7588 * deprecated state variable. */
7589 crtc->dpms_mode = -1;
7590
7591 /* Clear any frame start delays used for debugging left by the BIOS */
7592 reg = PIPECONF(crtc->pipe);
7593 I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
7594
7595 /* We need to sanitize the plane -> pipe mapping first because this will
7596 * disable the crtc (and hence change the state) if it is wrong. */
7597 if (!HAS_PCH_SPLIT(dev)) {
7598 struct intel_connector *connector;
7599 bool plane;
7600
7601 reg = DSPCNTR(crtc->plane);
7602 val = I915_READ(reg);
7603
7604 if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
7605 (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
7606 goto ok;
7607
7608 DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
7609 crtc->base.base.id);
7610
7611 /* Pipe has the wrong plane attached and the plane is active.
7612 * Temporarily change the plane mapping and disable everything
7613 * ... */
7614 plane = crtc->plane;
7615 crtc->plane = !plane;
7616 dev_priv->display.crtc_disable(&crtc->base);
7617 crtc->plane = plane;
7618
7619 /* ... and break all links. */
7620 list_for_each_entry(connector, &dev->mode_config.connector_list,
7621 base.head) {
7622 if (connector->encoder->base.crtc != &crtc->base)
7623 continue;
7624
7625 intel_connector_break_all_links(connector);
7626 }
7627
7628 WARN_ON(crtc->active);
7629 crtc->base.enabled = false;
7630 }
7631ok:
7632
7633 /* Adjust the state of the output pipe according to whether we
7634 * have active connectors/encoders. */
7635 intel_crtc_update_dpms(&crtc->base);
7636
7637 if (crtc->active != crtc->base.enabled) {
7638 struct intel_encoder *encoder;
7639
7640 /* This can happen either due to bugs in the get_hw_state
7641 * functions or because the pipe is force-enabled due to the
7642 * pipe A quirk. */
7643 DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
7644 crtc->base.base.id,
7645 crtc->base.enabled ? "enabled" : "disabled",
7646 crtc->active ? "enabled" : "disabled");
7647
7648 crtc->base.enabled = crtc->active;
7649
7650 /* Because we only establish the connector -> encoder ->
7651 * crtc links if something is active, this means the
7652 * crtc is now deactivated. Break the links. connector
7653 * -> encoder links are only establish when things are
7654 * actually up, hence no need to break them. */
7655 WARN_ON(crtc->active);
7656
7657 for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
7658 WARN_ON(encoder->connectors_active);
7659 encoder->base.crtc = NULL;
7660 }
7661 }
7662}
7663
7664static void intel_sanitize_encoder(struct intel_encoder *encoder)
7665{
7666 struct intel_connector *connector;
7667 struct drm_device *dev = encoder->base.dev;
7668
7669 /* We need to check both for a crtc link (meaning that the
7670 * encoder is active and trying to read from a pipe) and the
7671 * pipe itself being active. */
7672 bool has_active_crtc = encoder->base.crtc &&
7673 to_intel_crtc(encoder->base.crtc)->active;
7674
7675 if (encoder->connectors_active && !has_active_crtc) {
7676 DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
7677 encoder->base.base.id,
7678 drm_get_encoder_name(&encoder->base));
7679
7680 /* Connector is active, but has no active pipe. This is
7681 * fallout from our resume register restoring. Disable
7682 * the encoder manually again. */
7683 if (encoder->base.crtc) {
7684 DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
7685 encoder->base.base.id,
7686 drm_get_encoder_name(&encoder->base));
7687 encoder->disable(encoder);
7688 }
7689
7690 /* Inconsistent output/port/pipe state happens presumably due to
7691 * a bug in one of the get_hw_state functions. Or someplace else
7692 * in our code, like the register restore mess on resume. Clamp
7693 * things to off as a safer default. */
7694 list_for_each_entry(connector,
7695 &dev->mode_config.connector_list,
7696 base.head) {
7697 if (connector->encoder != encoder)
7698 continue;
7699
7700 intel_connector_break_all_links(connector);
7701 }
7702 }
7703 /* Enabled encoders without active connectors will be fixed in
7704 * the crtc fixup. */
7705}
7706
7707/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
7708 * and i915 state tracking structures. */
7709void intel_modeset_setup_hw_state(struct drm_device *dev)
7710{
7711 struct drm_i915_private *dev_priv = dev->dev_private;
7712 enum pipe pipe;
7713 u32 tmp;
7714 struct intel_crtc *crtc;
7715 struct intel_encoder *encoder;
7716 struct intel_connector *connector;
7717
7718 for_each_pipe(pipe) {
7719 crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
7720
7721 tmp = I915_READ(PIPECONF(pipe));
7722 if (tmp & PIPECONF_ENABLE)
7723 crtc->active = true;
7724 else
7725 crtc->active = false;
7726
7727 crtc->base.enabled = crtc->active;
7728
7729 DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
7730 crtc->base.base.id,
7731 crtc->active ? "enabled" : "disabled");
7732 }
7733
7734 list_for_each_entry(encoder, &dev->mode_config.encoder_list,
7735 base.head) {
7736 pipe = 0;
7737
7738 if (encoder->get_hw_state(encoder, &pipe)) {
7739 encoder->base.crtc =
7740 dev_priv->pipe_to_crtc_mapping[pipe];
7741 } else {
7742 encoder->base.crtc = NULL;
7743 }
7744
7745 encoder->connectors_active = false;
7746 DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
7747 encoder->base.base.id,
7748 drm_get_encoder_name(&encoder->base),
7749 encoder->base.crtc ? "enabled" : "disabled",
7750 pipe);
7751 }
7752
7753 list_for_each_entry(connector, &dev->mode_config.connector_list,
7754 base.head) {
7755 if (connector->get_hw_state(connector)) {
7756 connector->base.dpms = DRM_MODE_DPMS_ON;
7757 connector->encoder->connectors_active = true;
7758 connector->base.encoder = &connector->encoder->base;
7759 } else {
7760 connector->base.dpms = DRM_MODE_DPMS_OFF;
7761 connector->base.encoder = NULL;
7762 }
7763 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
7764 connector->base.base.id,
7765 drm_get_connector_name(&connector->base),
7766 connector->base.encoder ? "enabled" : "disabled");
7767 }
7768
7769 /* HW state is read out, now we need to sanitize this mess. */
7770 list_for_each_entry(encoder, &dev->mode_config.encoder_list,
7771 base.head) {
7772 intel_sanitize_encoder(encoder);
7773 }
7774
7775 for_each_pipe(pipe) {
7776 crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
7777 intel_sanitize_crtc(crtc);
7778 }
7779}
7780
7637void intel_modeset_gem_init(struct drm_device *dev) 7781void intel_modeset_gem_init(struct drm_device *dev)
7638{ 7782{
7639 intel_modeset_init_hw(dev); 7783 intel_modeset_init_hw(dev);
7640 7784
7641 intel_setup_overlay(dev); 7785 intel_setup_overlay(dev);
7786
7787 intel_modeset_setup_hw_state(dev);
7642} 7788}
7643 7789
7644void intel_modeset_cleanup(struct drm_device *dev) 7790void intel_modeset_cleanup(struct drm_device *dev)