[Intel-gfx] [PATCH 2/9] drm/i915: Move PCH modeset code to its own file

David Airlie airlied at redhat.com
Sun Oct 17 23:57:23 UTC 2021


On Fri, Oct 15, 2021 at 5:16 PM Ville Syrjala
<ville.syrjala at linux.intel.com> wrote:
>
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> Start moving the code for PCH modeset sequence/etc. to
> its own file.
>
> Still not sure about the file name though...

Name is good enough for now, there aren't a lot of great names, no
point getting stuck on it.

Otherwise

Reviewed-by: Dave Airlie <airlied at redhat.com>
>
> Cc: Dave Airlie <airlied at redhat.com>
> Cc: Jani Nikula <jani.nikula at intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_crt.c      |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  | 348 +----------------
>  drivers/gpu/drm/i915/display/intel_display.h  |   5 -
>  .../gpu/drm/i915/display/intel_pch_display.c  | 365 ++++++++++++++++++
>  .../gpu/drm/i915/display/intel_pch_display.h  |  22 ++
>  6 files changed, 390 insertions(+), 352 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pch_display.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pch_display.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 96f3b8f6c50d..467872cca027 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -226,6 +226,7 @@ i915-y += \
>         display/intel_hotplug.o \
>         display/intel_lpe_audio.o \
>         display/intel_overlay.o \
> +       display/intel_pch_display.o \
>         display/intel_pch_refclk.o \
>         display/intel_plane_initial.o \
>         display/intel_psr.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> index bf03bd0ecd43..54540138bd1d 100644
> --- a/drivers/gpu/drm/i915/display/intel_crt.c
> +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> @@ -45,6 +45,7 @@
>  #include "intel_fifo_underrun.h"
>  #include "intel_gmbus.h"
>  #include "intel_hotplug.h"
> +#include "intel_pch_display.h"
>  #include "intel_pch_refclk.h"
>
>  /* Here's the desired hotplug mode */
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 995050443065..69549886fe5b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -96,6 +96,7 @@
>  #include "intel_hotplug.h"
>  #include "intel_overlay.h"
>  #include "intel_panel.h"
> +#include "intel_pch_display.h"
>  #include "intel_pch_refclk.h"
>  #include "intel_pcode.h"
>  #include "intel_pipe_crc.h"
> @@ -454,80 +455,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc)
>                 assert_plane_disabled(plane);
>  }
>
> -void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
> -                                   enum pipe pipe)
> -{
> -       u32 val;
> -       bool enabled;
> -
> -       val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe));
> -       enabled = !!(val & TRANS_ENABLE);
> -       I915_STATE_WARN(enabled,
> -            "transcoder assertion failed, should be off on pipe %c but is still active\n",
> -            pipe_name(pipe));
> -}
> -
> -static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
> -                                  enum pipe pipe, enum port port,
> -                                  i915_reg_t dp_reg)
> -{
> -       enum pipe port_pipe;
> -       bool state;
> -
> -       state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe);
> -
> -       I915_STATE_WARN(state && port_pipe == pipe,
> -                       "PCH DP %c enabled on transcoder %c, should be disabled\n",
> -                       port_name(port), pipe_name(pipe));
> -
> -       I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
> -                       "IBX PCH DP %c still using transcoder B\n",
> -                       port_name(port));
> -}
> -
> -static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
> -                                    enum pipe pipe, enum port port,
> -                                    i915_reg_t hdmi_reg)
> -{
> -       enum pipe port_pipe;
> -       bool state;
> -
> -       state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe);
> -
> -       I915_STATE_WARN(state && port_pipe == pipe,
> -                       "PCH HDMI %c enabled on transcoder %c, should be disabled\n",
> -                       port_name(port), pipe_name(pipe));
> -
> -       I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
> -                       "IBX PCH HDMI %c still using transcoder B\n",
> -                       port_name(port));
> -}
> -
> -static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
> -                                     enum pipe pipe)
> -{
> -       enum pipe port_pipe;
> -
> -       assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B);
> -       assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C);
> -       assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D);
> -
> -       I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) &&
> -                       port_pipe == pipe,
> -                       "PCH VGA enabled on transcoder %c, should be disabled\n",
> -                       pipe_name(pipe));
> -
> -       I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) &&
> -                       port_pipe == pipe,
> -                       "PCH LVDS enabled on transcoder %c, should be disabled\n",
> -                       pipe_name(pipe));
> -
> -       /* PCH SDVOB multiplex with HDMIB */
> -       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB);
> -       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC);
> -       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID);
> -}
> -
>  void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
>                          struct intel_digital_port *dig_port,
>                          unsigned int expected_mask)
> @@ -562,154 +489,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
>                          expected_mask);
>  }
>
> -static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -       enum pipe pipe = crtc->pipe;
> -       i915_reg_t reg;
> -       u32 val, pipeconf_val;
> -
> -       /* Make sure PCH DPLL is enabled */
> -       assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll);
> -
> -       /* FDI must be feeding us bits for PCH ports */
> -       assert_fdi_tx_enabled(dev_priv, pipe);
> -       assert_fdi_rx_enabled(dev_priv, pipe);
> -
> -       if (HAS_PCH_CPT(dev_priv)) {
> -               reg = TRANS_CHICKEN2(pipe);
> -               val = intel_de_read(dev_priv, reg);
> -               /*
> -                * Workaround: Set the timing override bit
> -                * before enabling the pch transcoder.
> -                */
> -               val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> -               /* Configure frame start delay to match the CPU */
> -               val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> -               val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> -               intel_de_write(dev_priv, reg, val);
> -       }
> -
> -       reg = PCH_TRANSCONF(pipe);
> -       val = intel_de_read(dev_priv, reg);
> -       pipeconf_val = intel_de_read(dev_priv, PIPECONF(pipe));
> -
> -       if (HAS_PCH_IBX(dev_priv)) {
> -               /* Configure frame start delay to match the CPU */
> -               val &= ~TRANS_FRAME_START_DELAY_MASK;
> -               val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> -
> -               /*
> -                * Make the BPC in transcoder be consistent with
> -                * that in pipeconf reg. For HDMI we must use 8bpc
> -                * here for both 8bpc and 12bpc.
> -                */
> -               val &= ~PIPECONF_BPC_MASK;
> -               if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
> -                       val |= PIPECONF_8BPC;
> -               else
> -                       val |= pipeconf_val & PIPECONF_BPC_MASK;
> -       }
> -
> -       val &= ~TRANS_INTERLACE_MASK;
> -       if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
> -               if (HAS_PCH_IBX(dev_priv) &&
> -                   intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
> -                       val |= TRANS_LEGACY_INTERLACED_ILK;
> -               else
> -                       val |= TRANS_INTERLACED;
> -       } else {
> -               val |= TRANS_PROGRESSIVE;
> -       }
> -
> -       intel_de_write(dev_priv, reg, val | TRANS_ENABLE);
> -       if (intel_de_wait_for_set(dev_priv, reg, TRANS_STATE_ENABLE, 100))
> -               drm_err(&dev_priv->drm, "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;
> -
> -       /* 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, PIPE_A);
> -
> -       val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A));
> -       /* Workaround: set timing override bit. */
> -       val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> -       /* Configure frame start delay to match the CPU */
> -       val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> -       val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> -       intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
> -
> -       val = TRANS_ENABLE;
> -       pipeconf_val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder));
> -
> -       if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
> -           PIPECONF_INTERLACED_ILK)
> -               val |= TRANS_INTERLACED;
> -       else
> -               val |= TRANS_PROGRESSIVE;
> -
> -       intel_de_write(dev_priv, LPT_TRANSCONF, val);
> -       if (intel_de_wait_for_set(dev_priv, LPT_TRANSCONF,
> -                                 TRANS_STATE_ENABLE, 100))
> -               drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n");
> -}
> -
> -static void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv,
> -                                      enum pipe pipe)
> -{
> -       i915_reg_t reg;
> -       u32 val;
> -
> -       /* FDI relies on the transcoder */
> -       assert_fdi_tx_disabled(dev_priv, pipe);
> -       assert_fdi_rx_disabled(dev_priv, pipe);
> -
> -       /* Ports must be off as well */
> -       assert_pch_ports_disabled(dev_priv, pipe);
> -
> -       reg = PCH_TRANSCONF(pipe);
> -       val = intel_de_read(dev_priv, reg);
> -       val &= ~TRANS_ENABLE;
> -       intel_de_write(dev_priv, reg, val);
> -       /* wait for PCH transcoder off, transcoder state */
> -       if (intel_de_wait_for_clear(dev_priv, reg, TRANS_STATE_ENABLE, 50))
> -               drm_err(&dev_priv->drm, "failed to disable transcoder %c\n",
> -                       pipe_name(pipe));
> -
> -       if (HAS_PCH_CPT(dev_priv)) {
> -               /* Workaround: Clear the timing override chicken bit again. */
> -               reg = TRANS_CHICKEN2(pipe);
> -               val = intel_de_read(dev_priv, reg);
> -               val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
> -               intel_de_write(dev_priv, reg, val);
> -       }
> -}
> -
> -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
> -{
> -       u32 val;
> -
> -       val = intel_de_read(dev_priv, LPT_TRANSCONF);
> -       val &= ~TRANS_ENABLE;
> -       intel_de_write(dev_priv, LPT_TRANSCONF, val);
> -       /* wait for PCH transcoder off, transcoder state */
> -       if (intel_de_wait_for_clear(dev_priv, LPT_TRANSCONF,
> -                                   TRANS_STATE_ENABLE, 50))
> -               drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n");
> -
> -       /* Workaround: clear timing override bit. */
> -       val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A));
> -       val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
> -       intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
> -}
> -
>  enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
>  {
>         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> @@ -1388,31 +1167,6 @@ bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv)
>         return false;
>  }
>
> -
> -static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state,
> -                                          enum pipe pch_transcoder)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> -
> -       intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder),
> -                      intel_de_read(dev_priv, HTOTAL(cpu_transcoder)));
> -       intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder),
> -                      intel_de_read(dev_priv, HBLANK(cpu_transcoder)));
> -       intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder),
> -                      intel_de_read(dev_priv, HSYNC(cpu_transcoder)));
> -
> -       intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder),
> -                      intel_de_read(dev_priv, VTOTAL(cpu_transcoder)));
> -       intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder),
> -                      intel_de_read(dev_priv, VBLANK(cpu_transcoder)));
> -       intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder),
> -                      intel_de_read(dev_priv, VSYNC(cpu_transcoder)));
> -       intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder),
> -                      intel_de_read(dev_priv, VSYNCSHIFT(cpu_transcoder)));
> -}
> -
>  /*
>   * Finds the encoder associated with the given CRTC. This can only be
>   * used when we know that the CRTC isn't feeding multiple encoders!
> @@ -1443,106 +1197,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
>         return encoder;
>  }
>
> -/*
> - * Enable PCH resources required for PCH ports:
> - *   - PCH PLLs
> - *   - FDI training & RX/TX
> - *   - update transcoder timings
> - *   - DP transcoding bits
> - *   - transcoder
> - */
> -static void ilk_pch_enable(const struct intel_atomic_state *state,
> -                          const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       struct drm_device *dev = crtc->base.dev;
> -       struct drm_i915_private *dev_priv = to_i915(dev);
> -       enum pipe pipe = crtc->pipe;
> -       u32 temp;
> -
> -       assert_pch_transcoder_disabled(dev_priv, pipe);
> -
> -       /* For PCH output, training FDI link */
> -       intel_fdi_link_train(crtc, crtc_state);
> -
> -       /* We need to program the right clock selection before writing the pixel
> -        * mutliplier into the DPLL. */
> -       if (HAS_PCH_CPT(dev_priv)) {
> -               u32 sel;
> -
> -               temp = intel_de_read(dev_priv, PCH_DPLL_SEL);
> -               temp |= TRANS_DPLL_ENABLE(pipe);
> -               sel = TRANS_DPLLB_SEL(pipe);
> -               if (crtc_state->shared_dpll ==
> -                   intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
> -                       temp |= sel;
> -               else
> -                       temp &= ~sel;
> -               intel_de_write(dev_priv, PCH_DPLL_SEL, temp);
> -       }
> -
> -       /* XXX: pch pll's can be enabled any time before we enable the PCH
> -        * transcoder, and we actually should do this to not upset any PCH
> -        * transcoder that already use the clock when we share it.
> -        *
> -        * Note that enable_shared_dpll tries to do the right thing, but
> -        * get_shared_dpll unconditionally resets the pll - we need that to have
> -        * the right LVDS enable sequence. */
> -       intel_enable_shared_dpll(crtc_state);
> -
> -       /* set transcoder timing, panel must allow it */
> -       assert_pps_unlocked(dev_priv, pipe);
> -       ilk_pch_transcoder_set_timings(crtc_state, pipe);
> -
> -       intel_fdi_normal_train(crtc);
> -
> -       /* For PCH DP, enable TRANS_DP_CTL */
> -       if (HAS_PCH_CPT(dev_priv) &&
> -           intel_crtc_has_dp_encoder(crtc_state)) {
> -               const struct drm_display_mode *adjusted_mode =
> -                       &crtc_state->hw.adjusted_mode;
> -               u32 bpc = (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
> -               i915_reg_t reg = TRANS_DP_CTL(pipe);
> -               enum port port;
> -
> -               temp = intel_de_read(dev_priv, reg);
> -               temp &= ~(TRANS_DP_PORT_SEL_MASK |
> -                         TRANS_DP_SYNC_MASK |
> -                         TRANS_DP_BPC_MASK);
> -               temp |= TRANS_DP_OUTPUT_ENABLE;
> -               temp |= bpc << 9; /* same format but at 11:9 */
> -
> -               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> -                       temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
> -               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> -                       temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
> -
> -               port = intel_get_crtc_new_encoder(state, crtc_state)->port;
> -               drm_WARN_ON(dev, port < PORT_B || port > PORT_D);
> -               temp |= TRANS_DP_PORT_SEL(port);
> -
> -               intel_de_write(dev_priv, reg, temp);
> -       }
> -
> -       ilk_enable_pch_transcoder(crtc_state);
> -}
> -
> -void lpt_pch_enable(const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> -
> -       assert_pch_transcoder_disabled(dev_priv, PIPE_A);
> -
> -       lpt_program_iclkip(crtc_state);
> -
> -       /* Set transcoder timing. */
> -       ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);
> -
> -       lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
> -}
> -
>  static void cpt_verify_modeset(struct drm_i915_private *dev_priv,
>                                enum pipe pipe)
>  {
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 39c18b8807f9..93c84f2174b5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -541,8 +541,6 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
>                       const char *name, u32 reg, int ref_freq);
>  int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
>                            const char *name, u32 reg);
> -void lpt_pch_enable(const struct intel_crtc_state *crtc_state);
> -void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
>  void intel_init_display_hooks(struct drm_i915_private *dev_priv);
>  unsigned int intel_fb_xy_to_linear(int x, int y,
>                                    const struct intel_plane_state *state,
> @@ -578,9 +576,6 @@ struct drm_framebuffer *
>  intel_framebuffer_create(struct drm_i915_gem_object *obj,
>                          struct drm_mode_fb_cmd2 *mode_cmd);
>
> -void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
> -                                   enum pipe pipe);
> -
>  bool intel_fuzzy_clock_check(int clock1, int clock2);
>
>  void intel_display_prepare_reset(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c
> new file mode 100644
> index 000000000000..0056c2fe49ec
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c
> @@ -0,0 +1,365 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#include "g4x_dp.h"
> +#include "intel_crt.h"
> +#include "intel_de.h"
> +#include "intel_display_types.h"
> +#include "intel_fdi.h"
> +#include "intel_lvds.h"
> +#include "intel_pch_display.h"
> +#include "intel_pch_refclk.h"
> +#include "intel_pps.h"
> +#include "intel_sdvo.h"
> +
> +static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
> +                                  enum pipe pipe, enum port port,
> +                                  i915_reg_t dp_reg)
> +{
> +       enum pipe port_pipe;
> +       bool state;
> +
> +       state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe);
> +
> +       I915_STATE_WARN(state && port_pipe == pipe,
> +                       "PCH DP %c enabled on transcoder %c, should be disabled\n",
> +                       port_name(port), pipe_name(pipe));
> +
> +       I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
> +                       "IBX PCH DP %c still using transcoder B\n",
> +                       port_name(port));
> +}
> +
> +static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
> +                                    enum pipe pipe, enum port port,
> +                                    i915_reg_t hdmi_reg)
> +{
> +       enum pipe port_pipe;
> +       bool state;
> +
> +       state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe);
> +
> +       I915_STATE_WARN(state && port_pipe == pipe,
> +                       "PCH HDMI %c enabled on transcoder %c, should be disabled\n",
> +                       port_name(port), pipe_name(pipe));
> +
> +       I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
> +                       "IBX PCH HDMI %c still using transcoder B\n",
> +                       port_name(port));
> +}
> +
> +static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
> +                                     enum pipe pipe)
> +{
> +       enum pipe port_pipe;
> +
> +       assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B);
> +       assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C);
> +       assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D);
> +
> +       I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) &&
> +                       port_pipe == pipe,
> +                       "PCH VGA enabled on transcoder %c, should be disabled\n",
> +                       pipe_name(pipe));
> +
> +       I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) &&
> +                       port_pipe == pipe,
> +                       "PCH LVDS enabled on transcoder %c, should be disabled\n",
> +                       pipe_name(pipe));
> +
> +       /* PCH SDVOB multiplex with HDMIB */
> +       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB);
> +       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC);
> +       assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID);
> +}
> +
> +static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
> +                                          enum pipe pipe)
> +{
> +       u32 val;
> +       bool enabled;
> +
> +       val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe));
> +       enabled = !!(val & TRANS_ENABLE);
> +       I915_STATE_WARN(enabled,
> +                       "transcoder assertion failed, should be off on pipe %c but is still active\n",
> +                       pipe_name(pipe));
> +}
> +
> +static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state,
> +                                          enum pipe pch_transcoder)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> +
> +       intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder),
> +                      intel_de_read(dev_priv, HTOTAL(cpu_transcoder)));
> +       intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder),
> +                      intel_de_read(dev_priv, HBLANK(cpu_transcoder)));
> +       intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder),
> +                      intel_de_read(dev_priv, HSYNC(cpu_transcoder)));
> +
> +       intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder),
> +                      intel_de_read(dev_priv, VTOTAL(cpu_transcoder)));
> +       intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder),
> +                      intel_de_read(dev_priv, VBLANK(cpu_transcoder)));
> +       intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder),
> +                      intel_de_read(dev_priv, VSYNC(cpu_transcoder)));
> +       intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder),
> +                      intel_de_read(dev_priv, VSYNCSHIFT(cpu_transcoder)));
> +}
> +
> +static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +       enum pipe pipe = crtc->pipe;
> +       i915_reg_t reg;
> +       u32 val, pipeconf_val;
> +
> +       /* Make sure PCH DPLL is enabled */
> +       assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll);
> +
> +       /* FDI must be feeding us bits for PCH ports */
> +       assert_fdi_tx_enabled(dev_priv, pipe);
> +       assert_fdi_rx_enabled(dev_priv, pipe);
> +
> +       if (HAS_PCH_CPT(dev_priv)) {
> +               reg = TRANS_CHICKEN2(pipe);
> +               val = intel_de_read(dev_priv, reg);
> +               /*
> +                * Workaround: Set the timing override bit
> +                * before enabling the pch transcoder.
> +                */
> +               val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> +               /* Configure frame start delay to match the CPU */
> +               val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> +               val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> +               intel_de_write(dev_priv, reg, val);
> +       }
> +
> +       reg = PCH_TRANSCONF(pipe);
> +       val = intel_de_read(dev_priv, reg);
> +       pipeconf_val = intel_de_read(dev_priv, PIPECONF(pipe));
> +
> +       if (HAS_PCH_IBX(dev_priv)) {
> +               /* Configure frame start delay to match the CPU */
> +               val &= ~TRANS_FRAME_START_DELAY_MASK;
> +               val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> +
> +               /*
> +                * Make the BPC in transcoder be consistent with
> +                * that in pipeconf reg. For HDMI we must use 8bpc
> +                * here for both 8bpc and 12bpc.
> +                */
> +               val &= ~PIPECONF_BPC_MASK;
> +               if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
> +                       val |= PIPECONF_8BPC;
> +               else
> +                       val |= pipeconf_val & PIPECONF_BPC_MASK;
> +       }
> +
> +       val &= ~TRANS_INTERLACE_MASK;
> +       if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
> +               if (HAS_PCH_IBX(dev_priv) &&
> +                   intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
> +                       val |= TRANS_LEGACY_INTERLACED_ILK;
> +               else
> +                       val |= TRANS_INTERLACED;
> +       } else {
> +               val |= TRANS_PROGRESSIVE;
> +       }
> +
> +       intel_de_write(dev_priv, reg, val | TRANS_ENABLE);
> +       if (intel_de_wait_for_set(dev_priv, reg, TRANS_STATE_ENABLE, 100))
> +               drm_err(&dev_priv->drm, "failed to enable transcoder %c\n",
> +                       pipe_name(pipe));
> +}
> +
> +void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv,
> +                               enum pipe pipe)
> +{
> +       i915_reg_t reg;
> +       u32 val;
> +
> +       /* FDI relies on the transcoder */
> +       assert_fdi_tx_disabled(dev_priv, pipe);
> +       assert_fdi_rx_disabled(dev_priv, pipe);
> +
> +       /* Ports must be off as well */
> +       assert_pch_ports_disabled(dev_priv, pipe);
> +
> +       reg = PCH_TRANSCONF(pipe);
> +       val = intel_de_read(dev_priv, reg);
> +       val &= ~TRANS_ENABLE;
> +       intel_de_write(dev_priv, reg, val);
> +       /* wait for PCH transcoder off, transcoder state */
> +       if (intel_de_wait_for_clear(dev_priv, reg, TRANS_STATE_ENABLE, 50))
> +               drm_err(&dev_priv->drm, "failed to disable transcoder %c\n",
> +                       pipe_name(pipe));
> +
> +       if (HAS_PCH_CPT(dev_priv)) {
> +               /* Workaround: Clear the timing override chicken bit again. */
> +               reg = TRANS_CHICKEN2(pipe);
> +               val = intel_de_read(dev_priv, reg);
> +               val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
> +               intel_de_write(dev_priv, reg, val);
> +       }
> +}
> +
> +/*
> + * Enable PCH resources required for PCH ports:
> + *   - PCH PLLs
> + *   - FDI training & RX/TX
> + *   - update transcoder timings
> + *   - DP transcoding bits
> + *   - transcoder
> + */
> +void ilk_pch_enable(const struct intel_atomic_state *state,
> +                   const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       struct drm_device *dev = crtc->base.dev;
> +       struct drm_i915_private *dev_priv = to_i915(dev);
> +       enum pipe pipe = crtc->pipe;
> +       u32 temp;
> +
> +       assert_pch_transcoder_disabled(dev_priv, pipe);
> +
> +       /* For PCH output, training FDI link */
> +       intel_fdi_link_train(crtc, crtc_state);
> +
> +       /*
> +        * We need to program the right clock selection
> +        * before writing the pixel multiplier into the DPLL.
> +        */
> +       if (HAS_PCH_CPT(dev_priv)) {
> +               u32 sel;
> +
> +               temp = intel_de_read(dev_priv, PCH_DPLL_SEL);
> +               temp |= TRANS_DPLL_ENABLE(pipe);
> +               sel = TRANS_DPLLB_SEL(pipe);
> +               if (crtc_state->shared_dpll ==
> +                   intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
> +                       temp |= sel;
> +               else
> +                       temp &= ~sel;
> +               intel_de_write(dev_priv, PCH_DPLL_SEL, temp);
> +       }
> +
> +       /*
> +        * XXX: pch pll's can be enabled any time before we enable the PCH
> +        * transcoder, and we actually should do this to not upset any PCH
> +        * transcoder that already use the clock when we share it.
> +        *
> +        * Note that enable_shared_dpll tries to do the right thing, but
> +        * get_shared_dpll unconditionally resets the pll - we need that
> +        * to have the right LVDS enable sequence.
> +        */
> +       intel_enable_shared_dpll(crtc_state);
> +
> +       /* set transcoder timing, panel must allow it */
> +       assert_pps_unlocked(dev_priv, pipe);
> +       ilk_pch_transcoder_set_timings(crtc_state, pipe);
> +
> +       intel_fdi_normal_train(crtc);
> +
> +       /* For PCH DP, enable TRANS_DP_CTL */
> +       if (HAS_PCH_CPT(dev_priv) &&
> +           intel_crtc_has_dp_encoder(crtc_state)) {
> +               const struct drm_display_mode *adjusted_mode =
> +                       &crtc_state->hw.adjusted_mode;
> +               u32 bpc = (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
> +               i915_reg_t reg = TRANS_DP_CTL(pipe);
> +               enum port port;
> +
> +               temp = intel_de_read(dev_priv, reg);
> +               temp &= ~(TRANS_DP_PORT_SEL_MASK |
> +                         TRANS_DP_SYNC_MASK |
> +                         TRANS_DP_BPC_MASK);
> +               temp |= TRANS_DP_OUTPUT_ENABLE;
> +               temp |= bpc << 9; /* same format but at 11:9 */
> +
> +               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> +                       temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
> +               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> +                       temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
> +
> +               port = intel_get_crtc_new_encoder(state, crtc_state)->port;
> +               drm_WARN_ON(dev, port < PORT_B || port > PORT_D);
> +               temp |= TRANS_DP_PORT_SEL(port);
> +
> +               intel_de_write(dev_priv, reg, temp);
> +       }
> +
> +       ilk_enable_pch_transcoder(crtc_state);
> +}
> +
> +static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
> +                                     enum transcoder cpu_transcoder)
> +{
> +       u32 val, pipeconf_val;
> +
> +       /* 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, PIPE_A);
> +
> +       val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A));
> +       /* Workaround: set timing override bit. */
> +       val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
> +       /* Configure frame start delay to match the CPU */
> +       val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
> +       val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
> +       intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
> +
> +       val = TRANS_ENABLE;
> +       pipeconf_val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder));
> +
> +       if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
> +           PIPECONF_INTERLACED_ILK)
> +               val |= TRANS_INTERLACED;
> +       else
> +               val |= TRANS_PROGRESSIVE;
> +
> +       intel_de_write(dev_priv, LPT_TRANSCONF, val);
> +       if (intel_de_wait_for_set(dev_priv, LPT_TRANSCONF,
> +                                 TRANS_STATE_ENABLE, 100))
> +               drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n");
> +}
> +
> +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
> +{
> +       u32 val;
> +
> +       val = intel_de_read(dev_priv, LPT_TRANSCONF);
> +       val &= ~TRANS_ENABLE;
> +       intel_de_write(dev_priv, LPT_TRANSCONF, val);
> +       /* wait for PCH transcoder off, transcoder state */
> +       if (intel_de_wait_for_clear(dev_priv, LPT_TRANSCONF,
> +                                   TRANS_STATE_ENABLE, 50))
> +               drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n");
> +
> +       /* Workaround: clear timing override bit. */
> +       val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A));
> +       val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
> +       intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
> +}
> +
> +void lpt_pch_enable(const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> +
> +       assert_pch_transcoder_disabled(dev_priv, PIPE_A);
> +
> +       lpt_program_iclkip(crtc_state);
> +
> +       /* Set transcoder timing. */
> +       ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);
> +
> +       lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h
> new file mode 100644
> index 000000000000..6eba1fd667ea
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#ifndef _INTEL_PCH_DISPLAY_H_
> +#define _INTEL_PCH_DISPLAY_H_
> +
> +enum pipe;
> +struct drm_i915_private;
> +struct intel_atomic_state;
> +struct intel_crtc_state;
> +
> +void ilk_disable_pch_transcoder(struct drm_i915_private *dev_priv,
> +                               enum pipe pipe);
> +void ilk_pch_enable(const struct intel_atomic_state *state,
> +                   const struct intel_crtc_state *crtc_state);
> +
> +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
> +void lpt_pch_enable(const struct intel_crtc_state *crtc_state);
> +
> +#endif
> --
> 2.32.0
>



More information about the Intel-gfx mailing list