Unfortunately this requires a bunch of exports for pch handling
functions, but there's been various plans floating around to extract
them all into an intel_pch.c helper library anyway.

In any case haswell_crtc_enable is now pch encoder free.

Signed-off-by: Daniel Vetter <[email protected]>
---
 drivers/gpu/drm/i915/intel_crt.c     | 147 +++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c | 160 ++---------------------------------
 drivers/gpu/drm/i915/intel_drv.h     |  14 +++
 3 files changed, 168 insertions(+), 153 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index ec806e432545..9d7135b878c0 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -354,6 +354,150 @@ static void intel_enable_crt(struct intel_encoder 
*encoder)
        intel_crt_set_dpms(encoder, crt->connector->base.dpms);
 }
 
+/* Program iCLKIP clock to the desired frequency */
+static void lpt_program_iclkip(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
+       u32 divsel, phaseinc, auxdiv, phasedir = 0;
+       u32 temp;
+
+       mutex_lock(&dev_priv->dpio_lock);
+
+       /* It is necessary to ungate the pixclk gate prior to programming
+        * the divisors, and gate it back when it is done.
+        */
+       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
+
+       /* Disable SSCCTL */
+       intel_sbi_write(dev_priv, SBI_SSCCTL6,
+                       intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
+                               SBI_SSCCTL_DISABLE,
+                       SBI_ICLK);
+
+       /* 20MHz is a corner case which is out of range for the 7-bit divisor */
+       if (clock == 20000) {
+               auxdiv = 1;
+               divsel = 0x41;
+               phaseinc = 0x20;
+       } else {
+               /* The iCLK virtual clock root frequency is in MHz,
+                * but the adjusted_mode->crtc_clock in in KHz. To get the
+                * divisors, it is necessary to divide one by another, so we
+                * convert the virtual clock precision to KHz here for higher
+                * precision.
+                */
+               u32 iclk_virtual_root_freq = 172800 * 1000;
+               u32 iclk_pi_range = 64;
+               u32 desired_divisor, msb_divisor_value, pi_value;
+
+               desired_divisor = (iclk_virtual_root_freq / clock);
+               msb_divisor_value = desired_divisor / iclk_pi_range;
+               pi_value = desired_divisor % iclk_pi_range;
+
+               auxdiv = 0;
+               divsel = msb_divisor_value - 2;
+               phaseinc = pi_value;
+       }
+
+       /* This should not happen with any sane values */
+       WARN_ON(SBI_SSCDIVINTPHASE_DIVSEL(divsel) &
+               ~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
+       WARN_ON(SBI_SSCDIVINTPHASE_DIR(phasedir) &
+               ~SBI_SSCDIVINTPHASE_INCVAL_MASK);
+
+       DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: 
auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
+                       clock,
+                       auxdiv,
+                       divsel,
+                       phasedir,
+                       phaseinc);
+
+       /* Program SSCDIVINTPHASE6 */
+       temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
+       temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
+       temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel);
+       temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
+       temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc);
+       temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
+       temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
+       intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
+
+       /* Program SSCAUXDIV */
+       temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
+       temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
+       temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
+       intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
+
+       /* Enable modulator and associated divider */
+       temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+       temp &= ~SBI_SSCCTL_DISABLE;
+       intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
+
+       /* Wait for initialization time */
+       udelay(24);
+
+       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
+
+       mutex_unlock(&dev_priv->dpio_lock);
+}
+
+static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
+                                     enum transcoder cpu_transcoder)
+{
+       u32 val, pipeconf_val;
+
+       /* PCH only available on ILK+ */
+       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
+
+       /* FDI must be feeding us bits for PCH ports */
+       assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
+       assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
+
+       /* Workaround: set timing override bit. */
+       val = I915_READ(_TRANSA_CHICKEN2);
+       val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+       I915_WRITE(_TRANSA_CHICKEN2, val);
+
+       val = TRANS_ENABLE;
+       pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
+
+       if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
+           PIPECONF_INTERLACED_ILK)
+               val |= TRANS_INTERLACED;
+       else
+               val |= TRANS_PROGRESSIVE;
+
+       I915_WRITE(LPT_TRANSCONF, val);
+       if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100))
+               DRM_ERROR("Failed to enable PCH transcoder\n");
+}
+
+static void lpt_pch_enable(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+
+       assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
+
+       lpt_program_iclkip(crtc);
+
+       /* Set transcoder timing. */
+       ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
+
+       lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
+}
+
+static void hsw_crt_enable(struct intel_encoder *encoder)
+{
+       lpt_pch_enable(encoder->base.crtc);
+
+       intel_enable_crt(encoder);
+}
+
 /* Special dpms function to support cloning between dvo/sdvo/crt. */
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
@@ -1006,16 +1150,17 @@ void intel_crt_init(struct drm_device *dev)
 
        crt->base.compute_config = intel_crt_compute_config;
        crt->base.disable = intel_disable_crt;
-       crt->base.enable = intel_enable_crt;
        if (I915_HAS_HOTPLUG(dev))
                crt->base.hpd_pin = HPD_CRT;
        if (HAS_DDI(dev)) {
                crt->base.get_config = hsw_crt_get_config;
                crt->base.get_hw_state = hsw_crt_get_hw_state;
                crt->base.pre_enable = hsw_crt_pre_enable;
+               crt->base.enable = hsw_crt_enable;
        } else {
                crt->base.get_config = intel_crt_get_config;
                crt->base.get_hw_state = intel_crt_get_hw_state;
+               crt->base.enable = intel_enable_crt;
        }
        intel_connector->get_hw_state = intel_connector_get_hw_state;
        intel_connector->unregister = intel_connector_unregister;
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 43a40594841f..26b2eceb0d63 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -992,8 +992,8 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
             pll->name, state_string(state), state_string(cur_state));
 }
 
-static void assert_fdi_tx(struct drm_i915_private *dev_priv,
-                         enum pipe pipe, bool state)
+void assert_fdi_tx(struct drm_i915_private *dev_priv,
+                  enum pipe pipe, bool state)
 {
        int reg;
        u32 val;
@@ -1015,11 +1015,9 @@ static void assert_fdi_tx(struct drm_i915_private 
*dev_priv,
             "FDI TX state assertion failure (expected %s, current %s)\n",
             state_string(state), state_string(cur_state));
 }
-#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
-#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
 
-static void assert_fdi_rx(struct drm_i915_private *dev_priv,
-                         enum pipe pipe, bool state)
+void assert_fdi_rx(struct drm_i915_private *dev_priv,
+                  enum pipe pipe, bool state)
 {
        int reg;
        u32 val;
@@ -1032,8 +1030,6 @@ static void assert_fdi_rx(struct drm_i915_private 
*dev_priv,
             "FDI RX state assertion failure (expected %s, current %s)\n",
             state_string(state), state_string(cur_state));
 }
-#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
-#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
 
 static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
                                      enum pipe pipe)
@@ -1236,8 +1232,8 @@ static void ibx_assert_pch_refclk_enabled(struct 
drm_i915_private *dev_priv)
        WARN(!enabled, "PCH refclk assertion failure, should be active but is 
disabled\n");
 }
 
-static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
-                                          enum pipe pipe)
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+                                   enum pipe pipe)
 {
        int reg;
        u32 val;
@@ -1692,37 +1688,6 @@ static void ironlake_enable_pch_transcoder(struct 
drm_i915_private *dev_priv,
                DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
 }
 
-static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
-                                     enum transcoder cpu_transcoder)
-{
-       u32 val, pipeconf_val;
-
-       /* PCH only available on ILK+ */
-       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
-
-       /* FDI must be feeding us bits for PCH ports */
-       assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
-       assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
-
-       /* Workaround: set timing override bit. */
-       val = I915_READ(_TRANSA_CHICKEN2);
-       val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
-       I915_WRITE(_TRANSA_CHICKEN2, val);
-
-       val = TRANS_ENABLE;
-       pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
-
-       if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
-           PIPECONF_INTERLACED_ILK)
-               val |= TRANS_INTERLACED;
-       else
-               val |= TRANS_PROGRESSIVE;
-
-       I915_WRITE(LPT_TRANSCONF, val);
-       if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100))
-               DRM_ERROR("Failed to enable PCH transcoder\n");
-}
-
 static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
                                            enum pipe pipe)
 {
@@ -3120,97 +3085,8 @@ static void intel_crtc_wait_for_pending_flips(struct 
drm_crtc *crtc)
        mutex_unlock(&dev->struct_mutex);
 }
 
-/* Program iCLKIP clock to the desired frequency */
-static void lpt_program_iclkip(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-       u32 divsel, phaseinc, auxdiv, phasedir = 0;
-       u32 temp;
-
-       mutex_lock(&dev_priv->dpio_lock);
-
-       /* It is necessary to ungate the pixclk gate prior to programming
-        * the divisors, and gate it back when it is done.
-        */
-       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
-
-       /* Disable SSCCTL */
-       intel_sbi_write(dev_priv, SBI_SSCCTL6,
-                       intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
-                               SBI_SSCCTL_DISABLE,
-                       SBI_ICLK);
-
-       /* 20MHz is a corner case which is out of range for the 7-bit divisor */
-       if (clock == 20000) {
-               auxdiv = 1;
-               divsel = 0x41;
-               phaseinc = 0x20;
-       } else {
-               /* The iCLK virtual clock root frequency is in MHz,
-                * but the adjusted_mode->crtc_clock in in KHz. To get the
-                * divisors, it is necessary to divide one by another, so we
-                * convert the virtual clock precision to KHz here for higher
-                * precision.
-                */
-               u32 iclk_virtual_root_freq = 172800 * 1000;
-               u32 iclk_pi_range = 64;
-               u32 desired_divisor, msb_divisor_value, pi_value;
-
-               desired_divisor = (iclk_virtual_root_freq / clock);
-               msb_divisor_value = desired_divisor / iclk_pi_range;
-               pi_value = desired_divisor % iclk_pi_range;
-
-               auxdiv = 0;
-               divsel = msb_divisor_value - 2;
-               phaseinc = pi_value;
-       }
-
-       /* This should not happen with any sane values */
-       WARN_ON(SBI_SSCDIVINTPHASE_DIVSEL(divsel) &
-               ~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
-       WARN_ON(SBI_SSCDIVINTPHASE_DIR(phasedir) &
-               ~SBI_SSCDIVINTPHASE_INCVAL_MASK);
-
-       DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: 
auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
-                       clock,
-                       auxdiv,
-                       divsel,
-                       phasedir,
-                       phaseinc);
-
-       /* Program SSCDIVINTPHASE6 */
-       temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
-       temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
-       temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel);
-       temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
-       temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc);
-       temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
-       temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
-       intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
-
-       /* Program SSCAUXDIV */
-       temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
-       temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
-       temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
-       intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
-
-       /* Enable modulator and associated divider */
-       temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
-       temp &= ~SBI_SSCCTL_DISABLE;
-       intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
-
-       /* Wait for initialization time */
-       udelay(24);
-
-       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
-
-       mutex_unlock(&dev_priv->dpio_lock);
-}
-
-static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
-                                               enum pipe pch_transcoder)
+void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
+                                        enum pipe pch_transcoder)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3373,23 +3249,6 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        ironlake_enable_pch_transcoder(dev_priv, pipe);
 }
 
-static void lpt_pch_enable(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
-
-       assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
-
-       lpt_program_iclkip(crtc);
-
-       /* Set transcoder timing. */
-       ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
-
-       lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
-}
-
 static void intel_put_shared_dpll(struct intel_crtc *crtc)
 {
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
@@ -3876,9 +3735,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
 
-       if (intel_crtc->config.has_pch_encoder)
-               lpt_pch_enable(crtc);
-
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                encoder->enable(encoder);
                intel_opregion_notify_encoder(encoder, true);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7f1d7f675953..5b8e34c6907e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -782,6 +782,20 @@ void intel_mode_from_pipe_config(struct drm_display_mode 
*mode,
                                 struct intel_crtc_config *pipe_config);
 int intel_format_to_fourcc(int format);
 
+/* pch handling code shared with intel_crt on hsw/lpt */
+void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
+                                        enum pipe pch_transcoder);
+void assert_fdi_tx(struct drm_i915_private *dev_priv,
+                  enum pipe pipe, bool state);
+#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
+#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
+void assert_fdi_rx(struct drm_i915_private *dev_priv,
+                  enum pipe pipe, bool state);
+#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
+#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+                                   enum pipe pipe);
+
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
-- 
1.8.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to