drm/i915: Clean up CHV lane soft reset programming
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 9 Jul 2015 17:14:11 +0000 (20:14 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 1 Sep 2015 09:43:37 +0000 (11:43 +0200)
Currently we release the lane soft reset before lane stagger settings
have been programmed. I believe that means we don't actually do lane
staggering. So move the soft reset deassert to happen after lane
staggering has been programmed.

The one confusing thing in this is that when we remove the power down
override from the lanes, they power up with defaul register values,
which do not have the soft reset overrides enabled. And according to
some docs by default the data lane resets are tied to cmnreset. So that
would mean that lanes would come out of reset without staggering as
soon as the power down overrides are removed. But since we can't access
either the lane stagger register nor the soft reset override registers
until the lanes are powered on, we can't really do anything about it.
So let's just set the soft reset overrides as soon as the lane is
powered on and hope for the best.

v2: Fix typos in commit message (Daniel)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c

index b794439582587e4acae489f9a3051b5b2d935da9..3a9c43d2c2c446f42220a11671df31b4f3811625 100644 (file)
@@ -2426,42 +2426,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
        intel_dp_link_down(intel_dp);
 }
 
-static void chv_post_disable_dp(struct intel_encoder *encoder)
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+                                    bool reset)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-       struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = encoder->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc =
-               to_intel_crtc(encoder->base.crtc);
-       enum dpio_channel ch = vlv_dport_to_channel(dport);
-       enum pipe pipe = intel_crtc->pipe;
-       u32 val;
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       enum pipe pipe = crtc->pipe;
+       uint32_t val;
 
-       intel_dp_link_down(intel_dp);
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+       if (reset)
+               val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+       else
+               val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
 
-       mutex_lock(&dev_priv->sb_lock);
+       if (crtc->config->lane_count > 2) {
+               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+               if (reset)
+                       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+               else
+                       val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+       }
 
-       /* Propagate soft reset to data lane reset */
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
        val |= CHV_PCS_REQ_SOFTRESET_EN;
+       if (reset)
+               val &= ~DPIO_PCS_CLK_SOFT_RESET;
+       else
+               val |= DPIO_PCS_CLK_SOFT_RESET;
        vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
 
-       if (intel_crtc->config->lane_count > 2) {
+       if (crtc->config->lane_count > 2) {
                val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
                val |= CHV_PCS_REQ_SOFTRESET_EN;
+               if (reset)
+                       val &= ~DPIO_PCS_CLK_SOFT_RESET;
+               else
+                       val |= DPIO_PCS_CLK_SOFT_RESET;
                vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
        }
+}
 
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+static void chv_post_disable_dp(struct intel_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (intel_crtc->config->lane_count > 2) {
-               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-               val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-       }
+       intel_dp_link_down(intel_dp);
+
+       mutex_lock(&dev_priv->sb_lock);
+
+       /* Assert data lane reset */
+       chv_data_lane_soft_reset(encoder, true);
 
        mutex_unlock(&dev_priv->sb_lock);
 }
@@ -2839,27 +2859,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
                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;
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-       if (intel_crtc->config->lane_count > 2) {
-               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-               val |= CHV_PCS_REQ_SOFTRESET_EN;
-               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-       }
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-       val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-       if (intel_crtc->config->lane_count > 2) {
-               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-               val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-       }
-
        /* Program Tx lane latency optimal setting*/
        for (i = 0; i < intel_crtc->config->lane_count; i++) {
                /* Set the upar bit */
@@ -2909,6 +2908,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
                               DPIO_TX2_STAGGER_MULT(5));
        }
 
+       /* Deassert data lane reset */
+       chv_data_lane_soft_reset(encoder, false);
+
        mutex_unlock(&dev_priv->sb_lock);
 
        intel_enable_dp(encoder);
@@ -2947,6 +2949,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 
        mutex_lock(&dev_priv->sb_lock);
 
+       /* Assert data lane reset */
+       chv_data_lane_soft_reset(encoder, true);
+
        /* program left/right clock distribution */
        if (pipe != PIPE_B) {
                val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
index 7c56053d42406e94a2488fd6a4726939aada87a1..4da737ccf69a19ee96a6c4e50ffd06444d00a87a 100644 (file)
@@ -1615,6 +1615,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
        mutex_unlock(&dev_priv->sb_lock);
 }
 
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+                                    bool reset)
+{
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       enum pipe pipe = crtc->pipe;
+       uint32_t val;
+
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+       if (reset)
+               val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+       else
+               val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+
+       if (crtc->config->lane_count > 2) {
+               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+               if (reset)
+                       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+               else
+                       val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+       }
+
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
+       val |= CHV_PCS_REQ_SOFTRESET_EN;
+       if (reset)
+               val &= ~DPIO_PCS_CLK_SOFT_RESET;
+       else
+               val |= DPIO_PCS_CLK_SOFT_RESET;
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
+
+       if (crtc->config->lane_count > 2) {
+               val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+               val |= CHV_PCS_REQ_SOFTRESET_EN;
+               if (reset)
+                       val &= ~DPIO_PCS_CLK_SOFT_RESET;
+               else
+                       val |= DPIO_PCS_CLK_SOFT_RESET;
+               vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+       }
+}
+
 static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 {
        struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1640,6 +1684,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
        mutex_lock(&dev_priv->sb_lock);
 
+       /* Assert data lane reset */
+       chv_data_lane_soft_reset(encoder, true);
+
        /* program left/right clock distribution */
        if (pipe != PIPE_B) {
                val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
@@ -1742,33 +1789,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
 
 static void chv_hdmi_post_disable(struct intel_encoder *encoder)
 {
-       struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc =
-               to_intel_crtc(encoder->base.crtc);
-       enum dpio_channel ch = vlv_dport_to_channel(dport);
-       enum pipe pipe = intel_crtc->pipe;
-       u32 val;
 
        mutex_lock(&dev_priv->sb_lock);
 
-       /* Propagate soft reset to data lane reset */
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-       val |= CHV_PCS_REQ_SOFTRESET_EN;
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-       val |= CHV_PCS_REQ_SOFTRESET_EN;
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+       /* Assert data lane reset */
+       chv_data_lane_soft_reset(encoder, true);
 
        mutex_unlock(&dev_priv->sb_lock);
 }
@@ -1799,23 +1826,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
        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;
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-       val |= CHV_PCS_REQ_SOFTRESET_EN;
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-       val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-       val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-
        /* Program Tx latency optimal setting */
        for (i = 0; i < 4; i++) {
                /* Set the upar bit */
@@ -1858,6 +1868,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
                       DPIO_TX1_STAGGER_MULT(7) |
                       DPIO_TX2_STAGGER_MULT(5));
 
+       /* Deassert data lane reset */
+       chv_data_lane_soft_reset(encoder, false);
+
        /* 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);