drm/i915: Hook up pfit for DSI
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index f069a82deb57a42a814e2e5a30f5f1b1e4c51ad8..7523558190d17887d99c0ffa82de5e202c0bfadc 100644 (file)
@@ -129,6 +129,7 @@ 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);
+static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
 static unsigned int intel_dp_unused_lane_mask(int lane_count)
 {
@@ -671,60 +672,55 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
        return status;
 }
 
-static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        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 = to_i915(intel_dig_port->base.base.dev);
+
+       if (index)
+               return 0;
 
        /*
         * The clock divider is based off the hrawclk, and would like to run at
-        * 2MHz.  So, take the hrawclk value and divide by 2 and use that
+        * 2MHz.  So, take the hrawclk value and divide by 2000 and use that
         */
-       return index ? 0 : DIV_ROUND_CLOSEST(intel_hrawclk(dev), 2);
+       return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        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 drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
        if (index)
                return 0;
 
-       if (intel_dig_port->port == PORT_A) {
+       /*
+        * The clock divider is based off the cdclk or PCH rawclk, and would
+        * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
+        * divide by 2000 and use that
+        */
+       if (intel_dig_port->port == PORT_A)
                return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-
-       } else {
-               return DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
-       }
+       else
+               return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        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 drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
-       if (intel_dig_port->port == PORT_A) {
-               if (index)
-                       return 0;
-               return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-       } else if (HAS_PCH_LPT_H(dev_priv)) {
+       if (intel_dig_port->port != PORT_A && HAS_PCH_LPT_H(dev_priv)) {
                /* Workaround for non-ULT HSW */
                switch (index) {
                case 0: return 63;
                case 1: return 72;
                default: return 0;
                }
-       } else  {
-               return index ? 0 : DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
        }
-}
 
-static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-       return index ? 0 : 100;
+       return ilk_get_aux_clock_divider(intel_dp, index);
 }
 
 static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
@@ -737,10 +733,10 @@ static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return index ? 0 : 1;
 }
 
-static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
-                                     bool has_aux_irq,
-                                     int send_bytes,
-                                     uint32_t aux_clock_divider)
+static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
+                                    bool has_aux_irq,
+                                    int send_bytes,
+                                    uint32_t aux_clock_divider)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -1229,71 +1225,6 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
        intel_connector_unregister(intel_connector);
 }
 
-static void
-skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
-{
-       u32 ctrl1;
-
-       memset(&pipe_config->dpll_hw_state, 0,
-              sizeof(pipe_config->dpll_hw_state));
-
-       pipe_config->ddi_pll_sel = SKL_DPLL0;
-       pipe_config->dpll_hw_state.cfgcr1 = 0;
-       pipe_config->dpll_hw_state.cfgcr2 = 0;
-
-       ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-       switch (pipe_config->port_clock / 2) {
-       case 81000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
-                                             SKL_DPLL0);
-               break;
-       case 135000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,
-                                             SKL_DPLL0);
-               break;
-       case 270000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,
-                                             SKL_DPLL0);
-               break;
-       case 162000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,
-                                             SKL_DPLL0);
-               break;
-       /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
-       results in CDCLK change. Need to handle the change of CDCLK by
-       disabling pipes and re-enabling them */
-       case 108000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
-                                             SKL_DPLL0);
-               break;
-       case 216000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,
-                                             SKL_DPLL0);
-               break;
-
-       }
-       pipe_config->dpll_hw_state.ctrl1 = ctrl1;
-}
-
-void
-hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
-{
-       memset(&pipe_config->dpll_hw_state, 0,
-              sizeof(pipe_config->dpll_hw_state));
-
-       switch (pipe_config->port_clock / 2) {
-       case 81000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
-               break;
-       case 135000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
-               break;
-       case 270000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
-               break;
-       }
-}
-
 static int
 intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 {
@@ -1570,10 +1501,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
                /* Get bpp from vbt only for panels that dont have bpp in edid */
                if (intel_connector->base.display_info.bpc == 0 &&
-                       (dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp)) {
+                       (dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp)) {
                        DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
-                                     dev_priv->vbt.edp_bpp);
-                       bpp = dev_priv->vbt.edp_bpp;
+                                     dev_priv->vbt.edp.bpp);
+                       bpp = dev_priv->vbt.edp.bpp;
                }
 
                /*
@@ -1651,13 +1582,7 @@ found:
                                &pipe_config->dp_m2_n2);
        }
 
-       if ((IS_SKYLAKE(dev)  || IS_KABYLAKE(dev)) && is_edp(intel_dp))
-               skl_edp_set_pll_config(pipe_config);
-       else if (IS_BROXTON(dev))
-               /* handled in ddi */;
-       else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               hsw_dp_set_ddi_pll_sel(pipe_config);
-       else
+       if (!HAS_DDI(dev))
                intel_dp_set_clock(encoder, pipe_config);
 
        return true;
@@ -1779,11 +1704,11 @@ static void wait_panel_status(struct intel_dp *intel_dp,
                        I915_READ(pp_stat_reg),
                        I915_READ(pp_ctrl_reg));
 
-       if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) {
+       if (_wait_for((I915_READ(pp_stat_reg) & mask) == value,
+                     5 * USEC_PER_SEC, 10 * USEC_PER_MSEC))
                DRM_ERROR("Panel status timeout: status %08x control %08x\n",
                                I915_READ(pp_stat_reg),
                                I915_READ(pp_ctrl_reg));
-       }
 
        DRM_DEBUG_KMS("Wait complete\n");
 }
@@ -2290,6 +2215,15 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
        POSTING_READ(DP_A);
        udelay(500);
 
+       /*
+        * [DevILK] Work around required when enabling DP PLL
+        * while a pipe is enabled going to FDI:
+        * 1. Wait for the start of vertical blank on the enabled pipe going to FDI
+        * 2. Program DP PLL enable
+        */
+       if (IS_GEN5(dev_priv))
+               intel_wait_for_vblank_if_active(dev_priv->dev, !crtc->pipe);
+
        intel_dp->DP |= DP_PLL_ENABLE;
 
        I915_WRITE(DP_A, intel_dp->DP);
@@ -2409,7 +2343,6 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = dp_to_dig_port(intel_dp)->port;
        struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-       int dotclock;
 
        tmp = I915_READ(intel_dp->output_reg);
 
@@ -2459,16 +2392,12 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
                        pipe_config->port_clock = 270000;
        }
 
-       dotclock = intel_dotclock_calculate(pipe_config->port_clock,
-                                           &pipe_config->dp_m_n);
-
-       if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A)
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
+       pipe_config->base.adjusted_mode.crtc_clock =
+               intel_dotclock_calculate(pipe_config->port_clock,
+                                        &pipe_config->dp_m_n);
 
-       pipe_config->base.adjusted_mode.crtc_clock = dotclock;
-
-       if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
-           pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+       if (is_edp(intel_dp) && dev_priv->vbt.edp.bpp &&
+           pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
                /*
                 * This is a big fat ugly hack.
                 *
@@ -2483,8 +2412,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
                 * load.
                 */
                DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
-                             pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
-               dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+                             pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp);
+               dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
        }
 }
 
@@ -2710,7 +2639,6 @@ static void intel_enable_dp(struct intel_encoder *encoder)
        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);
-       enum port port = dp_to_dig_port(intel_dp)->port;
        enum pipe pipe = crtc->pipe;
 
        if (WARN_ON(dp_reg & DP_PORT_EN))
@@ -2721,35 +2649,12 @@ static void intel_enable_dp(struct intel_encoder *encoder)
        if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
                vlv_init_panel_power_sequencer(intel_dp);
 
-       /*
-        * We get an occasional spurious underrun between the port
-        * enable and vdd enable, when enabling port A eDP.
-        *
-        * FIXME: Not sure if this applies to (PCH) port D eDP as well
-        */
-       if (port == PORT_A)
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
        intel_dp_enable_port(intel_dp);
 
-       if (port == PORT_A && IS_GEN5(dev_priv)) {
-               /*
-                * Underrun reporting for the other pipe was disabled in
-                * g4x_pre_enable_dp(). The eDP PLL and port have now been
-                * enabled, so it's now safe to re-enable underrun reporting.
-                */
-               intel_wait_for_vblank_if_active(dev_priv->dev, !pipe);
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, true);
-               intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, true);
-       }
-
        edp_panel_vdd_on(intel_dp);
        edp_panel_on(intel_dp);
        edp_panel_vdd_off(intel_dp, true);
 
-       if (port == PORT_A)
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
        pps_unlock(intel_dp);
 
        if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
@@ -2791,26 +2696,11 @@ static void vlv_enable_dp(struct intel_encoder *encoder)
 
 static void g4x_pre_enable_dp(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = dp_to_dig_port(intel_dp)->port;
-       enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
 
        intel_dp_prepare(encoder);
 
-       if (port == PORT_A && IS_GEN5(dev_priv)) {
-               /*
-                * We get FIFO underruns on the other pipe when
-                * enabling the CPU eDP PLL, and when enabling CPU
-                * eDP port. We could potentially avoid the PLL
-                * underrun with a vblank wait just prior to enabling
-                * the PLL, but that doesn't appear to help the port
-                * enable case. Just sweep it all under the rug.
-                */
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, false);
-               intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, false);
-       }
-
        /* Only ilk+ has port A */
        if (port == PORT_A)
                ironlake_edp_pll_on(intel_dp);
@@ -3238,7 +3128,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
        if (IS_BROXTON(dev))
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
        else if (INTEL_INFO(dev)->gen >= 9) {
-               if (dev_priv->edp_low_vswing && port == PORT_A)
+               if (dev_priv->vbt.edp.low_vswing && port == PORT_A)
                        return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
        } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
@@ -3868,6 +3758,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
        if (intel_dp->dpcd[DP_DPCD_REV] == 0)
                return false; /* DPCD not present */
 
+       if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT,
+                                   &intel_dp->sink_count, 1) < 0)
+               return false;
+
+       /*
+        * Sink count can change between short pulse hpd hence
+        * a member variable in intel_dp will track any changes
+        * between short pulse interrupts.
+        */
+       intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count);
+
+       /*
+        * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
+        * a dongle is present but no display. Unless we require to know
+        * if a dongle is present or not, we don't need to update
+        * downstream port information. So, an early return here saves
+        * time from performing other operations which are not required.
+        */
+       if (!intel_dp->sink_count)
+               return false;
+
        /* Check if the panel supports PSR */
        memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
        if (is_edp(intel_dp)) {
@@ -3963,6 +3874,9 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 {
        u8 buf[1];
 
+       if (!i915.enable_dp_mst)
+               return false;
+
        if (!intel_dp->can_mst)
                return false;
 
@@ -4292,6 +4206,36 @@ go_again:
        return -EINVAL;
 }
 
+static void
+intel_dp_check_link_status(struct intel_dp *intel_dp)
+{
+       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       u8 link_status[DP_LINK_STATUS_SIZE];
+
+       WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
+       if (!intel_dp_get_link_status(intel_dp, link_status)) {
+               DRM_ERROR("Failed to get link status\n");
+               return;
+       }
+
+       if (!intel_encoder->base.crtc)
+               return;
+
+       if (!to_intel_crtc(intel_encoder->base.crtc)->active)
+               return;
+
+       /* if link training is requested we should perform it always */
+       if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
+           (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
+               DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
+                             intel_encoder->base.name);
+               intel_dp_start_link_train(intel_dp);
+               intel_dp_stop_link_train(intel_dp);
+       }
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -4299,16 +4243,19 @@ go_again:
  *  2. Configure link according to Receiver Capabilities
  *  3. Use Link Training from 2.5.3.3 and 3.5.1.3
  *  4. Check link status on receipt of hot-plug interrupt
+ *
+ * intel_dp_short_pulse -  handles short pulse interrupts
+ * when full detection is not required.
+ * Returns %true if short pulse is handled and full detection
+ * is NOT required and %false otherwise.
  */
-static void
-intel_dp_check_link_status(struct intel_dp *intel_dp)
+static bool
+intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
-       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
        u8 sink_irq_vector;
-       u8 link_status[DP_LINK_STATUS_SIZE];
-
-       WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+       u8 old_sink_count = intel_dp->sink_count;
+       bool ret;
 
        /*
         * Clearing compliance test variables to allow capturing
@@ -4318,20 +4265,17 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
        intel_dp->compliance_test_type = 0;
        intel_dp->compliance_test_data = 0;
 
-       if (!intel_encoder->base.crtc)
-               return;
-
-       if (!to_intel_crtc(intel_encoder->base.crtc)->active)
-               return;
-
-       /* Try to read receiver status if the link appears to be up */
-       if (!intel_dp_get_link_status(intel_dp, link_status)) {
-               return;
-       }
+       /*
+        * Now read the DPCD to see if it's actually running
+        * If the current value of sink count doesn't match with
+        * the value that was stored earlier or dpcd read failed
+        * we need to do full detection
+        */
+       ret = intel_dp_get_dpcd(intel_dp);
 
-       /* Now read the DPCD to see if it's actually running */
-       if (!intel_dp_get_dpcd(intel_dp)) {
-               return;
+       if ((old_sink_count != intel_dp->sink_count) || !ret) {
+               /* No need to proceed if we are going to do full detect */
+               return false;
        }
 
        /* Try to read the source of the interrupt */
@@ -4348,14 +4292,11 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                        DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
        }
 
-       /* if link training is requested we should perform it always */
-       if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
-               (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
-               DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
-                             intel_encoder->base.name);
-               intel_dp_start_link_train(intel_dp);
-               intel_dp_stop_link_train(intel_dp);
-       }
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+       intel_dp_check_link_status(intel_dp);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+       return true;
 }
 
 /* XXX this is probably wrong for multiple downstream ports */
@@ -4375,14 +4316,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
        /* If we're HPD-aware, SINK_COUNT changes dynamically */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
            intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
-               uint8_t reg;
 
-               if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT,
-                                           &reg, 1) < 0)
-                       return connector_status_unknown;
-
-               return DP_GET_SINK_COUNT(reg) ? connector_status_connected
-                                             : connector_status_disconnected;
+               return intel_dp->sink_count ?
+               connector_status_connected : connector_status_disconnected;
        }
 
        /* If no HPD, poke DDC gently */
@@ -4591,6 +4527,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        struct edid *edid;
 
+       intel_dp_unset_edid(intel_dp);
        edid = intel_dp_get_edid(intel_dp);
        intel_connector->detect_edid = edid;
 
@@ -4611,9 +4548,10 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
        intel_dp->has_audio = false;
 }
 
-static enum drm_connector_status
-intel_dp_detect(struct drm_connector *connector, bool force)
+static void
+intel_dp_long_pulse(struct intel_connector *intel_connector)
 {
+       struct drm_connector *connector = &intel_connector->base;
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *intel_encoder = &intel_dig_port->base;
@@ -4623,17 +4561,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
        bool ret;
        u8 sink_irq_vector;
 
-       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
-                     connector->base.id, connector->name);
-       intel_dp_unset_edid(intel_dp);
-
-       if (intel_dp->is_mst) {
-               /* MST devices are disconnected from a monitor POV */
-               if (intel_encoder->type != INTEL_OUTPUT_EDP)
-                       intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-               return connector_status_disconnected;
-       }
-
        power_domain = intel_display_port_aux_power_domain(intel_encoder);
        intel_display_power_get(to_i915(dev), power_domain);
 
@@ -4654,16 +4581,30 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                goto out;
        }
 
+       if (intel_encoder->type != INTEL_OUTPUT_EDP)
+               intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+
        intel_dp_probe_oui(intel_dp);
 
        ret = intel_dp_probe_mst(intel_dp);
        if (ret) {
-               /* if we are in MST mode then this connector
-                  won't appear connected or have anything with EDID on it */
-               if (intel_encoder->type != INTEL_OUTPUT_EDP)
-                       intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+               /*
+                * If we are in MST mode then this connector
+                * won't appear connected or have anything
+                * with EDID on it
+                */
                status = connector_status_disconnected;
                goto out;
+       } else if (connector->status == connector_status_connected) {
+               /*
+                * If display was connected already and is still connected
+                * check links status, there has been known issues of
+                * link loss triggerring long pulse!!!!
+                */
+               drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+               intel_dp_check_link_status(intel_dp);
+               drm_modeset_unlock(&dev->mode_config.connection_mutex);
+               goto out;
        }
 
        /*
@@ -4676,9 +4617,8 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
        intel_dp_set_edid(intel_dp);
 
-       if (intel_encoder->type != INTEL_OUTPUT_EDP)
-               intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
        status = connector_status_connected;
+       intel_dp->detect_done = true;
 
        /* Try to read the source of the interrupt */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
@@ -4695,8 +4635,54 @@ intel_dp_detect(struct drm_connector *connector, bool force)
        }
 
 out:
+       if (status != connector_status_connected) {
+               intel_dp_unset_edid(intel_dp);
+               /*
+                * If we were in MST mode, and device is not there,
+                * get out of MST mode
+                */
+               if (intel_dp->is_mst) {
+                       DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
+                                     intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+                       intel_dp->is_mst = false;
+                       drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+                                                       intel_dp->is_mst);
+               }
+       }
+
        intel_display_power_put(to_i915(dev), power_domain);
-       return status;
+       return;
+}
+
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector, bool force)
+{
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_encoder *intel_encoder = &intel_dig_port->base;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                     connector->base.id, connector->name);
+
+       if (intel_dp->is_mst) {
+               /* MST devices are disconnected from a monitor POV */
+               intel_dp_unset_edid(intel_dp);
+               if (intel_encoder->type != INTEL_OUTPUT_EDP)
+                       intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+               return connector_status_disconnected;
+       }
+
+       /* If full detect is not performed yet, do a full detect */
+       if (!intel_dp->detect_done)
+               intel_dp_long_pulse(intel_dp->attached_connector);
+
+       intel_dp->detect_done = false;
+
+       if (intel_connector->detect_edid)
+               return connector_status_connected;
+       else
+               return connector_status_disconnected;
 }
 
 static void
@@ -5023,44 +5009,37 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
                /* indicate that we need to restart link training */
                intel_dp->train_set_valid = false;
 
-               if (!intel_digital_port_connected(dev_priv, intel_dig_port))
-                       goto mst_fail;
+               intel_dp_long_pulse(intel_dp->attached_connector);
+               if (intel_dp->is_mst)
+                       ret = IRQ_HANDLED;
+               goto put_power;
 
-               if (!intel_dp_get_dpcd(intel_dp)) {
-                       goto mst_fail;
-               }
-
-               intel_dp_probe_oui(intel_dp);
-
-               if (!intel_dp_probe_mst(intel_dp)) {
-                       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-                       intel_dp_check_link_status(intel_dp);
-                       drm_modeset_unlock(&dev->mode_config.connection_mutex);
-                       goto mst_fail;
-               }
        } else {
                if (intel_dp->is_mst) {
-                       if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
-                               goto mst_fail;
+                       if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
+                               /*
+                                * If we were in MST mode, and device is not
+                                * there, get out of MST mode
+                                */
+                               DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
+                                             intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+                               intel_dp->is_mst = false;
+                               drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+                                                               intel_dp->is_mst);
+                               goto put_power;
+                       }
                }
 
                if (!intel_dp->is_mst) {
-                       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-                       intel_dp_check_link_status(intel_dp);
-                       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+                       if (!intel_dp_short_pulse(intel_dp)) {
+                               intel_dp_long_pulse(intel_dp->attached_connector);
+                               goto put_power;
+                       }
                }
        }
 
        ret = IRQ_HANDLED;
 
-       goto put_power;
-mst_fail:
-       /* if we were in MST mode, and device is not there get out of MST mode */
-       if (intel_dp->is_mst) {
-               DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
-               intel_dp->is_mst = false;
-               drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
-       }
 put_power:
        intel_display_power_put(dev_priv, power_domain);
 
@@ -5071,14 +5050,6 @@ put_power:
 bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       union child_device_config *p_child;
-       int i;
-       static const short port_mapping[] = {
-               [PORT_B] = DVO_PORT_DPB,
-               [PORT_C] = DVO_PORT_DPC,
-               [PORT_D] = DVO_PORT_DPD,
-               [PORT_E] = DVO_PORT_DPE,
-       };
 
        /*
         * eDP not supported on g4x. so bail out early just
@@ -5090,18 +5061,7 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port)
        if (port == PORT_A)
                return true;
 
-       if (!dev_priv->vbt.child_dev_num)
-               return false;
-
-       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-               p_child = dev_priv->vbt.child_dev + i;
-
-               if (p_child->common.dvo_port == port_mapping[port] &&
-                   (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
-                   (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
-                       return true;
-       }
-       return false;
+       return intel_bios_is_port_edp(dev_priv, port);
 }
 
 void
@@ -5208,7 +5168,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
                      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
 
-       vbt = dev_priv->vbt.edp_pps;
+       vbt = dev_priv->vbt.edp.pps;
 
        /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
         * our hw here, which are all in 100usec. */
@@ -5259,7 +5219,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 {
        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 div = dev_priv->rawclk_freq / 1000;
        i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg;
        enum port port = dp_to_dig_port(intel_dp)->port;
        const struct edp_power_seq *seq = &intel_dp->pps_delays;
@@ -5852,19 +5812,17 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        /* intel_dp vfuncs */
        if (INTEL_INFO(dev)->gen >= 9)
                intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-       else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(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;
        else if (HAS_PCH_SPLIT(dev))
                intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
        else
-               intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider;
+               intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 
        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;
+               intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
 
        if (HAS_DDI(dev))
                intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
This page took 0.035742 seconds and 5 git commands to generate.