diff options
author | Dave Airlie <airlied@redhat.com> | 2014-11-15 02:33:40 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-11-15 02:33:40 +0300 |
commit | fd172d0c47fddff801d998e38c3efdd236ed082f (patch) | |
tree | 4f59eaf250aacbed3e5ea30f445986343609a344 /drivers/gpu/drm/i915/intel_dp.c | |
parent | b853fdb3c0e7122193ea548aba42d1d63b6d4783 (diff) | |
parent | e1f234bde6edb2bcdb763c90076b9484e4c71a33 (diff) | |
download | linux-fd172d0c47fddff801d998e38c3efdd236ed082f.tar.xz |
Merge tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel into drm-next
- skl watermarks code (Damien, Vandana, Pradeep)
- reworked audio codec /eld handling code (Jani)
- rework the mmio_flip code to use the vblank evade logic and wait for rendering
using the standard wait_seqno interface (Ander)
- skl forcewake support (Zhe Wang)
- refactor the chv interrupt code to use functions shared with vlv (Ville)
- prep work for different global gtt views (Tvrtko Ursulin)
- precompute the display PLL config before touching hw state (Ander)
- completely reworked panel power sequencer code for chv/vlv (Ville)
- pre work to split the plane update code into a prepare and commit phase
(Gustavo Padovan)
- golden context for skl (Armin Reese)
- as usual tons of fixes and improvements all over
* tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel: (135 commits)
drm/i915: Use correct pipe config to update pll dividers. V2
drm/i915: Plug memory leak in intel_shared_dpll_start_config()
drm/i915: Update DRIVER_DATE to 20141107
drm/i915: Add gen to the gpu hang ecode
drm/i915: Cache HPLL frequency on VLV/CHV
Revert "drm/i915/vlv: Remove check for Old Ack during forcewake"
drm/i915: Make mmio flip wait for seqno in the work function
drm/i915: Make __wait_seqno non-static and rename to __i915_wait_seqno
drm/i915: Move the .global_resources() hook call into modeset_update_crtc_power_domains()
drm/i915/audio: add DOC comment describing HDA over HDMI/DP
drm/i915: make pipe/port based audio valid accessors easier to use
drm/i915/audio: add audio codec enable debug log for g4x
drm/i915/audio: add audio codec disable on g4x
drm/i915: enable audio codec after port
drm/i915/audio: add vlv/chv/gen5-7 audio codec disable sequence
drm/i915/audio: rewrite vlv/chv and gen 5-7 audio codec enable sequence
drm/i915/skl: Enable Gen9 RC6
drm/i915/skl: Gen9 Forcewake
drm/i915/skl: Log the order in which we flush the pipes in the WM code
drm/i915/skl: Flush the WM configuration
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 429 |
1 files changed, 283 insertions, 146 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dc4bc90a9df0..ceb528f07c25 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -113,6 +113,9 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector) static void intel_dp_link_down(struct intel_dp *intel_dp); static bool edp_panel_vdd_on(struct intel_dp *intel_dp); static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); +static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); +static void vlv_steal_power_sequencer(struct drm_device *dev, + enum pipe pipe); int intel_dp_max_link_bw(struct intel_dp *intel_dp) @@ -283,12 +286,10 @@ intel_hrawclk(struct drm_device *dev) static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out); + struct intel_dp *intel_dp); static void intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out); + struct intel_dp *intel_dp); static void pps_lock(struct intel_dp *intel_dp) { @@ -322,6 +323,66 @@ static void pps_unlock(struct intel_dp *intel_dp) intel_display_power_put(dev_priv, power_domain); } +static void +vlv_power_sequencer_kick(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_dp->pps_pipe; + bool pll_enabled; + uint32_t DP; + + if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, + "skipping pipe %c power seqeuncer kick due to port %c being active\n", + pipe_name(pipe), port_name(intel_dig_port->port))) + return; + + DRM_DEBUG_KMS("kicking pipe %c power sequencer for port %c\n", + pipe_name(pipe), port_name(intel_dig_port->port)); + + /* Preserve the BIOS-computed detected bit. This is + * supposed to be read-only. + */ + DP = I915_READ(intel_dp->output_reg) & DP_DETECTED; + DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; + DP |= DP_PORT_WIDTH(1); + DP |= DP_LINK_TRAIN_PAT_1; + + if (IS_CHERRYVIEW(dev)) + DP |= DP_PIPE_SELECT_CHV(pipe); + else if (pipe == PIPE_B) + DP |= DP_PIPEB_SELECT; + + pll_enabled = I915_READ(DPLL(pipe)) & DPLL_VCO_ENABLE; + + /* + * The DPLL for the pipe must be enabled for this to work. + * So enable temporarily it if it's not already enabled. + */ + if (!pll_enabled) + vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? + &chv_dpll[0].dpll : &vlv_dpll[0].dpll); + + /* + * Similar magic as in intel_dp_enable_port(). + * We _must_ do this port enable + disable trick + * to make this power seqeuencer lock onto the port. + * Otherwise even VDD force bit won't work. + */ + I915_WRITE(intel_dp->output_reg, DP); + POSTING_READ(intel_dp->output_reg); + + I915_WRITE(intel_dp->output_reg, DP | DP_PORT_EN); + POSTING_READ(intel_dp->output_reg); + + I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); + POSTING_READ(intel_dp->output_reg); + + if (!pll_enabled) + vlv_force_pll_off(dev, pipe); +} + static enum pipe vlv_power_sequencer_pipe(struct intel_dp *intel_dp) { @@ -330,10 +391,13 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B); - struct edp_power_seq power_seq; + enum pipe pipe; lockdep_assert_held(&dev_priv->pps_mutex); + /* We should never land here with regular DP ports */ + WARN_ON(!is_edp(intel_dp)); + if (intel_dp->pps_pipe != INVALID_PIPE) return intel_dp->pps_pipe; @@ -359,18 +423,26 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) * are two power sequencers and up to two eDP ports. */ if (WARN_ON(pipes == 0)) - return PIPE_A; + pipe = PIPE_A; + else + pipe = ffs(pipes) - 1; - intel_dp->pps_pipe = ffs(pipes) - 1; + vlv_steal_power_sequencer(dev, pipe); + intel_dp->pps_pipe = pipe; DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n", pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port)); /* init power sequencer on this pipe and port */ - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, - &power_seq); + intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); + + /* + * Even vdd force doesn't work until we've made + * the power sequencer lock in on the port. + */ + vlv_power_sequencer_kick(intel_dp); return intel_dp->pps_pipe; } @@ -425,7 +497,6 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct edp_power_seq power_seq; enum port port = intel_dig_port->port; lockdep_assert_held(&dev_priv->pps_mutex); @@ -453,9 +524,8 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n", port_name(port), pipe_name(intel_dp->pps_pipe)); - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, - &power_seq); + intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); } void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) @@ -550,6 +620,10 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); + if (IS_VALLEYVIEW(dev) && + intel_dp->pps_pipe == INVALID_PIPE) + return false; + return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; } @@ -560,6 +634,10 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); + if (IS_VALLEYVIEW(dev) && + intel_dp->pps_pipe == INVALID_PIPE) + return false; + return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD; } @@ -1246,12 +1324,8 @@ static void intel_dp_prepare(struct intel_encoder *encoder) intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count); - if (crtc->config.has_audio) { - DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", - pipe_name(crtc->pipe)); + if (crtc->config.has_audio) intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; - intel_write_eld(&encoder->base, adjusted_mode); - } /* Split out the IBX/CPU vs CPT settings */ @@ -1409,7 +1483,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - DRM_DEBUG_KMS("Turning eDP VDD on\n"); + DRM_DEBUG_KMS("Turning eDP port %c VDD on\n", + port_name(intel_dig_port->port)); if (!edp_have_panel_power(intel_dp)) wait_panel_power_cycle(intel_dp); @@ -1428,7 +1503,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) * If the panel wasn't on, delay before accessing aux channel */ if (!edp_have_panel_power(intel_dp)) { - DRM_DEBUG_KMS("eDP was not running\n"); + DRM_DEBUG_KMS("eDP port %c panel power wasn't enabled\n", + port_name(intel_dig_port->port)); msleep(intel_dp->panel_power_up_delay); } @@ -1453,7 +1529,8 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) vdd = edp_panel_vdd_on(intel_dp); pps_unlock(intel_dp); - WARN(!vdd, "eDP VDD already requested on\n"); + WARN(!vdd, "eDP port %c VDD already requested on\n", + port_name(dp_to_dig_port(intel_dp)->port)); } static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) @@ -1474,7 +1551,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) if (!edp_have_panel_vdd(intel_dp)) return; - DRM_DEBUG_KMS("Turning eDP VDD off\n"); + DRM_DEBUG_KMS("Turning eDP port %c VDD off\n", + port_name(intel_dig_port->port)); pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; @@ -1535,7 +1613,8 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) if (!is_edp(intel_dp)) return; - WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); + WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", + port_name(dp_to_dig_port(intel_dp)->port)); intel_dp->want_panel_vdd = false; @@ -1545,40 +1624,25 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) edp_panel_vdd_schedule_off(intel_dp); } -/* - * Must be paired with intel_edp_panel_vdd_on(). - * Nested calls to these functions are not allowed since - * we drop the lock. Caller must use some higher level - * locking to prevent nested calls from other threads. - */ -static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) -{ - if (!is_edp(intel_dp)) - return; - - pps_lock(intel_dp); - edp_panel_vdd_off(intel_dp, sync); - pps_unlock(intel_dp); -} - -void intel_edp_panel_on(struct intel_dp *intel_dp) +static void edp_panel_on(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; u32 pp_ctrl_reg; + lockdep_assert_held(&dev_priv->pps_mutex); + if (!is_edp(intel_dp)) return; - DRM_DEBUG_KMS("Turn eDP power on\n"); - - pps_lock(intel_dp); + DRM_DEBUG_KMS("Turn eDP port %c panel power on\n", + port_name(dp_to_dig_port(intel_dp)->port)); - if (edp_have_panel_power(intel_dp)) { - DRM_DEBUG_KMS("eDP power already on\n"); - goto out; - } + if (WARN(edp_have_panel_power(intel_dp), + "eDP port %c panel power already on\n", + port_name(dp_to_dig_port(intel_dp)->port))) + return; wait_panel_power_cycle(intel_dp); @@ -1606,12 +1670,20 @@ void intel_edp_panel_on(struct intel_dp *intel_dp) I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); } +} - out: +void intel_edp_panel_on(struct intel_dp *intel_dp) +{ + if (!is_edp(intel_dp)) + return; + + pps_lock(intel_dp); + edp_panel_on(intel_dp); pps_unlock(intel_dp); } -void intel_edp_panel_off(struct intel_dp *intel_dp) + +static void edp_panel_off(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *intel_encoder = &intel_dig_port->base; @@ -1621,14 +1693,16 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) u32 pp; u32 pp_ctrl_reg; + lockdep_assert_held(&dev_priv->pps_mutex); + if (!is_edp(intel_dp)) return; - DRM_DEBUG_KMS("Turn eDP power off\n"); + DRM_DEBUG_KMS("Turn eDP port %c panel power off\n", + port_name(dp_to_dig_port(intel_dp)->port)); - pps_lock(intel_dp); - - WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); + WARN(!intel_dp->want_panel_vdd, "Need eDP port %c VDD to turn off panel\n", + port_name(dp_to_dig_port(intel_dp)->port)); pp = ironlake_get_pp_control(intel_dp); /* We need to switch off panel power _and_ force vdd, for otherwise some @@ -1649,7 +1723,15 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) /* We got a reference when we enabled the VDD. */ power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_put(dev_priv, power_domain); +} + +void intel_edp_panel_off(struct intel_dp *intel_dp) +{ + if (!is_edp(intel_dp)) + return; + pps_lock(intel_dp); + edp_panel_off(intel_dp); pps_unlock(intel_dp); } @@ -2368,6 +2450,10 @@ static void intel_disable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + + if (crtc->config.has_audio) + intel_audio_codec_disable(encoder); /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ @@ -2522,14 +2608,23 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp) struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; - intel_dp->DP |= DP_PORT_EN; - /* enable with pattern 1 (as per spec) */ _intel_dp_set_link_train(intel_dp, &intel_dp->DP, DP_TRAINING_PATTERN_1); I915_WRITE(intel_dp->output_reg, intel_dp->DP); POSTING_READ(intel_dp->output_reg); + + /* + * Magic for VLV/CHV. We _must_ first set up the register + * without actually enabling the port, and then do another + * write to enable the port. Otherwise link training will + * fail when the power sequencer is freshly used for this port. + */ + intel_dp->DP |= DP_PORT_EN; + + I915_WRITE(intel_dp->output_reg, intel_dp->DP); + POSTING_READ(intel_dp->output_reg); } static void intel_enable_dp(struct intel_encoder *encoder) @@ -2537,19 +2632,38 @@ static void intel_enable_dp(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (WARN_ON(dp_reg & DP_PORT_EN)) return; + pps_lock(intel_dp); + + if (IS_VALLEYVIEW(dev)) + vlv_init_panel_power_sequencer(intel_dp); + intel_dp_enable_port(intel_dp); - intel_edp_panel_vdd_on(intel_dp); - intel_edp_panel_on(intel_dp); - intel_edp_panel_vdd_off(intel_dp, true); + + edp_panel_vdd_on(intel_dp); + edp_panel_on(intel_dp); + edp_panel_vdd_off(intel_dp, true); + + pps_unlock(intel_dp); + + if (IS_VALLEYVIEW(dev)) + vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp)); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); + + if (crtc->config.has_audio) { + DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", + pipe_name(crtc->pipe)); + intel_audio_codec_enable(encoder); + } } static void g4x_enable_dp(struct intel_encoder *encoder) @@ -2581,6 +2695,32 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder) } } +static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private; + enum pipe pipe = intel_dp->pps_pipe; + int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); + + edp_panel_vdd_off_sync(intel_dp); + + /* + * VLV seems to get confused when multiple power seqeuencers + * have the same port selected (even if only one has power/vdd + * enabled). The failure manifests as vlv_wait_port_ready() failing + * CHV on the other hand doesn't seem to mind having the same port + * selected in multiple power seqeuencers, but let's clear the + * port select always when logically disconnecting a power sequencer + * from a port. + */ + DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n", + pipe_name(pipe), port_name(intel_dig_port->port)); + I915_WRITE(pp_on_reg, 0); + POSTING_READ(pp_on_reg); + + intel_dp->pps_pipe = INVALID_PIPE; +} + static void vlv_steal_power_sequencer(struct drm_device *dev, enum pipe pipe) { @@ -2589,6 +2729,9 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, lockdep_assert_held(&dev_priv->pps_mutex); + if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) + return; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { struct intel_dp *intel_dp; @@ -2606,10 +2749,12 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n", pipe_name(pipe), port_name(port)); - /* make sure vdd is off before we steal it */ - edp_panel_vdd_off_sync(intel_dp); + WARN(encoder->connectors_active, + "stealing pipe %c power sequencer from active eDP port %c\n", + pipe_name(pipe), port_name(port)); - intel_dp->pps_pipe = INVALID_PIPE; + /* make sure vdd is off before we steal it */ + vlv_detach_power_sequencer(intel_dp); } } @@ -2620,10 +2765,12 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - struct edp_power_seq power_seq; lockdep_assert_held(&dev_priv->pps_mutex); + if (!is_edp(intel_dp)) + return; + if (intel_dp->pps_pipe == crtc->pipe) return; @@ -2633,7 +2780,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) * we still have control of it. */ if (intel_dp->pps_pipe != INVALID_PIPE) - edp_panel_vdd_off_sync(intel_dp); + vlv_detach_power_sequencer(intel_dp); /* * We may be stealing the power @@ -2648,9 +2795,8 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port)); /* init power sequencer on this pipe and port */ - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, - &power_seq); + intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); } static void vlv_pre_enable_dp(struct intel_encoder *encoder) @@ -2679,15 +2825,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); - if (is_edp(intel_dp)) { - pps_lock(intel_dp); - vlv_init_panel_power_sequencer(intel_dp); - pps_unlock(intel_dp); - } - intel_enable_dp(encoder); - - vlv_wait_port_ready(dev_priv, dport); } static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) @@ -2779,15 +2917,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); - if (is_edp(intel_dp)) { - pps_lock(intel_dp); - vlv_init_panel_power_sequencer(intel_dp); - pps_unlock(intel_dp); - } - intel_enable_dp(encoder); - - vlv_wait_port_ready(dev_priv, dport); } static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) @@ -3696,7 +3826,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) /* Try 5 times, then try clock recovery if that fails */ if (tries > 5) { - intel_dp_link_down(intel_dp); intel_dp_start_link_train(intel_dp); intel_dp_set_link_train(intel_dp, &DP, training_pattern | @@ -3854,8 +3983,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp) if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - intel_edp_panel_vdd_on(intel_dp); - if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); @@ -3863,8 +3990,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp) if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - - intel_edp_panel_vdd_off(intel_dp, false); } static bool @@ -3878,7 +4003,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) if (intel_dp->dpcd[DP_DPCD_REV] < 0x12) return false; - intel_edp_panel_vdd_on(intel_dp); if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) { if (buf[0] & DP_MST_CAP) { DRM_DEBUG_KMS("Sink is MST capable\n"); @@ -3888,7 +4012,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) intel_dp->is_mst = false; } } - intel_edp_panel_vdd_off(intel_dp, false); drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); return intel_dp->is_mst; @@ -4568,9 +4691,52 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) pps_unlock(intel_dp); } +static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; + + lockdep_assert_held(&dev_priv->pps_mutex); + + if (!edp_have_panel_vdd(intel_dp)) + return; + + /* + * The VDD bit needs a power domain reference, so if the bit is + * already enabled when we boot or resume, grab this reference and + * schedule a vdd off, so we don't hold on to the reference + * indefinitely. + */ + DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); + power_domain = intel_display_port_power_domain(&intel_dig_port->base); + intel_display_power_get(dev_priv, power_domain); + + edp_panel_vdd_schedule_off(intel_dp); +} + static void intel_dp_encoder_reset(struct drm_encoder *encoder) { - intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); + struct intel_dp *intel_dp; + + if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) + return; + + intel_dp = enc_to_intel_dp(encoder); + + pps_lock(intel_dp); + + /* + * Read out the current power sequencer assignment, + * in case the BIOS did something with it. + */ + if (IS_VALLEYVIEW(encoder->dev)) + vlv_initial_power_sequencer_setup(intel_dp); + + intel_edp_panel_vdd_sanitize(intel_dp); + + pps_unlock(intel_dp); } static const struct drm_connector_funcs intel_dp_connector_funcs = { @@ -4757,16 +4923,20 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp) static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out) + struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dev->dev_private; - struct edp_power_seq cur, vbt, spec, final; + struct edp_power_seq cur, vbt, spec, + *final = &intel_dp->pps_delays; u32 pp_on, pp_off, pp_div, pp; int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; lockdep_assert_held(&dev_priv->pps_mutex); + /* already initialized? */ + if (final->t11_t12 != 0) + return; + if (HAS_PCH_SPLIT(dev)) { pp_ctrl_reg = PCH_PP_CONTROL; pp_on_reg = PCH_PP_ON_DELAYS; @@ -4828,7 +4998,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, /* Use the max of the register settings and vbt. If both are * unset, fall back to the spec limits. */ -#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \ +#define assign_final(field) final->field = (max(cur.field, vbt.field) == 0 ? \ spec.field : \ max(cur.field, vbt.field)) assign_final(t1_t3); @@ -4838,7 +5008,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, assign_final(t11_t12); #undef assign_final -#define get_delay(field) (DIV_ROUND_UP(final.field, 10)) +#define get_delay(field) (DIV_ROUND_UP(final->field, 10)) intel_dp->panel_power_up_delay = get_delay(t1_t3); intel_dp->backlight_on_delay = get_delay(t8); intel_dp->backlight_off_delay = get_delay(t9); @@ -4852,21 +5022,18 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - - if (out) - *out = final; } static void intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *seq) + struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dev->dev_private; u32 pp_on, pp_off, pp_div, port_sel = 0; int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); int pp_on_reg, pp_off_reg, pp_div_reg; enum port port = dp_to_dig_port(intel_dp)->port; + const struct edp_power_seq *seq = &intel_dp->pps_delays; lockdep_assert_held(&dev_priv->pps_mutex); @@ -5052,40 +5219,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, return downclock_mode; } -void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder) -{ - struct drm_device *dev = intel_encoder->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_dp *intel_dp; - enum intel_display_power_domain power_domain; - - if (intel_encoder->type != INTEL_OUTPUT_EDP) - return; - - intel_dp = enc_to_intel_dp(&intel_encoder->base); - - pps_lock(intel_dp); - - if (!edp_have_panel_vdd(intel_dp)) - goto out; - /* - * The VDD bit needs a power domain reference, so if the bit is - * already enabled when we boot or resume, grab this reference and - * schedule a vdd off, so we don't hold on to the reference - * indefinitely. - */ - DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); - power_domain = intel_display_port_power_domain(intel_encoder); - intel_display_power_get(dev_priv, power_domain); - - edp_panel_vdd_schedule_off(intel_dp); - out: - pps_unlock(intel_dp); -} - static bool intel_edp_init_connector(struct intel_dp *intel_dp, - struct intel_connector *intel_connector, - struct edp_power_seq *power_seq) + struct intel_connector *intel_connector) { struct drm_connector *connector = &intel_connector->base; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); @@ -5103,12 +5238,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!is_edp(intel_dp)) return true; - intel_edp_panel_vdd_sanitize(intel_encoder); + pps_lock(intel_dp); + intel_edp_panel_vdd_sanitize(intel_dp); + pps_unlock(intel_dp); /* Cache DPCD and EDID for edp. */ - intel_edp_panel_vdd_on(intel_dp); has_dpcd = intel_dp_get_dpcd(intel_dp); - intel_edp_panel_vdd_off(intel_dp, false); if (has_dpcd) { if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) @@ -5123,7 +5258,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, /* We now know it's not a ghost, init power sequence regs. */ pps_lock(intel_dp); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); pps_unlock(intel_dp); mutex_lock(&dev->mode_config.mutex); @@ -5184,7 +5319,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_dig_port->port; - struct edp_power_seq power_seq = { 0 }; int type; intel_dp->pps_pipe = INVALID_PIPE; @@ -5223,6 +5357,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, if (type == DRM_MODE_CONNECTOR_eDP) intel_encoder->type = INTEL_OUTPUT_EDP; + /* eDP only on port B and/or C on vlv/chv */ + if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) && + port != PORT_B && port != PORT_C)) + return false; + DRM_DEBUG_KMS("Adding %s connector on port %c\n", type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP", port_name(port)); @@ -5265,13 +5404,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, if (is_edp(intel_dp)) { pps_lock(intel_dp); - if (IS_VALLEYVIEW(dev)) { + intel_dp_init_panel_power_timestamps(intel_dp); + if (IS_VALLEYVIEW(dev)) vlv_initial_power_sequencer_setup(intel_dp); - } else { - intel_dp_init_panel_power_timestamps(intel_dp); - intel_dp_init_panel_power_sequencer(dev, intel_dp, - &power_seq); - } + else + intel_dp_init_panel_power_sequencer(dev, intel_dp); pps_unlock(intel_dp); } @@ -5285,7 +5422,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, } } - if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { + if (!intel_edp_init_connector(intel_dp, intel_connector)) { drm_dp_aux_unregister(&intel_dp->aux); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |