]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_ddi.c
Merge tag 'v4.4-rc2' into drm-intel-next-queued
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_ddi.c
index a6752a61d99f268217e7054a8531036d109be7ee..76ce7c2960b6fb790984ff1f168be21c9a7132c7 100644 (file)
@@ -133,12 +133,12 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
        { 0x00002016, 0x000000A0, 0x0 },
        { 0x00005012, 0x0000009B, 0x0 },
        { 0x00007011, 0x00000088, 0x0 },
-       { 0x00009010, 0x000000C7, 0x0 },
+       { 0x80009010, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
        { 0x00002016, 0x0000009B, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
-       { 0x00007011, 0x000000C7, 0x0 },
+       { 0x80007011, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
        { 0x00002016, 0x000000DF, 0x0 },
-       { 0x00005012, 0x000000C7, 0x0 },
+       { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 };
 
 /* Skylake U */
@@ -146,12 +146,12 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
        { 0x0000201B, 0x000000A2, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
        { 0x00007011, 0x00000087, 0x0 },
-       { 0x80009010, 0x000000C7, 0x1 },        /* Uses I_boost level 0x1 */
+       { 0x80009010, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
        { 0x0000201B, 0x0000009D, 0x0 },
-       { 0x00005012, 0x000000C7, 0x0 },
-       { 0x00007011, 0x000000C7, 0x0 },
+       { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
+       { 0x80007011, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
        { 0x00002016, 0x00000088, 0x0 },
-       { 0x00005012, 0x000000C7, 0x0 },
+       { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 };
 
 /* Skylake Y */
@@ -159,12 +159,12 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
        { 0x00000018, 0x000000A2, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
        { 0x00007011, 0x00000087, 0x0 },
-       { 0x80009010, 0x000000C7, 0x3 },        /* Uses I_boost level 0x3 */
+       { 0x80009010, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
        { 0x00000018, 0x0000009D, 0x0 },
-       { 0x00005012, 0x000000C7, 0x0 },
-       { 0x00007011, 0x000000C7, 0x0 },
+       { 0x80005012, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
+       { 0x80007011, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
        { 0x00000018, 0x00000088, 0x0 },
-       { 0x00005012, 0x000000C7, 0x0 },
+       { 0x80005012, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
 };
 
 /*
@@ -345,7 +345,7 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
 static bool
 intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port)
 {
-       return intel_dig_port->hdmi.hdmi_reg;
+       return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg);
 }
 
 static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev,
@@ -448,7 +448,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
                bxt_ddi_vswing_sequence(dev, hdmi_level, port,
                                        INTEL_OUTPUT_HDMI);
                return;
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                ddi_translations_fdi = NULL;
                ddi_translations_dp =
                                skl_get_buf_trans_dp(dev, &n_dp_entries);
@@ -576,7 +576,7 @@ void intel_prepare_ddi(struct drm_device *dev)
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
                                    enum port port)
 {
-       uint32_t reg = DDI_BUF_CTL(port);
+       i915_reg_t reg = DDI_BUF_CTL(port);
        int i;
 
        for (i = 0; i < 16; i++) {
@@ -931,7 +931,8 @@ static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
        /* Otherwise a < c && b >= d, do nothing */
 }
 
-static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg)
+static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
+                                  i915_reg_t reg)
 {
        int refclk = LC_FREQ;
        int n, p, r;
@@ -967,7 +968,7 @@ static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg)
 static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
                               uint32_t dpll)
 {
-       uint32_t cfgcr1_reg, cfgcr2_reg;
+       i915_reg_t cfgcr1_reg, cfgcr2_reg;
        uint32_t cfgcr1_val, cfgcr2_val;
        uint32_t p0, p1, p2, dco_freq;
 
@@ -1112,10 +1113,10 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder,
                link_clock = 270000;
                break;
        case PORT_CLK_SEL_WRPLL1:
-               link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1);
+               link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(0));
                break;
        case PORT_CLK_SEL_WRPLL2:
-               link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2);
+               link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1));
                break;
        case PORT_CLK_SEL_SPLL:
                pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK;
@@ -1184,7 +1185,7 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
 
        if (INTEL_INFO(dev)->gen <= 8)
                hsw_ddi_clock_get(encoder, pipe_config);
-       else if (IS_SKYLAKE(dev))
+       else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_ddi_clock_get(encoder, pipe_config);
        else if (IS_BROXTON(dev))
                bxt_ddi_clock_get(encoder, pipe_config);
@@ -1780,7 +1781,7 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
        struct intel_encoder *intel_encoder =
                intel_ddi_get_crtc_new_encoder(crtc_state);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                return skl_ddi_pll_select(intel_crtc, crtc_state,
                                          intel_encoder);
        else if (IS_BROXTON(dev))
@@ -1942,7 +1943,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
                                       enum transcoder cpu_transcoder)
 {
-       uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
+       i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
        uint32_t val = I915_READ(reg);
 
        val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
@@ -2097,21 +2098,21 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level,
                        iboost = dp_iboost;
                } else {
                        ddi_translations = skl_get_buf_trans_dp(dev, &n_entries);
-                       iboost = ddi_translations[port].i_boost;
+                       iboost = ddi_translations[level].i_boost;
                }
        } else if (type == INTEL_OUTPUT_EDP) {
                if (dp_iboost) {
                        iboost = dp_iboost;
                } else {
                        ddi_translations = skl_get_buf_trans_edp(dev, &n_entries);
-                       iboost = ddi_translations[port].i_boost;
+                       iboost = ddi_translations[level].i_boost;
                }
        } else if (type == INTEL_OUTPUT_HDMI) {
                if (hdmi_iboost) {
                        iboost = hdmi_iboost;
                } else {
                        ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries);
-                       iboost = ddi_translations[port].i_boost;
+                       iboost = ddi_translations[level].i_boost;
                }
        } else {
                return;
@@ -2263,7 +2264,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
 
        level = translate_signal_level(signal_levels);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_ddi_set_iboost(dev, level, port, encoder->type);
        else if (IS_BROXTON(dev))
                bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
@@ -2271,30 +2272,21 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
        return DDI_BUF_TRANS_SELECT(level);
 }
 
-static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+void intel_ddi_clk_select(struct intel_encoder *encoder,
+                         const struct intel_crtc_state *pipe_config)
 {
-       struct drm_encoder *encoder = &intel_encoder->base;
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
-       enum port port = intel_ddi_get_encoder_port(intel_encoder);
-       int type = intel_encoder->type;
-       int hdmi_level;
-
-       if (type == INTEL_OUTPUT_EDP) {
-               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               intel_edp_panel_on(intel_dp);
-       }
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       enum port port = intel_ddi_get_encoder_port(encoder);
 
-       if (IS_SKYLAKE(dev)) {
-               uint32_t dpll = crtc->config->ddi_pll_sel;
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+               uint32_t dpll = pipe_config->ddi_pll_sel;
                uint32_t val;
 
                /*
                 * DPLL0 is used for eDP and is the only "private" DPLL (as
                 * opposed to shared) on SKL
                 */
-               if (type == INTEL_OUTPUT_EDP) {
+               if (encoder->type == INTEL_OUTPUT_EDP) {
                        WARN_ON(dpll != SKL_DPLL0);
 
                        val = I915_READ(DPLL_CTRL1);
@@ -2302,7 +2294,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
                        val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
                                 DPLL_CTRL1_SSC(dpll) |
                                 DPLL_CTRL1_LINK_RATE_MASK(dpll));
-                       val |= crtc->config->dpll_hw_state.ctrl1 << (dpll * 6);
+                       val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6);
 
                        I915_WRITE(DPLL_CTRL1, val);
                        POSTING_READ(DPLL_CTRL1);
@@ -2318,10 +2310,28 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
                I915_WRITE(DPLL_CTRL2, val);
 
-       } else if (INTEL_INFO(dev)->gen < 9) {
-               WARN_ON(crtc->config->ddi_pll_sel == PORT_CLK_SEL_NONE);
-               I915_WRITE(PORT_CLK_SEL(port), crtc->config->ddi_pll_sel);
+       } else if (INTEL_INFO(dev_priv)->gen < 9) {
+               WARN_ON(pipe_config->ddi_pll_sel == PORT_CLK_SEL_NONE);
+               I915_WRITE(PORT_CLK_SEL(port), pipe_config->ddi_pll_sel);
        }
+}
+
+static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+{
+       struct drm_encoder *encoder = &intel_encoder->base;
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
+       enum port port = intel_ddi_get_encoder_port(intel_encoder);
+       int type = intel_encoder->type;
+       int hdmi_level;
+
+       if (type == INTEL_OUTPUT_EDP) {
+               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+               intel_edp_panel_on(intel_dp);
+       }
+
+       intel_ddi_clk_select(intel_encoder, crtc->config);
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -2381,7 +2391,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
                intel_edp_panel_off(intel_dp);
        }
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
                                        DPLL_CTRL2_DDI_CLK_OFF(port)));
        else if (INTEL_INFO(dev)->gen < 9)
@@ -2553,7 +2563,7 @@ static const char * const skl_ddi_pll_names[] = {
 };
 
 struct skl_dpll_regs {
-       u32 ctl, cfgcr1, cfgcr2;
+       i915_reg_t ctl, cfgcr1, cfgcr2;
 };
 
 /* this array is indexed by the *shared* pll id */
@@ -2566,13 +2576,13 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = {
        },
        {
                /* DPLL 2 */
-               .ctl = WRPLL_CTL1,
+               .ctl = WRPLL_CTL(0),
                .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
                .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
        },
        {
                /* DPLL 3 */
-               .ctl = WRPLL_CTL2,
+               .ctl = WRPLL_CTL(1),
                .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
                .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
        },
@@ -2992,22 +3002,22 @@ void intel_ddi_pll_init(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t val = I915_READ(LCPLL_CTL);
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skl_shared_dplls_init(dev_priv);
        else if (IS_BROXTON(dev))
                bxt_shared_dplls_init(dev_priv);
        else
                hsw_shared_dplls_init(dev_priv);
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                int cdclk_freq;
 
                cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
                dev_priv->skl_boot_cdclk = cdclk_freq;
+               if (skl_sanitize_cdclk(dev_priv))
+                       DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
                if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
                        DRM_ERROR("LCPLL1 is disabled\n");
-               else
-                       intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
        } else if (IS_BROXTON(dev)) {
                broxton_init_cdclk(dev);
                broxton_ddi_phy_init(dev);
@@ -3026,11 +3036,11 @@ void intel_ddi_pll_init(struct drm_device *dev)
        }
 }
 
-void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
+void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
 {
-       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
-       struct intel_dp *intel_dp = &intel_dig_port->dp;
-       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv =
+               to_i915(intel_dig_port->base.base.dev);
        enum port port = intel_dig_port->port;
        uint32_t val;
        bool wait = false;
@@ -3289,6 +3299,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
                                          (DDI_BUF_PORT_REVERSAL |
                                           DDI_A_4_LANES);
 
+       /*
+        * Bspec says that DDI_A_4_LANES is the only supported configuration
+        * for Broxton.  Yet some BIOS fail to set this bit on port A if eDP
+        * wasn't lit up at boot.  Force this bit on in our internal
+        * configuration so that we use the proper lane count for our
+        * calculations.
+        */
+       if (IS_BROXTON(dev) && port == PORT_A) {
+               if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) {
+                       DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n");
+                       intel_dig_port->saved_port_bits |= DDI_A_4_LANES;
+               }
+       }
+
        intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
        intel_encoder->cloneable = 0;
@@ -3302,8 +3326,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
                 * On BXT A0/A1, sw needs to activate DDIA HPD logic and
                 * interrupts to check the external panel connection.
                 */
-               if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)
-                                        && port == PORT_B)
+               if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B)
                        dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port;
                else
                        dev_priv->hotplug.irq_port[port] = intel_dig_port;