From: Satheeshakrishna M <satheeshakrishn...@intel.com>

v2: Fixup compilation due to the removal of the intel_ddi_dpll_id enum.
And add a fixme about the abuse of pipe_config here.

v3: Rebase on top of the hsw_ddi_clock_get() rename (Damien)

v4: Modified as per review comments from Paulo

Signed-off-by: Satheeshakrishna M <satheeshakrishn...@intel.com> (v1)
Signed-off-by: Damien Lespiau <damien.lesp...@intel.com> (v3)
Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch> (v2)
Signed-off-by: Damien Lespiau <damien.lesp...@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |   5 ++
 drivers/gpu/drm/i915/intel_ddi.c | 115 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index eb35d05..3ef0312 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6457,6 +6457,7 @@ enum punit_power_well {
 #define  DPLL_CTRL1_HDMI_MODE(id)              (1<<((id)*6+5))
 #define  DPLL_CTRL1_SSC(id)                    (1<<((id)*6+4))
 #define  DPLL_CRTL1_LINK_RATE_MASK(id)         (7<<((id)*6+1))
+#define  DPLL_CRTL1_LINK_RATE_SHIFT(id)                ((id)*6+1)
 #define  DPLL_CRTL1_LINK_RATE(linkrate, id)    ((linkrate)<<((id)*6+1))
 #define  DPLL_CTRL1_OVERRIDE(id)               (1<<((id)*6))
 #define  DPLL_CRTL1_LINK_RATE_2700             0
@@ -6470,6 +6471,7 @@ enum punit_power_well {
 #define DPLL_CTRL2                             0x6C05C
 #define  DPLL_CTRL2_DDI_CLK_OFF(port)          (1<<(port+15))
 #define  DPLL_CTRL2_DDI_CLK_SEL_MASK(port)     (3<<((port)*3+1))
+#define  DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port)    ((port)*3+1)
 #define  DPLL_CTRL2_DDI_CLK_SEL(clk, port)     (clk<<((port)*3+1))
 #define  DPLL_CTRL2_DDI_SEL_OVERRIDE(port)     (1<<((port)*3))
 
@@ -6506,6 +6508,9 @@ enum punit_power_well {
 #define  DPLL_CFGCR2_PDIV_7 (4<<2)
 #define  DPLL_CFGCR2_CENTRAL_FREQ_MASK (3)
 
+#define GET_CFG_CR1_REG(id) (DPLL1_CFGCR1 + (id - SKL_DPLL1) * 8)
+#define GET_CFG_CR2_REG(id) (DPLL1_CFGCR2 + (id - SKL_DPLL1) * 8)
+
 /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this 
register,
  * since on HSW we can't write to it using I915_WRITE. */
 #define D_COMP_HSW                     (MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 72691ec..f5dd4d3 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -687,6 +687,115 @@ static int intel_ddi_calc_wrpll_link(struct 
drm_i915_private *dev_priv,
        return (refclk * n * 100) / (p * r);
 }
 
+static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
+                              uint32_t dpll)
+{
+       uint32_t cfgcr1_reg, cfgcr2_reg;
+       uint32_t cfgcr1_val, cfgcr2_val;
+       uint32_t p0, p1, p2, dco_freq;
+
+       cfgcr1_reg = GET_CFG_CR1_REG(dpll);
+       cfgcr2_reg = GET_CFG_CR2_REG(dpll);
+
+       cfgcr1_val = I915_READ(cfgcr1_reg);
+       cfgcr2_val = I915_READ(cfgcr2_reg);
+
+       p0 = cfgcr2_val & DPLL_CFGCR2_PDIV_MASK;
+       p2 = cfgcr2_val & DPLL_CFGCR2_KDIV_MASK;
+
+       if (cfgcr2_val &  DPLL_CFGCR2_QDIV_MODE(1))
+               p1 = (cfgcr2_val & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8;
+       else
+               p1 = 1;
+
+
+       switch (p0) {
+       case DPLL_CFGCR2_PDIV_1:
+               p0 = 1;
+               break;
+       case DPLL_CFGCR2_PDIV_2:
+               p0 = 2;
+               break;
+       case DPLL_CFGCR2_PDIV_3:
+               p0 = 3;
+               break;
+       case DPLL_CFGCR2_PDIV_7:
+               p0 = 7;
+               break;
+       }
+
+       switch (p2) {
+       case DPLL_CFGCR2_KDIV_5:
+               p2 = 5;
+               break;
+       case DPLL_CFGCR2_KDIV_2:
+               p2 = 2;
+               break;
+       case DPLL_CFGCR2_KDIV_3:
+               p2 = 3;
+               break;
+       case DPLL_CFGCR2_KDIV_1:
+               p2 = 1;
+               break;
+       }
+
+       dco_freq = (cfgcr1_val & DPLL_CFGCR1_DCO_INTEGER_MASK) * 24 * 1000;
+
+       dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 *
+               1000) / 0x8000;
+
+       return dco_freq / (p0 * p1 * p2 * 5);
+}
+
+
+static void skl_ddi_clock_get(struct intel_encoder *encoder,
+                               struct intel_crtc_config *pipe_config)
+{
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       enum port port = intel_ddi_get_encoder_port(encoder);
+       int link_clock = 0;
+       uint32_t dpll_ctl1, dpll;
+
+       /* FIXME: This should be tracked in the pipe config. */
+       dpll = I915_READ(DPLL_CTRL2);
+       dpll &= DPLL_CTRL2_DDI_CLK_SEL_MASK(port);
+       dpll >>= DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
+
+       dpll_ctl1 = I915_READ(DPLL_CTRL1);
+
+       if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(dpll)) {
+               link_clock = skl_calc_wrpll_link(dev_priv, dpll);
+       } else {
+               link_clock = dpll_ctl1 & DPLL_CRTL1_LINK_RATE_MASK(dpll);
+               link_clock >>= DPLL_CRTL1_LINK_RATE_SHIFT(dpll);
+
+               switch (link_clock) {
+               case DPLL_CRTL1_LINK_RATE_810:
+                       link_clock = 81000;
+                       break;
+               case DPLL_CRTL1_LINK_RATE_1350:
+                       link_clock = 135000;
+                       break;
+               case DPLL_CRTL1_LINK_RATE_2700:
+                       link_clock = 270000;
+                       break;
+               default:
+                       WARN(1, "Unsupported link rate\n");
+                       break;
+               }
+               link_clock *= 2;
+       }
+
+       pipe_config->port_clock = link_clock;
+
+       if (pipe_config->has_dp_encoder)
+               pipe_config->adjusted_mode.crtc_clock =
+                       intel_dotclock_calculate(pipe_config->port_clock,
+                                                &pipe_config->dp_m_n);
+       else
+               pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock;
+}
+
 static void hsw_ddi_clock_get(struct intel_encoder *encoder,
                              struct intel_crtc_config *pipe_config)
 {
@@ -1550,6 +1659,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
        u32 temp, flags = 0;
+       struct drm_device *dev = dev_priv->dev;
 
        temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
        if (temp & TRANS_DDI_PHSYNC)
@@ -1621,7 +1731,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
                dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
        }
 
-       hsw_ddi_clock_get(encoder, pipe_config);
+       if (INTEL_INFO(dev)->gen <= 8)
+               hsw_ddi_clock_get(encoder, pipe_config);
+       else
+               skl_ddi_clock_get(encoder, pipe_config);
 }
 
 static void intel_ddi_destroy(struct drm_encoder *encoder)
-- 
1.8.3.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to