drm/i915/skl: Program the DDB allocation
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index f6a3fdd5589e33420e2f9b15ef4de42193eea356..5f2c206aef130bfb681879c07d5d26534197f8d8 100644 (file)
@@ -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)
@@ -225,7 +228,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
 }
 
 static uint32_t
-pack_aux(uint8_t *src, int src_bytes)
+pack_aux(const uint8_t *src, int src_bytes)
 {
        int     i;
        uint32_t v = 0;
@@ -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;
 }
 
@@ -661,6 +739,16 @@ static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return index ? 0 : 100;
 }
 
+static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+       /*
+        * SKL doesn't need us to program the AUX clock divider (Hardware will
+        * derive the clock from CDCLK automatically). We still implement the
+        * get_aux_clock_divider vfunc to plug-in into the existing code.
+        */
+       return index ? 0 : 1;
+}
+
 static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
                                      bool has_aux_irq,
                                      int send_bytes,
@@ -691,9 +779,24 @@ static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
               (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
 }
 
+static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp,
+                                     bool has_aux_irq,
+                                     int send_bytes,
+                                     uint32_t unused)
+{
+       return DP_AUX_CH_CTL_SEND_BUSY |
+              DP_AUX_CH_CTL_DONE |
+              (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
+              DP_AUX_CH_CTL_TIME_OUT_ERROR |
+              DP_AUX_CH_CTL_TIME_OUT_1600us |
+              DP_AUX_CH_CTL_RECEIVE_ERROR |
+              (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+              DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
-               uint8_t *send, int send_bytes,
+               const uint8_t *send, int send_bytes,
                uint8_t *recv, int recv_size)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -925,7 +1028,16 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
                BUG();
        }
 
-       if (!HAS_DDI(dev))
+       /*
+        * The AUX_CTL register is usually DP_CTL + 0x10.
+        *
+        * On Haswell and Broadwell though:
+        *   - Both port A DDI_BUF_CTL and DDI_AUX_CTL are on the CPU
+        *   - Port B/C/D AUX channels are on the PCH, DDI_BUF_CTL on the CPU
+        *
+        * Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU.
+        */
+       if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
                intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
 
        intel_dp->aux.name = name;
@@ -1216,7 +1328,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
                DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
                                 pipe_name(crtc->pipe));
                intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
-               intel_write_eld(&encoder->base, adjusted_mode);
+               intel_audio_codec_enable(encoder);
        }
 
        /* Split out the IBX/CPU vs CPT settings */
@@ -1375,7 +1487,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);
@@ -1394,7 +1507,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);
        }
 
@@ -1419,7 +1533,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)
@@ -1440,7 +1555,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;
@@ -1501,7 +1617,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;
 
@@ -1511,40 +1628,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);
 
@@ -1572,12 +1674,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;
@@ -1587,14 +1697,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");
-
-       pps_lock(intel_dp);
+       DRM_DEBUG_KMS("Turn eDP port %c panel power off\n",
+                     port_name(dp_to_dig_port(intel_dp)->port));
 
-       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
@@ -1615,7 +1727,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);
 }
 
@@ -1819,7 +1939,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
        u32 tmp;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_enabled(dev_priv, power_domain))
+       if (!intel_display_power_is_enabled(dev_priv, power_domain))
                return false;
 
        tmp = I915_READ(intel_dp->output_reg);
@@ -1995,10 +2115,8 @@ static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
        POSTING_READ(ctl_reg);
 }
 
-static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+static void intel_edp_psr_setup_vsc(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct edp_vsc_psr psr_vsc;
 
        /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
@@ -2008,10 +2126,6 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp)
        psr_vsc.sdp_header.HB2 = 0x2;
        psr_vsc.sdp_header.HB3 = 0x8;
        intel_edp_psr_write_vsc(intel_dp, &psr_vsc);
-
-       /* Avoid continuous PSR exit by masking memup and hpd */
-       I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
-                  EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
 }
 
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
@@ -2021,8 +2135,17 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t aux_clock_divider;
        int precharge = 0x3;
-       int msg_size = 5;       /* Header(4) + Message(1) */
        bool only_standby = false;
+       static const uint8_t aux_msg[] = {
+               [0] = DP_AUX_NATIVE_WRITE << 4,
+               [1] = DP_SET_POWER >> 8,
+               [2] = DP_SET_POWER & 0xff,
+               [3] = 1 - 1,
+               [4] = DP_SET_POWER_D0,
+       };
+       int i;
+
+       BUILD_BUG_ON(sizeof(aux_msg) > 20);
 
        aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
 
@@ -2038,11 +2161,13 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
                                   DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE);
 
        /* Setup AUX registers */
-       I915_WRITE(EDP_PSR_AUX_DATA1(dev), EDP_PSR_DPCD_COMMAND);
-       I915_WRITE(EDP_PSR_AUX_DATA2(dev), EDP_PSR_DPCD_NORMAL_OPERATION);
+       for (i = 0; i < sizeof(aux_msg); i += 4)
+               I915_WRITE(EDP_PSR_AUX_DATA1(dev) + i,
+                          pack_aux(&aux_msg[i], sizeof(aux_msg) - i));
+
        I915_WRITE(EDP_PSR_AUX_CTL(dev),
                   DP_AUX_CH_CTL_TIME_OUT_400us |
-                  (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+                  (sizeof(aux_msg) << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
                   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
                   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
 }
@@ -2131,10 +2256,7 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
        WARN_ON(dev_priv->psr.active);
        lockdep_assert_held(&dev_priv->psr.lock);
 
-       /* Enable PSR on the panel */
-       intel_edp_psr_enable_sink(intel_dp);
-
-       /* Enable PSR on the host */
+       /* Enable/Re-enable PSR on the host */
        intel_edp_psr_enable_source(intel_dp);
 
        dev_priv->psr.active = true;
@@ -2158,17 +2280,25 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp)
        mutex_lock(&dev_priv->psr.lock);
        if (dev_priv->psr.enabled) {
                DRM_DEBUG_KMS("PSR already in use\n");
-               mutex_unlock(&dev_priv->psr.lock);
-               return;
+               goto unlock;
        }
 
+       if (!intel_edp_psr_match_conditions(intel_dp))
+               goto unlock;
+
        dev_priv->psr.busy_frontbuffer_bits = 0;
 
-       /* Setup PSR once */
-       intel_edp_psr_setup(intel_dp);
+       intel_edp_psr_setup_vsc(intel_dp);
 
-       if (intel_edp_psr_match_conditions(intel_dp))
-               dev_priv->psr.enabled = intel_dp;
+       /* Avoid continuous PSR exit by masking memup and hpd */
+       I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
+                  EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
+
+       /* Enable PSR on the panel */
+       intel_edp_psr_enable_sink(intel_dp);
+
+       dev_priv->psr.enabled = intel_dp;
+unlock:
        mutex_unlock(&dev_priv->psr.lock);
 }
 
@@ -2209,6 +2339,17 @@ static void intel_edp_psr_work(struct work_struct *work)
                container_of(work, typeof(*dev_priv), psr.work.work);
        struct intel_dp *intel_dp = dev_priv->psr.enabled;
 
+       /* We have to make sure PSR is ready for re-enable
+        * otherwise it keeps disabled until next full enable/disable cycle.
+        * PSR might take some time to get fully disabled
+        * and be ready for re-enable.
+        */
+       if (wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev_priv->dev)) &
+                     EDP_PSR_STATUS_STATE_MASK) == 0, 50)) {
+               DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n");
+               return;
+       }
+
        mutex_lock(&dev_priv->psr.lock);
        intel_dp = dev_priv->psr.enabled;
 
@@ -2467,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)
@@ -2487,10 +2637,22 @@ static void intel_enable_dp(struct intel_encoder *encoder)
        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);
@@ -2526,6 +2688,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)
 {
@@ -2534,6 +2722,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;
@@ -2551,10 +2742,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);
        }
 }
 
@@ -2565,10 +2758,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;
 
@@ -2578,7 +2773,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
@@ -2593,9 +2788,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)
@@ -2624,15 +2818,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)
@@ -2680,6 +2866,15 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 
        mutex_lock(&dev_priv->dpio_lock);
 
+       /* allow hardware to manage TX FIFO reset source */
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch));
+       val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
+
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+       val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+
        /* Deassert soft data lane reset*/
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
        val |= CHV_PCS_REQ_SOFTRESET_EN;
@@ -2715,15 +2910,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)
@@ -2836,7 +3023,9 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        enum port port = dp_to_dig_port(intel_dp)->port;
 
-       if (IS_VALLEYVIEW(dev))
+       if (INTEL_INFO(dev)->gen >= 9)
+               return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+       else if (IS_VALLEYVIEW(dev))
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
        else if (IS_GEN7(dev) && port == PORT_A)
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -2852,7 +3041,18 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        enum port port = dp_to_dig_port(intel_dp)->port;
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+       if (INTEL_INFO(dev)->gen >= 9) {
+               switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_3;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_2;
+               case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_1;
+               default:
+                       return DP_TRAIN_PRE_EMPH_LEVEL_0;
+               }
+       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
                case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
                        return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3088,12 +3288,26 @@ static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp)
        /* Clear calc init */
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
        val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
+       val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
+       val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
        vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
 
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
        val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
+       val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
+       val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
        vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
 
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch));
+       val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
+       val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val);
+
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
+       val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
+       val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
+
        /* Program swing deemph */
        for (i = 0; i < 4; i++) {
                val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i));
@@ -3334,7 +3548,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
        uint32_t signal_levels, mask;
        uint8_t train_set = intel_dp->train_set[0];
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
                signal_levels = intel_hsw_signal_levels(train_set);
                mask = DDI_BUF_EMP_MASK;
        } else if (IS_CHERRYVIEW(dev)) {
@@ -3598,7 +3812,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 |
@@ -3755,8 +3968,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]);
@@ -3764,8 +3975,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
@@ -3779,7 +3988,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");
@@ -3789,7 +3997,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;
@@ -3801,26 +4008,48 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(intel_dig_port->base.base.crtc);
-       u8 buf[1];
+       u8 buf;
+       int test_crc_count;
+       int attempts = 6;
 
-       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, buf) < 0)
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
                return -EIO;
 
-       if (!(buf[0] & DP_TEST_CRC_SUPPORTED))
+       if (!(buf & DP_TEST_CRC_SUPPORTED))
                return -ENOTTY;
 
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
+               return -EIO;
+
        if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
-                              DP_TEST_SINK_START) < 0)
+                               buf | DP_TEST_SINK_START) < 0)
+               return -EIO;
+
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
                return -EIO;
+       test_crc_count = buf & DP_TEST_COUNT_MASK;
 
-       /* Wait 2 vblanks to be sure we will have the correct CRC value */
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       do {
+               if (drm_dp_dpcd_readb(&intel_dp->aux,
+                                     DP_TEST_SINK_MISC, &buf) < 0)
+                       return -EIO;
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
+       } while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count);
+
+       if (attempts == 0) {
+               DRM_ERROR("Panel is unable to calculate CRC after 6 vblanks\n");
+               return -EIO;
+       }
 
        if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0)
                return -EIO;
 
-       drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, 0);
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
+               return -EIO;
+       if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
+                              buf & ~DP_TEST_SINK_START) < 0)
+               return -EIO;
+
        return 0;
 }
 
@@ -4447,9 +4676,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 = {
@@ -4624,16 +4896,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;
@@ -4695,7 +4971,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);
@@ -4705,7 +4981,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);
@@ -4719,21 +4995,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);
 
@@ -4919,40 +5192,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);
@@ -4970,12 +5211,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)
@@ -4990,7 +5231,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);
@@ -5051,13 +5292,14 @@ 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;
 
        /* intel_dp vfuncs */
-       if (IS_VALLEYVIEW(dev))
+       if (INTEL_INFO(dev)->gen >= 9)
+               intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
+       else if (IS_VALLEYVIEW(dev))
                intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
        else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
@@ -5066,7 +5308,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        else
                intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider;
 
-       intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
+       if (INTEL_INFO(dev)->gen >= 9)
+               intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
+       else
+               intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
 
        /* Preserve the current hw state. */
        intel_dp->DP = I915_READ(intel_dp->output_reg);
@@ -5085,6 +5330,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));
@@ -5127,13 +5377,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);
        }
 
@@ -5147,7 +5395,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);
This page took 0.055104 seconds and 5 git commands to generate.