drm/i915: Enable a PIPEDMC whenever its corresponding pipe is enabled
authorImre Deak <imre.deak@intel.com>
Mon, 2 Jan 2023 18:33:24 +0000 (20:33 +0200)
committerImre Deak <imre.deak@intel.com>
Fri, 20 Jan 2023 21:37:39 +0000 (23:37 +0200)
Make sure that PIPEDMCs are enabled whenever the corresponding pipe is
enabled.

This is required at least by the latest ADLP v2.18 firmware, which adds
a new handler enabled by default and running whenever the pipe is
enabled at the vertical referesh rate.

Bspec: 50344, 67620

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Tested-by: Gustavo Sousa <gustavo.sousa@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230102183324.862279-1-imre.deak@intel.com
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_dmc.c
drivers/gpu/drm/i915/display/intel_dmc.h
drivers/gpu/drm/i915/display/intel_dmc_regs.h
drivers/gpu/drm/i915/display/intel_modeset_setup.c

index c38a54e..e37cca6 100644 (file)
@@ -1867,6 +1867,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
        if (drm_WARN_ON(&dev_priv->drm, crtc->active))
                return;
 
+       intel_dmc_enable_pipe(dev_priv, crtc->pipe);
+
        if (!new_crtc_state->bigjoiner_pipes) {
                intel_encoders_pre_pll_enable(state, crtc);
 
@@ -2002,6 +2004,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
 {
        const struct intel_crtc_state *old_crtc_state =
                intel_atomic_get_old_crtc_state(state, crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
 
        /*
         * FIXME collapse everything to one hook.
@@ -2011,6 +2014,8 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
                intel_encoders_disable(state, crtc);
                intel_encoders_post_disable(state, crtc);
        }
+
+       intel_dmc_disable_pipe(i915, crtc->pipe);
 }
 
 static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
index 4124b3d..370c91d 100644 (file)
@@ -97,6 +97,8 @@ MODULE_FIRMWARE(BXT_DMC_PATH);
 #define DMC_V3_MAX_MMIO_COUNT          20
 #define DMC_V1_MMIO_START_RANGE                0x80000
 
+#define PIPE_TO_DMC_ID(pipe)            (DMC_FW_PIPEA + ((pipe) - PIPE_A))
+
 struct intel_css_header {
        /* 0x09 for DMC */
        u32 module_type;
@@ -396,6 +398,28 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
                                     PIPEDMC_GATING_DIS, 0);
 }
 
+void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe)
+{
+       if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe)))
+               return;
+
+       if (DISPLAY_VER(i915) >= 14)
+               intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe));
+       else
+               intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE);
+}
+
+void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe)
+{
+       if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe)))
+               return;
+
+       if (DISPLAY_VER(i915) >= 14)
+               intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0);
+       else
+               intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0);
+}
+
 /**
  * intel_dmc_load_program() - write the firmware from memory to register.
  * @dev_priv: i915 drm device.
index 435eab9..fd1725d 100644 (file)
@@ -13,6 +13,8 @@
 struct drm_i915_error_state_buf;
 struct drm_i915_private;
 
+enum pipe;
+
 enum {
        DMC_FW_MAIN = 0,
        DMC_FW_PIPEA,
@@ -47,6 +49,8 @@ struct intel_dmc {
 void intel_dmc_ucode_init(struct drm_i915_private *i915);
 void intel_dmc_load_program(struct drm_i915_private *i915);
 void intel_dmc_disable_program(struct drm_i915_private *i915);
+void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe);
+void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe);
 void intel_dmc_ucode_fini(struct drm_i915_private *i915);
 void intel_dmc_ucode_suspend(struct drm_i915_private *i915);
 void intel_dmc_ucode_resume(struct drm_i915_private *i915);
index 5e5e416..cf10094 100644 (file)
 #define DMC_PROGRAM(addr, i)   _MMIO((addr) + (i) * 4)
 #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
 
+#define _PIPEDMC_CONTROL_A             0x45250
+#define _PIPEDMC_CONTROL_B             0x45254
+#define PIPEDMC_CONTROL(pipe)          _MMIO_PIPE(pipe, \
+                                                  _PIPEDMC_CONTROL_A, \
+                                                  _PIPEDMC_CONTROL_B)
+#define  PIPEDMC_ENABLE                        REG_BIT(0)
+
+#define MTL_PIPEDMC_CONTROL            _MMIO(0x45250)
+#define  PIPEDMC_ENABLE_MTL(pipe)      REG_BIT(((pipe) - PIPE_A) * 4)
+
 #define _ADLP_PIPEDMC_REG_MMIO_BASE_A  0x5f000
 #define _TGL_PIPEDMC_REG_MMIO_BASE_A   0x92000
 
index 96395bf..52cdbd4 100644 (file)
@@ -698,8 +698,10 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
 
                drm_crtc_vblank_reset(&crtc->base);
 
-               if (crtc_state->hw.active)
+               if (crtc_state->hw.active) {
+                       intel_dmc_enable_pipe(i915, crtc->pipe);
                        intel_crtc_vblank_on(crtc_state);
+               }
        }
 
        intel_fbc_sanitize(i915);