]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/i915/intel_ddi.c
drm/i915: Check has_infoframes when enabling infoframes
[linux.git] / drivers / gpu / drm / i915 / intel_ddi.c
index 80e96f1f49d2d09deb59ec08e6ebe78ac07b8cf3..07ced1044001ba8e80a71e733584b842072bdec5 100644 (file)
@@ -1103,6 +1103,62 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
        return dco_freq / (p0 * p1 * p2 * 5);
 }
 
+static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
+                              uint32_t pll_id)
+{
+       uint32_t cfgcr0, cfgcr1;
+       uint32_t p0, p1, p2, dco_freq, ref_clock;
+
+       cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
+       cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll_id));
+
+       p0 = cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
+       p2 = cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
+
+       if (cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
+               p1 = (cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
+                       DPLL_CFGCR1_QDIV_RATIO_SHIFT;
+       else
+               p1 = 1;
+
+
+       switch (p0) {
+       case DPLL_CFGCR1_PDIV_2:
+               p0 = 2;
+               break;
+       case DPLL_CFGCR1_PDIV_3:
+               p0 = 3;
+               break;
+       case DPLL_CFGCR1_PDIV_5:
+               p0 = 5;
+               break;
+       case DPLL_CFGCR1_PDIV_7:
+               p0 = 7;
+               break;
+       }
+
+       switch (p2) {
+       case DPLL_CFGCR1_KDIV_1:
+               p2 = 1;
+               break;
+       case DPLL_CFGCR1_KDIV_2:
+               p2 = 2;
+               break;
+       case DPLL_CFGCR1_KDIV_4:
+               p2 = 4;
+               break;
+       }
+
+       ref_clock = dev_priv->cdclk.hw.ref;
+
+       dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock;
+
+       dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
+                     DPLL_CFGCR0_DCO_FRAC_SHIFT) * ref_clock) / 0x8000;
+
+       return dco_freq / (p0 * p1 * p2 * 5);
+}
+
 static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
 {
        int dotclock;
@@ -1118,12 +1174,68 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
        else
                dotclock = pipe_config->port_clock;
 
+       if (pipe_config->ycbcr420)
+               dotclock *= 2;
+
        if (pipe_config->pixel_multiplier)
                dotclock /= pipe_config->pixel_multiplier;
 
        pipe_config->base.adjusted_mode.crtc_clock = dotclock;
 }
 
+static void cnl_ddi_clock_get(struct intel_encoder *encoder,
+                             struct intel_crtc_state *pipe_config)
+{
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       int link_clock = 0;
+       uint32_t cfgcr0, pll_id;
+
+       pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
+
+       cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
+
+       if (cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
+               link_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
+       } else {
+               link_clock = cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
+
+               switch (link_clock) {
+               case DPLL_CFGCR0_LINK_RATE_810:
+                       link_clock = 81000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_1080:
+                       link_clock = 108000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_1350:
+                       link_clock = 135000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_1620:
+                       link_clock = 162000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_2160:
+                       link_clock = 216000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_2700:
+                       link_clock = 270000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_3240:
+                       link_clock = 324000;
+                       break;
+               case DPLL_CFGCR0_LINK_RATE_4050:
+                       link_clock = 405000;
+                       break;
+               default:
+                       WARN(1, "Unsupported link rate\n");
+                       break;
+               }
+               link_clock *= 2;
+       }
+
+       pipe_config->port_clock = link_clock;
+
+       ddi_dotclock_get(pipe_config);
+}
+
 static void skl_ddi_clock_get(struct intel_encoder *encoder,
                                struct intel_crtc_state *pipe_config)
 {
@@ -1267,6 +1379,8 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
                skl_ddi_clock_get(encoder, pipe_config);
        else if (IS_GEN9_LP(dev_priv))
                bxt_ddi_clock_get(encoder, pipe_config);
+       else if (IS_CANNONLAKE(dev_priv))
+               cnl_ddi_clock_get(encoder, pipe_config);
 }
 
 void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state)
@@ -1762,7 +1876,7 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv,
        if (dev_priv->vbt.edp.low_vswing) {
                if (voltage == VOLTAGE_INFO_0_85V) {
                        *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_85V);
-                       return cnl_ddi_translations_dp_0_85V;
+                       return cnl_ddi_translations_edp_0_85V;
                } else if (voltage == VOLTAGE_INFO_0_95V) {
                        *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_95V);
                        return cnl_ddi_translations_edp_0_95V;
@@ -1868,9 +1982,12 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level)
        if ((intel_dp) && (type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP)) {
                width = intel_dp->lane_count;
                rate = intel_dp->link_rate;
-       } else {
+       } else if (type == INTEL_OUTPUT_HDMI) {
                width = 4;
                /* Rate is always < than 6GHz for HDMI */
+       } else {
+               MISSING_CASE(type);
+               return;
        }
 
        /*
@@ -1896,8 +2013,8 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level)
                val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln));
                val &= ~LOADGEN_SELECT;
 
-               if (((rate < 600000) && (width == 4) && (ln >= 1))  ||
-                   ((rate < 600000) && (width < 4) && ((ln == 1) || (ln == 2)))) {
+               if ((rate <= 600000 && width == 4 && ln >= 1)  ||
+                   (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
                        val |= LOADGEN_SELECT;
                }
                I915_WRITE(CNL_PORT_TX_DW4_LN(port, ln), val);
@@ -2033,7 +2150,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 }
 
 static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
-                                     bool has_hdmi_sink,
+                                     bool has_infoframe,
                                      const struct intel_crtc_state *crtc_state,
                                      const struct drm_connector_state *conn_state,
                                      struct intel_shared_dpll *pll)
@@ -2060,7 +2177,7 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
                cnl_ddi_vswing_sequence(encoder, level);
 
        intel_hdmi->set_infoframes(drm_encoder,
-                                  has_hdmi_sink,
+                                  has_infoframe,
                                   crtc_state, conn_state);
 }
 
@@ -2080,7 +2197,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
        }
        if (type == INTEL_OUTPUT_HDMI) {
                intel_ddi_pre_enable_hdmi(encoder,
-                                         pipe_config->has_hdmi_sink,
+                                         pipe_config->has_infoframe,
                                          pipe_config, conn_state,
                                          pipe_config->shared_dpll);
        }