drm/i915: Enable Resource Streamer state save/restore on MI_SET_CONTEXT
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index 82dcc6ed8b1d8c4a241497b4f8d0cb664fda032d..367f71224c96a20bc48f0f72f57a38969a9407e9 100644 (file)
@@ -91,6 +91,8 @@ static const struct dp_link_dpll chv_dpll[] = {
                { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
 };
 
+static const int bxt_rates[] = { 162000, 216000, 243000, 270000,
+                                 324000, 432000, 540000 };
 static const int skl_rates[] = { 162000, 216000, 270000,
                                  324000, 432000, 540000 };
 static const int chv_rates[] = { 162000, 202500, 210000, 216000,
@@ -565,7 +567,9 @@ static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
-       if (HAS_PCH_SPLIT(dev))
+       if (IS_BROXTON(dev))
+               return BXT_PP_CONTROL(0);
+       else if (HAS_PCH_SPLIT(dev))
                return PCH_PP_CONTROL;
        else
                return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp));
@@ -575,7 +579,9 @@ static u32 _pp_stat_reg(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
-       if (HAS_PCH_SPLIT(dev))
+       if (IS_BROXTON(dev))
+               return BXT_PP_STATUS(0);
+       else if (HAS_PCH_SPLIT(dev))
                return PCH_PP_STATUS;
        else
                return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp));
@@ -708,7 +714,8 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
                return 0;
 
        if (intel_dig_port->port == PORT_A) {
-               return DIV_ROUND_UP(dev_priv->display.get_display_clock_speed(dev), 2000);
+               return DIV_ROUND_UP(dev_priv->cdclk_freq, 2000);
+
        } else {
                return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
        }
@@ -723,7 +730,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        if (intel_dig_port->port == PORT_A) {
                if (index)
                        return 0;
-               return DIV_ROUND_CLOSEST(dev_priv->display.get_display_clock_speed(dev), 2000);
+               return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
        } else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
                /* Workaround for non-ULT HSW */
                switch (index) {
@@ -1097,6 +1104,9 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
 {
        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;
@@ -1167,7 +1177,10 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 static int
 intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
 {
-       if (IS_SKYLAKE(dev)) {
+       if (IS_BROXTON(dev)) {
+               *source_rates = bxt_rates;
+               return ARRAY_SIZE(bxt_rates);
+       } else if (IS_SKYLAKE(dev)) {
                *source_rates = skl_rates;
                return ARRAY_SIZE(skl_rates);
        } else if (IS_CHERRYVIEW(dev)) {
@@ -1266,7 +1279,7 @@ static void snprintf_int_array(char *str, size_t len,
        str[0] = '\0';
 
        for (i = 0; i < nelem; i++) {
-               int r = snprintf(str, len, "%d,", array[i]);
+               int r = snprintf(str, len, "%s%d", i ? ", " : "", array[i]);
                if (r >= len)
                        return;
                str += r;
@@ -1361,7 +1374,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        pipe_config->has_dp_encoder = true;
        pipe_config->has_drrs = false;
-       pipe_config->has_audio = intel_dp->has_audio;
+       pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;
 
        if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
                intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
@@ -1369,7 +1382,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
                if (INTEL_INFO(dev)->gen >= 9) {
                        int ret;
-                       ret = skl_update_scaler_users(intel_crtc, pipe_config, NULL, NULL, 0);
+                       ret = skl_update_scaler_crtc(pipe_config, 0);
                        if (ret)
                                return ret;
                }
@@ -1567,7 +1580,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
 
        /* Split out the IBX/CPU vs CPT settings */
 
-       if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
+       if (IS_GEN7(dev) && port == PORT_A) {
                if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                        intel_dp->DP |= DP_SYNC_HS_HIGH;
                if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -1578,7 +1591,18 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
                        intel_dp->DP |= DP_ENHANCED_FRAMING;
 
                intel_dp->DP |= crtc->pipe << 29;
-       } else if (!HAS_PCH_CPT(dev) || port == PORT_A) {
+       } else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+               u32 trans_dp;
+
+               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
+
+               trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe));
+               if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+                       trans_dp |= TRANS_DP_ENH_FRAMING;
+               else
+                       trans_dp &= ~TRANS_DP_ENH_FRAMING;
+               I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp);
+       } else {
                if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
                        intel_dp->DP |= intel_dp->color_range;
 
@@ -1591,14 +1615,10 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
                if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
                        intel_dp->DP |= DP_ENHANCED_FRAMING;
 
-               if (!IS_CHERRYVIEW(dev)) {
-                       if (crtc->pipe == 1)
-                               intel_dp->DP |= DP_PIPEB_SELECT;
-               } else {
+               if (IS_CHERRYVIEW(dev))
                        intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe);
-               }
-       } else {
-               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
+               else if (crtc->pipe == PIPE_B)
+                       intel_dp->DP |= DP_PIPEB_SELECT;
        }
 }
 
@@ -1687,8 +1707,10 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
        lockdep_assert_held(&dev_priv->pps_mutex);
 
        control = I915_READ(_pp_ctrl_reg(intel_dp));
-       control &= ~PANEL_UNLOCK_MASK;
-       control |= PANEL_UNLOCK_REGS;
+       if (!IS_BROXTON(dev)) {
+               control &= ~PANEL_UNLOCK_MASK;
+               control |= PANEL_UNLOCK_REGS;
+       }
        return control;
 }
 
@@ -2182,41 +2204,25 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
        if (!(tmp & DP_PORT_EN))
                return false;
 
-       if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
+       if (IS_GEN7(dev) && port == PORT_A) {
                *pipe = PORT_TO_PIPE_CPT(tmp);
-       } else if (IS_CHERRYVIEW(dev)) {
-               *pipe = DP_PORT_TO_PIPE_CHV(tmp);
-       } else if (!HAS_PCH_CPT(dev) || port == PORT_A) {
-               *pipe = PORT_TO_PIPE(tmp);
-       } else {
-               u32 trans_sel;
-               u32 trans_dp;
-               int i;
-
-               switch (intel_dp->output_reg) {
-               case PCH_DP_B:
-                       trans_sel = TRANS_DP_PORT_SEL_B;
-                       break;
-               case PCH_DP_C:
-                       trans_sel = TRANS_DP_PORT_SEL_C;
-                       break;
-               case PCH_DP_D:
-                       trans_sel = TRANS_DP_PORT_SEL_D;
-                       break;
-               default:
-                       return true;
-               }
+       } else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+               enum pipe p;
 
-               for_each_pipe(dev_priv, i) {
-                       trans_dp = I915_READ(TRANS_DP_CTL(i));
-                       if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
-                               *pipe = i;
+               for_each_pipe(dev_priv, p) {
+                       u32 trans_dp = I915_READ(TRANS_DP_CTL(p));
+                       if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) {
+                               *pipe = p;
                                return true;
                        }
                }
 
                DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
                              intel_dp->output_reg);
+       } else if (IS_CHERRYVIEW(dev)) {
+               *pipe = DP_PORT_TO_PIPE_CHV(tmp);
+       } else {
+               *pipe = PORT_TO_PIPE(tmp);
        }
 
        return true;
@@ -2234,27 +2240,27 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
        int dotclock;
 
        tmp = I915_READ(intel_dp->output_reg);
-       if (tmp & DP_AUDIO_OUTPUT_ENABLE)
-               pipe_config->has_audio = true;
 
-       if ((port == PORT_A) || !HAS_PCH_CPT(dev)) {
-               if (tmp & DP_SYNC_HS_HIGH)
+       pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A;
+
+       if (HAS_PCH_CPT(dev) && port != PORT_A) {
+               tmp = I915_READ(TRANS_DP_CTL(crtc->pipe));
+               if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)
                        flags |= DRM_MODE_FLAG_PHSYNC;
                else
                        flags |= DRM_MODE_FLAG_NHSYNC;
 
-               if (tmp & DP_SYNC_VS_HIGH)
+               if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)
                        flags |= DRM_MODE_FLAG_PVSYNC;
                else
                        flags |= DRM_MODE_FLAG_NVSYNC;
        } else {
-               tmp = I915_READ(TRANS_DP_CTL(crtc->pipe));
-               if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)
+               if (tmp & DP_SYNC_HS_HIGH)
                        flags |= DRM_MODE_FLAG_PHSYNC;
                else
                        flags |= DRM_MODE_FLAG_NHSYNC;
 
-               if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)
+               if (tmp & DP_SYNC_VS_HIGH)
                        flags |= DRM_MODE_FLAG_PVSYNC;
                else
                        flags |= DRM_MODE_FLAG_NVSYNC;
@@ -2361,7 +2367,7 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
 
        intel_dp_link_down(intel_dp);
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
 
        /* Propagate soft reset to data lane reset */
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
@@ -2380,7 +2386,7 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
        val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
        vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
 
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 }
 
 static void
@@ -2419,7 +2425,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
                }
                I915_WRITE(DP_TP_CTL(port), temp);
 
-       } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
+       } else if ((IS_GEN7(dev) && port == PORT_A) ||
+                  (HAS_PCH_CPT(dev) && port != PORT_A)) {
                *DP &= ~DP_LINK_TRAIN_MASK_CPT;
 
                switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
@@ -2676,7 +2683,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
        int pipe = intel_crtc->pipe;
        u32 val;
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
 
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
@@ -2689,7 +2696,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
 
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        intel_enable_dp(encoder);
 }
@@ -2707,7 +2714,7 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
        intel_dp_prepare(encoder);
 
        /* Program Tx lane resets to default */
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
@@ -2721,7 +2728,7 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 }
 
 static void chv_pre_enable_dp(struct intel_encoder *encoder)
@@ -2737,7 +2744,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
        int data, i, stagger;
        u32 val;
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
 
        /* allow hardware to manage TX FIFO reset source */
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch));
@@ -2807,7 +2814,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
                       DPIO_TX1_STAGGER_MULT(7) |
                       DPIO_TX2_STAGGER_MULT(5));
 
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        intel_enable_dp(encoder);
 }
@@ -2825,7 +2832,7 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 
        intel_dp_prepare(encoder);
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
 
        /* program left/right clock distribution */
        if (pipe != PIPE_B) {
@@ -2875,7 +2882,7 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
                val |= CHV_CMN_USEDCLKCHANNEL;
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
 
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 }
 
 /*
@@ -3100,7 +3107,7 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
                return 0;
        }
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port),
@@ -3109,7 +3116,7 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
        vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);
        vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000);
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        return 0;
 }
@@ -3196,7 +3203,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
                return 0;
        }
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
 
        /* Clear calc init */
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
@@ -3283,7 +3290,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
        val |= DPIO_LRC_BYPASS;
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val);
 
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        return 0;
 }
@@ -3417,92 +3424,6 @@ gen7_edp_signal_levels(uint8_t train_set)
        }
 }
 
-/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
-static uint32_t
-hsw_signal_levels(uint8_t train_set)
-{
-       int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
-                                        DP_TRAIN_PRE_EMPHASIS_MASK);
-       switch (signal_levels) {
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               return DDI_BUF_TRANS_SELECT(0);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               return DDI_BUF_TRANS_SELECT(1);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
-               return DDI_BUF_TRANS_SELECT(2);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3:
-               return DDI_BUF_TRANS_SELECT(3);
-
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               return DDI_BUF_TRANS_SELECT(4);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               return DDI_BUF_TRANS_SELECT(5);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
-               return DDI_BUF_TRANS_SELECT(6);
-
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               return DDI_BUF_TRANS_SELECT(7);
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               return DDI_BUF_TRANS_SELECT(8);
-
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               return DDI_BUF_TRANS_SELECT(9);
-       default:
-               DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
-                             "0x%x\n", signal_levels);
-               return DDI_BUF_TRANS_SELECT(0);
-       }
-}
-
-static void bxt_signal_levels(struct intel_dp *intel_dp)
-{
-       struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
-       enum port port = dport->port;
-       struct drm_device *dev = dport->base.base.dev;
-       struct intel_encoder *encoder = &dport->base;
-       uint8_t train_set = intel_dp->train_set[0];
-       uint32_t level = 0;
-
-       int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
-                                        DP_TRAIN_PRE_EMPHASIS_MASK);
-       switch (signal_levels) {
-       default:
-               DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n");
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               level = 0;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               level = 1;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
-               level = 2;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3:
-               level = 3;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               level = 4;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               level = 5;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
-               level = 6;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               level = 7;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
-               level = 8;
-               break;
-       case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
-               level = 9;
-               break;
-       }
-
-       bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
-}
-
 /* Properly updates "DP" with the correct signal levels. */
 static void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
@@ -3510,22 +3431,20 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        enum port port = intel_dig_port->port;
        struct drm_device *dev = intel_dig_port->base.base.dev;
-       uint32_t signal_levels, mask;
+       uint32_t signal_levels, mask = 0;
        uint8_t train_set = intel_dp->train_set[0];
 
-       if (IS_BROXTON(dev)) {
-               signal_levels = 0;
-               bxt_signal_levels(intel_dp);
-               mask = 0;
-       } else if (HAS_DDI(dev)) {
-               signal_levels = hsw_signal_levels(train_set);
-               mask = DDI_BUF_EMP_MASK;
+       if (HAS_DDI(dev)) {
+               signal_levels = ddi_signal_levels(intel_dp);
+
+               if (IS_BROXTON(dev))
+                       signal_levels = 0;
+               else
+                       mask = DDI_BUF_EMP_MASK;
        } else if (IS_CHERRYVIEW(dev)) {
                signal_levels = chv_signal_levels(intel_dp);
-               mask = 0;
        } else if (IS_VALLEYVIEW(dev)) {
                signal_levels = vlv_signal_levels(intel_dp);
-               mask = 0;
        } else if (IS_GEN7(dev) && port == PORT_A) {
                signal_levels = gen7_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
@@ -3848,6 +3767,7 @@ static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
        enum port port = intel_dig_port->port;
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3861,36 +3781,41 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        DRM_DEBUG_KMS("\n");
 
-       if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
+       if ((IS_GEN7(dev) && port == PORT_A) ||
+           (HAS_PCH_CPT(dev) && port != PORT_A)) {
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
-               I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
+               DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
        } else {
                if (IS_CHERRYVIEW(dev))
                        DP &= ~DP_LINK_TRAIN_MASK_CHV;
                else
                        DP &= ~DP_LINK_TRAIN_MASK;
-               I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+               DP |= DP_LINK_TRAIN_PAT_IDLE;
        }
+       I915_WRITE(intel_dp->output_reg, DP);
        POSTING_READ(intel_dp->output_reg);
 
-       if (HAS_PCH_IBX(dev) &&
-           I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-               /* Hardware workaround: leaving our transcoder select
-                * set to transcoder B while it's off will prevent the
-                * corresponding HDMI output on transcoder A.
-                *
-                * Combine this with another hardware workaround:
-                * transcoder select bit can only be cleared while the
-                * port is enabled.
-                */
-               DP &= ~DP_PIPEB_SELECT;
+       DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
+       I915_WRITE(intel_dp->output_reg, DP);
+       POSTING_READ(intel_dp->output_reg);
+
+       /*
+        * HW workaround for IBX, we need to move the port
+        * to transcoder A after disabling it to allow the
+        * matching HDMI port to be enabled on transcoder A.
+        */
+       if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
+               /* always enable with pattern 1 (as per spec) */
+               DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK);
+               DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1;
+               I915_WRITE(intel_dp->output_reg, DP);
+               POSTING_READ(intel_dp->output_reg);
+
+               DP &= ~DP_PORT_EN;
                I915_WRITE(intel_dp->output_reg, DP);
                POSTING_READ(intel_dp->output_reg);
        }
 
-       DP &= ~DP_AUDIO_OUTPUT_ENABLE;
-       I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
-       POSTING_READ(intel_dp->output_reg);
        msleep(intel_dp->panel_power_down_delay);
 }
 
@@ -3966,7 +3891,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
                        if (val == 0)
                                break;
 
-                       intel_dp->sink_rates[i] = val * 200;
+                       /* Value read is in kHz while drm clock is saved in deca-kHz */
+                       intel_dp->sink_rates[i] = (val * 200) / 10;
                }
                intel_dp->num_sink_rates = i;
        }
@@ -4039,46 +3965,70 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
        u8 buf;
        int test_crc_count;
        int attempts = 6;
+       int ret = 0;
 
-       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
-               return -EIO;
+       hsw_disable_ips(intel_crtc);
 
-       if (!(buf & DP_TEST_CRC_SUPPORTED))
-               return -ENOTTY;
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) {
+               ret = -EIO;
+               goto out;
+       }
 
-       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
-               return -EIO;
+       if (!(buf & DP_TEST_CRC_SUPPORTED)) {
+               ret = -ENOTTY;
+               goto out;
+       }
+
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) {
+               ret = -EIO;
+               goto out;
+       }
 
        if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
-                               buf | DP_TEST_SINK_START) < 0)
-               return -EIO;
+                               buf | DP_TEST_SINK_START) < 0) {
+               ret = -EIO;
+               goto out;
+       }
+
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) {
+               ret = -EIO;
+               goto out;
+       }
 
-       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
-               return -EIO;
        test_crc_count = buf & DP_TEST_COUNT_MASK;
 
        do {
                if (drm_dp_dpcd_readb(&intel_dp->aux,
-                                     DP_TEST_SINK_MISC, &buf) < 0)
-                       return -EIO;
+                                     DP_TEST_SINK_MISC, &buf) < 0) {
+                       ret = -EIO;
+                       goto out;
+               }
                intel_wait_for_vblank(dev, intel_crtc->pipe);
        } while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count);
 
        if (attempts == 0) {
                DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n");
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto out;
        }
 
-       if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0)
-               return -EIO;
+       if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
+               ret = -EIO;
+               goto out;
+       }
 
-       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
-               return -EIO;
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) {
+               ret = -EIO;
+               goto out;
+       }
        if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
-                              buf & ~DP_TEST_SINK_START) < 0)
-               return -EIO;
-
-       return 0;
+                              buf & ~DP_TEST_SINK_START) < 0) {
+               ret = -EIO;
+               goto out;
+       }
+out:
+       hsw_enable_ips(intel_crtc);
+       return ret;
 }
 
 static bool
@@ -4141,7 +4091,7 @@ static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
                if (!drm_dp_dpcd_write(&intel_dp->aux,
                                        DP_TEST_EDID_CHECKSUM,
                                        &intel_connector->detect_edid->checksum,
-                                       1));
+                                       1))
                        DRM_DEBUG_KMS("Failed to write EDID checksum\n");
 
                test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
@@ -4894,12 +4844,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
        .destroy = intel_dp_encoder_destroy,
 };
 
-void
-intel_dp_hot_plug(struct intel_encoder *intel_encoder)
-{
-       return;
-}
-
 enum irqreturn
 intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 {
@@ -5067,8 +5011,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        struct drm_i915_private *dev_priv = dev->dev_private;
        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;
+       u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0;
+       int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg = 0;
 
        lockdep_assert_held(&dev_priv->pps_mutex);
 
@@ -5076,7 +5020,16 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        if (final->t11_t12 != 0)
                return;
 
-       if (HAS_PCH_SPLIT(dev)) {
+       if (IS_BROXTON(dev)) {
+               /*
+                * TODO: BXT has 2 sets of PPS registers.
+                * Correct Register for Broxton need to be identified
+                * using VBT. hardcoding for now
+                */
+               pp_ctrl_reg = BXT_PP_CONTROL(0);
+               pp_on_reg = BXT_PP_ON_DELAYS(0);
+               pp_off_reg = BXT_PP_OFF_DELAYS(0);
+       } else if (HAS_PCH_SPLIT(dev)) {
                pp_ctrl_reg = PCH_PP_CONTROL;
                pp_on_reg = PCH_PP_ON_DELAYS;
                pp_off_reg = PCH_PP_OFF_DELAYS;
@@ -5092,12 +5045,14 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 
        /* Workaround: Need to write PP_CONTROL with the unlock key as
         * the very first thing. */
-       pp = ironlake_get_pp_control(intel_dp);
-       I915_WRITE(pp_ctrl_reg, pp);
+       pp_ctl = ironlake_get_pp_control(intel_dp);
 
        pp_on = I915_READ(pp_on_reg);
        pp_off = I915_READ(pp_off_reg);
-       pp_div = I915_READ(pp_div_reg);
+       if (!IS_BROXTON(dev)) {
+               I915_WRITE(pp_ctrl_reg, pp_ctl);
+               pp_div = I915_READ(pp_div_reg);
+       }
 
        /* Pull timing values out of registers */
        cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
@@ -5112,8 +5067,17 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
                PANEL_POWER_DOWN_DELAY_SHIFT;
 
-       cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+       if (IS_BROXTON(dev)) {
+               u16 tmp = (pp_ctl & BXT_POWER_CYCLE_DELAY_MASK) >>
+                       BXT_POWER_CYCLE_DELAY_SHIFT;
+               if (tmp > 0)
+                       cur.t11_t12 = (tmp - 1) * 1000;
+               else
+                       cur.t11_t12 = 0;
+       } else {
+               cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
                       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+       }
 
        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);
@@ -5170,13 +5134,23 @@ 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 pp_on_reg, pp_off_reg, pp_div_reg;
+       int pp_on_reg, pp_off_reg, pp_div_reg = 0, pp_ctrl_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);
 
-       if (HAS_PCH_SPLIT(dev)) {
+       if (IS_BROXTON(dev)) {
+               /*
+                * TODO: BXT has 2 sets of PPS registers.
+                * Correct Register for Broxton need to be identified
+                * using VBT. hardcoding for now
+                */
+               pp_ctrl_reg = BXT_PP_CONTROL(0);
+               pp_on_reg = BXT_PP_ON_DELAYS(0);
+               pp_off_reg = BXT_PP_OFF_DELAYS(0);
+
+       } else if (HAS_PCH_SPLIT(dev)) {
                pp_on_reg = PCH_PP_ON_DELAYS;
                pp_off_reg = PCH_PP_OFF_DELAYS;
                pp_div_reg = PCH_PP_DIVISOR;
@@ -5202,9 +5176,16 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
                 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
        /* Compute the divisor for the pp clock, simply match the Bspec
         * formula. */
-       pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT;
-       pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
-                       << PANEL_POWER_CYCLE_DELAY_SHIFT);
+       if (IS_BROXTON(dev)) {
+               pp_div = I915_READ(pp_ctrl_reg);
+               pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK;
+               pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000)
+                               << BXT_POWER_CYCLE_DELAY_SHIFT);
+       } else {
+               pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT;
+               pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
+                               << PANEL_POWER_CYCLE_DELAY_SHIFT);
+       }
 
        /* Haswell doesn't have any port selection bits for the panel
         * power sequencer any more. */
@@ -5221,11 +5202,16 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 
        I915_WRITE(pp_on_reg, pp_on);
        I915_WRITE(pp_off_reg, pp_off);
-       I915_WRITE(pp_div_reg, pp_div);
+       if (IS_BROXTON(dev))
+               I915_WRITE(pp_ctrl_reg, pp_div);
+       else
+               I915_WRITE(pp_div_reg, pp_div);
 
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
                      I915_READ(pp_on_reg),
                      I915_READ(pp_off_reg),
+                     IS_BROXTON(dev) ?
+                     (I915_READ(pp_ctrl_reg) & BXT_POWER_CYCLE_DELAY_MASK) :
                      I915_READ(pp_div_reg));
 }
 
@@ -5430,13 +5416,12 @@ unlock:
 }
 
 /**
- * intel_edp_drrs_invalidate - Invalidate DRRS
+ * intel_edp_drrs_invalidate - Disable Idleness DRRS
  * @dev: DRM device
  * @frontbuffer_bits: frontbuffer plane tracking bits
  *
- * When there is a disturbance on screen (due to cursor movement/time
- * update etc), DRRS needs to be invalidated, i.e. need to switch to
- * high RR.
+ * This function gets called everytime rendering on the given planes start.
+ * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
  *
  * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
  */
@@ -5461,26 +5446,27 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
        crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
        pipe = to_intel_crtc(crtc)->pipe;
 
-       if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
+       frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
+       dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
+
+       /* invalidate means busy screen hence upclock */
+       if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
                intel_dp_set_drrs_state(dev_priv->dev,
                                dev_priv->drrs.dp->attached_connector->panel.
                                fixed_mode->vrefresh);
-       }
-
-       frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
 
-       dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
        mutex_unlock(&dev_priv->drrs.mutex);
 }
 
 /**
- * intel_edp_drrs_flush - Flush DRRS
+ * intel_edp_drrs_flush - Restart Idleness DRRS
  * @dev: DRM device
  * @frontbuffer_bits: frontbuffer plane tracking bits
  *
- * When there is no movement on screen, DRRS work can be scheduled.
- * This DRRS work is responsible for setting relevant registers after a
- * timeout of 1 second.
+ * This function gets called every time rendering on the given planes has
+ * completed or flip on a crtc is completed. So DRRS should be upclocked
+ * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
+ * if no other planes are dirty.
  *
  * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
  */
@@ -5504,10 +5490,21 @@ void intel_edp_drrs_flush(struct drm_device *dev,
 
        crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
        pipe = to_intel_crtc(crtc)->pipe;
+
+       frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
        dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
 
-       if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR &&
-                       !dev_priv->drrs.busy_frontbuffer_bits)
+       /* flush means busy screen hence upclock */
+       if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
+               intel_dp_set_drrs_state(dev_priv->dev,
+                               dev_priv->drrs.dp->attached_connector->panel.
+                               fixed_mode->vrefresh);
+
+       /*
+        * flush also means no more activity hence schedule downclock, if all
+        * other fbs are quiescent too
+        */
+       if (!dev_priv->drrs.busy_frontbuffer_bits)
                schedule_delayed_work(&dev_priv->drrs.work,
                                msecs_to_jiffies(1000));
        mutex_unlock(&dev_priv->drrs.mutex);
@@ -5813,12 +5810,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        intel_dp_aux_init(intel_dp, intel_connector);
 
        /* init MST on ports that can support it */
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
-               if (port == PORT_B || port == PORT_C || port == PORT_D) {
-                       intel_dp_mst_encoder_init(intel_dig_port,
-                                                 intel_connector->base.base.id);
-               }
-       }
+       if (HAS_DP_MST(dev) &&
+           (port == PORT_B || port == PORT_C || port == PORT_D))
+               intel_dp_mst_encoder_init(intel_dig_port,
+                                         intel_connector->base.base.id);
 
        if (!intel_edp_init_connector(intel_dp, intel_connector)) {
                drm_dp_aux_unregister(&intel_dp->aux);
@@ -5913,10 +5908,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
        }
        intel_encoder->cloneable = 0;
-       intel_encoder->hot_plug = intel_dp_hot_plug;
 
        intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
-       dev_priv->hpd_irq_port[port] = intel_dig_port;
+       dev_priv->hotplug.irq_port[port] = intel_dig_port;
 
        if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
                drm_encoder_cleanup(encoder);
@@ -5932,7 +5926,7 @@ void intel_dp_mst_suspend(struct drm_device *dev)
 
        /* disable MST */
        for (i = 0; i < I915_MAX_PORTS; i++) {
-               struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+               struct intel_digital_port *intel_dig_port = dev_priv->hotplug.irq_port[i];
                if (!intel_dig_port)
                        continue;
 
@@ -5951,7 +5945,7 @@ void intel_dp_mst_resume(struct drm_device *dev)
        int i;
 
        for (i = 0; i < I915_MAX_PORTS; i++) {
-               struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+               struct intel_digital_port *intel_dig_port = dev_priv->hotplug.irq_port[i];
                if (!intel_dig_port)
                        continue;
                if (intel_dig_port->base.type == INTEL_OUTPUT_DISPLAYPORT) {
This page took 0.042152 seconds and 5 git commands to generate.