Merge tag 'drm-intel-next-2022-04-13-1' of git://anongit.freedesktop.org/drm/drm...
authorDave Airlie <airlied@redhat.com>
Thu, 14 Apr 2022 02:03:08 +0000 (12:03 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 14 Apr 2022 02:03:09 +0000 (12:03 +1000)
drm/i915 feature pull for v5.19:

Features and functionality:
- Add support for new Tile 4 format on DG2 (Stan)
- Add support for new CCS clear color compression on DG2 (Mika, Juha-Pekka)
- Add support for new render and media compression formats on DG2 (Matt)
- Support multiple eDP and LVDS native mode refresh rates (Ville)
- Support static DRRS (Ville)
- ATS-M platform info (Matt)
- RPL-S PCI IDs (Tejas)
- Extend DP HDR support to HSW+ (Uma)
- Bump ADL-P DMC version to v2.16 (Madhumitha)
- Let users disable PSR2 while enabling PSR1 (José)

Refactoring and cleanups:
- Massive DRRS and panel fixed mode refactoring and cleanups (Ville)
- Power well refactoring and cleanup (Imre)
- Clean up and refactor crtc readout and compute config (Ville)
- Use kernel string helpers (Lucas)
- Refactor gmbus pin lookups and allocation (Jani)
- PCH display cleanups (Ville)
- DPLL and DPLL manager refactoring (Ville)
- Include and header refactoring (Jani, Tvrtko)
- DMC abstractions (Jani)
- Non-x86 build refactoring (Casey)
- VBT parsing refactoring (Ville)
- Bigjoiner refactoring (Ville)
- Optimize plane, pfit, scaler, etc. programming using unlocked writes (Ville)
- Split several register writes in commit to noarm+arm pairs (Ville)
- Clean up SAGV handling (Ville)
- Clean up bandwidth and ddb allocation (Ville)
- FBC cleanups (Ville)

Fixes:
- Fix native HDMI and DP HDMI DFP clock limits on deep color/4:2:0 (Ville)
- Fix DMC firmware platform check (Lucas)
- Fix cursor coordinates on bigjoiner secondary (Ville)
- Fix MSO vs. bigjoiner timing confusion (Ville)
- Fix ADL-P eDP voltage swing (José)
- Fix VRR capability property update (Manasi)
- Log DG2 SNPS PHY calibration errors (Matt, Lucas)
- Fix PCODE request status checks (Stan)
- Fix uncore unclaimed access warnings (Lucas)
- Fix VBT new max TMDS clock parsing (Shawn)
- Fix ADL-P non-existent underrun recovery (Swathi Dhanavanthri)
- Fix ADL-N stepping info (Tejas)
- Fix DPT mapping flags to contiguous (Stan)
- Fix DG2 max display bandwidth (Vinod)
- Fix DP low voltage SKU checks (Ankit)
- Fix RPL-S VT-d translation enable via quirk (Tejas)
- Fixes to PSR2 (José)
- Fix PIPE_MBUS_DBOX_CTL programming (José)
- Fix LTTPR capability read/check on DP 1.2 (Imre)
- Fix ADL-P register corruption after DDI clock enabling (Imre)
- Fix ADL-P MBUS DBOX BW and B credits (Caz)

Merges:
- Backmerge drm-next (Rodrigo, Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/874k2xgewe.fsf@intel.com
149 files changed:
Documentation/gpu/i915.rst
arch/x86/kernel/early-quirks.c
drivers/gpu/drm/dp/drm_dp.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/g4x_dp.c
drivers/gpu/drm/i915/display/g4x_hdmi.c
drivers/gpu/drm/i915/display/i9xx_plane.c
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_atomic_plane.c
drivers/gpu/drm/i915/display/intel_atomic_plane.h
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/display/intel_backlight.c
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_bw.h
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/intel_cdclk.h
drivers/gpu/drm/i915/display/intel_color.c
drivers/gpu/drm/i915/display/intel_color.h
drivers/gpu/drm/i915/display/intel_combo_phy.c
drivers/gpu/drm/i915/display/intel_connector.c
drivers/gpu/drm/i915/display/intel_crtc.c
drivers/gpu/drm/i915/display/intel_cursor.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display.h
drivers/gpu/drm/i915/display/intel_display_debugfs.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_display_power.h
drivers/gpu/drm/i915/display/intel_display_power_well.c [new file with mode: 0644]
drivers/gpu/drm/i915/display/intel_display_power_well.h [new file with mode: 0644]
drivers/gpu/drm/i915/display/intel_display_trace.h
drivers/gpu/drm/i915/display/intel_display_types.h
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 [new file with mode: 0644]
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp_link_training.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_dpll.c
drivers/gpu/drm/i915/display/intel_dpll_mgr.c
drivers/gpu/drm/i915/display/intel_dpt.c
drivers/gpu/drm/i915/display/intel_drrs.c
drivers/gpu/drm/i915/display/intel_drrs.h
drivers/gpu/drm/i915/display/intel_dsb.c
drivers/gpu/drm/i915/display/intel_dsi.c
drivers/gpu/drm/i915/display/intel_dsi_vbt.c
drivers/gpu/drm/i915/display/intel_dvo.c
drivers/gpu/drm/i915/display/intel_fb.c
drivers/gpu/drm/i915/display/intel_fb.h
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_fbc.h
drivers/gpu/drm/i915/display/intel_fdi.c
drivers/gpu/drm/i915/display/intel_gmbus.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/display/intel_lvds.c
drivers/gpu/drm/i915/display/intel_overlay.c
drivers/gpu/drm/i915/display/intel_panel.c
drivers/gpu/drm/i915/display/intel_panel.h
drivers/gpu/drm/i915/display/intel_pch_display.c
drivers/gpu/drm/i915/display/intel_pch_display.h
drivers/gpu/drm/i915/display/intel_plane_initial.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/intel_psr.h
drivers/gpu/drm/i915/display/intel_sdvo.c
drivers/gpu/drm/i915/display/intel_snps_phy.c
drivers/gpu/drm/i915/display/intel_sprite.c
drivers/gpu/drm/i915/display/intel_tv.c
drivers/gpu/drm/i915/display/intel_vbt_defs.h
drivers/gpu/drm/i915/display/intel_vdsc.c
drivers/gpu/drm/i915/display/intel_vrr.c
drivers/gpu/drm/i915/display/skl_scaler.c
drivers/gpu/drm/i915/display/skl_universal_plane.c
drivers/gpu/drm/i915/display/vlv_dsi.c
drivers/gpu/drm/i915/display/vlv_dsi_pll.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_lmem.c
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_phys.c
drivers/gpu/drm/i915/gem/i915_gem_region.c
drivers/gpu/drm/i915/gem/i915_gem_shmem.c
drivers/gpu/drm/i915/gem/i915_gem_stolen.c
drivers/gpu/drm/i915/gem/i915_gem_tiling.c
drivers/gpu/drm/i915/gem/i915_gem_tiling.h
drivers/gpu/drm/i915/gem/i915_gemfs.c
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/intel_ggtt.c
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
drivers/gpu/drm/i915/gt/intel_gt_regs.h
drivers/gpu/drm/i915/gt/intel_gtt.c
drivers/gpu/drm/i915/gt/intel_gtt.h
drivers/gpu/drm/i915/gt/intel_rc6.c
drivers/gpu/drm/i915/gt/intel_reset.c
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_sseu.c
drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
drivers/gpu/drm/i915/gt/selftest_timeline.c
drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
drivers/gpu/drm/i915/gt/uc/intel_uc.c
drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/i915_cmd_parser.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/i915/i915_driver.h
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_utils.c
drivers/gpu/drm/i915/i915_utils.h
drivers/gpu/drm/i915/intel_device_info.c
drivers/gpu/drm/i915/intel_device_info.h
drivers/gpu/drm/i915/intel_dram.c
drivers/gpu/drm/i915/intel_memory_region.c
drivers/gpu/drm/i915/intel_memory_region.h
drivers/gpu/drm/i915/intel_pch.c
drivers/gpu/drm/i915/intel_pcode.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_pm.h
drivers/gpu/drm/i915/intel_step.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c
drivers/gpu/drm/i915/pxp/intel_pxp_session.c
drivers/gpu/drm/i915/selftests/i915_active.c
drivers/gpu/drm/i915/vlv_suspend.c
drivers/iommu/intel/iommu.c
include/drm/dp/drm_dp_helper.h
include/drm/i915_drm.h
include/drm/i915_pciids.h
include/uapi/drm/drm_fourcc.h

index bcaefc9..0f08693 100644 (file)
@@ -187,19 +187,7 @@ Display Refresh Rate Switching (DRRS)
    :doc: Display Refresh Rate Switching (DRRS)
 
 .. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
-   :functions: intel_drrs_enable
-
-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
-   :functions: intel_drrs_disable
-
-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
-   :functions: intel_drrs_invalidate
-
-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
-   :functions: intel_drrs_flush
-
-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
-   :functions: intel_drrs_init
+   :internal:
 
 DPIO
 ----
index bd6dad8..8055967 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/bcma/bcma_regs.h>
 #include <linux/platform_data/x86/apple.h>
 #include <drm/i915_drm.h>
+#include <drm/i915_pciids.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
 #include <asm/io_apic.h>
index 703972a..580016a 100644 (file)
@@ -2390,9 +2390,36 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
 
+static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux,
+                                 const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
+                                 u8 *buf, int buf_size)
+{
+       /*
+        * At least the DELL P2715Q monitor with a DPCD_REV < 0x14 returns
+        * corrupted values when reading from the 0xF0000- range with a block
+        * size bigger than 1.
+        */
+       int block_size = dpcd[DP_DPCD_REV] < 0x14 ? 1 : buf_size;
+       int offset;
+       int ret;
+
+       for (offset = 0; offset < buf_size; offset += block_size) {
+               ret = drm_dp_dpcd_read(aux,
+                                      address + offset,
+                                      &buf[offset], block_size);
+               if (ret < 0)
+                       return ret;
+
+               WARN_ON(ret != block_size);
+       }
+
+       return 0;
+}
+
 /**
  * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
  * @aux: DisplayPort AUX channel
+ * @dpcd: DisplayPort configuration data
  * @caps: buffer to return the capability info in
  *
  * Read capabilities common to all LTTPRs.
@@ -2400,25 +2427,19 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
  * Returns 0 on success or a negative error code on failure.
  */
 int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+                                 const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                                  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
 {
-       int ret;
-
-       ret = drm_dp_dpcd_read(aux,
-                              DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
-                              caps, DP_LTTPR_COMMON_CAP_SIZE);
-       if (ret < 0)
-               return ret;
-
-       WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
-
-       return 0;
+       return drm_dp_read_lttpr_regs(aux, dpcd,
+                                     DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
+                                     caps, DP_LTTPR_COMMON_CAP_SIZE);
 }
 EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
 
 /**
  * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
  * @aux: DisplayPort AUX channel
+ * @dpcd: DisplayPort configuration data
  * @dp_phy: LTTPR PHY to read the capabilities for
  * @caps: buffer to return the capability info in
  *
@@ -2427,20 +2448,13 @@ EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
  * Returns 0 on success or a negative error code on failure.
  */
 int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+                              const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                               enum drm_dp_phy dp_phy,
                               u8 caps[DP_LTTPR_PHY_CAP_SIZE])
 {
-       int ret;
-
-       ret = drm_dp_dpcd_read(aux,
-                              DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
-                              caps, DP_LTTPR_PHY_CAP_SIZE);
-       if (ret < 0)
-               return ret;
-
-       WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
-
-       return 0;
+       return drm_dp_read_lttpr_regs(aux, dpcd,
+                                     DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
+                                     caps, DP_LTTPR_PHY_CAP_SIZE);
 }
 EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
 
index 7df74a7..815589f 100644 (file)
@@ -213,6 +213,7 @@ i915-y += \
        display/intel_cursor.o \
        display/intel_display.o \
        display/intel_display_power.o \
+       display/intel_display_power_well.o \
        display/intel_dmc.o \
        display/intel_dpio_phy.o \
        display/intel_dpll.o \
index f67bbaa..16bb21a 100644 (file)
@@ -5,6 +5,8 @@
  * DisplayPort support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code).
  */
 
+#include <linux/string_helpers.h>
+
 #include "g4x_dp.h"
 #include "intel_audio.h"
 #include "intel_backlight.h"
 #include "intel_pps.h"
 #include "vlv_sideband.h"
 
-struct dp_link_dpll {
-       int clock;
-       struct dpll dpll;
+static const struct dpll g4x_dpll[] = {
+       { .dot = 162000, .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8, },
+       { .dot = 270000, .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2, },
 };
 
-static const struct dp_link_dpll g4x_dpll[] = {
-       { 162000,
-               { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } },
-       { 270000,
-               { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } }
+static const struct dpll pch_dpll[] = {
+       { .dot = 162000, .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9, },
+       { .dot = 270000, .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8, },
 };
 
-static const struct dp_link_dpll pch_dpll[] = {
-       { 162000,
-               { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } },
-       { 270000,
-               { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } }
+static const struct dpll vlv_dpll[] = {
+       { .dot = 162000, .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81, },
+       { .dot = 270000, .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27, },
 };
 
-static const struct dp_link_dpll vlv_dpll[] = {
-       { 162000,
-               { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } },
-       { 270000,
-               { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } }
-};
-
-/*
- * CHV supports eDP 1.4 that have  more link rates.
- * Below only provides the fixed rate but exclude variable rate.
- */
-static const struct dp_link_dpll chv_dpll[] = {
-       /*
-        * CHV requires to program fractional division for m2.
-        * m2 is stored in fixed point format using formula below
-        * (m2_int << 22) | m2_fraction
-        */
-       { 162000,       /* m2_int = 32, m2_fraction = 1677722 */
-               { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } },
-       { 270000,       /* m2_int = 27, m2_fraction = 0 */
-               { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
+static const struct dpll chv_dpll[] = {
+       /* m2 is .22 binary fixed point  */
+       { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
+       { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
 };
 
 const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
 {
-       return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll;
+       return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0];
 }
 
 void g4x_dp_set_clock(struct intel_encoder *encoder,
                      struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       const struct dp_link_dpll *divisor = NULL;
+       const struct dpll *divisor = NULL;
        int i, count = 0;
 
        if (IS_G4X(dev_priv)) {
@@ -92,8 +73,8 @@ void g4x_dp_set_clock(struct intel_encoder *encoder,
 
        if (divisor && count) {
                for (i = 0; i < count; i++) {
-                       if (pipe_config->port_clock == divisor[i].clock) {
-                               pipe_config->dpll = divisor[i].dpll;
+                       if (pipe_config->port_clock == divisor[i].dot) {
+                               pipe_config->dpll = divisor[i];
                                pipe_config->clock_set = true;
                                break;
                        }
@@ -192,7 +173,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
        I915_STATE_WARN(cur_state != state,
                        "[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n",
                        dig_port->base.base.base.id, dig_port->base.base.name,
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 #define assert_dp_port_disabled(d) assert_dp_port((d), false)
 
@@ -202,7 +183,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
 
        I915_STATE_WARN(cur_state != state,
                        "eDP PLL state assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 #define assert_edp_pll_enabled(d) assert_edp_pll((d), true)
 #define assert_edp_pll_disabled(d) assert_edp_pll((d), false)
@@ -514,9 +495,7 @@ static void intel_disable_dp(struct intel_atomic_state *state,
 
        intel_dp->link_trained = false;
 
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 
        /*
         * Make sure the panel is off before trying to change the mode.
@@ -677,9 +656,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
        u32 dp_reg = intel_de_read(dev_priv, intel_dp->output_reg);
-       enum pipe pipe = crtc->pipe;
        intel_wakeref_t wakeref;
 
        if (drm_WARN_ON(&dev_priv->drm, dp_reg & DP_PORT_EN))
@@ -713,11 +690,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
        intel_dp_start_link_train(intel_dp, pipe_config);
        intel_dp_stop_link_train(intel_dp, pipe_config);
 
-       if (pipe_config->has_audio) {
-               drm_dbg(&dev_priv->drm, "Enabling DP audio on pipe %c\n",
-                       pipe_name(pipe));
-               intel_audio_codec_enable(encoder, pipe_config, conn_state);
-       }
+       intel_audio_codec_enable(encoder, pipe_config, conn_state);
 }
 
 static void g4x_enable_dp(struct intel_atomic_state *state,
index 06e00b1..8bfef08 100644 (file)
@@ -143,19 +143,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
                             &pipe_config->infoframes.hdmi);
 }
 
-static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
-                                   const struct intel_crtc_state *pipe_config,
-                                   const struct drm_connector_state *conn_state)
-{
-       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
-
-       drm_WARN_ON(&i915->drm, !pipe_config->has_hdmi_sink);
-       drm_dbg_kms(&i915->drm, "Enabling HDMI audio on pipe %c\n",
-                   pipe_name(crtc->pipe));
-       intel_audio_codec_enable(encoder, pipe_config, conn_state);
-}
-
 static void g4x_enable_hdmi(struct intel_atomic_state *state,
                            struct intel_encoder *encoder,
                            const struct intel_crtc_state *pipe_config,
@@ -175,8 +162,9 @@ static void g4x_enable_hdmi(struct intel_atomic_state *state,
        intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
        intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
 
-       if (pipe_config->has_audio)
-               intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
+       drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
+                   !pipe_config->has_hdmi_sink);
+       intel_audio_codec_enable(encoder, pipe_config, conn_state);
 }
 
 static void ibx_enable_hdmi(struct intel_atomic_state *state,
@@ -227,8 +215,9 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state,
                intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
        }
 
-       if (pipe_config->has_audio)
-               intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
+       drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
+                   !pipe_config->has_hdmi_sink);
+       intel_audio_codec_enable(encoder, pipe_config, conn_state);
 }
 
 static void cpt_enable_hdmi(struct intel_atomic_state *state,
@@ -281,8 +270,9 @@ static void cpt_enable_hdmi(struct intel_atomic_state *state,
                               intel_de_read(dev_priv, TRANS_CHICKEN1(pipe)) & ~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
        }
 
-       if (pipe_config->has_audio)
-               intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
+       drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
+                   !pipe_config->has_hdmi_sink);
+       intel_audio_codec_enable(encoder, pipe_config, conn_state);
 }
 
 static void vlv_enable_hdmi(struct intel_atomic_state *state,
@@ -356,9 +346,7 @@ static void g4x_disable_hdmi(struct intel_atomic_state *state,
                             const struct intel_crtc_state *old_crtc_state,
                             const struct drm_connector_state *old_conn_state)
 {
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 
        intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state);
 }
@@ -368,9 +356,7 @@ static void pch_disable_hdmi(struct intel_atomic_state *state,
                             const struct intel_crtc_state *old_crtc_state,
                             const struct drm_connector_state *old_conn_state)
 {
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
 
 static void pch_post_disable_hdmi(struct intel_atomic_state *state,
index a87b65c..7fe1a4e 100644 (file)
@@ -418,9 +418,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
                          plane_state->view.color_plane[0].mapping_stride);
@@ -441,8 +438,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
                intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
                                  DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
        }
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void i9xx_plane_update_arm(struct intel_plane *plane,
@@ -454,7 +449,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
        int x = plane_state->view.color_plane[0].x;
        int y = plane_state->view.color_plane[0].y;
        u32 dspcntr, dspaddr_offset, linear_offset;
-       unsigned long irqflags;
 
        dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
 
@@ -465,8 +459,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
        else
                dspaddr_offset = linear_offset;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
                int crtc_x = plane_state->uapi.dst.x1;
                int crtc_y = plane_state->uapi.dst.y1;
@@ -496,14 +488,13 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
         * the control register just before the surface register.
         */
        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+
        if (DISPLAY_VER(dev_priv) >= 4)
                intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
                                  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
        else
                intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
                                  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void i830_plane_update_arm(struct intel_plane *plane,
@@ -525,7 +516,6 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-       unsigned long irqflags;
        u32 dspcntr;
 
        /*
@@ -540,15 +530,12 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
         */
        dspcntr = i9xx_plane_ctl_crtc(crtc_state);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+
        if (DISPLAY_VER(dev_priv) >= 4)
                intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
        else
                intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -561,16 +548,14 @@ g4x_primary_async_flip(struct intel_plane *plane,
        u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
        u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-       unsigned long irqflags;
 
        if (async_flip)
                dspcntr |= DISP_ASYNC_FLIP;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+
        intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
                          intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -582,12 +567,9 @@ vlv_primary_async_flip(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-       unsigned long irqflags;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane),
                          intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
index 13b07c6..084cc51 100644 (file)
@@ -1967,6 +1967,8 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
 
 static void icl_dsi_add_properties(struct intel_connector *connector)
 {
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_preferred_fixed_mode(connector);
        u32 allowed_scalers;
 
        allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) |
@@ -1979,9 +1981,9 @@ static void icl_dsi_add_properties(struct intel_connector *connector)
        connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT;
 
        drm_connector_set_panel_orientation_with_quirk(&connector->base,
-                               intel_dsi_get_panel_orientation(connector),
-                               connector->panel.fixed_mode->hdisplay,
-                               connector->panel.fixed_mode->vdisplay);
+                                                      intel_dsi_get_panel_orientation(connector),
+                                                      fixed_mode->hdisplay,
+                                                      fixed_mode->vdisplay);
 }
 
 void icl_dsi_init(struct drm_i915_private *dev_priv)
@@ -1991,7 +1993,6 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
        struct intel_encoder *encoder;
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
-       struct drm_display_mode *fixed_mode;
        enum port port;
 
        if (!intel_bios_is_dsi_present(dev_priv, &port))
@@ -2048,15 +2049,16 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
        intel_connector_attach_encoder(intel_connector, encoder);
 
        mutex_lock(&dev->mode_config.mutex);
-       fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
+       intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
        mutex_unlock(&dev->mode_config.mutex);
 
-       if (!fixed_mode) {
+       if (!intel_panel_preferred_fixed_mode(intel_connector)) {
                drm_err(&dev_priv->drm, "DSI fixed mode info missing\n");
                goto err;
        }
 
-       intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+       intel_panel_init(intel_connector);
+
        intel_backlight_setup(intel_connector, INVALID_PIPE);
 
        if (dev_priv->vbt.dsi.config->dual_link)
index 5712688..3d87da2 100644 (file)
@@ -181,29 +181,67 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
 }
 
 unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
-                                  const struct intel_plane_state *plane_state)
+                                  const struct intel_plane_state *plane_state,
+                                  int color_plane)
 {
        const struct drm_framebuffer *fb = plane_state->hw.fb;
-       unsigned int cpp;
-       unsigned int pixel_rate;
 
        if (!plane_state->uapi.visible)
                return 0;
 
-       pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+       return intel_plane_pixel_rate(crtc_state, plane_state) *
+               fb->format->cpp[color_plane];
+}
+
+static bool
+use_min_ddb(const struct intel_crtc_state *crtc_state,
+           struct intel_plane *plane)
+{
+       struct drm_i915_private *i915 = to_i915(plane->base.dev);
+
+       return DISPLAY_VER(i915) >= 13 &&
+              crtc_state->uapi.async_flip &&
+              plane->async_flip;
+}
+
+static unsigned int
+intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
+                              const struct intel_plane_state *plane_state,
+                              int color_plane)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       int width, height;
 
-       cpp = fb->format->cpp[0];
+       if (plane->id == PLANE_CURSOR)
+               return 0;
+
+       if (!plane_state->uapi.visible)
+               return 0;
 
        /*
-        * Based on HSD#:1408715493
-        * NV12 cpp == 4, P010 cpp == 8
-        *
-        * FIXME what is the logic behind this?
+        * We calculate extra ddb based on ratio plane rate/total data rate
+        * in case, in some cases we should not allocate extra ddb for the plane,
+        * so do not count its data rate, if this is the case.
         */
-       if (fb->format->is_yuv && fb->format->num_planes > 1)
-               cpp *= 4;
+       if (use_min_ddb(crtc_state, plane))
+               return 0;
+
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
+       width = drm_rect_width(&plane_state->uapi.src) >> 16;
+       height = drm_rect_height(&plane_state->uapi.src) >> 16;
+
+       /* UV plane does 1/2 pixel sub-sampling */
+       if (color_plane == 1) {
+               width /= 2;
+               height /= 2;
+       }
 
-       return pixel_rate * cpp;
+       return width * height * fb->format->cpp[color_plane];
 }
 
 int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
@@ -326,6 +364,9 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
        crtc_state->nv12_planes &= ~BIT(plane->id);
        crtc_state->c8_planes &= ~BIT(plane->id);
        crtc_state->data_rate[plane->id] = 0;
+       crtc_state->data_rate_y[plane->id] = 0;
+       crtc_state->rel_data_rate[plane->id] = 0;
+       crtc_state->rel_data_rate_y[plane->id] = 0;
        crtc_state->min_cdclk[plane->id] = 0;
 
        plane_state->uapi.visible = false;
@@ -551,8 +592,27 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
        if (new_plane_state->uapi.visible || old_plane_state->uapi.visible)
                new_crtc_state->update_planes |= BIT(plane->id);
 
-       new_crtc_state->data_rate[plane->id] =
-               intel_plane_data_rate(new_crtc_state, new_plane_state);
+       if (new_plane_state->uapi.visible &&
+           intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
+               new_crtc_state->data_rate_y[plane->id] =
+                       intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
+               new_crtc_state->data_rate[plane->id] =
+                       intel_plane_data_rate(new_crtc_state, new_plane_state, 1);
+
+               new_crtc_state->rel_data_rate_y[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 0);
+               new_crtc_state->rel_data_rate[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 1);
+       } else if (new_plane_state->uapi.visible) {
+               new_crtc_state->data_rate[plane->id] =
+                       intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
+
+               new_crtc_state->rel_data_rate[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 0);
+       }
 
        return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
                                               old_plane_state, new_plane_state);
@@ -616,8 +676,8 @@ int intel_plane_atomic_check(struct intel_atomic_state *state,
 static struct intel_plane *
 skl_next_plane_to_commit(struct intel_atomic_state *state,
                         struct intel_crtc *crtc,
-                        struct skl_ddb_entry entries_y[I915_MAX_PLANES],
-                        struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
+                        struct skl_ddb_entry ddb[I915_MAX_PLANES],
+                        struct skl_ddb_entry ddb_y[I915_MAX_PLANES],
                         unsigned int *update_mask)
 {
        struct intel_crtc_state *crtc_state =
@@ -636,17 +696,15 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
                    !(*update_mask & BIT(plane_id)))
                        continue;
 
-               if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
-                                               entries_y,
-                                               I915_MAX_PLANES, plane_id) ||
-                   skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
-                                               entries_uv,
-                                               I915_MAX_PLANES, plane_id))
+               if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb[plane_id],
+                                               ddb, I915_MAX_PLANES, plane_id) ||
+                   skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
+                                               ddb_y, I915_MAX_PLANES, plane_id))
                        continue;
 
                *update_mask &= ~BIT(plane_id);
-               entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
-               entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
+               ddb[plane_id] = crtc_state->wm.skl.plane_ddb[plane_id];
+               ddb_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
 
                return plane;
        }
@@ -728,19 +786,17 @@ static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
                intel_atomic_get_old_crtc_state(state, crtc);
        struct intel_crtc_state *new_crtc_state =
                intel_atomic_get_new_crtc_state(state, crtc);
-       struct skl_ddb_entry entries_y[I915_MAX_PLANES];
-       struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
+       struct skl_ddb_entry ddb[I915_MAX_PLANES];
+       struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
        u32 update_mask = new_crtc_state->update_planes;
        struct intel_plane *plane;
 
-       memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
+       memcpy(ddb, old_crtc_state->wm.skl.plane_ddb,
+              sizeof(old_crtc_state->wm.skl.plane_ddb));
+       memcpy(ddb_y, old_crtc_state->wm.skl.plane_ddb_y,
               sizeof(old_crtc_state->wm.skl.plane_ddb_y));
-       memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
-              sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
 
-       while ((plane = skl_next_plane_to_commit(state, crtc,
-                                                entries_y, entries_uv,
-                                                &update_mask))) {
+       while ((plane = skl_next_plane_to_commit(state, crtc, ddb, ddb_y, &update_mask))) {
                struct intel_plane_state *new_plane_state =
                        intel_atomic_get_new_plane_state(state, plane);
 
@@ -802,8 +858,8 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
        struct drm_framebuffer *fb = plane_state->hw.fb;
        struct drm_rect *src = &plane_state->uapi.src;
        struct drm_rect *dst = &plane_state->uapi.dst;
+       const struct drm_rect *clip = &crtc_state->pipe_src;
        unsigned int rotation = plane_state->hw.rotation;
-       struct drm_rect clip = {};
        int hscale, vscale;
 
        if (!fb) {
@@ -823,31 +879,25 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
                return -ERANGE;
        }
 
-       if (crtc_state->hw.enable) {
-               clip.x2 = crtc_state->pipe_src_w;
-               clip.y2 = crtc_state->pipe_src_h;
-       }
-
-       /* right side of the image is on the slave crtc, adjust dst to match */
-       if (intel_crtc_is_bigjoiner_slave(crtc_state))
-               drm_rect_translate(dst, -crtc_state->pipe_src_w, 0);
-
        /*
         * FIXME: This might need further adjustment for seamless scaling
         * with phase information, for the 2p2 and 2p1 scenarios.
         */
-       plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, &clip);
+       plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, clip);
 
        drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
 
        if (!can_position && plane_state->uapi.visible &&
-           !drm_rect_equals(dst, &clip)) {
+           !drm_rect_equals(dst, clip)) {
                drm_dbg_kms(&i915->drm, "Plane must cover entire CRTC\n");
                drm_rect_debug_print("dst: ", dst, false);
-               drm_rect_debug_print("clip: ", &clip, false);
+               drm_rect_debug_print("clip: ", clip, false);
                return -EINVAL;
        }
 
+       /* final plane coordinates will be relative to the plane's pipe */
+       drm_rect_translate(dst, -clip->x1, -clip->y1);
+
        return 0;
 }
 
index f4763a5..74b6d3b 100644 (file)
@@ -25,7 +25,8 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
                                    const struct intel_plane_state *plane_state);
 
 unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
-                                  const struct intel_plane_state *plane_state);
+                                  const struct intel_plane_state *plane_state,
+                                  int color_plane);
 void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
                                       const struct intel_plane_state *from_plane_state,
                                       struct intel_crtc *crtc);
index 3bdca0f..1c87bf6 100644 (file)
@@ -337,8 +337,6 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        u32 eldv, tmp;
 
-       drm_dbg_kms(&dev_priv->drm, "Disable audio codec\n");
-
        tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
        if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
                eldv = G4X_ELDV_DEVCL_DEVBLC;
@@ -362,9 +360,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder,
        u32 tmp;
        int len, i;
 
-       drm_dbg_kms(&dev_priv->drm, "Enable audio codec, %u bytes ELD\n",
-                   drm_eld_size(eld));
-
        tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
        if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
                eldv = G4X_ELDV_DEVCL_DEVBLC;
@@ -383,7 +378,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder,
        intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp);
 
        len = min(drm_eld_size(eld) / 4, len);
-       drm_dbg(&dev_priv->drm, "ELD size %d\n", len);
        for (i = 0; i < len; i++)
                intel_de_write(dev_priv, G4X_HDMIW_HDMIEDID,
                               *((const u32 *)eld + i));
@@ -501,9 +495,6 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
        enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
        u32 tmp;
 
-       drm_dbg_kms(&dev_priv->drm, "Disable audio codec on transcoder %s\n",
-                   transcoder_name(cpu_transcoder));
-
        mutex_lock(&dev_priv->audio.mutex);
 
        /* Disable timestamps */
@@ -647,10 +638,6 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
        u32 tmp;
        int len, i;
 
-       drm_dbg_kms(&dev_priv->drm,
-                   "Enable audio codec on transcoder %s, %u bytes ELD\n",
-                    transcoder_name(cpu_transcoder), drm_eld_size(eld));
-
        mutex_lock(&dev_priv->audio.mutex);
 
        /* Enable Audio WA for 4k DSC usecases */
@@ -703,11 +690,6 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder,
        u32 tmp, eldv;
        i915_reg_t aud_config, aud_cntrl_st2;
 
-       drm_dbg_kms(&dev_priv->drm,
-                   "Disable audio codec on [ENCODER:%d:%s], pipe %c\n",
-                    encoder->base.base.id, encoder->base.name,
-                    pipe_name(pipe));
-
        if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
                return;
 
@@ -754,11 +736,6 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder,
        int len, i;
        i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
 
-       drm_dbg_kms(&dev_priv->drm,
-                   "Enable audio codec on [ENCODER:%d:%s], pipe %c, %u bytes ELD\n",
-                   encoder->base.base.id, encoder->base.name,
-                   pipe_name(pipe), drm_eld_size(eld));
-
        if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
                return;
 
@@ -844,18 +821,20 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
        enum port port = encoder->port;
        enum pipe pipe = crtc->pipe;
 
+       if (!crtc_state->has_audio)
+               return;
+
+       drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n",
+                   connector->base.id, connector->name,
+                   encoder->base.base.id, encoder->base.name,
+                   pipe, drm_eld_size(connector->eld));
+
        /* FIXME precompute the ELD in .compute_config() */
        if (!connector->eld[0])
                drm_dbg_kms(&dev_priv->drm,
                            "Bogus ELD on [CONNECTOR:%d:%s]\n",
                            connector->base.id, connector->name);
 
-       drm_dbg(&dev_priv->drm, "ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
-               connector->base.id,
-               connector->name,
-               encoder->base.base.id,
-               encoder->base.name);
-
        connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
 
        if (dev_priv->audio.funcs)
@@ -900,9 +879,17 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct i915_audio_component *acomp = dev_priv->audio.component;
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
+       struct drm_connector *connector = old_conn_state->connector;
        enum port port = encoder->port;
        enum pipe pipe = crtc->pipe;
 
+       if (!old_crtc_state->has_audio)
+               return;
+
+       drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n",
+                   connector->base.id, connector->name,
+                   encoder->base.base.id, encoder->base.name, pipe);
+
        if (dev_priv->audio.funcs)
                dev_priv->audio.funcs->audio_codec_disable(encoder,
                                                           old_crtc_state,
index 98f7ea4..c8e1fc5 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pwm.h>
+#include <linux/string_helpers.h>
 
 #include "intel_backlight.h"
 #include "intel_connector.h"
@@ -1633,7 +1634,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
        drm_dbg_kms(&dev_priv->drm,
                    "Connector %s backlight initialized, %s, brightness %u/%u\n",
                    connector->base.name,
-                   enableddisabled(panel->backlight.enabled),
+                   str_enabled_disabled(panel->backlight.enabled),
                    panel->backlight.level, panel->backlight.max);
 
        return 0;
index 40b5e7e..bc19576 100644 (file)
@@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
 }
 
 static const void *
-find_section(const void *_bdb, enum bdb_block_id section_id)
+find_raw_section(const void *_bdb, enum bdb_block_id section_id)
 {
        const struct bdb_header *bdb = _bdb;
        const u8 *base = _bdb;
@@ -118,6 +118,250 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
        return NULL;
 }
 
+/*
+ * Offset from the start of BDB to the start of the
+ * block data (just past the block header).
+ */
+static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
+{
+       const void *block;
+
+       block = find_raw_section(bdb, section_id);
+       if (!block)
+               return 0;
+
+       return block - bdb;
+}
+
+/* size of the block excluding the header */
+static u32 block_size(const void *bdb, enum bdb_block_id section_id)
+{
+       const void *block;
+
+       block = find_raw_section(bdb, section_id);
+       if (!block)
+               return 0;
+
+       return get_blocksize(block);
+}
+
+struct bdb_block_entry {
+       struct list_head node;
+       enum bdb_block_id section_id;
+       u8 data[];
+};
+
+static const void *
+find_section(struct drm_i915_private *i915,
+            enum bdb_block_id section_id)
+{
+       struct bdb_block_entry *entry;
+
+       list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
+               if (entry->section_id == section_id)
+                       return entry->data + 3;
+       }
+
+       return NULL;
+}
+
+static const struct {
+       enum bdb_block_id section_id;
+       size_t min_size;
+} bdb_blocks[] = {
+       { .section_id = BDB_GENERAL_FEATURES,
+         .min_size = sizeof(struct bdb_general_features), },
+       { .section_id = BDB_GENERAL_DEFINITIONS,
+         .min_size = sizeof(struct bdb_general_definitions), },
+       { .section_id = BDB_PSR,
+         .min_size = sizeof(struct bdb_psr), },
+       { .section_id = BDB_DRIVER_FEATURES,
+         .min_size = sizeof(struct bdb_driver_features), },
+       { .section_id = BDB_SDVO_LVDS_OPTIONS,
+         .min_size = sizeof(struct bdb_sdvo_lvds_options), },
+       { .section_id = BDB_SDVO_PANEL_DTDS,
+         .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
+       { .section_id = BDB_EDP,
+         .min_size = sizeof(struct bdb_edp), },
+       { .section_id = BDB_LVDS_OPTIONS,
+         .min_size = sizeof(struct bdb_lvds_options), },
+       { .section_id = BDB_LVDS_LFP_DATA_PTRS,
+         .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
+       { .section_id = BDB_LVDS_LFP_DATA,
+         .min_size = sizeof(struct bdb_lvds_lfp_data), },
+       { .section_id = BDB_LVDS_BACKLIGHT,
+         .min_size = sizeof(struct bdb_lfp_backlight_data), },
+       { .section_id = BDB_LFP_POWER,
+         .min_size = sizeof(struct bdb_lfp_power), },
+       { .section_id = BDB_MIPI_CONFIG,
+         .min_size = sizeof(struct bdb_mipi_config), },
+       { .section_id = BDB_MIPI_SEQUENCE,
+         .min_size = sizeof(struct bdb_mipi_sequence) },
+       { .section_id = BDB_COMPRESSION_PARAMETERS,
+         .min_size = sizeof(struct bdb_compression_parameters), },
+       { .section_id = BDB_GENERIC_DTD,
+         .min_size = sizeof(struct bdb_generic_dtd), },
+};
+
+static bool validate_lfp_data_ptrs(const void *bdb,
+                                  const struct bdb_lvds_lfp_data_ptrs *ptrs)
+{
+       int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size;
+       int data_block_size, lfp_data_size;
+       int i;
+
+       data_block_size = block_size(bdb, BDB_LVDS_LFP_DATA);
+       if (data_block_size == 0)
+               return false;
+
+       /* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */
+       if (ptrs->lvds_entries != 3)
+               return false;
+
+       fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
+       dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
+       panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
+       panel_name_size = ptrs->panel_name.table_size;
+
+       /* fp_timing has variable size */
+       if (fp_timing_size < 32 ||
+           dvo_timing_size != sizeof(struct lvds_dvo_timing) ||
+           panel_pnp_id_size != sizeof(struct lvds_pnp_id))
+               return false;
+
+       /* panel_name is not present in old VBTs */
+       if (panel_name_size != 0 &&
+           panel_name_size != sizeof(struct lvds_lfp_panel_name))
+               return false;
+
+       lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
+       if (16 * lfp_data_size > data_block_size)
+               return false;
+
+       /*
+        * Except for vlv/chv machines all real VBTs seem to have 6
+        * unaccounted bytes in the fp_timing table. And it doesn't
+        * appear to be a really intentional hole as the fp_timing
+        * 0xffff terminator is always within those 6 missing bytes.
+        */
+       if (fp_timing_size + dvo_timing_size + panel_pnp_id_size != lfp_data_size &&
+           fp_timing_size + 6 + dvo_timing_size + panel_pnp_id_size != lfp_data_size)
+               return false;
+
+       if (ptrs->ptr[0].fp_timing.offset + fp_timing_size > ptrs->ptr[0].dvo_timing.offset ||
+           ptrs->ptr[0].dvo_timing.offset + dvo_timing_size != ptrs->ptr[0].panel_pnp_id.offset ||
+           ptrs->ptr[0].panel_pnp_id.offset + panel_pnp_id_size != lfp_data_size)
+               return false;
+
+       /* make sure the table entries have uniform size */
+       for (i = 1; i < 16; i++) {
+               if (ptrs->ptr[i].fp_timing.table_size != fp_timing_size ||
+                   ptrs->ptr[i].dvo_timing.table_size != dvo_timing_size ||
+                   ptrs->ptr[i].panel_pnp_id.table_size != panel_pnp_id_size)
+                       return false;
+
+               if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
+                   ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
+                   ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
+                       return false;
+       }
+
+       /* make sure the tables fit inside the data block */
+       for (i = 0; i < 16; i++) {
+               if (ptrs->ptr[i].fp_timing.offset + fp_timing_size > data_block_size ||
+                   ptrs->ptr[i].dvo_timing.offset + dvo_timing_size > data_block_size ||
+                   ptrs->ptr[i].panel_pnp_id.offset + panel_pnp_id_size > data_block_size)
+                       return false;
+       }
+
+       if (ptrs->panel_name.offset + 16 * panel_name_size > data_block_size)
+               return false;
+
+       return true;
+}
+
+/* make the data table offsets relative to the data block */
+static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
+{
+       struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block;
+       u32 offset;
+       int i;
+
+       offset = block_offset(bdb, BDB_LVDS_LFP_DATA);
+
+       for (i = 0; i < 16; i++) {
+               if (ptrs->ptr[i].fp_timing.offset < offset ||
+                   ptrs->ptr[i].dvo_timing.offset < offset ||
+                   ptrs->ptr[i].panel_pnp_id.offset < offset)
+                       return false;
+
+               ptrs->ptr[i].fp_timing.offset -= offset;
+               ptrs->ptr[i].dvo_timing.offset -= offset;
+               ptrs->ptr[i].panel_pnp_id.offset -= offset;
+       }
+
+       if (ptrs->panel_name.table_size) {
+               if (ptrs->panel_name.offset < offset)
+                       return false;
+
+               ptrs->panel_name.offset -= offset;
+       }
+
+       return validate_lfp_data_ptrs(bdb, ptrs);
+}
+
+static void
+init_bdb_block(struct drm_i915_private *i915,
+              const void *bdb, enum bdb_block_id section_id,
+              size_t min_size)
+{
+       struct bdb_block_entry *entry;
+       const void *block;
+       size_t block_size;
+
+       block = find_raw_section(bdb, section_id);
+       if (!block)
+               return;
+
+       drm_WARN(&i915->drm, min_size == 0,
+                "Block %d min_size is zero\n", section_id);
+
+       block_size = get_blocksize(block);
+
+       entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
+                       GFP_KERNEL);
+       if (!entry)
+               return;
+
+       entry->section_id = section_id;
+       memcpy(entry->data, block - 3, block_size + 3);
+
+       drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
+                   section_id, block_size, min_size);
+
+       if (section_id == BDB_LVDS_LFP_DATA_PTRS &&
+           !fixup_lfp_data_ptrs(bdb, entry->data + 3)) {
+               drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n");
+               kfree(entry);
+               return;
+       }
+
+       list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
+}
+
+static void init_bdb_blocks(struct drm_i915_private *i915,
+                           const void *bdb)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
+               enum bdb_block_id section_id = bdb_blocks[i].section_id;
+               size_t min_size = bdb_blocks[i].min_size;
+
+               init_bdb_block(i915, bdb, section_id, min_size);
+       }
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
                        const struct lvds_dvo_timing *dvo_timing)
@@ -169,60 +413,31 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 }
 
 static const struct lvds_dvo_timing *
-get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
-                   const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
+get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *data,
+                   const struct bdb_lvds_lfp_data_ptrs *ptrs,
                    int index)
 {
-       /*
-        * the size of fp_timing varies on the different platform.
-        * So calculate the DVO timing relative offset in LVDS data
-        * entry to get the DVO timing entry
-        */
-
-       int lfp_data_size =
-               lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
-               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
-       int dvo_timing_offset =
-               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
-               lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
-       char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
-
-       return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+       return (const void *)data + ptrs->ptr[index].dvo_timing.offset;
 }
 
-/* get lvds_fp_timing entry
- * this function may return NULL if the corresponding entry is invalid
- */
 static const struct lvds_fp_timing *
-get_lvds_fp_timing(const struct bdb_header *bdb,
-                  const struct bdb_lvds_lfp_data *data,
+get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
                   const struct bdb_lvds_lfp_data_ptrs *ptrs,
                   int index)
 {
-       size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
-       u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
-       size_t ofs;
-
-       if (index >= ARRAY_SIZE(ptrs->ptr))
-               return NULL;
-       ofs = ptrs->ptr[index].fp_timing_offset;
-       if (ofs < data_ofs ||
-           ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
-               return NULL;
-       return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
+       return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
 /* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915,
-                   const struct bdb_header *bdb)
+parse_panel_options(struct drm_i915_private *i915)
 {
        const struct bdb_lvds_options *lvds_options;
        int panel_type;
        int drrs_mode;
        int ret;
 
-       lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+       lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
        if (!lvds_options)
                return;
 
@@ -257,16 +472,16 @@ parse_panel_options(struct drm_i915_private *i915,
         */
        switch (drrs_mode) {
        case 0:
-               i915->vbt.drrs_type = STATIC_DRRS_SUPPORT;
+               i915->vbt.drrs_type = DRRS_TYPE_STATIC;
                drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n");
                break;
        case 2:
-               i915->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
+               i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
                drm_dbg_kms(&i915->drm,
                            "DRRS supported mode is seamless\n");
                break;
        default:
-               i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
+               i915->vbt.drrs_type = DRRS_TYPE_NONE;
                drm_dbg_kms(&i915->drm,
                            "DRRS not supported (VBT input)\n");
                break;
@@ -275,8 +490,7 @@ parse_panel_options(struct drm_i915_private *i915,
 
 /* Try to find integrated panel timing data */
 static void
-parse_lfp_panel_dtd(struct drm_i915_private *i915,
-                   const struct bdb_header *bdb)
+parse_lfp_panel_dtd(struct drm_i915_private *i915)
 {
        const struct bdb_lvds_lfp_data *lvds_lfp_data;
        const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
@@ -285,11 +499,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
        struct drm_display_mode *panel_fixed_mode;
        int panel_type = i915->vbt.panel_type;
 
-       lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+       lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
        if (!lvds_lfp_data)
                return;
 
-       lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+       lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
        if (!lvds_lfp_data_ptrs)
                return;
 
@@ -306,34 +520,32 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
        i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 
        drm_dbg_kms(&i915->drm,
-                   "Found panel mode in BIOS VBT legacy lfp table:\n");
-       drm_mode_debug_printmodeline(panel_fixed_mode);
+                   "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(panel_fixed_mode));
 
-       fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
+       fp_timing = get_lvds_fp_timing(lvds_lfp_data,
                                       lvds_lfp_data_ptrs,
                                       panel_type);
-       if (fp_timing) {
-               /* check the resolution, just to be sure */
-               if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
-                   fp_timing->y_res == panel_fixed_mode->vdisplay) {
-                       i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
-                       drm_dbg_kms(&i915->drm,
-                                   "VBT initial LVDS value %x\n",
-                                   i915->vbt.bios_lvds_val);
-               }
+
+       /* check the resolution, just to be sure */
+       if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
+           fp_timing->y_res == panel_fixed_mode->vdisplay) {
+               i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
+               drm_dbg_kms(&i915->drm,
+                           "VBT initial LVDS value %x\n",
+                           i915->vbt.bios_lvds_val);
        }
 }
 
 static void
-parse_generic_dtd(struct drm_i915_private *i915,
-                 const struct bdb_header *bdb)
+parse_generic_dtd(struct drm_i915_private *i915)
 {
        const struct bdb_generic_dtd *generic_dtd;
        const struct generic_dtd_entry *dtd;
        struct drm_display_mode *panel_fixed_mode;
        int num_dtd;
 
-       generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
+       generic_dtd = find_section(i915, BDB_GENERIC_DTD);
        if (!generic_dtd)
                return;
 
@@ -397,15 +609,14 @@ parse_generic_dtd(struct drm_i915_private *i915,
                panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
 
        drm_dbg_kms(&i915->drm,
-                   "Found panel mode in BIOS VBT generic dtd table:\n");
-       drm_mode_debug_printmodeline(panel_fixed_mode);
+                   "Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(panel_fixed_mode));
 
        i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 }
 
 static void
-parse_panel_dtd(struct drm_i915_private *i915,
-               const struct bdb_header *bdb)
+parse_panel_dtd(struct drm_i915_private *i915)
 {
        /*
         * Older VBTs provided provided DTD information for internal displays
@@ -415,22 +626,21 @@ parse_panel_dtd(struct drm_i915_private *i915,
         * try the new generic DTD block first on VBT >= 229, but still fall
         * back to trying the old LFP block if that fails.
         */
-       if (bdb->version >= 229)
-               parse_generic_dtd(i915, bdb);
+       if (i915->vbt.version >= 229)
+               parse_generic_dtd(i915);
        if (!i915->vbt.lfp_lvds_vbt_mode)
-               parse_lfp_panel_dtd(i915, bdb);
+               parse_lfp_panel_dtd(i915);
 }
 
 static void
-parse_lfp_backlight(struct drm_i915_private *i915,
-                   const struct bdb_header *bdb)
+parse_lfp_backlight(struct drm_i915_private *i915)
 {
        const struct bdb_lfp_backlight_data *backlight_data;
        const struct lfp_backlight_data_entry *entry;
        int panel_type = i915->vbt.panel_type;
        u16 level;
 
-       backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+       backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
        if (!backlight_data)
                return;
 
@@ -452,12 +662,12 @@ parse_lfp_backlight(struct drm_i915_private *i915,
        }
 
        i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
-       if (bdb->version >= 191) {
+       if (i915->vbt.version >= 191) {
                size_t exp_size;
 
-               if (bdb->version >= 236)
+               if (i915->vbt.version >= 236)
                        exp_size = sizeof(struct bdb_lfp_backlight_data);
-               else if (bdb->version >= 234)
+               else if (i915->vbt.version >= 234)
                        exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234;
                else
                        exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191;
@@ -474,14 +684,14 @@ parse_lfp_backlight(struct drm_i915_private *i915,
        i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
        i915->vbt.backlight.active_low_pwm = entry->active_low_pwm;
 
-       if (bdb->version >= 234) {
+       if (i915->vbt.version >= 234) {
                u16 min_level;
                bool scale;
 
                level = backlight_data->brightness_level[panel_type].level;
                min_level = backlight_data->brightness_min_level[panel_type].level;
 
-               if (bdb->version >= 236)
+               if (i915->vbt.version >= 236)
                        scale = backlight_data->brightness_precision_bits[panel_type] == 16;
                else
                        scale = level > 255;
@@ -514,8 +724,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
 
 /* Try to find sdvo panel data */
 static void
-parse_sdvo_panel_data(struct drm_i915_private *i915,
-                     const struct bdb_header *bdb)
+parse_sdvo_panel_data(struct drm_i915_private *i915)
 {
        const struct bdb_sdvo_panel_dtds *dtds;
        struct drm_display_mode *panel_fixed_mode;
@@ -531,14 +740,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
        if (index == -1) {
                const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 
-               sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+               sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
                if (!sdvo_lvds_options)
                        return;
 
                index = sdvo_lvds_options->panel_type;
        }
 
-       dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+       dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
        if (!dtds)
                return;
 
@@ -551,8 +760,8 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
        i915->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
 
        drm_dbg_kms(&i915->drm,
-                   "Found SDVO panel mode in BIOS VBT tables:\n");
-       drm_mode_debug_printmodeline(panel_fixed_mode);
+                   "Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(panel_fixed_mode));
 }
 
 static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
@@ -570,18 +779,17 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
 }
 
 static void
-parse_general_features(struct drm_i915_private *i915,
-                      const struct bdb_header *bdb)
+parse_general_features(struct drm_i915_private *i915)
 {
        const struct bdb_general_features *general;
 
-       general = find_section(bdb, BDB_GENERAL_FEATURES);
+       general = find_section(i915, BDB_GENERAL_FEATURES);
        if (!general)
                return;
 
        i915->vbt.int_tv_support = general->int_tv_support;
        /* int_crt_support can't be trusted on earlier platforms */
-       if (bdb->version >= 155 &&
+       if (i915->vbt.version >= 155 &&
            (HAS_DDI(i915) || IS_VALLEYVIEW(i915)))
                i915->vbt.int_crt_support = general->int_crt_support;
        i915->vbt.lvds_use_ssc = general->enable_ssc;
@@ -589,7 +797,7 @@ parse_general_features(struct drm_i915_private *i915,
                intel_bios_ssc_frequency(i915, general->ssc_freq);
        i915->vbt.display_clock_mode = general->display_clock_mode;
        i915->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
-       if (bdb->version >= 181) {
+       if (i915->vbt.version >= 181) {
                i915->vbt.orientation = general->rotate_180 ?
                        DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
                        DRM_MODE_PANEL_ORIENTATION_NORMAL;
@@ -597,7 +805,7 @@ parse_general_features(struct drm_i915_private *i915,
                i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
        }
 
-       if (bdb->version >= 249 && general->afc_startup_config) {
+       if (i915->vbt.version >= 249 && general->afc_startup_config) {
                i915->vbt.override_afc_startup = true;
                i915->vbt.override_afc_startup_val = general->afc_startup_config == 0x1 ? 0x0 : 0x7;
        }
@@ -695,12 +903,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
 }
 
 static void
-parse_driver_features(struct drm_i915_private *i915,
-                     const struct bdb_header *bdb)
+parse_driver_features(struct drm_i915_private *i915)
 {
        const struct bdb_driver_features *driver;
 
-       driver = find_section(bdb, BDB_DRIVER_FEATURES);
+       driver = find_section(i915, BDB_DRIVER_FEATURES);
        if (!driver)
                return;
 
@@ -724,13 +931,13 @@ parse_driver_features(struct drm_i915_private *i915,
                 * in the wild with the bits correctly populated. Version
                 * 108 (on i85x) does not have the bits correctly populated.
                 */
-               if (bdb->version >= 134 &&
+               if (i915->vbt.version >= 134 &&
                    driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
                    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
                        i915->vbt.int_lvds_support = 0;
        }
 
-       if (bdb->version < 228) {
+       if (i915->vbt.version < 228) {
                drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
                            driver->drrs_enabled);
                /*
@@ -740,23 +947,22 @@ parse_driver_features(struct drm_i915_private *i915,
                 * driver->drrs_enabled=false
                 */
                if (!driver->drrs_enabled)
-                       i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
+                       i915->vbt.drrs_type = DRRS_TYPE_NONE;
 
                i915->vbt.psr.enable = driver->psr_enabled;
        }
 }
 
 static void
-parse_power_conservation_features(struct drm_i915_private *i915,
-                                 const struct bdb_header *bdb)
+parse_power_conservation_features(struct drm_i915_private *i915)
 {
        const struct bdb_lfp_power *power;
        u8 panel_type = i915->vbt.panel_type;
 
-       if (bdb->version < 228)
+       if (i915->vbt.version < 228)
                return;
 
-       power = find_section(bdb, BDB_LFP_POWER);
+       power = find_section(i915, BDB_LFP_POWER);
        if (!power)
                return;
 
@@ -769,21 +975,21 @@ parse_power_conservation_features(struct drm_i915_private *i915,
         * power->drrs & BIT(panel_type)=false
         */
        if (!(power->drrs & BIT(panel_type)))
-               i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
+               i915->vbt.drrs_type = DRRS_TYPE_NONE;
 
-       if (bdb->version >= 232)
+       if (i915->vbt.version >= 232)
                i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
 }
 
 static void
-parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_edp(struct drm_i915_private *i915)
 {
        const struct bdb_edp *edp;
        const struct edp_power_seq *edp_pps;
        const struct edp_fast_link_params *edp_link_params;
        int panel_type = i915->vbt.panel_type;
 
-       edp = find_section(bdb, BDB_EDP);
+       edp = find_section(i915, BDB_EDP);
        if (!edp)
                return;
 
@@ -876,7 +1082,7 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
                break;
        }
 
-       if (bdb->version >= 173) {
+       if (i915->vbt.version >= 173) {
                u8 vswing;
 
                /* Don't read from VBT if module parameter has valid value*/
@@ -888,16 +1094,19 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
                        i915->vbt.edp.low_vswing = vswing == 0;
                }
        }
+
+       i915->vbt.edp.drrs_msa_timing_delay =
+               (edp->sdrrs_msa_timing_delay >> (panel_type * 2)) & 3;
 }
 
 static void
-parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_psr(struct drm_i915_private *i915)
 {
        const struct bdb_psr *psr;
        const struct psr_table *psr_table;
        int panel_type = i915->vbt.panel_type;
 
-       psr = find_section(bdb, BDB_PSR);
+       psr = find_section(i915, BDB_PSR);
        if (!psr) {
                drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
                return;
@@ -916,7 +1125,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
         * New psr options 0=500us, 1=100us, 2=2500us, 3=0us
         * Old decimal value is wake up time in multiples of 100 us.
         */
-       if (bdb->version >= 205 &&
+       if (i915->vbt.version >= 205 &&
            (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
                switch (psr_table->tp1_wakeup_time) {
                case 0:
@@ -962,7 +1171,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
                i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
        }
 
-       if (bdb->version >= 226) {
+       if (i915->vbt.version >= 226) {
                u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
 
                wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
@@ -1031,8 +1240,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
 }
 
 static void
-parse_mipi_config(struct drm_i915_private *i915,
-                 const struct bdb_header *bdb)
+parse_mipi_config(struct drm_i915_private *i915)
 {
        const struct bdb_mipi_config *start;
        const struct mipi_config *config;
@@ -1055,7 +1263,7 @@ parse_mipi_config(struct drm_i915_private *i915,
        /* Parse #52 for panel index used from panel_type already
         * parsed
         */
-       start = find_section(bdb, BDB_MIPI_CONFIG);
+       start = find_section(i915, BDB_MIPI_CONFIG);
        if (!start) {
                drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
                return;
@@ -1082,7 +1290,7 @@ parse_mipi_config(struct drm_i915_private *i915,
                return;
        }
 
-       parse_dsi_backlight_ports(i915, bdb->version, port);
+       parse_dsi_backlight_ports(i915, i915->vbt.version, port);
 
        /* FIXME is the 90 vs. 270 correct? */
        switch (config->rotation) {
@@ -1351,8 +1559,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
 }
 
 static void
-parse_mipi_sequence(struct drm_i915_private *i915,
-                   const struct bdb_header *bdb)
+parse_mipi_sequence(struct drm_i915_private *i915)
 {
        int panel_type = i915->vbt.panel_type;
        const struct bdb_mipi_sequence *sequence;
@@ -1365,7 +1572,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
        if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
                return;
 
-       sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+       sequence = find_section(i915, BDB_MIPI_SEQUENCE);
        if (!sequence) {
                drm_dbg_kms(&i915->drm,
                            "No MIPI Sequence found, parsing complete\n");
@@ -1436,8 +1643,7 @@ err:
 }
 
 static void
-parse_compression_parameters(struct drm_i915_private *i915,
-                            const struct bdb_header *bdb)
+parse_compression_parameters(struct drm_i915_private *i915)
 {
        const struct bdb_compression_parameters *params;
        struct intel_bios_encoder_data *devdata;
@@ -1445,10 +1651,10 @@ parse_compression_parameters(struct drm_i915_private *i915,
        u16 block_size;
        int index;
 
-       if (bdb->version < 198)
+       if (i915->vbt.version < 198)
                return;
 
-       params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
+       params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
        if (params) {
                /* Sanity checks */
                if (params->entry_size != sizeof(params->data[0])) {
@@ -1955,6 +2161,12 @@ static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devd
                fallthrough;
        case HDMI_MAX_DATA_RATE_PLATFORM:
                return 0;
+       case HDMI_MAX_DATA_RATE_594:
+               return 594000;
+       case HDMI_MAX_DATA_RATE_340:
+               return 340000;
+       case HDMI_MAX_DATA_RATE_300:
+               return 300000;
        case HDMI_MAX_DATA_RATE_297:
                return 297000;
        case HDMI_MAX_DATA_RATE_165:
@@ -2077,8 +2289,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
 }
 
 static void
-parse_general_definitions(struct drm_i915_private *i915,
-                         const struct bdb_header *bdb)
+parse_general_definitions(struct drm_i915_private *i915)
 {
        const struct bdb_general_definitions *defs;
        struct intel_bios_encoder_data *devdata;
@@ -2088,7 +2299,7 @@ parse_general_definitions(struct drm_i915_private *i915,
        u16 block_size;
        int bus_pin;
 
-       defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
        if (!defs) {
                drm_dbg_kms(&i915->drm,
                            "No general definition block is found, no devices defined.\n");
@@ -2108,31 +2319,31 @@ parse_general_definitions(struct drm_i915_private *i915,
        if (intel_gmbus_is_valid_pin(i915, bus_pin))
                i915->vbt.crt_ddc_pin = bus_pin;
 
-       if (bdb->version < 106) {
+       if (i915->vbt.version < 106) {
                expected_size = 22;
-       } else if (bdb->version < 111) {
+       } else if (i915->vbt.version < 111) {
                expected_size = 27;
-       } else if (bdb->version < 195) {
+       } else if (i915->vbt.version < 195) {
                expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE;
-       } else if (bdb->version == 195) {
+       } else if (i915->vbt.version == 195) {
                expected_size = 37;
-       } else if (bdb->version <= 215) {
+       } else if (i915->vbt.version <= 215) {
                expected_size = 38;
-       } else if (bdb->version <= 237) {
+       } else if (i915->vbt.version <= 237) {
                expected_size = 39;
        } else {
                expected_size = sizeof(*child);
                BUILD_BUG_ON(sizeof(*child) < 39);
                drm_dbg(&i915->drm,
                        "Expected child device config size for VBT version %u not known; assuming %u\n",
-                       bdb->version, expected_size);
+                       i915->vbt.version, expected_size);
        }
 
        /* Flag an error for unexpected size, but continue anyway. */
        if (defs->child_dev_size != expected_size)
                drm_err(&i915->drm,
                        "Unexpected child device config size %u (expected %u for VBT version %u)\n",
-                       defs->child_dev_size, expected_size, bdb->version);
+                       defs->child_dev_size, expected_size, i915->vbt.version);
 
        /* The legacy sized child device config is the minimum we need. */
        if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
@@ -2457,6 +2668,7 @@ void intel_bios_init(struct drm_i915_private *i915)
        const struct bdb_header *bdb;
 
        INIT_LIST_HEAD(&i915->vbt.display_devices);
+       INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
 
        if (!HAS_DISPLAY(i915)) {
                drm_dbg_kms(&i915->drm,
@@ -2488,24 +2700,26 @@ void intel_bios_init(struct drm_i915_private *i915)
 
        drm_dbg_kms(&i915->drm,
                    "VBT signature \"%.*s\", BDB version %d\n",
-                   (int)sizeof(vbt->signature), vbt->signature, bdb->version);
+                   (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
+
+       init_bdb_blocks(i915, bdb);
 
        /* Grab useful general definitions */
-       parse_general_features(i915, bdb);
-       parse_general_definitions(i915, bdb);
-       parse_panel_options(i915, bdb);
-       parse_panel_dtd(i915, bdb);
-       parse_lfp_backlight(i915, bdb);
-       parse_sdvo_panel_data(i915, bdb);
-       parse_driver_features(i915, bdb);
-       parse_power_conservation_features(i915, bdb);
-       parse_edp(i915, bdb);
-       parse_psr(i915, bdb);
-       parse_mipi_config(i915, bdb);
-       parse_mipi_sequence(i915, bdb);
+       parse_general_features(i915);
+       parse_general_definitions(i915);
+       parse_panel_options(i915);
+       parse_panel_dtd(i915);
+       parse_lfp_backlight(i915);
+       parse_sdvo_panel_data(i915);
+       parse_driver_features(i915);
+       parse_power_conservation_features(i915);
+       parse_edp(i915);
+       parse_psr(i915);
+       parse_mipi_config(i915);
+       parse_mipi_sequence(i915);
 
        /* Depends on child device list */
-       parse_compression_parameters(i915, bdb);
+       parse_compression_parameters(i915);
 
 out:
        if (!vbt) {
@@ -2527,14 +2741,20 @@ out:
  */
 void intel_bios_driver_remove(struct drm_i915_private *i915)
 {
-       struct intel_bios_encoder_data *devdata, *n;
+       struct intel_bios_encoder_data *devdata, *nd;
+       struct bdb_block_entry *entry, *ne;
 
-       list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
+       list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
                list_del(&devdata->node);
                kfree(devdata->dsc);
                kfree(devdata);
        }
 
+       list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
+               list_del(&entry->node);
+               kfree(entry);
+       }
+
        kfree(i915->vbt.sdvo_lvds_vbt_mode);
        i915->vbt.sdvo_lvds_vbt_mode = NULL;
        kfree(i915->vbt.lfp_lvds_vbt_mode);
index adf58c5..37bd7b1 100644 (file)
@@ -6,6 +6,7 @@
 #include <drm/drm_atomic_state_helper.h>
 
 #include "i915_reg.h"
+#include "i915_utils.h"
 #include "intel_atomic.h"
 #include "intel_bw.h"
 #include "intel_cdclk.h"
@@ -124,8 +125,8 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
        /* bspec says to keep retrying for at least 1 ms */
        ret = skl_pcode_request(dev_priv, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
                                points_mask,
-                               ICL_PCODE_POINTS_RESTRICTED_MASK,
-                               ICL_PCODE_POINTS_RESTRICTED,
+                               ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
+                               ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
                                1);
 
        if (ret < 0) {
@@ -464,20 +465,25 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
 
 static void dg2_get_bw_info(struct drm_i915_private *i915)
 {
-       struct intel_bw_info *bi = &i915->max_bw[0];
+       unsigned int deratedbw = IS_DG2_G11(i915) ? 38000 : 50000;
+       int num_groups = ARRAY_SIZE(i915->max_bw);
+       int i;
 
        /*
         * DG2 doesn't have SAGV or QGV points, just a constant max bandwidth
-        * that doesn't depend on the number of planes enabled.  Create a
-        * single dummy QGV point to reflect that.  DG2-G10 platforms have a
-        * constant 50 GB/s bandwidth, whereas DG2-G11 platforms have 38 GB/s.
+        * that doesn't depend on the number of planes enabled. So fill all the
+        * plane group with constant bw information for uniformity with other
+        * platforms. DG2-G10 platforms have a constant 50 GB/s bandwidth,
+        * whereas DG2-G11 platforms have 38 GB/s.
         */
-       bi->num_planes = 1;
-       bi->num_qgv_points = 1;
-       if (IS_DG2_G11(i915))
-               bi->deratedbw[0] = 38000;
-       else
-               bi->deratedbw[0] = 50000;
+       for (i = 0; i < num_groups; i++) {
+               struct intel_bw_info *bi = &i915->max_bw[i];
+
+               bi->num_planes = 1;
+               /* Need only one dummy QGV point per group */
+               bi->num_qgv_points = 1;
+               bi->deratedbw[0] = deratedbw;
+       }
 
        i915->sagv_status = I915_SAGV_NOT_CONTROLLED;
 }
@@ -578,6 +584,7 @@ static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_stat
 static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
        unsigned int data_rate = 0;
        enum plane_id plane_id;
 
@@ -590,11 +597,26 @@ static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_
                        continue;
 
                data_rate += crtc_state->data_rate[plane_id];
+
+               if (DISPLAY_VER(i915) < 11)
+                       data_rate += crtc_state->data_rate_y[plane_id];
        }
 
        return data_rate;
 }
 
+/* "Maximum Pipe Read Bandwidth" */
+static int intel_bw_crtc_min_cdclk(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+       if (DISPLAY_VER(i915) < 12)
+               return 0;
+
+       return DIV_ROUND_UP_ULL(mul_u32_u32(intel_bw_crtc_data_rate(crtc_state), 10), 512);
+}
+
 void intel_bw_crtc_update(struct intel_bw_state *bw_state,
                          const struct intel_crtc_state *crtc_state)
 {
@@ -633,8 +655,8 @@ static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
        for_each_pipe(dev_priv, pipe)
                data_rate += bw_state->data_rate[pipe];
 
-       if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active(dev_priv))
-               data_rate = data_rate * 105 / 100;
+       if (DISPLAY_VER(dev_priv) >= 13 && i915_vtd_active(dev_priv))
+               data_rate = DIV_ROUND_UP(data_rate * 105, 100);
 
        return data_rate;
 }
@@ -674,6 +696,53 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state)
        return to_intel_bw_state(bw_state);
 }
 
+static bool intel_bw_state_changed(struct drm_i915_private *i915,
+                                  const struct intel_bw_state *old_bw_state,
+                                  const struct intel_bw_state *new_bw_state)
+{
+       enum pipe pipe;
+
+       for_each_pipe(i915, pipe) {
+               const struct intel_dbuf_bw *old_crtc_bw =
+                       &old_bw_state->dbuf_bw[pipe];
+               const struct intel_dbuf_bw *new_crtc_bw =
+                       &new_bw_state->dbuf_bw[pipe];
+               enum dbuf_slice slice;
+
+               for_each_dbuf_slice(i915, slice) {
+                       if (old_crtc_bw->max_bw[slice] != new_crtc_bw->max_bw[slice] ||
+                           old_crtc_bw->active_planes[slice] != new_crtc_bw->active_planes[slice])
+                               return true;
+               }
+
+               if (old_bw_state->min_cdclk[pipe] != new_bw_state->min_cdclk[pipe])
+                       return true;
+       }
+
+       return false;
+}
+
+static void skl_plane_calc_dbuf_bw(struct intel_bw_state *bw_state,
+                                  struct intel_crtc *crtc,
+                                  enum plane_id plane_id,
+                                  const struct skl_ddb_entry *ddb,
+                                  unsigned int data_rate)
+{
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+       struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe];
+       unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb);
+       enum dbuf_slice slice;
+
+       /*
+        * The arbiter can only really guarantee an
+        * equal share of the total bw to each plane.
+        */
+       for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) {
+               crtc_bw->max_bw[slice] = max(crtc_bw->max_bw[slice], data_rate);
+               crtc_bw->active_planes[slice] |= BIT(plane_id);
+       }
+}
+
 static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state,
                                  const struct intel_crtc_state *crtc_state)
 {
@@ -682,136 +751,145 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state,
        struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe];
        enum plane_id plane_id;
 
-       memset(&crtc_bw->used_bw, 0, sizeof(crtc_bw->used_bw));
+       memset(crtc_bw, 0, sizeof(*crtc_bw));
 
        if (!crtc_state->hw.active)
                return;
 
        for_each_plane_id_on_crtc(crtc, plane_id) {
-               const struct skl_ddb_entry *ddb_y =
-                       &crtc_state->wm.skl.plane_ddb_y[plane_id];
-               const struct skl_ddb_entry *ddb_uv =
-                       &crtc_state->wm.skl.plane_ddb_uv[plane_id];
-               unsigned int data_rate = crtc_state->data_rate[plane_id];
-               unsigned int dbuf_mask = 0;
-               enum dbuf_slice slice;
-
-               dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_y);
-               dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_uv);
-
                /*
-                * FIXME: To calculate that more properly we probably
-                * need to split per plane data_rate into data_rate_y
-                * and data_rate_uv for multiplanar formats in order not
-                * to get accounted those twice if they happen to reside
-                * on different slices.
-                * However for pre-icl this would work anyway because
-                * we have only single slice and for icl+ uv plane has
-                * non-zero data rate.
-                * So in worst case those calculation are a bit
-                * pessimistic, which shouldn't pose any significant
-                * problem anyway.
+                * We assume cursors are small enough
+                * to not cause bandwidth problems.
                 */
-               for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask)
-                       crtc_bw->used_bw[slice] += data_rate;
-       }
-}
-
-int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       struct intel_bw_state *new_bw_state = NULL;
-       struct intel_bw_state *old_bw_state = NULL;
-       const struct intel_crtc_state *crtc_state;
-       struct intel_crtc *crtc;
-       int max_bw = 0;
-       enum pipe pipe;
-       int i;
-
-       for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-               new_bw_state = intel_atomic_get_bw_state(state);
-               if (IS_ERR(new_bw_state))
-                       return PTR_ERR(new_bw_state);
+               if (plane_id == PLANE_CURSOR)
+                       continue;
 
-               old_bw_state = intel_atomic_get_old_bw_state(state);
+               skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id,
+                                      &crtc_state->wm.skl.plane_ddb[plane_id],
+                                      crtc_state->data_rate[plane_id]);
 
-               skl_crtc_calc_dbuf_bw(new_bw_state, crtc_state);
+               if (DISPLAY_VER(i915) < 11)
+                       skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id,
+                                              &crtc_state->wm.skl.plane_ddb_y[plane_id],
+                                              crtc_state->data_rate[plane_id]);
        }
+}
 
-       if (!old_bw_state)
-               return 0;
+/* "Maximum Data Buffer Bandwidth" */
+static int
+intel_bw_dbuf_min_cdclk(struct drm_i915_private *i915,
+                       const struct intel_bw_state *bw_state)
+{
+       unsigned int total_max_bw = 0;
+       enum dbuf_slice slice;
 
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_dbuf_bw *crtc_bw;
-               enum dbuf_slice slice;
+       for_each_dbuf_slice(i915, slice) {
+               int num_active_planes = 0;
+               unsigned int max_bw = 0;
+               enum pipe pipe;
 
-               crtc_bw = &new_bw_state->dbuf_bw[pipe];
+               /*
+                * The arbiter can only really guarantee an
+                * equal share of the total bw to each plane.
+                */
+               for_each_pipe(i915, pipe) {
+                       const struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[pipe];
 
-               for_each_dbuf_slice(dev_priv, slice) {
-                       /*
-                        * Current experimental observations show that contrary
-                        * to BSpec we get underruns once we exceed 64 * CDCLK
-                        * for slices in total.
-                        * As a temporary measure in order not to keep CDCLK
-                        * bumped up all the time we calculate CDCLK according
-                        * to this formula for  overall bw consumed by slices.
-                        */
-                       max_bw += crtc_bw->used_bw[slice];
+                       max_bw = max(crtc_bw->max_bw[slice], max_bw);
+                       num_active_planes += hweight8(crtc_bw->active_planes[slice]);
                }
+               max_bw *= num_active_planes;
+
+               total_max_bw = max(total_max_bw, max_bw);
        }
 
-       new_bw_state->min_cdclk = max_bw / 64;
+       return DIV_ROUND_UP(total_max_bw, 64);
+}
 
-       if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
-               int ret = intel_atomic_lock_global_state(&new_bw_state->base);
+int intel_bw_min_cdclk(struct drm_i915_private *i915,
+                      const struct intel_bw_state *bw_state)
+{
+       enum pipe pipe;
+       int min_cdclk;
 
-               if (ret)
-                       return ret;
-       }
+       min_cdclk = intel_bw_dbuf_min_cdclk(i915, bw_state);
 
-       return 0;
+       for_each_pipe(i915, pipe)
+               min_cdclk = max(bw_state->min_cdclk[pipe], min_cdclk);
+
+       return min_cdclk;
 }
 
-int intel_bw_calc_min_cdclk(struct intel_atomic_state *state)
+int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
+                           bool *need_cdclk_calc)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
        struct intel_bw_state *new_bw_state = NULL;
-       struct intel_bw_state *old_bw_state = NULL;
+       const struct intel_bw_state *old_bw_state = NULL;
+       const struct intel_cdclk_state *cdclk_state;
        const struct intel_crtc_state *crtc_state;
+       int old_min_cdclk, new_min_cdclk;
        struct intel_crtc *crtc;
-       int min_cdclk = 0;
-       enum pipe pipe;
        int i;
 
+       if (DISPLAY_VER(dev_priv) < 9)
+               return 0;
+
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
                new_bw_state = intel_atomic_get_bw_state(state);
                if (IS_ERR(new_bw_state))
                        return PTR_ERR(new_bw_state);
 
                old_bw_state = intel_atomic_get_old_bw_state(state);
+
+               skl_crtc_calc_dbuf_bw(new_bw_state, crtc_state);
+
+               new_bw_state->min_cdclk[crtc->pipe] =
+                       intel_bw_crtc_min_cdclk(crtc_state);
        }
 
        if (!old_bw_state)
                return 0;
 
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_cdclk_state *cdclk_state;
+       if (intel_bw_state_changed(dev_priv, old_bw_state, new_bw_state)) {
+               int ret = intel_atomic_lock_global_state(&new_bw_state->base);
+               if (ret)
+                       return ret;
+       }
 
-               cdclk_state = intel_atomic_get_new_cdclk_state(state);
-               if (!cdclk_state)
-                       return 0;
+       old_min_cdclk = intel_bw_min_cdclk(dev_priv, old_bw_state);
+       new_min_cdclk = intel_bw_min_cdclk(dev_priv, new_bw_state);
 
-               min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
-       }
+       /*
+        * No need to check against the cdclk state if
+        * the min cdclk doesn't increase.
+        *
+        * Ie. we only ever increase the cdclk due to bandwidth
+        * requirements. This can reduce back and forth
+        * display blinking due to constant cdclk changes.
+        */
+       if (new_min_cdclk <= old_min_cdclk)
+               return 0;
 
-       new_bw_state->min_cdclk = min_cdclk;
+       cdclk_state = intel_atomic_get_cdclk_state(state);
+       if (IS_ERR(cdclk_state))
+               return PTR_ERR(cdclk_state);
 
-       if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
-               int ret = intel_atomic_lock_global_state(&new_bw_state->base);
+       /*
+        * No need to recalculate the cdclk state if
+        * the min cdclk doesn't increase.
+        *
+        * Ie. we only ever increase the cdclk due to bandwidth
+        * requirements. This can reduce back and forth
+        * display blinking due to constant cdclk changes.
+        */
+       if (new_min_cdclk <= cdclk_state->bw_min_cdclk)
+               return 0;
 
-               if (ret)
-                       return ret;
-       }
+       drm_dbg_kms(&dev_priv->drm,
+                   "new bandwidth min cdclk (%d kHz) > old min cdclk (%d kHz)\n",
+                   new_min_cdclk, cdclk_state->bw_min_cdclk);
+       *need_cdclk_calc = true;
 
        return 0;
 }
@@ -820,7 +898,7 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
 {
        unsigned int num_psf_gv_points = i915->max_bw[0].num_psf_gv_points;
        unsigned int num_qgv_points = i915->max_bw[0].num_qgv_points;
-       u16 mask = 0;
+       u16 qgv_points = 0, psf_points = 0;
 
        /*
         * We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
@@ -828,12 +906,12 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
         * So need to operate only with those returned from PCode.
         */
        if (num_qgv_points > 0)
-               mask |= REG_GENMASK(num_qgv_points - 1, 0);
+               qgv_points = GENMASK(num_qgv_points - 1, 0);
 
        if (num_psf_gv_points > 0)
-               mask |= REG_GENMASK(num_psf_gv_points - 1, 0) << ADLS_PSF_PT_SHIFT;
+               psf_points = GENMASK(num_psf_gv_points - 1, 0);
 
-       return mask;
+       return ICL_PCODE_REQ_QGV_PT(qgv_points) | ADLS_PCODE_REQ_PSF_PT(psf_points);
 }
 
 static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed)
@@ -890,7 +968,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
        unsigned int data_rate;
        unsigned int num_active_planes;
        int i, ret;
-       u32 allowed_points = 0;
+       u16 qgv_points = 0, psf_points = 0;
        unsigned int max_bw_point = 0, max_bw = 0;
        unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points;
        unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points;
@@ -948,7 +1026,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
                        max_bw = max_data_rate;
                }
                if (max_data_rate >= data_rate)
-                       allowed_points |= REG_FIELD_PREP(ADLS_QGV_PT_MASK, BIT(i));
+                       qgv_points |= BIT(i);
 
                drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
                            i, max_data_rate, data_rate);
@@ -958,7 +1036,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
                unsigned int max_data_rate = adl_psf_bw(dev_priv, i);
 
                if (max_data_rate >= data_rate)
-                       allowed_points |= REG_FIELD_PREP(ADLS_PSF_PT_MASK, BIT(i));
+                       psf_points |= BIT(i);
 
                drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d"
                            " required %d\n",
@@ -970,20 +1048,18 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
         * left, so if we couldn't - simply reject the configuration for obvious
         * reasons.
         */
-       if ((allowed_points & ADLS_QGV_PT_MASK) == 0) {
+       if (qgv_points == 0) {
                drm_dbg_kms(&dev_priv->drm, "No QGV points provide sufficient memory"
                            " bandwidth %d for display configuration(%d active planes).\n",
                            data_rate, num_active_planes);
                return -EINVAL;
        }
 
-       if (num_psf_gv_points > 0) {
-               if ((allowed_points & ADLS_PSF_PT_MASK) == 0) {
-                       drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory"
-                                   " bandwidth %d for display configuration(%d active planes).\n",
-                                   data_rate, num_active_planes);
-                       return -EINVAL;
-               }
+       if (num_psf_gv_points > 0 && psf_points == 0) {
+               drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory"
+                           " bandwidth %d for display configuration(%d active planes).\n",
+                           data_rate, num_active_planes);
+               return -EINVAL;
        }
 
        /*
@@ -992,16 +1068,18 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
         * cause.
         */
        if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
-               allowed_points &= ADLS_PSF_PT_MASK;
-               allowed_points |= BIT(max_bw_point);
+               qgv_points = BIT(max_bw_point);
                drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n",
                            max_bw_point);
        }
+
        /*
         * We store the ones which need to be masked as that is what PCode
         * actually accepts as a parameter.
         */
-       new_bw_state->qgv_points_mask = ~allowed_points &
+       new_bw_state->qgv_points_mask =
+               ~(ICL_PCODE_REQ_QGV_PT(qgv_points) |
+                 ADLS_PCODE_REQ_PSF_PT(psf_points)) &
                icl_qgv_points_mask(dev_priv);
 
        /*
index 0ceaed1..cb7ee3a 100644 (file)
@@ -17,7 +17,8 @@ struct intel_atomic_state;
 struct intel_crtc_state;
 
 struct intel_dbuf_bw {
-       int used_bw[I915_MAX_DBUF_SLICES];
+       unsigned int max_bw[I915_MAX_DBUF_SLICES];
+       u8 active_planes[I915_MAX_DBUF_SLICES];
 };
 
 struct intel_bw_state {
@@ -40,10 +41,9 @@ struct intel_bw_state {
         */
        u16 qgv_points_mask;
 
+       int min_cdclk[I915_MAX_PIPES];
        unsigned int data_rate[I915_MAX_PIPES];
        u8 num_active_planes[I915_MAX_PIPES];
-
-       int min_cdclk;
 };
 
 #define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base)
@@ -64,7 +64,9 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state,
                          const struct intel_crtc_state *crtc_state);
 int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
                                  u32 points_mask);
-int intel_bw_calc_min_cdclk(struct intel_atomic_state *state);
-int skl_bw_calc_min_cdclk(struct intel_atomic_state *state);
+int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
+                           bool *need_cdclk_calc);
+int intel_bw_min_cdclk(struct drm_i915_private *i915,
+                      const struct intel_bw_state *bw_state);
 
 #endif /* __INTEL_BW_H__ */
index 8888fda..b2017d8 100644 (file)
@@ -72,7 +72,6 @@ struct intel_cdclk_funcs {
        void (*set_cdclk)(struct drm_i915_private *i915,
                          const struct intel_cdclk_config *cdclk_config,
                          enum pipe pipe);
-       int (*bw_calc_min_cdclk)(struct intel_atomic_state *state);
        int (*modeset_calc_cdclk)(struct intel_cdclk_state *state);
        u8 (*calc_voltage_level)(int cdclk);
 };
@@ -83,12 +82,6 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
        dev_priv->cdclk_funcs->get_cdclk(dev_priv, cdclk_config);
 }
 
-static int intel_cdclk_bw_calc_min_cdclk(struct intel_atomic_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       return dev_priv->cdclk_funcs->bw_calc_min_cdclk(state);
-}
-
 static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv,
                                  const struct intel_cdclk_config *cdclk_config,
                                  enum pipe pipe)
@@ -2325,13 +2318,6 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
                                        dev_priv->max_cdclk_freq));
        }
 
-       if (min_cdclk > dev_priv->max_cdclk_freq) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "required cdclk (%d kHz) exceeds max (%d kHz)\n",
-                           min_cdclk, dev_priv->max_cdclk_freq);
-               return -EINVAL;
-       }
-
        return min_cdclk;
 }
 
@@ -2339,7 +2325,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
 {
        struct intel_atomic_state *state = cdclk_state->base.state;
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       struct intel_bw_state *bw_state = NULL;
+       const struct intel_bw_state *bw_state;
        struct intel_crtc *crtc;
        struct intel_crtc_state *crtc_state;
        int min_cdclk, i;
@@ -2352,10 +2338,6 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
                if (min_cdclk < 0)
                        return min_cdclk;
 
-               bw_state = intel_atomic_get_bw_state(state);
-               if (IS_ERR(bw_state))
-                       return PTR_ERR(bw_state);
-
                if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk)
                        continue;
 
@@ -2366,14 +2348,31 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
                        return ret;
        }
 
-       min_cdclk = cdclk_state->force_min_cdclk;
-       for_each_pipe(dev_priv, pipe) {
-               min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
+       bw_state = intel_atomic_get_new_bw_state(state);
+       if (bw_state) {
+               min_cdclk = intel_bw_min_cdclk(dev_priv, bw_state);
 
-               if (!bw_state)
-                       continue;
+               if (cdclk_state->bw_min_cdclk != min_cdclk) {
+                       int ret;
+
+                       cdclk_state->bw_min_cdclk = min_cdclk;
+
+                       ret = intel_atomic_lock_global_state(&cdclk_state->base);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       min_cdclk = max(cdclk_state->force_min_cdclk,
+                       cdclk_state->bw_min_cdclk);
+       for_each_pipe(dev_priv, pipe)
+               min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
 
-               min_cdclk = max(bw_state->min_cdclk, min_cdclk);
+       if (min_cdclk > dev_priv->max_cdclk_freq) {
+               drm_dbg_kms(&dev_priv->drm,
+                           "required cdclk (%d kHz) exceeds max (%d kHz)\n",
+                           min_cdclk, dev_priv->max_cdclk_freq);
+               return -EINVAL;
        }
 
        return min_cdclk;
@@ -2654,14 +2653,10 @@ intel_atomic_get_cdclk_state(struct intel_atomic_state *state)
 int intel_cdclk_atomic_check(struct intel_atomic_state *state,
                             bool *need_cdclk_calc)
 {
-       struct drm_i915_private *i915 = to_i915(state->base.dev);
        const struct intel_cdclk_state *old_cdclk_state;
        const struct intel_cdclk_state *new_cdclk_state;
        struct intel_plane_state *plane_state;
-       struct intel_bw_state *new_bw_state;
        struct intel_plane *plane;
-       int min_cdclk = 0;
-       enum pipe pipe;
        int ret;
        int i;
 
@@ -2676,6 +2671,10 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
                        return ret;
        }
 
+       ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc);
+       if (ret)
+               return ret;
+
        old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
        new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
 
@@ -2683,23 +2682,6 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
            old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk)
                *need_cdclk_calc = true;
 
-       ret = intel_cdclk_bw_calc_min_cdclk(state);
-       if (ret)
-               return ret;
-
-       new_bw_state = intel_atomic_get_new_bw_state(state);
-
-       if (!new_cdclk_state || !new_bw_state)
-               return 0;
-
-       for_each_pipe(i915, pipe) {
-               min_cdclk = max(new_cdclk_state->min_cdclk[pipe], min_cdclk);
-
-               /* Currently do this change only if we need to increase */
-               if (new_bw_state->min_cdclk > min_cdclk)
-                       *need_cdclk_calc = true;
-       }
-
        return 0;
 }
 
@@ -3072,7 +3054,6 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
 static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
        .get_cdclk = bxt_get_cdclk,
        .set_cdclk = bxt_set_cdclk,
-       .bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
        .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
        .calc_voltage_level = tgl_calc_voltage_level,
 };
@@ -3080,7 +3061,6 @@ static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
 static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
        .get_cdclk = bxt_get_cdclk,
        .set_cdclk = bxt_set_cdclk,
-       .bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
        .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
        .calc_voltage_level = ehl_calc_voltage_level,
 };
@@ -3088,7 +3068,6 @@ static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
 static const struct intel_cdclk_funcs icl_cdclk_funcs = {
        .get_cdclk = bxt_get_cdclk,
        .set_cdclk = bxt_set_cdclk,
-       .bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
        .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
        .calc_voltage_level = icl_calc_voltage_level,
 };
@@ -3096,7 +3075,6 @@ static const struct intel_cdclk_funcs icl_cdclk_funcs = {
 static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
        .get_cdclk = bxt_get_cdclk,
        .set_cdclk = bxt_set_cdclk,
-       .bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
        .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
        .calc_voltage_level = bxt_calc_voltage_level,
 };
@@ -3104,53 +3082,45 @@ static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
 static const struct intel_cdclk_funcs skl_cdclk_funcs = {
        .get_cdclk = skl_get_cdclk,
        .set_cdclk = skl_set_cdclk,
-       .bw_calc_min_cdclk = skl_bw_calc_min_cdclk,
        .modeset_calc_cdclk = skl_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs bdw_cdclk_funcs = {
        .get_cdclk = bdw_get_cdclk,
        .set_cdclk = bdw_set_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = bdw_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs chv_cdclk_funcs = {
        .get_cdclk = vlv_get_cdclk,
        .set_cdclk = chv_set_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = vlv_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs vlv_cdclk_funcs = {
        .get_cdclk = vlv_get_cdclk,
        .set_cdclk = vlv_set_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = vlv_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs hsw_cdclk_funcs = {
        .get_cdclk = hsw_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 /* SNB, IVB, 965G, 945G */
 static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = {
        .get_cdclk = fixed_400mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs ilk_cdclk_funcs = {
        .get_cdclk = fixed_450mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
        .get_cdclk = gm45_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
@@ -3158,7 +3128,6 @@ static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
 
 static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
        .get_cdclk = i965gm_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
@@ -3166,19 +3135,16 @@ static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
 
 static const struct intel_cdclk_funcs pnv_cdclk_funcs = {
        .get_cdclk = pnv_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs g33_cdclk_funcs = {
        .get_cdclk = g33_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
        .get_cdclk = i945gm_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
@@ -3186,37 +3152,31 @@ static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
 
 static const struct intel_cdclk_funcs i915gm_cdclk_funcs = {
        .get_cdclk = i915gm_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i915g_cdclk_funcs = {
        .get_cdclk = fixed_333mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i865g_cdclk_funcs = {
        .get_cdclk = fixed_266mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i85x_cdclk_funcs = {
        .get_cdclk = i85x_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i845g_cdclk_funcs = {
        .get_cdclk = fixed_200mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
 static const struct intel_cdclk_funcs i830_cdclk_funcs = {
        .get_cdclk = fixed_133mhz_get_cdclk,
-       .bw_calc_min_cdclk = intel_bw_calc_min_cdclk,
        .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
 };
 
index df66f66..b535cf6 100644 (file)
@@ -36,6 +36,8 @@ struct intel_cdclk_state {
         */
        struct intel_cdclk_config actual;
 
+       /* minimum acceptable cdclk to satisfy bandwidth requirements */
+       int bw_min_cdclk;
        /* minimum acceptable cdclk for each pipe */
        int min_cdclk[I915_MAX_PIPES];
        /* minimum acceptable voltage level for each pipe */
index e94ec57..34128c9 100644 (file)
 struct intel_color_funcs {
        int (*color_check)(struct intel_crtc_state *crtc_state);
        /*
-        * Program double buffered color management registers during
-        * vblank evasion. The registers should then latch during the
-        * next vblank start, alongside any other double buffered registers
-        * involved with the same commit.
+        * Program non-arming double buffered color management registers
+        * before vblank evasion. The registers should then latch after
+        * the arming register is written (by color_commit_arm()) during
+        * the next vblank start, alongside any other double buffered
+        * registers involved with the same commit. This hook is optional.
+        */
+       void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state);
+       /*
+        * Program arming double buffered color management registers
+        * during vblank evasion. The registers (and whatever other registers
+        * they arm that were written by color_commit_noarm) should then latch
+        * during the next vblank start, alongside any other double buffered
+        * registers involved with the same commit.
         */
-       void (*color_commit)(const struct intel_crtc_state *crtc_state);
+       void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
        /*
         * Load LUTs (and other single buffered color management
         * registers). Will (hopefully) be called during the vblank
@@ -337,15 +346,11 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
                                    ilk_csc_coeff_identity,
                                    ilk_csc_off_zero);
        }
-
-       intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
-                         crtc_state->csc_mode);
 }
 
 static void icl_load_csc_matrix(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);
 
        if (crtc_state->hw.ctm) {
                u16 coeff[9];
@@ -364,9 +369,6 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
                                      ilk_csc_coeff_limited_range,
                                      ilk_csc_postoff_limited_range);
        }
-
-       intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
-                         crtc_state->csc_mode);
 }
 
 static void chv_load_cgm_csc(struct intel_crtc *crtc,
@@ -491,7 +493,17 @@ static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw
                                    REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw);
 }
 
-static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
+static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
+{
+       icl_load_csc_matrix(crtc_state);
+}
+
+static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
+{
+       ilk_load_csc_matrix(crtc_state);
+}
+
+static void i9xx_color_commit_arm(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);
@@ -504,7 +516,7 @@ static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
        intel_de_write(dev_priv, PIPECONF(pipe), val);
 }
 
-static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
+static void ilk_color_commit_arm(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);
@@ -516,10 +528,11 @@ static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
        val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
        intel_de_write(dev_priv, PIPECONF(pipe), val);
 
-       ilk_load_csc_matrix(crtc_state);
+       intel_de_write_fw(dev_priv, PIPE_CSC_MODE(pipe),
+                         crtc_state->csc_mode);
 }
 
-static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
+static void hsw_color_commit_arm(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);
@@ -527,10 +540,11 @@ static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
        intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
                       crtc_state->gamma_mode);
 
-       ilk_load_csc_matrix(crtc_state);
+       intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
+                         crtc_state->csc_mode);
 }
 
-static void skl_color_commit(const struct intel_crtc_state *crtc_state)
+static void skl_color_commit_arm(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);
@@ -551,10 +565,8 @@ static void skl_color_commit(const struct intel_crtc_state *crtc_state)
        intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
                       crtc_state->gamma_mode);
 
-       if (DISPLAY_VER(dev_priv) >= 11)
-               icl_load_csc_matrix(crtc_state);
-       else
-               ilk_load_csc_matrix(crtc_state);
+       intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
+                         crtc_state->csc_mode);
 }
 
 static void i9xx_load_lut_8(struct intel_crtc *crtc,
@@ -1169,11 +1181,19 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
        dev_priv->color_funcs->load_luts(crtc_state);
 }
 
-void intel_color_commit(const struct intel_crtc_state *crtc_state)
+void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+
+       if (dev_priv->color_funcs->color_commit_noarm)
+               dev_priv->color_funcs->color_commit_noarm(crtc_state);
+}
+
+void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
-       dev_priv->color_funcs->color_commit(crtc_state);
+       dev_priv->color_funcs->color_commit_arm(crtc_state);
 }
 
 static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
@@ -2132,70 +2152,77 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
 
 static const struct intel_color_funcs chv_color_funcs = {
        .color_check = chv_color_check,
-       .color_commit = i9xx_color_commit,
+       .color_commit_arm = i9xx_color_commit_arm,
        .load_luts = chv_load_luts,
        .read_luts = chv_read_luts,
 };
 
 static const struct intel_color_funcs i965_color_funcs = {
        .color_check = i9xx_color_check,
-       .color_commit = i9xx_color_commit,
+       .color_commit_arm = i9xx_color_commit_arm,
        .load_luts = i965_load_luts,
        .read_luts = i965_read_luts,
 };
 
 static const struct intel_color_funcs i9xx_color_funcs = {
        .color_check = i9xx_color_check,
-       .color_commit = i9xx_color_commit,
+       .color_commit_arm = i9xx_color_commit_arm,
        .load_luts = i9xx_load_luts,
        .read_luts = i9xx_read_luts,
 };
 
 static const struct intel_color_funcs icl_color_funcs = {
        .color_check = icl_color_check,
-       .color_commit = skl_color_commit,
+       .color_commit_noarm = icl_color_commit_noarm,
+       .color_commit_arm = skl_color_commit_arm,
        .load_luts = icl_load_luts,
        .read_luts = icl_read_luts,
 };
 
 static const struct intel_color_funcs glk_color_funcs = {
        .color_check = glk_color_check,
-       .color_commit = skl_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = skl_color_commit_arm,
        .load_luts = glk_load_luts,
        .read_luts = glk_read_luts,
 };
 
 static const struct intel_color_funcs skl_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit = skl_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = skl_color_commit_arm,
        .load_luts = bdw_load_luts,
        .read_luts = NULL,
 };
 
 static const struct intel_color_funcs bdw_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit = hsw_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = hsw_color_commit_arm,
        .load_luts = bdw_load_luts,
        .read_luts = NULL,
 };
 
 static const struct intel_color_funcs hsw_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit = hsw_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = hsw_color_commit_arm,
        .load_luts = ivb_load_luts,
        .read_luts = NULL,
 };
 
 static const struct intel_color_funcs ivb_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit = ilk_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = ilk_color_commit_arm,
        .load_luts = ivb_load_luts,
        .read_luts = NULL,
 };
 
 static const struct intel_color_funcs ilk_color_funcs = {
        .color_check = ilk_color_check,
-       .color_commit = ilk_color_commit,
+       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_arm = ilk_color_commit_arm,
        .load_luts = ilk_load_luts,
        .read_luts = ilk_read_luts,
 };
index 173727a..fd87342 100644 (file)
@@ -14,7 +14,8 @@ struct drm_property_blob;
 
 void intel_color_init(struct intel_crtc *crtc);
 int intel_color_check(struct intel_crtc_state *crtc_state);
-void intel_color_commit(const struct intel_crtc_state *crtc_state);
+void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
+void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
 void intel_color_get_config(struct intel_crtc_state *crtc_state);
 int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state);
index 4dfe773..64890f3 100644 (file)
@@ -25,18 +25,29 @@ enum {
 };
 
 static const struct icl_procmon {
+       const char *name;
        u32 dw1, dw9, dw10;
 } icl_procmon_values[] = {
-       [PROCMON_0_85V_DOT_0] =
-               { .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
-       [PROCMON_0_95V_DOT_0] =
-               { .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, },
-       [PROCMON_0_95V_DOT_1] =
-               { .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, },
-       [PROCMON_1_05V_DOT_0] =
-               { .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, },
-       [PROCMON_1_05V_DOT_1] =
-               { .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
+       [PROCMON_0_85V_DOT_0] = {
+               .name = "0.85V dot0 (low-voltage)",
+               .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96,
+       },
+       [PROCMON_0_95V_DOT_0] = {
+               .name = "0.95V dot0",
+               .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB,
+       },
+       [PROCMON_0_95V_DOT_1] = {
+               .name = "0.95V dot1",
+               .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5,
+       },
+       [PROCMON_1_05V_DOT_0] = {
+               .name = "1.05V dot0",
+               .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1,
+       },
+       [PROCMON_1_05V_DOT_1] = {
+               .name = "1.05V dot1",
+               .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1,
+       },
 };
 
 static const struct icl_procmon *
@@ -113,6 +124,10 @@ static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
 
        procmon = icl_get_procmon_ref_values(dev_priv, phy);
 
+       drm_dbg_kms(&dev_priv->drm,
+                   "Combo PHY %c Voltage/Process Info : %s\n",
+                   phy_name(phy), procmon->name);
+
        ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
                            (0xff << 16) | 0xff, procmon->dw1);
        ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy),
index c65f95a..1dcc268 100644 (file)
@@ -54,6 +54,8 @@ int intel_connector_init(struct intel_connector *connector)
        __drm_atomic_helper_connector_reset(&connector->base,
                                            &conn_state->base);
 
+       INIT_LIST_HEAD(&connector->panel.fixed_modes);
+
        return 0;
 }
 
@@ -100,7 +102,7 @@ void intel_connector_destroy(struct drm_connector *connector)
        if (!IS_ERR_OR_NULL(intel_connector->edid))
                kfree(intel_connector->edid);
 
-       intel_panel_fini(&intel_connector->panel);
+       intel_panel_fini(intel_connector);
 
        drm_connector_cleanup(connector);
 
index 6582748..4442aa3 100644 (file)
@@ -24,6 +24,7 @@
 #include "intel_display_debugfs.h"
 #include "intel_display_trace.h"
 #include "intel_display_types.h"
+#include "intel_drrs.h"
 #include "intel_dsi.h"
 #include "intel_pipe_crc.h"
 #include "intel_psr.h"
@@ -367,6 +368,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        intel_color_init(crtc);
 
+       intel_crtc_drrs_init(crtc);
        intel_crtc_crc_init(crtc);
 
        cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
@@ -485,6 +487,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
                intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
        DEFINE_WAIT(wait);
 
+       intel_psr_lock(new_crtc_state);
+
        if (new_crtc_state->do_async_flip)
                return;
 
@@ -516,7 +520,7 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
         * VBL interrupts will start the PSR exit and prevent a PSR
         * re-entry as well.
         */
-       intel_psr_wait_for_idle(new_crtc_state);
+       intel_psr_wait_for_idle_locked(new_crtc_state);
 
        local_irq_disable();
 
@@ -630,6 +634,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
        ktime_t end_vbl_time = ktime_get();
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
+       intel_psr_unlock(new_crtc_state);
+
        if (new_crtc_state->do_async_flip)
                return;
 
index 2ade8fd..8c80de8 100644 (file)
@@ -153,6 +153,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        plane_state->uapi.src = src;
        plane_state->uapi.dst = dst;
 
+       /* final plane coordinates will be relative to the plane's pipe */
+       drm_rect_translate(&plane_state->uapi.dst,
+                          -crtc_state->pipe_src.x1,
+                          -crtc_state->pipe_src.y1);
+
        ret = intel_cursor_check_surface(plane_state);
        if (ret)
                return ret;
@@ -255,7 +260,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        u32 cntl = 0, base = 0, pos = 0, size = 0;
-       unsigned long irqflags;
 
        if (plane_state && plane_state->uapi.visible) {
                unsigned int width = drm_rect_width(&plane_state->uapi.dst);
@@ -270,8 +274,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
                pos = intel_cursor_position(plane_state);
        }
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        /* On these chipsets we can only modify the base/size/stride
         * whilst the cursor is disabled.
         */
@@ -290,8 +292,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
        } else {
                intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
        }
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void i845_cursor_disable_arm(struct intel_plane *plane,
@@ -492,7 +492,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
        u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
-       unsigned long irqflags;
 
        if (plane_state && plane_state->uapi.visible) {
                int width = drm_rect_width(&plane_state->uapi.dst);
@@ -508,8 +507,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
                pos = intel_cursor_position(plane_state);
        }
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        /*
         * On some platforms writing CURCNTR first will also
         * cause CURPOS to be armed by the CURBASE write.
@@ -555,8 +552,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
                intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
                intel_de_write_fw(dev_priv, CURBASE(pipe), base);
        }
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void i9xx_cursor_disable_arm(struct intel_plane *plane,
@@ -637,7 +632,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
         * FIXME bigjoiner fastpath would be good
         */
        if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
-           crtc_state->update_pipe || crtc_state->bigjoiner)
+           crtc_state->update_pipe || crtc_state->bigjoiner_pipes)
                goto slow;
 
        /*
@@ -715,6 +710,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
         */
        crtc_state->active_planes = new_crtc_state->active_planes;
 
+       /*
+        * Technically we should do a vblank evasion here to make
+        * sure all the cursor registers update on the same frame.
+        * For now just make sure the register writes happen as
+        * quickly as possible to minimize the race window.
+        */
+       local_irq_disable();
+
        if (new_plane_state->uapi.visible) {
                intel_plane_update_noarm(plane, crtc_state, new_plane_state);
                intel_plane_update_arm(plane, crtc_state, new_plane_state);
@@ -722,6 +725,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
                intel_plane_disable_arm(plane, crtc_state);
        }
 
+       local_irq_enable();
+
        intel_plane_unpin_fb(old_plane_state);
 
 out_free:
index e426080..027cc4c 100644 (file)
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_privacy_screen_consumer.h>
 #include <drm/drm_scdc_helper.h>
 
@@ -43,7 +45,6 @@
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
 #include "intel_dpio_phy.h"
-#include "intel_drrs.h"
 #include "intel_dsi.h"
 #include "intel_fdi.h"
 #include "intel_fifo_underrun.h"
@@ -2152,7 +2153,7 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel
                               enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
                drm_dbg_kms(&i915->drm,
                            "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
-                           enabledisable(enable));
+                           str_enable_disable(enable));
 }
 
 static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
@@ -2818,10 +2819,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
        if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
                intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
 
-       intel_drrs_enable(intel_dp, crtc_state);
-
-       if (crtc_state->has_audio)
-               intel_audio_codec_enable(encoder, crtc_state, conn_state);
+       intel_audio_codec_enable(encoder, crtc_state, conn_state);
 
        trans_port_sync_stop_link_train(state, encoder, crtc_state);
 }
@@ -2915,8 +2913,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
        intel_de_write(dev_priv, DDI_BUF_CTL(port),
                       dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE);
 
-       if (crtc_state->has_audio)
-               intel_audio_codec_enable(encoder, crtc_state, conn_state);
+       intel_audio_codec_enable(encoder, crtc_state, conn_state);
 }
 
 static void intel_enable_ddi(struct intel_atomic_state *state,
@@ -2957,11 +2954,8 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
 
        intel_dp->link_trained = false;
 
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 
-       intel_drrs_disable(intel_dp, old_crtc_state);
        intel_psr_disable(intel_dp, old_crtc_state);
        intel_edp_backlight_off(old_conn_state);
        /* Disable the decompression in DP Sink */
@@ -2980,9 +2974,7 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
        struct drm_connector *connector = old_conn_state->connector;
 
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 
        if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
                                               false, false))
@@ -3011,12 +3003,9 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
                                     const struct intel_crtc_state *crtc_state,
                                     const struct drm_connector_state *conn_state)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
        intel_ddi_set_dp_msa(crtc_state, conn_state);
 
        intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
-       intel_drrs_update(intel_dp, crtc_state);
 
        intel_backlight_update(state, encoder, crtc_state, conn_state);
        drm_connector_update_privacy_screen(conn_state);
@@ -4308,6 +4297,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
                return;
        }
 
+       if (intel_phy_is_snps(dev_priv, phy) &&
+           dev_priv->snps_phy_failed_calibration & BIT(phy)) {
+               drm_dbg_kms(&dev_priv->drm,
+                           "SNPS PHY %c failed to calibrate, proceeding anyway\n",
+                           phy_name(phy));
+       }
+
        dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
        if (!dig_port)
                return;
index 934a9f9..94e6466 100644 (file)
@@ -907,7 +907,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr[] = {
        { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } },     /* 500   500      0.0   */
        { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } },     /* 500   700      2.9   */
        { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } },     /* 500   900      5.1   */
-       { .icl = { 0xC, 0x73, 0x3E, 0x00, 0x01 } },     /* 650   700      0.6   */
+       { .icl = { 0xC, 0x7C, 0x3C, 0x00, 0x03 } },     /* 650   700      0.6   */
        { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } },     /* 600   900      3.5   */
        { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } },     /* 900   900      0.0   */
 };
@@ -921,7 +921,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[
                                                        /* NT mV Trans mV db    */
        { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } },     /* 350   350      0.0   */
        { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } },     /* 350   500      3.1   */
-       { .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } },     /* 350   700      6.0   */
+       { .icl = { 0xC, 0x71, 0x30, 0x00, 0x0F } },     /* 350   700      6.0   */
        { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } },     /* 350   900      8.2   */
        { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } },     /* 500   500      0.0   */
        { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } },     /* 500   700      2.9   */
@@ -931,19 +931,47 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[
        { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } },     /* 900   900      0.0   */
 };
 
+static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_edp_hbr2[] = {
+                                                       /* NT mV Trans mV db    */
+       { .icl = { 0x4, 0x50, 0x38, 0x00, 0x07 } },     /* 200   200      0.0   */
+       { .icl = { 0x4, 0x58, 0x35, 0x00, 0x0A } },     /* 200   250      1.9   */
+       { .icl = { 0x4, 0x60, 0x34, 0x00, 0x0B } },     /* 200   300      3.5   */
+       { .icl = { 0x4, 0x6A, 0x32, 0x00, 0x0D } },     /* 200   350      4.9   */
+       { .icl = { 0x4, 0x5E, 0x38, 0x00, 0x07 } },     /* 250   250      0.0   */
+       { .icl = { 0x4, 0x61, 0x36, 0x00, 0x09 } },     /* 250   300      1.6   */
+       { .icl = { 0x4, 0x6B, 0x34, 0x00, 0x0B } },     /* 250   350      2.9   */
+       { .icl = { 0x4, 0x69, 0x39, 0x00, 0x06 } },     /* 300   300      0.0   */
+       { .icl = { 0x4, 0x73, 0x37, 0x00, 0x08 } },     /* 300   350      1.3   */
+       { .icl = { 0x4, 0x7A, 0x38, 0x00, 0x07 } },     /* 350   350      0.0   */
+};
+
+static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_edp_hbr3[] = {
+                                                       /* NT mV Trans mV db    */
+       { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } },     /* 350   350      0.0   */
+       { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } },     /* 350   500      3.1   */
+       { .icl = { 0xC, 0x71, 0x30, 0x00, 0x0f } },     /* 350   700      6.0   */
+       { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } },     /* 350   900      8.2   */
+       { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } },     /* 500   500      0.0   */
+       { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } },     /* 500   700      2.9   */
+       { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } },     /* 500   900      5.1   */
+       { .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } },     /* 650   700      0.6   */
+       { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } },     /* 600   900      3.5   */
+       { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } },     /* 900   900      0.0   */
+};
+
 static const struct intel_ddi_buf_trans adlp_combo_phy_trans_dp_hbr2_hbr3 = {
        .entries = _adlp_combo_phy_trans_dp_hbr2_hbr3,
        .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_hbr3),
 };
 
 static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_hbr3 = {
-       .entries = _icl_combo_phy_trans_dp_hbr2_edp_hbr3,
-       .num_entries = ARRAY_SIZE(_icl_combo_phy_trans_dp_hbr2_edp_hbr3),
+       .entries = _adlp_combo_phy_trans_dp_hbr2_edp_hbr3,
+       .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_edp_hbr3),
 };
 
 static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_up_to_hbr2 = {
-       .entries = _icl_combo_phy_trans_edp_hbr2,
-       .num_entries = ARRAY_SIZE(_icl_combo_phy_trans_edp_hbr2),
+       .entries = _adlp_combo_phy_trans_edp_hbr2,
+       .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_edp_hbr2),
 };
 
 static const union intel_ddi_buf_trans_entry _adlp_dkl_phy_trans_dp_hbr[] = {
index 7dfeb45..29044cf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/dma-resv.h>
 #include <linux/slab.h>
+#include <linux/string_helpers.h>
 #include <linux/vga_switcheroo.h>
 
 #include <drm/drm_atomic.h>
@@ -76,6 +77,7 @@
 #include "g4x_hdmi.h"
 #include "hsw_ips.h"
 #include "i915_drv.h"
+#include "i915_utils.h"
 #include "icl_dsi.h"
 #include "intel_acpi.h"
 #include "intel_atomic.h"
@@ -368,6 +370,11 @@ bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state)
                crtc->pipe == bigjoiner_master_pipe(crtc_state);
 }
 
+static int intel_bigjoiner_num_pipes(const struct intel_crtc_state *crtc_state)
+{
+       return hweight8(crtc_state->bigjoiner_pipes);
+}
+
 struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
@@ -400,7 +407,7 @@ static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state)
        if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100))
                drm_err(&dev_priv->drm,
                        "pipe %c scanline %s wait timed out\n",
-                       pipe_name(pipe), onoff(state));
+                       pipe_name(pipe), str_on_off(state));
 }
 
 static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc)
@@ -456,7 +463,7 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
        I915_STATE_WARN(cur_state != state,
                        "transcoder %s assertion failure (expected %s, current %s)\n",
                        transcoder_name(cpu_transcoder),
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 static void assert_plane(struct intel_plane *plane, bool state)
@@ -468,7 +475,8 @@ static void assert_plane(struct intel_plane *plane, bool state)
 
        I915_STATE_WARN(cur_state != state,
                        "%s assertion failure (expected %s, current %s)\n",
-                       plane->base.name, onoff(state), onoff(cur_state));
+                       plane->base.name, str_on_off(state),
+                       str_on_off(cur_state));
 }
 
 #define assert_plane_enabled(p) assert_plane(p, true)
@@ -517,16 +525,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
                         expected_mask);
 }
 
-enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
-       if (HAS_PCH_LPT(dev_priv))
-               return PIPE_A;
-       else
-               return crtc->pipe;
-}
-
 void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -783,6 +781,9 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
        intel_set_plane_visible(crtc_state, plane_state, false);
        fixup_plane_bitmasks(crtc_state);
        crtc_state->data_rate[plane->id] = 0;
+       crtc_state->data_rate_y[plane->id] = 0;
+       crtc_state->rel_data_rate[plane->id] = 0;
+       crtc_state->rel_data_rate_y[plane->id] = 0;
        crtc_state->min_cdclk[plane->id] = 0;
 
        if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 &&
@@ -1117,13 +1118,13 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state)
         * e.g. x201.
         */
        if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv))
-               intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE |
-                              PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe));
+               intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE |
+                                 PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe));
        else
-               intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE |
-                              PF_FILTER_MED_3x3);
-       intel_de_write(dev_priv, PF_WIN_POS(pipe), x << 16 | y);
-       intel_de_write(dev_priv, PF_WIN_SZ(pipe), width << 16 | height);
+               intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE |
+                                 PF_FILTER_MED_3x3);
+       intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), x << 16 | y);
+       intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), width << 16 | height);
 }
 
 static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc)
@@ -1197,7 +1198,7 @@ static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
 
-       return crtc_state->uapi.async_flip && intel_vtd_active(i915) &&
+       return crtc_state->uapi.async_flip && i915_vtd_active(i915) &&
                (DISPLAY_VER(i915) == 9 || IS_BROADWELL(i915) || IS_HASWELL(i915));
 }
 
@@ -1232,7 +1233,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
 
        hsw_ips_post_update(state, crtc);
        intel_fbc_post_update(state, crtc);
-       intel_drrs_page_flip(state, crtc);
 
        if (needs_async_flip_vtd_wa(old_crtc_state) &&
            !needs_async_flip_vtd_wa(new_crtc_state))
@@ -1250,6 +1250,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
            !needs_cursorclk_wa(new_crtc_state))
                icl_wa_cursorclkgating(dev_priv, pipe, false);
 
+       intel_drrs_activate(new_crtc_state);
 }
 
 static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -1327,6 +1328,8 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
                intel_atomic_get_new_crtc_state(state, crtc);
        enum pipe pipe = crtc->pipe;
 
+       intel_drrs_deactivate(old_crtc_state);
+
        intel_psr_pre_plane_update(state, crtc);
 
        if (hsw_ips_pre_update(state, crtc))
@@ -1777,7 +1780,8 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
         * clocks enabled
         */
        intel_color_load_luts(new_crtc_state);
-       intel_color_commit(new_crtc_state);
+       intel_color_commit_noarm(new_crtc_state);
+       intel_color_commit_arm(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
        intel_disable_primary_plane(new_crtc_state);
 
@@ -1822,29 +1826,6 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
        intel_de_write(dev_priv, CLKGATE_DIS_PSL(pipe), val);
 }
 
-static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum pipe pipe = crtc->pipe;
-       u32 val;
-
-       /* Wa_22010947358:adl-p */
-       if (IS_ALDERLAKE_P(dev_priv))
-               val = joined_mbus ? MBUS_DBOX_A_CREDIT(6) : MBUS_DBOX_A_CREDIT(4);
-       else
-               val = MBUS_DBOX_A_CREDIT(2);
-
-       if (DISPLAY_VER(dev_priv) >= 12) {
-               val |= MBUS_DBOX_BW_CREDIT(2);
-               val |= MBUS_DBOX_B_CREDIT(12);
-       } else {
-               val |= MBUS_DBOX_BW_CREDIT(1);
-               val |= MBUS_DBOX_B_CREDIT(8);
-       }
-
-       intel_de_write(dev_priv, PIPE_MBUS_DBOX_CTL(pipe), val);
-}
-
 static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -1864,7 +1845,7 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
 
        val = intel_de_read(dev_priv, reg);
        val &= ~HSW_FRAME_START_DELAY_MASK;
-       val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+       val |= HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
        intel_de_write(dev_priv, reg, val);
 }
 
@@ -1926,7 +1907,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
        if (drm_WARN_ON(&dev_priv->drm, crtc->active))
                return;
 
-       if (!new_crtc_state->bigjoiner) {
+       if (!new_crtc_state->bigjoiner_pipes) {
                intel_encoders_pre_pll_enable(state, crtc);
 
                if (new_crtc_state->shared_dpll)
@@ -1968,7 +1949,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
         * clocks enabled
         */
        intel_color_load_luts(new_crtc_state);
-       intel_color_commit(new_crtc_state);
+       intel_color_commit_noarm(new_crtc_state);
+       intel_color_commit_arm(new_crtc_state);
        /* update DSPCNTR to configure gamma/csc for pipe bottom color */
        if (DISPLAY_VER(dev_priv) < 9)
                intel_disable_primary_plane(new_crtc_state);
@@ -1980,13 +1962,6 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
 
        intel_initial_watermarks(state, crtc);
 
-       if (DISPLAY_VER(dev_priv) >= 11) {
-               const struct intel_dbuf_state *dbuf_state =
-                               intel_atomic_get_new_dbuf_state(state);
-
-               icl_pipe_mbus_enable(crtc, dbuf_state->joined_mbus);
-       }
-
        if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
                intel_crtc_vblank_on(new_crtc_state);
 
@@ -2021,9 +1996,9 @@ void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state)
        if (!old_crtc_state->pch_pfit.enabled)
                return;
 
-       intel_de_write(dev_priv, PF_CTL(pipe), 0);
-       intel_de_write(dev_priv, PF_WIN_POS(pipe), 0);
-       intel_de_write(dev_priv, PF_WIN_SZ(pipe), 0);
+       intel_de_write_fw(dev_priv, PF_CTL(pipe), 0);
+       intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), 0);
+       intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), 0);
 }
 
 static void ilk_crtc_disable(struct intel_atomic_state *state,
@@ -2388,7 +2363,8 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
        i9xx_pfit_enable(new_crtc_state);
 
        intel_color_load_luts(new_crtc_state);
-       intel_color_commit(new_crtc_state);
+       intel_color_commit_noarm(new_crtc_state);
+       intel_color_commit_arm(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
        intel_disable_primary_plane(new_crtc_state);
 
@@ -2427,7 +2403,8 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
        i9xx_pfit_enable(new_crtc_state);
 
        intel_color_load_luts(new_crtc_state);
-       intel_color_commit(new_crtc_state);
+       intel_color_commit_noarm(new_crtc_state);
+       intel_color_commit_arm(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
        intel_disable_primary_plane(new_crtc_state);
 
@@ -2683,8 +2660,8 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state)
                return pixel_rate;
 
        drm_rect_init(&src, 0, 0,
-                     crtc_state->pipe_src_w << 16,
-                     crtc_state->pipe_src_h << 16);
+                     drm_rect_width(&crtc_state->pipe_src) << 16,
+                     drm_rect_height(&crtc_state->pipe_src) << 16);
 
        return intel_adjusted_rate(&src, &crtc_state->pch_pfit.dst,
                                   pixel_rate);
@@ -2724,58 +2701,81 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
                        ilk_pipe_pixel_rate(crtc_state);
 }
 
+static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state,
+                                          struct drm_display_mode *mode)
+{
+       int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+
+       if (num_pipes < 2)
+               return;
+
+       mode->crtc_clock /= num_pipes;
+       mode->crtc_hdisplay /= num_pipes;
+       mode->crtc_hblank_start /= num_pipes;
+       mode->crtc_hblank_end /= num_pipes;
+       mode->crtc_hsync_start /= num_pipes;
+       mode->crtc_hsync_end /= num_pipes;
+       mode->crtc_htotal /= num_pipes;
+}
+
+static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state,
+                                         struct drm_display_mode *mode)
+{
+       int overlap = crtc_state->splitter.pixel_overlap;
+       int n = crtc_state->splitter.link_count;
+
+       if (!crtc_state->splitter.enable)
+               return;
+
+       /*
+        * eDP MSO uses segment timings from EDID for transcoder
+        * timings, but full mode for everything else.
+        *
+        * h_full = (h_segment - pixel_overlap) * link_count
+        */
+       mode->crtc_hdisplay = (mode->crtc_hdisplay - overlap) * n;
+       mode->crtc_hblank_start = (mode->crtc_hblank_start - overlap) * n;
+       mode->crtc_hblank_end = (mode->crtc_hblank_end - overlap) * n;
+       mode->crtc_hsync_start = (mode->crtc_hsync_start - overlap) * n;
+       mode->crtc_hsync_end = (mode->crtc_hsync_end - overlap) * n;
+       mode->crtc_htotal = (mode->crtc_htotal - overlap) * n;
+       mode->crtc_clock *= n;
+}
+
 static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state)
 {
        struct drm_display_mode *mode = &crtc_state->hw.mode;
        struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
        struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
 
+       /*
+        * Start with the adjusted_mode crtc timings, which
+        * have been filled with the transcoder timings.
+        */
        drm_mode_copy(pipe_mode, adjusted_mode);
 
-       if (crtc_state->bigjoiner) {
-               /*
-                * transcoder is programmed to the full mode,
-                * but pipe timings are half of the transcoder mode
-                */
-               pipe_mode->crtc_hdisplay /= 2;
-               pipe_mode->crtc_hblank_start /= 2;
-               pipe_mode->crtc_hblank_end /= 2;
-               pipe_mode->crtc_hsync_start /= 2;
-               pipe_mode->crtc_hsync_end /= 2;
-               pipe_mode->crtc_htotal /= 2;
-               pipe_mode->crtc_clock /= 2;
-       }
+       /* Expand MSO per-segment transcoder timings to full */
+       intel_splitter_adjust_timings(crtc_state, pipe_mode);
 
-       if (crtc_state->splitter.enable) {
-               int n = crtc_state->splitter.link_count;
-               int overlap = crtc_state->splitter.pixel_overlap;
+       /*
+        * We want the full numbers in adjusted_mode normal timings,
+        * adjusted_mode crtc timings are left with the raw transcoder
+        * timings.
+        */
+       intel_mode_from_crtc_timings(adjusted_mode, pipe_mode);
 
-               /*
-                * eDP MSO uses segment timings from EDID for transcoder
-                * timings, but full mode for everything else.
-                *
-                * h_full = (h_segment - pixel_overlap) * link_count
-                */
-               pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n;
-               pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n;
-               pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n;
-               pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n;
-               pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n;
-               pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n;
-               pipe_mode->crtc_clock *= n;
-
-               intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
-               intel_mode_from_crtc_timings(adjusted_mode, pipe_mode);
-       } else {
-               intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
-               intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode);
-       }
+       /* Populate the "user" mode with full numbers */
+       drm_mode_copy(mode, pipe_mode);
+       intel_mode_from_crtc_timings(mode, mode);
+       mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) *
+               (intel_bigjoiner_num_pipes(crtc_state) ?: 1);
+       mode->vdisplay = drm_rect_height(&crtc_state->pipe_src);
 
-       intel_crtc_compute_pixel_rate(crtc_state);
+       /* Derive per-pipe timings in case bigjoiner is used */
+       intel_bigjoiner_adjust_timings(crtc_state, pipe_mode);
+       intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
 
-       drm_mode_copy(mode, adjusted_mode);
-       mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner;
-       mode->vdisplay = crtc_state->pipe_src_h;
+       intel_crtc_compute_pixel_rate(crtc_state);
 }
 
 static void intel_encoder_get_config(struct intel_encoder *encoder,
@@ -2786,44 +2786,77 @@ static void intel_encoder_get_config(struct intel_encoder *encoder,
        intel_crtc_readout_derived_state(crtc_state);
 }
 
-static int intel_crtc_compute_config(struct intel_crtc *crtc,
-                                    struct intel_crtc_state *pipe_config)
+static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       struct drm_display_mode *pipe_mode = &pipe_config->hw.pipe_mode;
-       int clock_limit = dev_priv->max_dotclk_freq;
+       int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+       int width, height;
 
-       drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode);
+       if (num_pipes < 2)
+               return;
 
-       /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */
-       if (pipe_config->bigjoiner) {
-               pipe_mode->crtc_clock /= 2;
-               pipe_mode->crtc_hdisplay /= 2;
-               pipe_mode->crtc_hblank_start /= 2;
-               pipe_mode->crtc_hblank_end /= 2;
-               pipe_mode->crtc_hsync_start /= 2;
-               pipe_mode->crtc_hsync_end /= 2;
-               pipe_mode->crtc_htotal /= 2;
-               pipe_config->pipe_src_w /= 2;
-       }
+       width = drm_rect_width(&crtc_state->pipe_src);
+       height = drm_rect_height(&crtc_state->pipe_src);
 
-       if (pipe_config->splitter.enable) {
-               int n = pipe_config->splitter.link_count;
-               int overlap = pipe_config->splitter.pixel_overlap;
+       drm_rect_init(&crtc_state->pipe_src, 0, 0,
+                     width / num_pipes, height);
+}
 
-               pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n;
-               pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n;
-               pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n;
-               pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n;
-               pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n;
-               pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n;
-               pipe_mode->crtc_clock *= n;
+static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+       intel_bigjoiner_compute_pipe_src(crtc_state);
+
+       /*
+        * Pipe horizontal size must be even in:
+        * - DVO ganged mode
+        * - LVDS dual channel mode
+        * - Double wide pipe
+        */
+       if (drm_rect_width(&crtc_state->pipe_src) & 1) {
+               if (crtc_state->double_wide) {
+                       drm_dbg_kms(&i915->drm,
+                                   "[CRTC:%d:%s] Odd pipe source width not supported with double wide pipe\n",
+                                   crtc->base.base.id, crtc->base.name);
+                       return -EINVAL;
+               }
+
+               if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+                   intel_is_dual_link_lvds(i915)) {
+                       drm_dbg_kms(&i915->drm,
+                                   "[CRTC:%d:%s] Odd pipe source width not supported with dual link LVDS\n",
+                                   crtc->base.base.id, crtc->base.name);
+                       return -EINVAL;
+               }
        }
 
+       return 0;
+}
+
+static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+       struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+       struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
+       int clock_limit = i915->max_dotclk_freq;
+
+       /*
+        * Start with the adjusted_mode crtc timings, which
+        * have been filled with the transcoder timings.
+        */
+       drm_mode_copy(pipe_mode, adjusted_mode);
+
+       /* Expand MSO per-segment transcoder timings to full */
+       intel_splitter_adjust_timings(crtc_state, pipe_mode);
+
+       /* Derive per-pipe timings in case bigjoiner is used */
+       intel_bigjoiner_adjust_timings(crtc_state, pipe_mode);
        intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
 
-       if (DISPLAY_VER(dev_priv) < 4) {
-               clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
+       if (DISPLAY_VER(i915) < 4) {
+               clock_limit = i915->max_cdclk_freq * 9 / 10;
 
                /*
                 * Enable double wide mode when the dot clock
@@ -2831,44 +2864,40 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                 */
                if (intel_crtc_supports_double_wide(crtc) &&
                    pipe_mode->crtc_clock > clock_limit) {
-                       clock_limit = dev_priv->max_dotclk_freq;
-                       pipe_config->double_wide = true;
+                       clock_limit = i915->max_dotclk_freq;
+                       crtc_state->double_wide = true;
                }
        }
 
        if (pipe_mode->crtc_clock > clock_limit) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+               drm_dbg_kms(&i915->drm,
+                           "[CRTC:%d:%s] requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+                           crtc->base.base.id, crtc->base.name,
                            pipe_mode->crtc_clock, clock_limit,
-                           yesno(pipe_config->double_wide));
+                           str_yes_no(crtc_state->double_wide));
                return -EINVAL;
        }
 
-       /*
-        * Pipe horizontal size must be even in:
-        * - DVO ganged mode
-        * - LVDS dual channel mode
-        * - Double wide pipe
-        */
-       if (pipe_config->pipe_src_w & 1) {
-               if (pipe_config->double_wide) {
-                       drm_dbg_kms(&dev_priv->drm,
-                                   "Odd pipe source width not supported with double wide pipe\n");
-                       return -EINVAL;
-               }
+       return 0;
+}
 
-               if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
-                   intel_is_dual_link_lvds(dev_priv)) {
-                       drm_dbg_kms(&dev_priv->drm,
-                                   "Odd pipe source width not supported with dual link LVDS\n");
-                       return -EINVAL;
-               }
-       }
+static int intel_crtc_compute_config(struct intel_crtc *crtc,
+                                    struct intel_crtc_state *crtc_state)
+{
+       int ret;
 
-       intel_crtc_compute_pixel_rate(pipe_config);
+       ret = intel_crtc_compute_pipe_src(crtc_state);
+       if (ret)
+               return ret;
 
-       if (pipe_config->has_pch_encoder)
-               return ilk_fdi_compute_config(crtc, pipe_config);
+       ret = intel_crtc_compute_pipe_mode(crtc_state);
+       if (ret)
+               return ret;
+
+       intel_crtc_compute_pixel_rate(crtc_state);
+
+       if (crtc_state->has_pch_encoder)
+               return ilk_fdi_compute_config(crtc, crtc_state);
 
        return 0;
 }
@@ -2941,8 +2970,8 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
                if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
                        drm_dbg_kms(&dev_priv->drm,
                                    "SSC %s by BIOS, overriding VBT which says %s\n",
-                                   enableddisabled(bios_lvds_use_ssc),
-                                   enableddisabled(dev_priv->vbt.lvds_use_ssc));
+                                   str_enabled_disabled(bios_lvds_use_ssc),
+                                   str_enabled_disabled(dev_priv->vbt.lvds_use_ssc));
                        dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
                }
        }
@@ -3072,14 +3101,15 @@ static void intel_set_pipe_src_size(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);
+       int width = drm_rect_width(&crtc_state->pipe_src);
+       int height = drm_rect_height(&crtc_state->pipe_src);
        enum pipe pipe = crtc->pipe;
 
        /* pipesrc controls the size that is scaled from, which should
         * always be the user's requested size.
         */
        intel_de_write(dev_priv, PIPESRC(pipe),
-                      PIPESRC_WIDTH(crtc_state->pipe_src_w - 1) |
-                      PIPESRC_HEIGHT(crtc_state->pipe_src_h - 1));
+                      PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1));
 }
 
 static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
@@ -3142,6 +3172,23 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc,
        }
 }
 
+static void intel_bigjoiner_adjust_pipe_src(struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+       enum pipe master_pipe, pipe = crtc->pipe;
+       int width;
+
+       if (num_pipes < 2)
+               return;
+
+       master_pipe = bigjoiner_master_pipe(crtc_state);
+       width = drm_rect_width(&crtc_state->pipe_src);
+
+       drm_rect_translate_to(&crtc_state->pipe_src,
+                             (pipe - master_pipe) * width, 0);
+}
+
 static void intel_get_pipe_src_size(struct intel_crtc *crtc,
                                    struct intel_crtc_state *pipe_config)
 {
@@ -3150,8 +3197,12 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc,
        u32 tmp;
 
        tmp = intel_de_read(dev_priv, PIPESRC(crtc->pipe));
-       pipe_config->pipe_src_w = REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1;
-       pipe_config->pipe_src_h = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1;
+
+       drm_rect_init(&pipe_config->pipe_src, 0, 0,
+                     REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1,
+                     REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1);
+
+       intel_bigjoiner_adjust_pipe_src(pipe_config);
 }
 
 static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
@@ -3207,7 +3258,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 
        pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
-       pipeconf |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+       pipeconf |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
 
        intel_de_write(dev_priv, PIPECONF(crtc->pipe), pipeconf);
        intel_de_posting_read(dev_priv, PIPECONF(crtc->pipe));
@@ -3397,6 +3448,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 
        pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_I9XX, tmp);
 
+       pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1;
+
        if (IS_CHERRYVIEW(dev_priv))
                pipe_config->cgm_mode = intel_de_read(dev_priv,
                                                      CGM_PIPE_MODE(crtc->pipe));
@@ -3522,7 +3575,8 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)
 
        val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
-       val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+       val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
+       val |= PIPECONF_MSA_TIMING_DELAY(crtc_state->msa_timing_delay);
 
        intel_de_write(dev_priv, PIPECONF(pipe), val);
        intel_de_posting_read(dev_priv, PIPECONF(pipe));
@@ -3554,12 +3608,8 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state)
 static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-       const struct intel_crtc_scaler_state *scaler_state =
-               &crtc_state->scaler_state;
-
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 val = 0;
-       int i;
 
        switch (crtc_state->pipe_bpp) {
        case 18:
@@ -3598,23 +3648,6 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
        if (DISPLAY_VER(dev_priv) >= 12)
                val |= PIPEMISC_PIXEL_ROUNDING_TRUNC;
 
-       if (IS_ALDERLAKE_P(dev_priv)) {
-               bool scaler_in_use = false;
-
-               for (i = 0; i < crtc->num_scalers; i++) {
-                       if (!scaler_state->scalers[i].in_use)
-                               continue;
-
-                       scaler_in_use = true;
-                       break;
-               }
-
-               intel_de_rmw(dev_priv, PIPE_MISC2(crtc->pipe),
-                            PIPE_MISC2_BUBBLE_COUNTER_MASK,
-                            scaler_in_use ? PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN :
-                            PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS);
-       }
-
        intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val);
 }
 
@@ -3830,6 +3863,10 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
 
        pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_ILK, tmp);
 
+       pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1;
+
+       pipe_config->msa_timing_delay = REG_FIELD_GET(PIPECONF_MSA_TIMING_DELAY_MASK, tmp);
+
        pipe_config->csc_mode = intel_de_read(dev_priv,
                                              PIPE_CSC_MODE(crtc->pipe));
 
@@ -4164,7 +4201,6 @@ static void intel_bigjoiner_get_config(struct intel_crtc_state *crtc_state)
        if (((master_pipes | slave_pipes) & BIT(pipe)) == 0)
                return;
 
-       crtc_state->bigjoiner = true;
        crtc_state->bigjoiner_pipes =
                BIT(get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes)) |
                get_bigjoiner_slave_pipes(pipe, master_pipes, slave_pipes);
@@ -4265,6 +4301,15 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
+       if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) {
+               tmp = intel_de_read(dev_priv, CHICKEN_TRANS(pipe_config->cpu_transcoder));
+
+               pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1;
+       } else {
+               /* no idea if this is correct */
+               pipe_config->framestart_delay = 1;
+       }
+
 out:
        intel_display_power_put_all_in_set(dev_priv, &power_domain_set);
 
@@ -4746,6 +4791,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                        crtc_state->enabled_planes &= ~BIT(plane->id);
                        crtc_state->active_planes &= ~BIT(plane->id);
                        crtc_state->update_planes |= BIT(plane->id);
+                       crtc_state->data_rate[plane->id] = 0;
+                       crtc_state->rel_data_rate[plane->id] = 0;
                }
 
                plane_state->planar_slave = false;
@@ -4790,6 +4837,10 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                crtc_state->enabled_planes |= BIT(linked->id);
                crtc_state->active_planes |= BIT(linked->id);
                crtc_state->update_planes |= BIT(linked->id);
+               crtc_state->data_rate[linked->id] =
+                       crtc_state->data_rate_y[plane->id];
+               crtc_state->rel_data_rate[linked->id] =
+                       crtc_state->rel_data_rate_y[plane->id];
                drm_dbg_kms(&dev_priv->drm, "Using %s as Y plane for %s\n",
                            linked->base.name, plane->base.name);
 
@@ -5222,7 +5273,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
                drm_dbg_kms(&i915->drm,
                            "[PLANE:%d:%s] fb: [NOFB], visible: %s\n",
                            plane->base.base.id, plane->base.name,
-                           yesno(plane_state->uapi.visible));
+                           str_yes_no(plane_state->uapi.visible));
                return;
        }
 
@@ -5230,7 +5281,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
                    "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n",
                    plane->base.base.id, plane->base.name,
                    fb->base.id, fb->width, fb->height, &fb->format->format,
-                   fb->modifier, yesno(plane_state->uapi.visible));
+                   fb->modifier, str_yes_no(plane_state->uapi.visible));
        drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d\n",
                    plane_state->hw.rotation, plane_state->scaler_id);
        if (plane_state->uapi.visible)
@@ -5253,7 +5304,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
 
        drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] enable: %s %s\n",
                    crtc->base.base.id, crtc->base.name,
-                   yesno(pipe_config->hw.enable), context);
+                   str_yes_no(pipe_config->hw.enable), context);
 
        if (!pipe_config->hw.enable)
                goto dump_planes;
@@ -5261,7 +5312,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
        snprintf_output_types(buf, sizeof(buf), pipe_config->output_types);
        drm_dbg_kms(&dev_priv->drm,
                    "active: %s, output_types: %s (0x%x), output format: %s\n",
-                   yesno(pipe_config->hw.active),
+                   str_yes_no(pipe_config->hw.active),
                    buf, pipe_config->output_types,
                    output_formats(pipe_config->output_format));
 
@@ -5284,7 +5335,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                    pipe_config->bigjoiner_pipes);
 
        drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n",
-                   enableddisabled(pipe_config->splitter.enable),
+                   str_enabled_disabled(pipe_config->splitter.enable),
                    pipe_config->splitter.link_count,
                    pipe_config->splitter.pixel_overlap);
 
@@ -5302,6 +5353,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                                      &pipe_config->dp_m2_n2);
        }
 
+       drm_dbg_kms(&dev_priv->drm, "framestart delay: %d, MSA timing delay: %d\n",
+                   pipe_config->framestart_delay, pipe_config->msa_timing_delay);
+
        drm_dbg_kms(&dev_priv->drm,
                    "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n",
                    pipe_config->has_audio, pipe_config->has_infoframe,
@@ -5331,25 +5385,24 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc);
 
        drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
-                   yesno(pipe_config->vrr.enable),
+                   str_yes_no(pipe_config->vrr.enable),
                    pipe_config->vrr.vmin, pipe_config->vrr.vmax,
                    pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband,
                    pipe_config->vrr.flipline,
                    intel_vrr_vmin_vblank_start(pipe_config),
                    intel_vrr_vmax_vblank_start(pipe_config));
 
-       drm_dbg_kms(&dev_priv->drm, "requested mode:\n");
-       drm_mode_debug_printmodeline(&pipe_config->hw.mode);
-       drm_dbg_kms(&dev_priv->drm, "adjusted mode:\n");
-       drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode);
+       drm_dbg_kms(&dev_priv->drm, "requested mode: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(&pipe_config->hw.mode));
+       drm_dbg_kms(&dev_priv->drm, "adjusted mode: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(&pipe_config->hw.adjusted_mode));
        intel_dump_crtc_timings(dev_priv, &pipe_config->hw.adjusted_mode);
-       drm_dbg_kms(&dev_priv->drm, "pipe mode:\n");
-       drm_mode_debug_printmodeline(&pipe_config->hw.pipe_mode);
+       drm_dbg_kms(&dev_priv->drm, "pipe mode: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(&pipe_config->hw.pipe_mode));
        intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode);
        drm_dbg_kms(&dev_priv->drm,
-                   "port clock: %d, pipe src size: %dx%d, pixel rate %d\n",
-                   pipe_config->port_clock,
-                   pipe_config->pipe_src_w, pipe_config->pipe_src_h,
+                   "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n",
+                   pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src),
                    pipe_config->pixel_rate);
 
        drm_dbg_kms(&dev_priv->drm, "linetime: %d, ips linetime: %d\n",
@@ -5372,11 +5425,12 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                drm_dbg_kms(&dev_priv->drm,
                            "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n",
                            DRM_RECT_ARG(&pipe_config->pch_pfit.dst),
-                           enableddisabled(pipe_config->pch_pfit.enabled),
-                           yesno(pipe_config->pch_pfit.force_thru));
+                           str_enabled_disabled(pipe_config->pch_pfit.enabled),
+                           str_yes_no(pipe_config->pch_pfit.force_thru));
 
-       drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i\n",
-                   pipe_config->ips_enabled, pipe_config->double_wide);
+       drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i, drrs: %i\n",
+                   pipe_config->ips_enabled, pipe_config->double_wide,
+                   pipe_config->has_drrs);
 
        intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state);
 
@@ -5504,8 +5558,10 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state,
 
        crtc_state->hw.enable = crtc_state->uapi.enable;
        crtc_state->hw.active = crtc_state->uapi.active;
-       crtc_state->hw.mode = crtc_state->uapi.mode;
-       crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode;
+       drm_mode_copy(&crtc_state->hw.mode,
+                     &crtc_state->uapi.mode);
+       drm_mode_copy(&crtc_state->hw.adjusted_mode,
+                     &crtc_state->uapi.adjusted_mode);
        crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter;
 
        intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
@@ -5563,6 +5619,9 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state,
                intel_atomic_get_new_crtc_state(state, master_crtc);
        struct intel_crtc_state *saved_state;
 
+       WARN_ON(master_crtc_state->bigjoiner_pipes !=
+               slave_crtc_state->bigjoiner_pipes);
+
        saved_state = kmemdup(master_crtc_state, sizeof(*saved_state), GFP_KERNEL);
        if (!saved_state)
                return -ENOMEM;
@@ -5582,19 +5641,22 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state,
        memset(&slave_crtc_state->hw, 0, sizeof(slave_crtc_state->hw));
        slave_crtc_state->hw.enable = master_crtc_state->hw.enable;
        slave_crtc_state->hw.active = master_crtc_state->hw.active;
-       slave_crtc_state->hw.mode = master_crtc_state->hw.mode;
-       slave_crtc_state->hw.pipe_mode = master_crtc_state->hw.pipe_mode;
-       slave_crtc_state->hw.adjusted_mode = master_crtc_state->hw.adjusted_mode;
+       drm_mode_copy(&slave_crtc_state->hw.mode,
+                     &master_crtc_state->hw.mode);
+       drm_mode_copy(&slave_crtc_state->hw.pipe_mode,
+                     &master_crtc_state->hw.pipe_mode);
+       drm_mode_copy(&slave_crtc_state->hw.adjusted_mode,
+                     &master_crtc_state->hw.adjusted_mode);
        slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter;
 
        copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc);
 
-       /* Some fixups */
        slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed;
        slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed;
        slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed;
-       slave_crtc_state->cpu_transcoder = master_crtc_state->cpu_transcoder;
-       slave_crtc_state->has_audio = master_crtc_state->has_audio;
+
+       WARN_ON(master_crtc_state->bigjoiner_pipes !=
+               slave_crtc_state->bigjoiner_pipes);
 
        return 0;
 }
@@ -5647,12 +5709,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
        struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev);
        struct drm_connector *connector;
        struct drm_connector_state *connector_state;
+       int pipe_src_w, pipe_src_h;
        int base_bpp, ret, i;
        bool retry = true;
 
        pipe_config->cpu_transcoder =
                (enum transcoder) to_intel_crtc(crtc)->pipe;
 
+       pipe_config->framestart_delay = 1;
+
        /*
         * Sanitize sync polarity flags based on requested ones. If neither
         * positive or negative polarity is requested, treat this as meaning
@@ -5682,8 +5747,9 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
         * can be changed by the connectors in the below retry loop.
         */
        drm_mode_get_hv_timing(&pipe_config->hw.mode,
-                              &pipe_config->pipe_src_w,
-                              &pipe_config->pipe_src_h);
+                              &pipe_src_w, &pipe_src_h);
+       drm_rect_init(&pipe_config->pipe_src, 0, 0,
+                     pipe_src_w, pipe_src_h);
 
        for_each_new_connector_in_state(&state->base, connector, connector_state, i) {
                struct intel_encoder *encoder =
@@ -5786,6 +5852,8 @@ intel_modeset_pipe_config_late(struct intel_crtc_state *crtc_state)
        struct drm_connector *connector;
        int i;
 
+       intel_bigjoiner_adjust_pipe_src(crtc_state);
+
        for_each_new_connector_in_state(&state->base, connector,
                                        conn_state, i) {
                struct intel_encoder *encoder =
@@ -6022,8 +6090,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        if (current_config->name != pipe_config->name) { \
                pipe_config_mismatch(fastset, crtc,  __stringify(name), \
                                     "(expected %s, found %s)", \
-                                    yesno(current_config->name), \
-                                    yesno(pipe_config->name)); \
+                                    str_yes_no(current_config->name), \
+                                    str_yes_no(pipe_config->name)); \
                ret = false; \
        } \
 } while (0)
@@ -6039,8 +6107,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        } else { \
                pipe_config_mismatch(fastset, crtc, __stringify(name), \
                                     "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)", \
-                                    yesno(current_config->name), \
-                                    yesno(pipe_config->name)); \
+                                    str_yes_no(current_config->name), \
+                                    str_yes_no(pipe_config->name)); \
                ret = false; \
        } \
 } while (0)
@@ -6190,6 +6258,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
        PIPE_CONF_CHECK_X(output_types);
 
+       PIPE_CONF_CHECK_I(framestart_delay);
+       PIPE_CONF_CHECK_I(msa_timing_delay);
+
        PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay);
        PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal);
        PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start);
@@ -6260,8 +6331,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        PIPE_CONF_CHECK_BOOL(pch_pfit.force_thru);
 
        if (!fastset) {
-               PIPE_CONF_CHECK_I(pipe_src_w);
-               PIPE_CONF_CHECK_I(pipe_src_h);
+               PIPE_CONF_CHECK_I(pipe_src.x1);
+               PIPE_CONF_CHECK_I(pipe_src.y1);
+               PIPE_CONF_CHECK_I(pipe_src.x2);
+               PIPE_CONF_CHECK_I(pipe_src.y2);
 
                PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
                if (current_config->pch_pfit.enabled) {
@@ -6363,7 +6436,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
        PIPE_CONF_CHECK_X(sync_mode_slaves_mask);
        PIPE_CONF_CHECK_I(master_transcoder);
-       PIPE_CONF_CHECK_BOOL(bigjoiner);
        PIPE_CONF_CHECK_X(bigjoiner_pipes);
 
        PIPE_CONF_CHECK_I(dsc.compression_enable);
@@ -6420,8 +6492,8 @@ static void verify_wm_state(struct intel_crtc *crtc,
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct skl_hw_state {
+               struct skl_ddb_entry ddb[I915_MAX_PLANES];
                struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
-               struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
                struct skl_pipe_wm wm;
        } *hw;
        const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal;
@@ -6438,7 +6510,7 @@ static void verify_wm_state(struct intel_crtc *crtc,
 
        skl_pipe_wm_get_hw_state(crtc, &hw->wm);
 
-       skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
+       skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y);
 
        hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
 
@@ -6520,8 +6592,8 @@ static void verify_wm_state(struct intel_crtc *crtc,
                }
 
                /* DDB */
-               hw_ddb_entry = &hw->ddb_y[plane->id];
-               sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb_y[plane->id];
+               hw_ddb_entry = &hw->ddb[PLANE_CURSOR];
+               sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
 
                if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
                        drm_err(&dev_priv->drm,
@@ -7294,32 +7366,26 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
        struct intel_crtc_state *master_crtc_state =
                intel_atomic_get_new_crtc_state(state, master_crtc);
        struct intel_crtc *slave_crtc;
-       u8 slave_pipes;
-
-       /*
-        * TODO: encoder.compute_config() may be the best
-        * place to populate the bitmask for the master crtc.
-        * For now encoder.compute_config() just flags things
-        * as needing bigjoiner and we populate the bitmask
-        * here.
-        */
-       WARN_ON(master_crtc_state->bigjoiner_pipes);
 
-       if (!master_crtc_state->bigjoiner)
+       if (!master_crtc_state->bigjoiner_pipes)
                return 0;
 
-       slave_pipes = BIT(master_crtc->pipe + 1);
+       /* sanity check */
+       if (drm_WARN_ON(&i915->drm,
+                       master_crtc->pipe != bigjoiner_master_pipe(master_crtc_state)))
+               return -EINVAL;
 
-       if (slave_pipes & ~bigjoiner_pipes(i915)) {
+       if (master_crtc_state->bigjoiner_pipes & ~bigjoiner_pipes(i915)) {
                drm_dbg_kms(&i915->drm,
                            "[CRTC:%d:%s] Cannot act as big joiner master "
-                           "(need 0x%x as slave pipes, only 0x%x possible)\n",
+                           "(need 0x%x as pipes, only 0x%x possible)\n",
                            master_crtc->base.base.id, master_crtc->base.name,
-                           slave_pipes, bigjoiner_pipes(i915));
+                           master_crtc_state->bigjoiner_pipes, bigjoiner_pipes(i915));
                return -EINVAL;
        }
 
-       for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, slave_pipes) {
+       for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
+                                        intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) {
                struct intel_crtc_state *slave_crtc_state;
                int ret;
 
@@ -7353,10 +7419,8 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
                            slave_crtc->base.base.id, slave_crtc->base.name,
                            master_crtc->base.base.id, master_crtc->base.name);
 
-               master_crtc_state->bigjoiner_pipes =
-                       BIT(master_crtc->pipe) | BIT(slave_crtc->pipe);
                slave_crtc_state->bigjoiner_pipes =
-                       BIT(master_crtc->pipe) | BIT(slave_crtc->pipe);
+                       master_crtc_state->bigjoiner_pipes;
 
                ret = copy_bigjoiner_crtc_state_modeset(state, slave_crtc);
                if (ret)
@@ -7379,13 +7443,11 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state,
                struct intel_crtc_state *slave_crtc_state =
                        intel_atomic_get_new_crtc_state(state, slave_crtc);
 
-               slave_crtc_state->bigjoiner = false;
                slave_crtc_state->bigjoiner_pipes = 0;
 
                intel_crtc_copy_uapi_to_hw_state_modeset(state, slave_crtc);
        }
 
-       master_crtc_state->bigjoiner = false;
        master_crtc_state->bigjoiner_pipes = 0;
 }
 
@@ -7479,18 +7541,24 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
        if (!new_crtc_state->uapi.async_flip)
                return 0;
 
-       if (intel_crtc_needs_modeset(new_crtc_state)) {
-               drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n");
+       if (!new_crtc_state->hw.active) {
+               drm_dbg_kms(&i915->drm,
+                           "[CRTC:%d:%s] not active\n",
+                           crtc->base.base.id, crtc->base.name);
                return -EINVAL;
        }
 
-       if (!new_crtc_state->hw.active) {
-               drm_dbg_kms(&i915->drm, "CRTC inactive\n");
+       if (intel_crtc_needs_modeset(new_crtc_state)) {
+               drm_dbg_kms(&i915->drm,
+                           "[CRTC:%d:%s] modeset required\n",
+                           crtc->base.base.id, crtc->base.name);
                return -EINVAL;
        }
+
        if (old_crtc_state->active_planes != new_crtc_state->active_planes) {
                drm_dbg_kms(&i915->drm,
-                           "Active planes cannot be changed during async flip\n");
+                           "[CRTC:%d:%s] Active planes cannot be in async flip\n",
+                           crtc->base.base.id, crtc->base.name);
                return -EINVAL;
        }
 
@@ -7528,78 +7596,98 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
                case I915_FORMAT_MOD_X_TILED:
                case I915_FORMAT_MOD_Y_TILED:
                case I915_FORMAT_MOD_Yf_TILED:
+               case I915_FORMAT_MOD_4_TILED:
                        break;
                default:
                        drm_dbg_kms(&i915->drm,
-                                   "Linear memory/CCS does not support async flips\n");
+                                   "[PLANE:%d:%s] Modifier does not support async flips\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (new_plane_state->hw.fb->format->num_planes > 1) {
                        drm_dbg_kms(&i915->drm,
-                                   "Planar formats not supported with async flips\n");
+                                   "[PLANE:%d:%s] Planar formats do not support async flips\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->view.color_plane[0].mapping_stride !=
                    new_plane_state->view.color_plane[0].mapping_stride) {
-                       drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n");
+                       drm_dbg_kms(&i915->drm,
+                                   "[PLANE:%d:%s] Stride cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.fb->modifier !=
                    new_plane_state->hw.fb->modifier) {
                        drm_dbg_kms(&i915->drm,
-                                   "Framebuffer modifiers cannot be changed in async flip\n");
+                                   "[PLANE:%d:%s] Modifier cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.fb->format !=
                    new_plane_state->hw.fb->format) {
                        drm_dbg_kms(&i915->drm,
-                                   "Framebuffer format cannot be changed in async flip\n");
+                                   "[PLANE:%d:%s] Pixel format cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.rotation !=
                    new_plane_state->hw.rotation) {
-                       drm_dbg_kms(&i915->drm, "Rotation cannot be changed in async flip\n");
+                       drm_dbg_kms(&i915->drm,
+                                   "[PLANE:%d:%s] Rotation cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (!drm_rect_equals(&old_plane_state->uapi.src, &new_plane_state->uapi.src) ||
                    !drm_rect_equals(&old_plane_state->uapi.dst, &new_plane_state->uapi.dst)) {
                        drm_dbg_kms(&i915->drm,
-                                   "Plane size/co-ordinates cannot be changed in async flip\n");
+                                   "[PLANE:%d:%s] Size/co-ordinates cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.alpha != new_plane_state->hw.alpha) {
-                       drm_dbg_kms(&i915->drm, "Alpha value cannot be changed in async flip\n");
+                       drm_dbg_kms(&i915->drm,
+                                   "[PLANES:%d:%s] Alpha value cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.pixel_blend_mode !=
                    new_plane_state->hw.pixel_blend_mode) {
                        drm_dbg_kms(&i915->drm,
-                                   "Pixel blend mode cannot be changed in async flip\n");
+                                   "[PLANE:%d:%s] Pixel blend mode cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.color_encoding != new_plane_state->hw.color_encoding) {
                        drm_dbg_kms(&i915->drm,
-                                   "Color encoding cannot be changed in async flip\n");
+                                   "[PLANE:%d:%s] Color encoding cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                if (old_plane_state->hw.color_range != new_plane_state->hw.color_range) {
-                       drm_dbg_kms(&i915->drm, "Color range cannot be changed in async flip\n");
+                       drm_dbg_kms(&i915->drm,
+                                   "[PLANE:%d:%s] Color range cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
                }
 
                /* plane decryption is allow to change only in synchronous flips */
-               if (old_plane_state->decrypt != new_plane_state->decrypt)
+               if (old_plane_state->decrypt != new_plane_state->decrypt) {
+                       drm_dbg_kms(&i915->drm,
+                                   "[PLANE:%d:%s] Decryption cannot be changed in async flip\n",
+                                   plane->base.base.id, plane->base.name);
                        return -EINVAL;
+               }
        }
 
        return 0;
@@ -7772,7 +7860,7 @@ static int intel_atomic_check(struct drm_device *dev,
                        }
                }
 
-               if (new_crtc_state->bigjoiner) {
+               if (new_crtc_state->bigjoiner_pipes) {
                        if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) {
                                new_crtc_state->uapi.mode_changed = true;
                                new_crtc_state->update_pipe = false;
@@ -7970,7 +8058,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state,
        if (!modeset) {
                if (new_crtc_state->uapi.color_mgmt_changed ||
                    new_crtc_state->update_pipe)
-                       intel_color_commit(new_crtc_state);
+                       intel_color_commit_arm(new_crtc_state);
 
                if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
                        bdw_set_pipemisc(new_crtc_state);
@@ -8050,6 +8138,11 @@ static void intel_update_crtc(struct intel_atomic_state *state,
 
        intel_fbc_update(state, crtc);
 
+       if (!modeset &&
+           (new_crtc_state->uapi.color_mgmt_changed ||
+            new_crtc_state->update_pipe))
+               intel_color_commit_noarm(new_crtc_state);
+
        intel_crtc_planes_update_noarm(state, crtc);
 
        /* Perform vblank evasion around commit operation */
@@ -8384,7 +8477,9 @@ static void intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s
 
                /*
                 * The layout of the fast clear color value expected by HW
-                * (the DRM ABI requiring this value to be located in fb at offset 0 of plane#2):
+                * (the DRM ABI requiring this value to be located in fb at
+                * offset 0 of cc plane, plane #2 previous generations or
+                * plane #1 for flat ccs):
                 * - 4 x 4 bytes per-channel value
                 *   (in surface type specific float/int format provided by the fb user)
                 * - 8 bytes native color value used by the display
@@ -8467,6 +8562,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
        intel_encoders_update_prepare(state);
 
        intel_dbuf_pre_plane_update(state);
+       intel_mbus_dbox_update(state);
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
                if (new_crtc_state->do_async_flip)
@@ -9573,8 +9669,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
        i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI |
                                        WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
 
-       i915->framestart_delay = 1; /* 1-4 */
-
        i915->window2_delay = 0; /* No DSB so no window2 delay */
 
        intel_mode_config_init(i915);
@@ -9871,64 +9965,6 @@ static struct intel_connector *intel_encoder_find_connector(struct intel_encoder
        return NULL;
 }
 
-static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
-                             enum pipe pch_transcoder)
-{
-       return HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
-               (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);
-}
-
-static void intel_sanitize_frame_start_delay(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;
-
-       if (DISPLAY_VER(dev_priv) >= 9 ||
-           IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
-               i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
-               u32 val;
-
-               if (transcoder_is_dsi(cpu_transcoder))
-                       return;
-
-               val = intel_de_read(dev_priv, reg);
-               val &= ~HSW_FRAME_START_DELAY_MASK;
-               val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
-               intel_de_write(dev_priv, reg, val);
-       } else {
-               i915_reg_t reg = PIPECONF(cpu_transcoder);
-               u32 val;
-
-               val = intel_de_read(dev_priv, reg);
-               val &= ~PIPECONF_FRAME_START_DELAY_MASK;
-               val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
-               intel_de_write(dev_priv, reg, val);
-       }
-
-       if (!crtc_state->has_pch_encoder)
-               return;
-
-       if (HAS_PCH_IBX(dev_priv)) {
-               i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
-               u32 val;
-
-               val = intel_de_read(dev_priv, reg);
-               val &= ~TRANS_FRAME_START_DELAY_MASK;
-               val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
-               intel_de_write(dev_priv, reg, val);
-       } else {
-               enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc);
-               i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder);
-               u32 val;
-
-               val = intel_de_read(dev_priv, reg);
-               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);
-       }
-}
-
 static void intel_sanitize_crtc(struct intel_crtc *crtc,
                                struct drm_modeset_acquire_ctx *ctx)
 {
@@ -9939,9 +9975,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
        if (crtc_state->hw.active) {
                struct intel_plane *plane;
 
-               /* Clear any frame start delays used for debugging left by the BIOS */
-               intel_sanitize_frame_start_delay(crtc_state);
-
                /* Disable everything but the primary plane */
                for_each_intel_plane_on_crtc(dev, crtc, plane) {
                        const struct intel_plane_state *plane_state =
@@ -9953,7 +9986,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
                }
 
                /* Disable any background color/etc. set by the BIOS */
-               intel_color_commit(crtc_state);
+               intel_color_commit_noarm(crtc_state);
+               intel_color_commit_arm(crtc_state);
        }
 
        /* Adjust the state of the output pipe according to whether we
@@ -9986,7 +10020,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
                 * PCH transcoders B and C would prevent enabling the south
                 * error interrupt (see cpt_can_enable_serr_int()).
                 */
-               if (has_pch_trancoder(dev_priv, crtc->pipe))
+               if (intel_has_pch_trancoder(dev_priv, crtc->pipe))
                        crtc->pch_fifo_underrun_disabled = true;
        }
 }
@@ -10105,7 +10139,7 @@ static void readout_plane_state(struct drm_i915_private *dev_priv)
                drm_dbg_kms(&dev_priv->drm,
                            "[PLANE:%d:%s] hw state readout: %s, pipe %c\n",
                            plane->base.base.id, plane->base.name,
-                           enableddisabled(visible), pipe_name(pipe));
+                           str_enabled_disabled(visible), pipe_name(pipe));
        }
 
        for_each_intel_crtc(&dev_priv->drm, crtc) {
@@ -10151,7 +10185,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                drm_dbg_kms(&dev_priv->drm,
                            "[CRTC:%d:%s] hw state readout: %s\n",
                            crtc->base.base.id, crtc->base.name,
-                           enableddisabled(crtc_state->hw.active));
+                           str_enabled_disabled(crtc_state->hw.active));
        }
 
        cdclk_state->active_pipes = dbuf_state->active_pipes = active_pipes;
@@ -10171,7 +10205,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        intel_encoder_get_config(encoder, crtc_state);
 
                        /* read out to slave crtc as well for bigjoiner */
-                       if (crtc_state->bigjoiner) {
+                       if (crtc_state->bigjoiner_pipes) {
                                struct intel_crtc *slave_crtc;
 
                                /* encoder should read be linked to bigjoiner master */
@@ -10195,7 +10229,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                drm_dbg_kms(&dev_priv->drm,
                            "[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
                            encoder->base.base.id, encoder->base.name,
-                           enableddisabled(encoder->base.crtc),
+                           str_enabled_disabled(encoder->base.crtc),
                            pipe_name(pipe));
        }
 
@@ -10233,7 +10267,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                drm_dbg_kms(&dev_priv->drm,
                            "[CONNECTOR:%d:%s] hw state readout: %s\n",
                            connector->base.base.id, connector->base.name,
-                           enableddisabled(connector->base.encoder));
+                           str_enabled_disabled(connector->base.encoder));
        }
        drm_connector_list_iter_end(&conn_iter);
 
@@ -10359,66 +10393,6 @@ static void intel_early_display_was(struct drm_i915_private *dev_priv)
        }
 }
 
-static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
-                                      enum port port, i915_reg_t hdmi_reg)
-{
-       u32 val = intel_de_read(dev_priv, hdmi_reg);
-
-       if (val & SDVO_ENABLE ||
-           (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A))
-               return;
-
-       drm_dbg_kms(&dev_priv->drm,
-                   "Sanitizing transcoder select for HDMI %c\n",
-                   port_name(port));
-
-       val &= ~SDVO_PIPE_SEL_MASK;
-       val |= SDVO_PIPE_SEL(PIPE_A);
-
-       intel_de_write(dev_priv, hdmi_reg, val);
-}
-
-static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv,
-                                    enum port port, i915_reg_t dp_reg)
-{
-       u32 val = intel_de_read(dev_priv, dp_reg);
-
-       if (val & DP_PORT_EN ||
-           (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A))
-               return;
-
-       drm_dbg_kms(&dev_priv->drm,
-                   "Sanitizing transcoder select for DP %c\n",
-                   port_name(port));
-
-       val &= ~DP_PIPE_SEL_MASK;
-       val |= DP_PIPE_SEL(PIPE_A);
-
-       intel_de_write(dev_priv, dp_reg, val);
-}
-
-static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv)
-{
-       /*
-        * The BIOS may select transcoder B on some of the PCH
-        * ports even it doesn't enable the port. This would trip
-        * assert_pch_dp_disabled() and assert_pch_hdmi_disabled().
-        * Sanitize the transcoder select bits to prevent that. We
-        * assume that the BIOS never actually enabled the port,
-        * because if it did we'd actually have to toggle the port
-        * on and back off to make the transcoder A select stick
-        * (see. intel_dp_link_down(), intel_disable_hdmi(),
-        * intel_disable_sdvo()).
-        */
-       ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B);
-       ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C);
-       ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D);
-
-       /* PCH SDVOB multiplex with HDMIB */
-       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB);
-       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC);
-       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID);
-}
 
 /* Scan out the current hw modeset state,
  * and sanitizes it to the current state
@@ -10440,8 +10414,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
        /* HW state is read out, now we need to sanitize this mess. */
        get_encoder_power_domains(dev_priv);
 
-       if (HAS_PCH_IBX(dev_priv))
-               ibx_sanitize_pch_ports(dev_priv);
+       intel_pch_sanitize(dev_priv);
 
        /*
         * intel_sanitize_plane_mapping() may need to do vblank
@@ -10457,6 +10430,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                        intel_crtc_vblank_on(crtc_state);
        }
 
+       intel_fbc_sanitize(dev_priv);
+
        intel_sanitize_plane_mapping(dev_priv);
 
        for_each_intel_encoder(dev, encoder)
@@ -10595,8 +10570,6 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
 
        intel_unregister_dsm_handler();
 
-       intel_fbc_global_disable(i915);
-
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
@@ -10697,3 +10670,8 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)
        acpi_video_unregister();
        intel_opregion_unregister(i915);
 }
+
+bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915)
+{
+       return DISPLAY_VER(i915) >= 6 && i915_vtd_active(i915);
+}
index 11d6134..867fa24 100644 (file)
@@ -565,7 +565,6 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state);
 void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state);
 void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
 void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
-enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
 int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
 int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
                      const char *name, u32 reg, int ref_freq);
@@ -695,4 +694,6 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
 #define I915_STATE_WARN_ON(x)                                          \
        I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
 
+bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
+
 #endif
index ffe6822..452d773 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_debugfs.h>
 #include <drm/drm_fourcc.h>
 
@@ -10,6 +12,7 @@
 #include "intel_de.h"
 #include "intel_display_debugfs.h"
 #include "intel_display_power.h"
+#include "intel_display_power_well.h"
 #include "intel_display_types.h"
 #include "intel_dmc.h"
 #include "intel_dp.h"
@@ -19,6 +22,7 @@
 #include "intel_fbdev.h"
 #include "intel_hdcp.h"
 #include "intel_hdmi.h"
+#include "intel_panel.h"
 #include "intel_pm.h"
 #include "intel_psr.h"
 #include "intel_sprite.h"
@@ -52,7 +56,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
        wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
 
        seq_printf(m, "Enabled by kernel parameter: %s\n",
-                  yesno(dev_priv->params.enable_ips));
+                  str_yes_no(dev_priv->params.enable_ips));
 
        if (DISPLAY_VER(dev_priv) >= 8) {
                seq_puts(m, "Currently: unknown\n");
@@ -92,7 +96,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 
        intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
 
-       seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
+       seq_printf(m, "self-refresh: %s\n", str_enabled_disabled(sr_enabled));
 
        return 0;
 }
@@ -260,7 +264,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
        bool enabled;
        u32 val;
 
-       seq_printf(m, "Sink support: %s", yesno(psr->sink_support));
+       seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
        if (psr->sink_support)
                seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
        seq_puts(m, "\n");
@@ -279,7 +283,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
 
        if (!psr->enabled) {
                seq_printf(m, "PSR sink not reliable: %s\n",
-                          yesno(psr->sink_not_reliable));
+                          str_yes_no(psr->sink_not_reliable));
 
                goto unlock;
        }
@@ -294,7 +298,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
                enabled = val & EDP_PSR_ENABLE;
        }
        seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
-                  enableddisabled(enabled), val);
+                  str_enabled_disabled(enabled), val);
        psr_source_status(intel_dp, m);
        seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
                   psr->busy_frontbuffer_bits);
@@ -341,7 +345,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
                }
 
                seq_printf(m, "PSR2 selective fetch: %s\n",
-                          enableddisabled(psr->psr2_sel_fetch_enabled));
+                          str_enabled_disabled(psr->psr2_sel_fetch_enabled));
        }
 
 unlock:
@@ -432,75 +436,6 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
        return 0;
 }
 
-static int i915_dmc_info(struct seq_file *m, void *unused)
-{
-       struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       intel_wakeref_t wakeref;
-       struct intel_dmc *dmc;
-       i915_reg_t dc5_reg, dc6_reg = {};
-
-       if (!HAS_DMC(dev_priv))
-               return -ENODEV;
-
-       dmc = &dev_priv->dmc;
-
-       wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
-
-       seq_printf(m, "fw loaded: %s\n", yesno(intel_dmc_has_payload(dev_priv)));
-       seq_printf(m, "path: %s\n", dmc->fw_path);
-       seq_printf(m, "Pipe A fw support: %s\n",
-                  yesno(GRAPHICS_VER(dev_priv) >= 12));
-       seq_printf(m, "Pipe A fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEA].payload));
-       seq_printf(m, "Pipe B fw support: %s\n", yesno(IS_ALDERLAKE_P(dev_priv)));
-       seq_printf(m, "Pipe B fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEB].payload));
-
-       if (!intel_dmc_has_payload(dev_priv))
-               goto out;
-
-       seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
-                  DMC_VERSION_MINOR(dmc->version));
-
-       if (DISPLAY_VER(dev_priv) >= 12) {
-               if (IS_DGFX(dev_priv)) {
-                       dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
-               } else {
-                       dc5_reg = TGL_DMC_DEBUG_DC5_COUNT;
-                       dc6_reg = TGL_DMC_DEBUG_DC6_COUNT;
-               }
-
-               /*
-                * NOTE: DMC_DEBUG3 is a general purpose reg.
-                * According to B.Specs:49196 DMC f/w reuses DC5/6 counter
-                * reg for DC3CO debugging and validation,
-                * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
-                */
-               seq_printf(m, "DC3CO count: %d\n", intel_de_read(dev_priv, IS_DGFX(dev_priv) ?
-                                       DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
-       } else {
-               dc5_reg = IS_BROXTON(dev_priv) ? BXT_DMC_DC3_DC5_COUNT :
-                                                SKL_DMC_DC3_DC5_COUNT;
-               if (!IS_GEMINILAKE(dev_priv) && !IS_BROXTON(dev_priv))
-                       dc6_reg = SKL_DMC_DC5_DC6_COUNT;
-       }
-
-       seq_printf(m, "DC3 -> DC5 count: %d\n",
-                  intel_de_read(dev_priv, dc5_reg));
-       if (dc6_reg.reg)
-               seq_printf(m, "DC5 -> DC6 count: %d\n",
-                          intel_de_read(dev_priv, dc6_reg));
-
-out:
-       seq_printf(m, "program base: 0x%08x\n",
-                  intel_de_read(dev_priv, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
-       seq_printf(m, "ssp base: 0x%08x\n",
-                  intel_de_read(dev_priv, DMC_SSP_BASE));
-       seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, DMC_HTP_SKL));
-
-       intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
-
-       return 0;
-}
-
 static void intel_seq_print_mode(struct seq_file *m, int tabs,
                                 const struct drm_display_mode *mode)
 {
@@ -537,11 +472,18 @@ static void intel_encoder_info(struct seq_file *m,
        drm_connector_list_iter_end(&conn_iter);
 }
 
-static void intel_panel_info(struct seq_file *m, struct intel_panel *panel)
+static void intel_panel_info(struct seq_file *m,
+                            struct intel_connector *connector)
 {
-       const struct drm_display_mode *mode = panel->fixed_mode;
+       const struct drm_display_mode *fixed_mode;
+
+       if (list_empty(&connector->panel.fixed_modes))
+               return;
 
-       seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
+       seq_puts(m, "\tfixed modes:\n");
+
+       list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head)
+               intel_seq_print_mode(m, 2, fixed_mode);
 }
 
 static void intel_hdcp_info(struct seq_file *m,
@@ -577,9 +519,8 @@ static void intel_dp_info(struct seq_file *m,
        const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;
 
        seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
-       seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
-       if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
-               intel_panel_info(m, &intel_connector->panel);
+       seq_printf(m, "\taudio support: %s\n",
+                  str_yes_no(intel_dp->has_audio));
 
        drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
                                edid ? edid->data : NULL, &intel_dp->aux);
@@ -590,7 +531,7 @@ static void intel_dp_mst_info(struct seq_file *m,
 {
        bool has_audio = intel_connector->port->has_audio;
 
-       seq_printf(m, "\taudio support: %s\n", yesno(has_audio));
+       seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio));
 }
 
 static void intel_hdmi_info(struct seq_file *m,
@@ -599,13 +540,8 @@ static void intel_hdmi_info(struct seq_file *m,
        struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder);
 
-       seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio));
-}
-
-static void intel_lvds_info(struct seq_file *m,
-                           struct intel_connector *intel_connector)
-{
-       intel_panel_info(m, &intel_connector->panel);
+       seq_printf(m, "\taudio support: %s\n",
+                  str_yes_no(intel_hdmi->has_audio));
 }
 
 static void intel_connector_info(struct seq_file *m,
@@ -642,10 +578,6 @@ static void intel_connector_info(struct seq_file *m,
                else
                        intel_dp_info(m, intel_connector);
                break;
-       case DRM_MODE_CONNECTOR_LVDS:
-               if (encoder->type == INTEL_OUTPUT_LVDS)
-                       intel_lvds_info(m, intel_connector);
-               break;
        case DRM_MODE_CONNECTOR_HDMIA:
                if (encoder->type == INTEL_OUTPUT_HDMI ||
                    encoder->type == INTEL_OUTPUT_DDI)
@@ -658,6 +590,8 @@ static void intel_connector_info(struct seq_file *m,
        seq_puts(m, "\tHDCP version: ");
        intel_hdcp_info(m, intel_connector);
 
+       intel_panel_info(m, intel_connector);
+
        seq_printf(m, "\tmodes:\n");
        list_for_each_entry(mode, &connector->modes, head)
                intel_seq_print_mode(m, 2, mode);
@@ -757,7 +691,7 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane)
                   DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n",
                   fb->base.id, &fb->format->format,
                   fb->modifier, fb->width, fb->height,
-                  yesno(plane_state->uapi.visible),
+                  str_yes_no(plane_state->uapi.visible),
                   DRM_RECT_FP_ARG(&plane_state->uapi.src),
                   DRM_RECT_ARG(&plane_state->uapi.dst),
                   rot_str);
@@ -796,7 +730,7 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc)
                                &crtc_state->scaler_state.scalers[i];
 
                        seq_printf(m, ", scalers[%d]: use=%s, mode=%x",
-                                  i, yesno(sc->in_use), sc->mode);
+                                  i, str_yes_no(sc->in_use), sc->mode);
                }
                seq_puts(m, "\n");
        } else {
@@ -919,24 +853,24 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
                   crtc->base.base.id, crtc->base.name);
 
        seq_printf(m, "\tuapi: enable=%s, active=%s, mode=" DRM_MODE_FMT "\n",
-                  yesno(crtc_state->uapi.enable),
-                  yesno(crtc_state->uapi.active),
+                  str_yes_no(crtc_state->uapi.enable),
+                  str_yes_no(crtc_state->uapi.active),
                   DRM_MODE_ARG(&crtc_state->uapi.mode));
 
        seq_printf(m, "\thw: enable=%s, active=%s\n",
-                  yesno(crtc_state->hw.enable), yesno(crtc_state->hw.active));
+                  str_yes_no(crtc_state->hw.enable), str_yes_no(crtc_state->hw.active));
        seq_printf(m, "\tadjusted_mode=" DRM_MODE_FMT "\n",
                   DRM_MODE_ARG(&crtc_state->hw.adjusted_mode));
        seq_printf(m, "\tpipe__mode=" DRM_MODE_FMT "\n",
                   DRM_MODE_ARG(&crtc_state->hw.pipe_mode));
 
-       seq_printf(m, "\tpipe src size=%dx%d, dither=%s, bpp=%d\n",
-                  crtc_state->pipe_src_w, crtc_state->pipe_src_h,
-                  yesno(crtc_state->dither), crtc_state->pipe_bpp);
+       seq_printf(m, "\tpipe src=" DRM_RECT_FMT ", dither=%s, bpp=%d\n",
+                  DRM_RECT_ARG(&crtc_state->pipe_src),
+                  str_yes_no(crtc_state->dither), crtc_state->pipe_bpp);
 
        intel_scaler_info(m, crtc);
 
-       if (crtc_state->bigjoiner)
+       if (crtc_state->bigjoiner_pipes)
                seq_printf(m, "\tLinked to 0x%x pipes as a %s\n",
                           crtc_state->bigjoiner_pipes,
                           intel_crtc_is_bigjoiner_slave(crtc_state) ? "slave" : "master");
@@ -948,8 +882,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
        intel_plane_info(m, crtc);
 
        seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n",
-                  yesno(!crtc->cpu_fifo_underrun_disabled),
-                  yesno(!crtc->pch_fifo_underrun_disabled));
+                  str_yes_no(!crtc->cpu_fifo_underrun_disabled),
+                  str_yes_no(!crtc->pch_fifo_underrun_disabled));
 
        crtc_updates_info(m, crtc, "\t");
 }
@@ -1005,7 +939,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
                seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
                           pll->info->id);
                seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
-                          pll->state.pipe_mask, pll->active_mask, yesno(pll->on));
+                          pll->state.pipe_mask, pll->active_mask,
+                          str_yes_no(pll->on));
                seq_printf(m, " tracked hardware state:\n");
                seq_printf(m, " dpll:    0x%08x\n", pll->state.hw_state.dpll);
                seq_printf(m, " dpll_md: 0x%08x\n",
@@ -1047,7 +982,7 @@ static int i915_ipc_status_show(struct seq_file *m, void *data)
        struct drm_i915_private *dev_priv = m->private;
 
        seq_printf(m, "Isochronous Priority Control: %s\n",
-                       yesno(dev_priv->ipc_enabled));
+                       str_yes_no(dev_priv->ipc_enabled));
        return 0;
 }
 
@@ -1117,13 +1052,13 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
                seq_printf(m, "Pipe %c\n", pipe_name(pipe));
 
                for_each_plane_id_on_crtc(crtc, plane_id) {
-                       entry = &crtc_state->wm.skl.plane_ddb_y[plane_id];
+                       entry = &crtc_state->wm.skl.plane_ddb[plane_id];
                        seq_printf(m, "  Plane%-8d%8u%8u%8u\n", plane_id + 1,
                                   entry->start, entry->end,
                                   skl_ddb_entry_size(entry));
                }
 
-               entry = &crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR];
+               entry = &crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
                seq_printf(m, "  %-13s%8u%8u%8u\n", "Cursor", entry->start,
                           entry->end, skl_ddb_entry_size(entry));
        }
@@ -1133,97 +1068,48 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
        return 0;
 }
 
-static void drrs_status_per_crtc(struct seq_file *m,
-                                struct drm_device *dev,
-                                struct intel_crtc *crtc)
+static int i915_drrs_status(struct seq_file *m, void *unused)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_drrs *drrs = &dev_priv->drrs;
-       int vrefresh = 0;
-       struct drm_connector *connector;
+       struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct drm_connector_list_iter conn_iter;
+       struct intel_connector *connector;
+       struct intel_crtc *crtc;
 
-       drm_connector_list_iter_begin(dev, &conn_iter);
-       drm_for_each_connector_iter(connector, &conn_iter) {
-               bool supported = false;
-
-               if (connector->state->crtc != &crtc->base)
-                       continue;
-
-               seq_printf(m, "%s:\n", connector->name);
-
-               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
-                   drrs->type == SEAMLESS_DRRS_SUPPORT)
-                       supported = true;
-
-               seq_printf(m, "\tDRRS Supported: %s\n", yesno(supported));
+       drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
+       for_each_intel_connector_iter(connector, &conn_iter) {
+               seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n",
+                          connector->base.base.id, connector->base.name,
+                          intel_drrs_type_str(intel_panel_drrs_type(connector)));
        }
        drm_connector_list_iter_end(&conn_iter);
 
        seq_puts(m, "\n");
 
-       if (to_intel_crtc_state(crtc->base.state)->has_drrs) {
-               struct intel_panel *panel;
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               const struct intel_crtc_state *crtc_state =
+                       to_intel_crtc_state(crtc->base.state);
 
-               mutex_lock(&drrs->mutex);
-               /* DRRS Supported */
-               seq_puts(m, "\tDRRS Enabled: Yes\n");
+               seq_printf(m, "[CRTC:%d:%s]:\n",
+                          crtc->base.base.id, crtc->base.name);
 
-               /* disable_drrs() will make drrs->dp NULL */
-               if (!drrs->dp) {
-                       seq_puts(m, "Idleness DRRS: Disabled\n");
-                       mutex_unlock(&drrs->mutex);
-                       return;
-               }
+               mutex_lock(&crtc->drrs.mutex);
 
-               panel = &drrs->dp->attached_connector->panel;
-               seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
-                                       drrs->busy_frontbuffer_bits);
-
-               seq_puts(m, "\n\t\t");
-               if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
-                       seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
-                       vrefresh = drm_mode_vrefresh(panel->fixed_mode);
-               } else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
-                       seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
-                       vrefresh = drm_mode_vrefresh(panel->downclock_mode);
-               } else {
-                       seq_printf(m, "DRRS_State: Unknown(%d)\n",
-                                               drrs->refresh_rate_type);
-                       mutex_unlock(&drrs->mutex);
-                       return;
-               }
-               seq_printf(m, "\t\tVrefresh: %d", vrefresh);
+               /* DRRS Supported */
+               seq_printf(m, "\tDRRS Enabled: %s\n",
+                          str_yes_no(crtc_state->has_drrs));
 
-               seq_puts(m, "\n\t\t");
-               mutex_unlock(&drrs->mutex);
-       } else {
-               /* DRRS not supported. Print the VBT parameter*/
-               seq_puts(m, "\tDRRS Enabled : No");
-       }
-       seq_puts(m, "\n");
-}
+               seq_printf(m, "\tDRRS Active: %s\n",
+                          str_yes_no(intel_drrs_is_active(crtc)));
 
-static int i915_drrs_status(struct seq_file *m, void *unused)
-{
-       struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
-       struct intel_crtc *crtc;
-       int active_crtc_cnt = 0;
+               seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n",
+                          crtc->drrs.busy_frontbuffer_bits);
 
-       drm_modeset_lock_all(dev);
-       for_each_intel_crtc(dev, crtc) {
-               if (crtc->base.state->active) {
-                       active_crtc_cnt++;
-                       seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
+               seq_printf(m, "\tDRRS refresh rate: %s\n",
+                          crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
+                          "low" : "high");
 
-                       drrs_status_per_crtc(m, dev, crtc);
-               }
+               mutex_unlock(&crtc->drrs.mutex);
        }
-       drm_modeset_unlock_all(dev);
-
-       if (!active_crtc_cnt)
-               seq_puts(m, "No active crtc found\n");
 
        return 0;
 }
@@ -1259,7 +1145,7 @@ static int i915_lpsp_status(struct seq_file *m, void *unused)
                return 0;
        }
 
-       seq_printf(m, "LPSP: %s\n", enableddisabled(lpsp_enabled));
+       seq_printf(m, "LPSP: %s\n", str_enabled_disabled(lpsp_enabled));
 
        return 0;
 }
@@ -1740,7 +1626,7 @@ static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
 
        seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold);
        seq_printf(m, "Detected: %s\n",
-                  yesno(delayed_work_pending(&hotplug->reenable_work)));
+                  str_yes_no(delayed_work_pending(&hotplug->reenable_work)));
 
        return 0;
 }
@@ -1814,7 +1700,7 @@ static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data)
        struct drm_i915_private *dev_priv = m->private;
 
        seq_printf(m, "Enabled: %s\n",
-                  yesno(dev_priv->hotplug.hpd_short_storm_enabled));
+                  str_yes_no(dev_priv->hotplug.hpd_short_storm_enabled));
 
        return 0;
 }
@@ -1888,13 +1774,8 @@ static int i915_drrs_ctl_set(void *data, u64 val)
        struct drm_device *dev = &dev_priv->drm;
        struct intel_crtc *crtc;
 
-       if (DISPLAY_VER(dev_priv) < 7)
-               return -ENODEV;
-
        for_each_intel_crtc(dev, crtc) {
-               struct drm_connector_list_iter conn_iter;
                struct intel_crtc_state *crtc_state;
-               struct drm_connector *connector;
                struct drm_crtc_commit *commit;
                int ret;
 
@@ -1915,30 +1796,13 @@ static int i915_drrs_ctl_set(void *data, u64 val)
                                goto out;
                }
 
-               drm_connector_list_iter_begin(dev, &conn_iter);
-               drm_for_each_connector_iter(connector, &conn_iter) {
-                       struct intel_encoder *encoder;
-                       struct intel_dp *intel_dp;
-
-                       if (!(crtc_state->uapi.connector_mask &
-                             drm_connector_mask(connector)))
-                               continue;
-
-                       encoder = intel_attached_encoder(to_intel_connector(connector));
-                       if (encoder->type != INTEL_OUTPUT_EDP)
-                               continue;
-
-                       drm_dbg(&dev_priv->drm,
-                               "Manually %sabling DRRS. %llu\n",
-                               val ? "en" : "dis", val);
+               drm_dbg(&dev_priv->drm,
+                       "Manually %sactivating DRRS\n", val ? "" : "de");
 
-                       intel_dp = enc_to_intel_dp(encoder);
-                       if (val)
-                               intel_drrs_enable(intel_dp, crtc_state);
-                       else
-                               intel_drrs_disable(intel_dp, crtc_state);
-               }
-               drm_connector_list_iter_end(&conn_iter);
+               if (val)
+                       intel_drrs_activate(crtc_state);
+               else
+                       intel_drrs_deactivate(crtc_state);
 
 out:
                drm_modeset_unlock(&crtc->base.mutex);
@@ -2020,7 +1884,6 @@ static const struct drm_info_list intel_display_debugfs_list[] = {
        {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
        {"i915_edp_psr_status", i915_edp_psr_status, 0},
        {"i915_power_domain_info", i915_power_domain_info, 0},
-       {"i915_dmc_info", i915_dmc_info, 0},
        {"i915_display_info", i915_display_info, 0},
        {"i915_shared_dplls_info", i915_shared_dplls_info, 0},
        {"i915_dp_mst_info", i915_dp_mst_info, 0},
@@ -2064,6 +1927,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
                                 ARRAY_SIZE(intel_display_debugfs_list),
                                 minor->debugfs_root, minor);
 
+       intel_dmc_debugfs_register(i915);
        intel_fbc_debugfs_register(i915);
 }
 
@@ -2209,14 +2073,14 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
                intel_dp = intel_attached_dp(to_intel_connector(connector));
                crtc_state = to_intel_crtc_state(crtc->state);
                seq_printf(m, "DSC_Enabled: %s\n",
-                          yesno(crtc_state->dsc.compression_enable));
+                          str_yes_no(crtc_state->dsc.compression_enable));
                seq_printf(m, "DSC_Sink_Support: %s\n",
-                          yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
+                          str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
                seq_printf(m, "Force_DSC_Enable: %s\n",
-                          yesno(intel_dp->force_dsc_en));
+                          str_yes_no(intel_dp->force_dsc_en));
                if (!intel_dp_is_edp(intel_dp))
                        seq_printf(m, "FEC_Sink_Support: %s\n",
-                                  yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
+                                  str_yes_no(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
        } while (try_again);
 
        drm_modeset_drop_locks(&ctx);
index 9ebae7a..6a56950 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "i915_drv.h"
 #include "i915_irq.h"
 #include "intel_cdclk.h"
@@ -11,6 +13,7 @@
 #include "intel_crt.h"
 #include "intel_de.h"
 #include "intel_display_power.h"
+#include "intel_display_power_well.h"
 #include "intel_display_types.h"
 #include "intel_dmc.h"
 #include "intel_dpio_phy.h"
 #include "intel_vga.h"
 #include "vlv_sideband.h"
 
-struct i915_power_well_ops {
-       /*
-        * Synchronize the well's hw state to match the current sw state, for
-        * example enable/disable it based on the current refcount. Called
-        * during driver init and resume time, possibly after first calling
-        * the enable/disable handlers.
-        */
-       void (*sync_hw)(struct drm_i915_private *dev_priv,
-                       struct i915_power_well *power_well);
-       /*
-        * Enable the well and resources that depend on it (for example
-        * interrupts located on the well). Called after the 0->1 refcount
-        * transition.
-        */
-       void (*enable)(struct drm_i915_private *dev_priv,
-                      struct i915_power_well *power_well);
-       /*
-        * Disable the well and resources that depend on it. Called after
-        * the 1->0 refcount transition.
-        */
-       void (*disable)(struct drm_i915_private *dev_priv,
-                       struct i915_power_well *power_well);
-       /* Returns the hw enabled state. */
-       bool (*is_enabled)(struct drm_i915_private *dev_priv,
-                          struct i915_power_well *power_well);
-};
-
-struct i915_power_well_regs {
-       i915_reg_t bios;
-       i915_reg_t driver;
-       i915_reg_t kvmr;
-       i915_reg_t debug;
-};
-
-/* Power well structure for haswell */
-struct i915_power_well_desc {
-       const char *name;
-       bool always_on;
-       u64 domains;
-       /* unique identifier for this power well */
-       enum i915_power_well_id id;
-       /*
-        * Arbitraty data associated with this power well. Platform and power
-        * well specific.
-        */
-       union {
-               struct {
-                       /*
-                        * request/status flag index in the PUNIT power well
-                        * control/status registers.
-                        */
-                       u8 idx;
-               } vlv;
-               struct {
-                       enum dpio_phy phy;
-               } bxt;
-               struct {
-                       const struct i915_power_well_regs *regs;
-                       /*
-                        * request/status flag index in the power well
-                        * constrol/status registers.
-                        */
-                       u8 idx;
-                       /* Mask of pipes whose IRQ logic is backed by the pw */
-                       u8 irq_pipe_mask;
-                       /*
-                        * Instead of waiting for the status bit to ack enables,
-                        * just wait a specific amount of time and then consider
-                        * the well enabled.
-                        */
-                       u16 fixed_enable_delay;
-                       /* The pw is backing the VGA functionality */
-                       bool has_vga:1;
-                       bool has_fuses:1;
-                       /*
-                        * The pw is for an ICL+ TypeC PHY port in
-                        * Thunderbolt mode.
-                        */
-                       bool is_tc_tbt:1;
-               } hsw;
-       };
-       const struct i915_power_well_ops *ops;
-};
-
-struct i915_power_well {
-       const struct i915_power_well_desc *desc;
-       /* power well enable/disable usage count */
-       int count;
-       /* cached hw enabled state */
-       bool hw_enabled;
-};
-
-bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
-                                        enum i915_power_well_id power_well_id);
-
 const char *
 intel_display_power_domain_str(enum intel_display_power_domain domain)
 {
@@ -153,12 +61,12 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
                return "TRANSCODER_D";
        case POWER_DOMAIN_TRANSCODER_EDP:
                return "TRANSCODER_EDP";
-       case POWER_DOMAIN_TRANSCODER_VDSC_PW2:
-               return "TRANSCODER_VDSC_PW2";
        case POWER_DOMAIN_TRANSCODER_DSI_A:
                return "TRANSCODER_DSI_A";
        case POWER_DOMAIN_TRANSCODER_DSI_C:
                return "TRANSCODER_DSI_C";
+       case POWER_DOMAIN_TRANSCODER_VDSC_PW2:
+               return "TRANSCODER_VDSC_PW2";
        case POWER_DOMAIN_PORT_DDI_A_LANES:
                return "PORT_DDI_A_LANES";
        case POWER_DOMAIN_PORT_DDI_B_LANES:
@@ -259,40 +167,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
        }
 }
 
-static void intel_power_well_enable(struct drm_i915_private *dev_priv,
-                                   struct i915_power_well *power_well)
-{
-       drm_dbg_kms(&dev_priv->drm, "enabling %s\n", power_well->desc->name);
-       power_well->desc->ops->enable(dev_priv, power_well);
-       power_well->hw_enabled = true;
-}
-
-static void intel_power_well_disable(struct drm_i915_private *dev_priv,
-                                    struct i915_power_well *power_well)
-{
-       drm_dbg_kms(&dev_priv->drm, "disabling %s\n", power_well->desc->name);
-       power_well->hw_enabled = false;
-       power_well->desc->ops->disable(dev_priv, power_well);
-}
-
-static void intel_power_well_get(struct drm_i915_private *dev_priv,
-                                struct i915_power_well *power_well)
-{
-       if (!power_well->count++)
-               intel_power_well_enable(dev_priv, power_well);
-}
-
-static void intel_power_well_put(struct drm_i915_private *dev_priv,
-                                struct i915_power_well *power_well)
-{
-       drm_WARN(&dev_priv->drm, !power_well->count,
-                "Use count on power well %s is already zero",
-                power_well->desc->name);
-
-       if (!--power_well->count)
-               intel_power_well_disable(dev_priv, power_well);
-}
-
 /**
  * __intel_display_power_is_enabled - unlocked check for a power domain
  * @dev_priv: i915 device instance
@@ -317,10 +191,10 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
        is_enabled = true;
 
        for_each_power_domain_well_reverse(dev_priv, power_well, BIT_ULL(domain)) {
-               if (power_well->desc->always_on)
+               if (intel_power_well_is_always_on(power_well))
                        continue;
 
-               if (!power_well->hw_enabled) {
+               if (!intel_power_well_is_enabled_cached(power_well)) {
                        is_enabled = false;
                        break;
                }
@@ -438,7 +312,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
                                           struct i915_power_well *power_well,
                                           bool timeout_expected)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        int enable_delay = power_well->desc->hsw.fixed_enable_delay;
 
@@ -456,7 +330,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
        if (intel_de_wait_for_set(dev_priv, regs->driver,
                                  HSW_PWR_WELL_CTL_STATE(pw_idx), 1)) {
                drm_dbg_kms(&dev_priv->drm, "%s power well enable timeout\n",
-                           power_well->desc->name);
+                           intel_power_well_name(power_well));
 
                drm_WARN_ON(&dev_priv->drm, !timeout_expected);
 
@@ -482,7 +356,7 @@ static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv,
 static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv,
                                            struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        bool disabled;
        u32 reqs;
@@ -504,7 +378,7 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv,
 
        drm_dbg_kms(&dev_priv->drm,
                    "%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n",
-                   power_well->desc->name,
+                   intel_power_well_name(power_well),
                    !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8));
 }
 
@@ -520,7 +394,7 @@ static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv,
 static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
                                  struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        u32 val;
 
@@ -567,7 +441,7 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
 static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
                                   struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        u32 val;
 
@@ -584,7 +458,7 @@ static void
 icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
                                    struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
        u32 val;
@@ -616,7 +490,7 @@ static void
 icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
                                     struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
        u32 val;
@@ -636,28 +510,10 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
 
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 
-static u64 async_put_domains_mask(struct i915_power_domains *power_domains);
-
-static int power_well_async_ref_count(struct drm_i915_private *dev_priv,
-                                     struct i915_power_well *power_well)
-{
-       int refs = hweight64(power_well->desc->domains &
-                            async_put_domains_mask(&dev_priv->power_domains));
-
-       drm_WARN_ON(&dev_priv->drm, refs > power_well->count);
-
-       return refs;
-}
-
 static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
                                        struct i915_power_well *power_well,
                                        struct intel_digital_port *dig_port)
 {
-       /* Bypass the check if all references are released asynchronously */
-       if (power_well_async_ref_count(dev_priv, power_well) ==
-           power_well->count)
-               return;
-
        if (drm_WARN_ON(&dev_priv->drm, !dig_port))
                return;
 
@@ -706,7 +562,7 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
 {
        enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
        struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        bool is_tbt = power_well->desc->hsw.is_tc_tbt;
        bool timeout_expected;
        u32 val;
@@ -748,18 +604,6 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
        }
 }
 
-static void
-icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
-                                 struct i915_power_well *power_well)
-{
-       enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
-       struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
-
-       icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port);
-
-       hsw_power_well_disable(dev_priv, power_well);
-}
-
 static void
 icl_aux_power_well_enable(struct drm_i915_private *dev_priv,
                          struct i915_power_well *power_well)
@@ -782,7 +626,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv,
        enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
 
        if (intel_phy_is_tc(dev_priv, phy))
-               return icl_tc_phy_aux_power_well_disable(dev_priv, power_well);
+               return hsw_power_well_disable(dev_priv, power_well);
        else if (IS_ICELAKE(dev_priv))
                return icl_combo_phy_aux_power_well_disable(dev_priv,
                                                            power_well);
@@ -798,7 +642,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv,
 static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
                                   struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        enum i915_power_well_id id = power_well->desc->id;
        int pw_idx = power_well->desc->hsw.idx;
        u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) |
@@ -1061,41 +905,6 @@ static void bxt_disable_dc9(struct drm_i915_private *dev_priv)
        intel_pps_unlock_regs_wa(dev_priv);
 }
 
-static void assert_dmc_loaded(struct drm_i915_private *dev_priv)
-{
-       drm_WARN_ONCE(&dev_priv->drm,
-                     !intel_de_read(dev_priv,
-                                    DMC_PROGRAM(dev_priv->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
-                                    "DMC program storage start is NULL\n");
-       drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_SSP_BASE),
-                     "DMC SSP Base Not fine\n");
-       drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_HTP_SKL),
-                     "DMC HTP Not fine\n");
-}
-
-static struct i915_power_well *
-lookup_power_well(struct drm_i915_private *dev_priv,
-                 enum i915_power_well_id power_well_id)
-{
-       struct i915_power_well *power_well;
-
-       for_each_power_well(dev_priv, power_well)
-               if (power_well->desc->id == power_well_id)
-                       return power_well;
-
-       /*
-        * It's not feasible to add error checking code to the callers since
-        * this condition really shouldn't happen and it doesn't even make sense
-        * to abort things like display initialization sequences. Just return
-        * the first power well and hope the WARN gets reported so we can fix
-        * our driver.
-        */
-       drm_WARN(&dev_priv->drm, 1,
-                "Power well %d not defined for this platform\n",
-                power_well_id);
-       return &dev_priv->power_domains.power_wells[0];
-}
-
 /**
  * intel_display_power_set_target_dc_state - Set target dc state.
  * @dev_priv: i915 device
@@ -1123,19 +932,18 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
        if (state == dev_priv->dmc.target_dc_state)
                goto unlock;
 
-       dc_off_enabled = power_well->desc->ops->is_enabled(dev_priv,
-                                                          power_well);
+       dc_off_enabled = intel_power_well_is_enabled(dev_priv, power_well);
        /*
         * If DC off power well is disabled, need to enable and disable the
         * DC off power well to effect target DC state.
         */
        if (!dc_off_enabled)
-               power_well->desc->ops->enable(dev_priv, power_well);
+               intel_power_well_enable(dev_priv, power_well);
 
        dev_priv->dmc.target_dc_state = state;
 
        if (!dc_off_enabled)
-               power_well->desc->ops->disable(dev_priv, power_well);
+               intel_power_well_disable(dev_priv, power_well);
 
 unlock:
        mutex_unlock(&power_domains->lock);
@@ -1208,7 +1016,7 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv)
 static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
                                   struct i915_power_well *power_well)
 {
-       const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
+       const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
        int pw_idx = power_well->desc->hsw.idx;
        u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx);
        u32 bios_req = intel_de_read(dev_priv, regs->bios);
@@ -1246,17 +1054,17 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
        struct i915_power_well *power_well;
 
        power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A);
-       if (power_well->count > 0)
+       if (intel_power_well_refcount(power_well) > 0)
                bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy);
 
        power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
-       if (power_well->count > 0)
+       if (intel_power_well_refcount(power_well) > 0)
                bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy);
 
        if (IS_GEMINILAKE(dev_priv)) {
                power_well = lookup_power_well(dev_priv,
                                               GLK_DISP_PW_DPIO_CMN_C);
-               if (power_well->count > 0)
+               if (intel_power_well_refcount(power_well) > 0)
                        bxt_ddi_phy_verify_state(dev_priv,
                                                 power_well->desc->bxt.phy);
        }
@@ -1382,7 +1190,7 @@ static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv,
 static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv,
                                          struct i915_power_well *power_well)
 {
-       if (power_well->count > 0)
+       if (intel_power_well_refcount(power_well) > 0)
                i830_pipes_power_well_enable(dev_priv, power_well);
        else
                i830_pipes_power_well_disable(dev_priv, power_well);
@@ -1655,7 +1463,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
                                     PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) |
                                     PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1));
 
-       if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) {
+       if (intel_power_well_is_enabled(dev_priv, cmn_bc)) {
                phy_status |= PHY_POWERGOOD(DPIO_PHY0);
 
                /* this assumes override is only used to enable lanes */
@@ -1696,7 +1504,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
                        phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
        }
 
-       if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) {
+       if (intel_power_well_is_enabled(dev_priv, cmn_d)) {
                phy_status |= PHY_POWERGOOD(DPIO_PHY1);
 
                /* this assumes override is only used to enable lanes */
@@ -3280,7 +3088,15 @@ static const struct i915_power_well_desc i830_power_wells[] = {
        },
 };
 
+static const struct i915_power_well_regs hsw_power_well_regs = {
+       .bios   = HSW_PWR_WELL_CTL1,
+       .driver = HSW_PWR_WELL_CTL2,
+       .kvmr   = HSW_PWR_WELL_CTL3,
+       .debug  = HSW_PWR_WELL_CTL4,
+};
+
 static const struct i915_power_well_ops hsw_power_well_ops = {
+       .regs = &hsw_power_well_regs,
        .sync_hw = hsw_power_well_sync_hw,
        .enable = hsw_power_well_enable,
        .disable = hsw_power_well_disable,
@@ -3301,13 +3117,6 @@ static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = {
        .is_enabled = bxt_dpio_cmn_power_well_enabled,
 };
 
-static const struct i915_power_well_regs hsw_power_well_regs = {
-       .bios   = HSW_PWR_WELL_CTL1,
-       .driver = HSW_PWR_WELL_CTL2,
-       .kvmr   = HSW_PWR_WELL_CTL3,
-       .debug  = HSW_PWR_WELL_CTL4,
-};
-
 static const struct i915_power_well_desc hsw_power_wells[] = {
        {
                .name = "always-on",
@@ -3322,7 +3131,6 @@ static const struct i915_power_well_desc hsw_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = HSW_DISP_PW_GLOBAL,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
                        .hsw.has_vga = true,
                },
@@ -3343,7 +3151,6 @@ static const struct i915_power_well_desc bdw_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = HSW_DISP_PW_GLOBAL,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
                        .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
                        .hsw.has_vga = true,
@@ -3487,18 +3294,6 @@ static const struct i915_power_well_desc chv_power_wells[] = {
        },
 };
 
-bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
-                                        enum i915_power_well_id power_well_id)
-{
-       struct i915_power_well *power_well;
-       bool ret;
-
-       power_well = lookup_power_well(dev_priv, power_well_id);
-       ret = power_well->desc->ops->is_enabled(dev_priv, power_well);
-
-       return ret;
-}
-
 static const struct i915_power_well_desc skl_power_wells[] = {
        {
                .name = "always-on",
@@ -3515,7 +3310,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -3528,7 +3322,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_MISC_IO,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_MISC_IO,
                },
        },
@@ -3544,7 +3337,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_2,
                        .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
                        .hsw.has_vga = true,
@@ -3557,7 +3349,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E,
                },
        },
@@ -3567,7 +3358,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
                },
        },
@@ -3577,7 +3367,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
                },
        },
@@ -3587,7 +3376,6 @@ static const struct i915_power_well_desc skl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_D,
                },
        },
@@ -3609,7 +3397,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -3626,7 +3413,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_2,
                        .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
                        .hsw.has_vga = true,
@@ -3669,7 +3455,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -3686,7 +3471,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_PW_2,
                        .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
                        .hsw.has_vga = true,
@@ -3726,7 +3510,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = GLK_PW_CTL_IDX_AUX_A,
                },
        },
@@ -3736,7 +3519,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = GLK_PW_CTL_IDX_AUX_B,
                },
        },
@@ -3746,7 +3528,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = GLK_PW_CTL_IDX_AUX_C,
                },
        },
@@ -3756,7 +3537,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = GLK_PW_CTL_IDX_DDI_A,
                },
        },
@@ -3766,7 +3546,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
                },
        },
@@ -3776,31 +3555,39 @@ static const struct i915_power_well_desc glk_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
                },
        },
 };
 
+static const struct i915_power_well_regs icl_aux_power_well_regs = {
+       .bios   = ICL_PWR_WELL_CTL_AUX1,
+       .driver = ICL_PWR_WELL_CTL_AUX2,
+       .debug  = ICL_PWR_WELL_CTL_AUX4,
+};
+
 static const struct i915_power_well_ops icl_aux_power_well_ops = {
+       .regs = &icl_aux_power_well_regs,
        .sync_hw = hsw_power_well_sync_hw,
        .enable = icl_aux_power_well_enable,
        .disable = icl_aux_power_well_disable,
        .is_enabled = hsw_power_well_enabled,
 };
 
-static const struct i915_power_well_regs icl_aux_power_well_regs = {
-       .bios   = ICL_PWR_WELL_CTL_AUX1,
-       .driver = ICL_PWR_WELL_CTL_AUX2,
-       .debug  = ICL_PWR_WELL_CTL_AUX4,
-};
-
 static const struct i915_power_well_regs icl_ddi_power_well_regs = {
        .bios   = ICL_PWR_WELL_CTL_DDI1,
        .driver = ICL_PWR_WELL_CTL_DDI2,
        .debug  = ICL_PWR_WELL_CTL_DDI4,
 };
 
+static const struct i915_power_well_ops icl_ddi_power_well_ops = {
+       .regs = &icl_ddi_power_well_regs,
+       .sync_hw = hsw_power_well_sync_hw,
+       .enable = hsw_power_well_enable,
+       .disable = hsw_power_well_disable,
+       .is_enabled = hsw_power_well_enabled,
+};
+
 static const struct i915_power_well_desc icl_power_wells[] = {
        {
                .name = "always-on",
@@ -3817,7 +3604,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -3834,7 +3620,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_2,
                        .hsw.has_fuses = true,
                },
@@ -3845,7 +3630,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = ICL_DISP_PW_3,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_3,
                        .hsw.irq_pipe_mask = BIT(PIPE_B),
                        .hsw.has_vga = true,
@@ -3855,60 +3639,54 @@ static const struct i915_power_well_desc icl_power_wells[] = {
        {
                .name = "DDI A IO",
                .domains = ICL_DDI_IO_A_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
                },
        },
        {
                .name = "DDI B IO",
                .domains = ICL_DDI_IO_B_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
                },
        },
        {
                .name = "DDI C IO",
                .domains = ICL_DDI_IO_C_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
                },
        },
        {
                .name = "DDI D IO",
                .domains = ICL_DDI_IO_D_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_D,
                },
        },
        {
                .name = "DDI E IO",
                .domains = ICL_DDI_IO_E_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_E,
                },
        },
        {
                .name = "DDI F IO",
                .domains = ICL_DDI_IO_F_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_F,
                },
        },
@@ -3918,7 +3696,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
                },
        },
@@ -3928,7 +3705,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
                },
        },
@@ -3938,7 +3714,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
                        .hsw.is_tc_tbt = false,
                },
@@ -3949,7 +3724,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_D,
                        .hsw.is_tc_tbt = false,
                },
@@ -3960,7 +3734,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_E,
                        .hsw.is_tc_tbt = false,
                },
@@ -3971,7 +3744,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_F,
                        .hsw.is_tc_tbt = false,
                },
@@ -3982,7 +3754,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1,
                        .hsw.is_tc_tbt = true,
                },
@@ -3993,7 +3764,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2,
                        .hsw.is_tc_tbt = true,
                },
@@ -4004,7 +3774,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3,
                        .hsw.is_tc_tbt = true,
                },
@@ -4015,7 +3784,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4,
                        .hsw.is_tc_tbt = true,
                },
@@ -4026,7 +3794,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_4,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_C),
@@ -4094,7 +3861,7 @@ static void
 tgl_tc_cold_off_power_well_sync_hw(struct drm_i915_private *i915,
                                   struct i915_power_well *power_well)
 {
-       if (power_well->count > 0)
+       if (intel_power_well_refcount(power_well) > 0)
                tgl_tc_cold_off_power_well_enable(i915, power_well);
        else
                tgl_tc_cold_off_power_well_disable(i915, power_well);
@@ -4108,7 +3875,7 @@ tgl_tc_cold_off_power_well_is_enabled(struct drm_i915_private *dev_priv,
         * Not the correctly implementation but there is no way to just read it
         * from PCODE, so returning count to avoid state mismatch errors
         */
-       return power_well->count;
+       return intel_power_well_refcount(power_well);
 }
 
 static const struct i915_power_well_ops tgl_tc_cold_off_ops = {
@@ -4134,7 +3901,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -4151,7 +3917,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_2,
                        .hsw.has_fuses = true,
                },
@@ -4162,7 +3927,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = ICL_DISP_PW_3,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_3,
                        .hsw.irq_pipe_mask = BIT(PIPE_B),
                        .hsw.has_vga = true,
@@ -4172,90 +3936,81 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "DDI A IO",
                .domains = ICL_DDI_IO_A_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
                }
        },
        {
                .name = "DDI B IO",
                .domains = ICL_DDI_IO_B_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
                }
        },
        {
                .name = "DDI C IO",
                .domains = ICL_DDI_IO_C_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
                }
        },
        {
                .name = "DDI IO TC1",
                .domains = TGL_DDI_IO_TC1_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
                },
        },
        {
                .name = "DDI IO TC2",
                .domains = TGL_DDI_IO_TC2_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
                },
        },
        {
                .name = "DDI IO TC3",
                .domains = TGL_DDI_IO_TC3_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3,
                },
        },
        {
                .name = "DDI IO TC4",
                .domains = TGL_DDI_IO_TC4_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4,
                },
        },
        {
                .name = "DDI IO TC5",
                .domains = TGL_DDI_IO_TC5_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC5,
                },
        },
        {
                .name = "DDI IO TC6",
                .domains = TGL_DDI_IO_TC6_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6,
                },
        },
@@ -4271,7 +4026,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
                },
        },
@@ -4281,7 +4035,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
                },
        },
@@ -4291,7 +4044,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
                },
        },
@@ -4301,7 +4053,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
                        .hsw.is_tc_tbt = false,
                },
@@ -4312,7 +4063,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
                        .hsw.is_tc_tbt = false,
                },
@@ -4323,7 +4073,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3,
                        .hsw.is_tc_tbt = false,
                },
@@ -4334,7 +4083,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4,
                        .hsw.is_tc_tbt = false,
                },
@@ -4345,7 +4093,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC5,
                        .hsw.is_tc_tbt = false,
                },
@@ -4356,7 +4103,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC6,
                        .hsw.is_tc_tbt = false,
                },
@@ -4367,7 +4113,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1,
                        .hsw.is_tc_tbt = true,
                },
@@ -4378,7 +4123,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2,
                        .hsw.is_tc_tbt = true,
                },
@@ -4389,7 +4133,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3,
                        .hsw.is_tc_tbt = true,
                },
@@ -4400,7 +4143,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4,
                        .hsw.is_tc_tbt = true,
                },
@@ -4411,7 +4153,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT5,
                        .hsw.is_tc_tbt = true,
                },
@@ -4422,7 +4163,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT6,
                        .hsw.is_tc_tbt = true,
                },
@@ -4433,7 +4173,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_4,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_C),
@@ -4445,7 +4184,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_PW_5,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_D),
@@ -4469,7 +4207,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -4486,7 +4223,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = ICL_DISP_PW_3,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_3,
                        .hsw.irq_pipe_mask = BIT(PIPE_B),
                        .hsw.has_vga = true,
@@ -4499,7 +4235,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_4,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_C),
@@ -4508,40 +4243,36 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
        {
                .name = "DDI A IO",
                .domains = ICL_DDI_IO_A_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
                }
        },
        {
                .name = "DDI B IO",
                .domains = ICL_DDI_IO_B_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
                }
        },
        {
                .name = "DDI IO TC1",
                .domains = TGL_DDI_IO_TC1_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
                },
        },
        {
                .name = "DDI IO TC2",
                .domains = TGL_DDI_IO_TC2_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
                },
        },
@@ -4551,7 +4282,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
                },
        },
@@ -4561,7 +4291,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
                },
        },
@@ -4571,7 +4300,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
                },
        },
@@ -4581,7 +4309,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
                },
        },
@@ -4603,7 +4330,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -4620,7 +4346,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_2,
                        .hsw.has_fuses = true,
                },
@@ -4631,7 +4356,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = ICL_DISP_PW_3,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_3,
                        .hsw.irq_pipe_mask = BIT(PIPE_B),
                        .hsw.has_vga = true,
@@ -4641,40 +4365,36 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
        {
                .name = "DDI A IO",
                .domains = ICL_DDI_IO_A_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
                }
        },
        {
                .name = "DDI B IO",
                .domains = ICL_DDI_IO_B_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
                }
        },
        {
                .name = "DDI IO TC1",
                .domains = TGL_DDI_IO_TC1_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
                },
        },
        {
                .name = "DDI IO TC2",
                .domains = TGL_DDI_IO_TC2_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
                },
        },
@@ -4684,7 +4404,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
                },
        },
@@ -4694,7 +4413,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
                },
        },
@@ -4704,7 +4422,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
                        .hsw.is_tc_tbt = false,
                },
@@ -4715,7 +4432,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
                        .hsw.is_tc_tbt = false,
                },
@@ -4726,7 +4442,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_4,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_C),
@@ -4738,7 +4453,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_PW_5,
                        .hsw.has_fuses = true,
                        .hsw.irq_pipe_mask = BIT(PIPE_D),
@@ -4762,7 +4476,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_1,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_1,
                        .hsw.has_fuses = true,
                },
@@ -4779,7 +4492,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = SKL_DISP_PW_2,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_PW_2,
                        .hsw.has_vga = true,
                        .hsw.has_fuses = true,
@@ -4791,7 +4503,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_PW_A,
                        .hsw.irq_pipe_mask = BIT(PIPE_A),
                        .hsw.has_fuses = true,
@@ -4803,7 +4514,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_PW_B,
                        .hsw.irq_pipe_mask = BIT(PIPE_B),
                        .hsw.has_fuses = true,
@@ -4815,7 +4525,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_PW_C,
                        .hsw.irq_pipe_mask = BIT(PIPE_C),
                        .hsw.has_fuses = true,
@@ -4827,7 +4536,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &hsw_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_PW_D,
                        .hsw.irq_pipe_mask = BIT(PIPE_D),
                        .hsw.has_fuses = true,
@@ -4836,90 +4544,81 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
        {
                .name = "DDI A IO",
                .domains = ICL_DDI_IO_A_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
                }
        },
        {
                .name = "DDI B IO",
                .domains = ICL_DDI_IO_B_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
                }
        },
        {
                .name = "DDI C IO",
                .domains = ICL_DDI_IO_C_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
                }
        },
        {
                .name = "DDI IO D_XELPD",
                .domains = XELPD_DDI_IO_D_XELPD_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_DDI_D,
                }
        },
        {
                .name = "DDI IO E_XELPD",
                .domains = XELPD_DDI_IO_E_XELPD_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_DDI_E,
                }
        },
        {
                .name = "DDI IO TC1",
                .domains = XELPD_DDI_IO_TC1_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
                }
        },
        {
                .name = "DDI IO TC2",
                .domains = XELPD_DDI_IO_TC2_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
                }
        },
        {
                .name = "DDI IO TC3",
                .domains = XELPD_DDI_IO_TC3_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3,
                }
        },
        {
                .name = "DDI IO TC4",
                .domains = XELPD_DDI_IO_TC4_POWER_DOMAINS,
-               .ops = &hsw_power_well_ops,
+               .ops = &icl_ddi_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_ddi_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4,
                }
        },
@@ -4929,7 +4628,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
                        .hsw.fixed_enable_delay = 600,
                },
@@ -4940,7 +4638,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
                        .hsw.fixed_enable_delay = 600,
                },
@@ -4951,7 +4648,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
                        .hsw.fixed_enable_delay = 600,
                },
@@ -4962,7 +4658,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_AUX_D,
                        .hsw.fixed_enable_delay = 600,
                },
@@ -4973,7 +4668,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = XELPD_PW_CTL_IDX_AUX_E,
                },
        },
@@ -4983,7 +4677,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
                        .hsw.fixed_enable_delay = 600,
                },
@@ -4994,7 +4687,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
                },
        },
@@ -5004,7 +4696,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3,
                },
        },
@@ -5014,7 +4705,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4,
                },
        },
@@ -5024,7 +4714,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1,
                        .hsw.is_tc_tbt = true,
                },
@@ -5035,7 +4724,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2,
                        .hsw.is_tc_tbt = true,
                },
@@ -5046,7 +4734,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3,
                        .hsw.is_tc_tbt = true,
                },
@@ -5057,7 +4744,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
                .ops = &icl_aux_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
-                       .hsw.regs = &icl_aux_power_well_regs,
                        .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4,
                        .hsw.is_tc_tbt = true,
                },
@@ -5281,11 +4967,8 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
        struct i915_power_well *power_well;
 
        mutex_lock(&power_domains->lock);
-       for_each_power_well(dev_priv, power_well) {
-               power_well->desc->ops->sync_hw(dev_priv, power_well);
-               power_well->hw_enabled =
-                       power_well->desc->ops->is_enabled(dev_priv, power_well);
-       }
+       for_each_power_well(dev_priv, power_well)
+               intel_power_well_sync_hw(dev_priv, power_well);
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5303,7 +4986,7 @@ static void gen9_dbuf_slice_set(struct drm_i915_private *dev_priv,
        state = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE;
        drm_WARN(&dev_priv->drm, enable != state,
                 "DBuf slice %d power %s timeout!\n",
-                slice, enabledisable(enable));
+                slice, str_enable_disable(enable));
 }
 
 void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
@@ -5692,7 +5375,7 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
 
        gen9_dbuf_enable(dev_priv);
 
-       if (resume && intel_dmc_has_payload(dev_priv))
+       if (resume)
                intel_dmc_load_program(dev_priv);
 }
 
@@ -5759,7 +5442,7 @@ static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume
 
        gen9_dbuf_enable(dev_priv);
 
-       if (resume && intel_dmc_has_payload(dev_priv))
+       if (resume)
                intel_dmc_load_program(dev_priv);
 }
 
@@ -5923,7 +5606,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
        if (IS_DG2(dev_priv))
                intel_snps_phy_wait_for_calibration(dev_priv);
 
-       if (resume && intel_dmc_has_payload(dev_priv))
+       if (resume)
                intel_dmc_load_program(dev_priv);
 
        /* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p */
@@ -5998,7 +5681,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
         * override and set the lane powerdown bits accding to the
         * current lane status.
         */
-       if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) {
+       if (intel_power_well_is_enabled(dev_priv, cmn_bc)) {
                u32 status = intel_de_read(dev_priv, DPLL(PIPE_A));
                unsigned int mask;
 
@@ -6029,7 +5712,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
                dev_priv->chv_phy_assert[DPIO_PHY0] = true;
        }
 
-       if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) {
+       if (intel_power_well_is_enabled(dev_priv, cmn_d)) {
                u32 status = intel_de_read(dev_priv, DPIO_PHY_STATUS);
                unsigned int mask;
 
@@ -6065,15 +5748,15 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
                lookup_power_well(dev_priv, VLV_DISP_PW_DISP2D);
 
        /* If the display might be already active skip this */
-       if (cmn->desc->ops->is_enabled(dev_priv, cmn) &&
-           disp2d->desc->ops->is_enabled(dev_priv, disp2d) &&
+       if (intel_power_well_is_enabled(dev_priv, cmn) &&
+           intel_power_well_is_enabled(dev_priv, disp2d) &&
            intel_de_read(dev_priv, DPIO_CTL) & DPIO_CMNRST)
                return;
 
        drm_dbg_kms(&dev_priv->drm, "toggling display PHY side reset\n");
 
        /* cmnlane needs DPLL registers */
-       disp2d->desc->ops->enable(dev_priv, disp2d);
+       intel_power_well_enable(dev_priv, disp2d);
 
        /*
         * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
@@ -6082,7 +5765,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
         * Simply ungating isn't enough to reset the PHY enough to get
         * ports and lanes running.
         */
-       cmn->desc->ops->disable(dev_priv, cmn);
+       intel_power_well_disable(dev_priv, cmn);
 }
 
 static bool vlv_punit_is_power_gated(struct drm_i915_private *dev_priv, u32 reg0)
@@ -6233,12 +5916,12 @@ void intel_power_domains_sanitize_state(struct drm_i915_private *i915)
 
        for_each_power_well_reverse(i915, power_well) {
                if (power_well->desc->always_on || power_well->count ||
-                   !power_well->desc->ops->is_enabled(i915, power_well))
+                   !intel_power_well_is_enabled(i915, power_well))
                        continue;
 
                drm_dbg_kms(&i915->drm,
                            "BIOS left unused %s power well enabled, disabling it\n",
-                           power_well->desc->name);
+                           intel_power_well_name(power_well));
                intel_power_well_disable(i915, power_well);
        }
 
@@ -6377,9 +6060,9 @@ static void intel_power_domains_dump_info(struct drm_i915_private *i915)
                enum intel_display_power_domain domain;
 
                drm_dbg(&i915->drm, "%-25s %d\n",
-                       power_well->desc->name, power_well->count);
+                       intel_power_well_name(power_well), intel_power_well_refcount(power_well));
 
-               for_each_power_domain(domain, power_well->desc->domains)
+               for_each_power_domain(domain, intel_power_well_domains(power_well))
                        drm_dbg(&i915->drm, "  %-23s %d\n",
                                intel_display_power_domain_str(domain),
                                power_domains->domain_use_count[domain]);
@@ -6412,23 +6095,25 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915)
                int domains_count;
                bool enabled;
 
-               enabled = power_well->desc->ops->is_enabled(i915, power_well);
-               if ((power_well->count || power_well->desc->always_on) !=
+               enabled = intel_power_well_is_enabled(i915, power_well);
+               if ((intel_power_well_refcount(power_well) ||
+                    intel_power_well_is_always_on(power_well)) !=
                    enabled)
                        drm_err(&i915->drm,
                                "power well %s state mismatch (refcount %d/enabled %d)",
-                               power_well->desc->name,
-                               power_well->count, enabled);
+                               intel_power_well_name(power_well),
+                               intel_power_well_refcount(power_well), enabled);
 
                domains_count = 0;
-               for_each_power_domain(domain, power_well->desc->domains)
+               for_each_power_domain(domain, intel_power_well_domains(power_well))
                        domains_count += power_domains->domain_use_count[domain];
 
-               if (power_well->count != domains_count) {
+               if (intel_power_well_refcount(power_well) != domains_count) {
                        drm_err(&i915->drm,
                                "power well %s refcount/domain refcount mismatch "
                                "(refcount %d/domains refcount %d)\n",
-                               power_well->desc->name, power_well->count,
+                               intel_power_well_name(power_well),
+                               intel_power_well_refcount(power_well),
                                domains_count);
                        dump_domain_info = true;
                }
@@ -6533,10 +6218,10 @@ void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m
                enum intel_display_power_domain power_domain;
 
                power_well = &power_domains->power_wells[i];
-               seq_printf(m, "%-25s %d\n", power_well->desc->name,
-                          power_well->count);
+               seq_printf(m, "%-25s %d\n", intel_power_well_name(power_well),
+                          intel_power_well_refcount(power_well));
 
-               for_each_power_domain(power_domain, power_well->desc->domains)
+               for_each_power_domain(power_domain, intel_power_well_domains(power_well))
                        seq_printf(m, "  %-23s %d\n",
                                   intel_display_power_domain_str(power_domain),
                                   power_domains->domain_use_count[power_domain]);
index f6d0e6e..ced384b 100644 (file)
@@ -14,6 +14,11 @@ struct drm_i915_private;
 struct i915_power_well;
 struct intel_encoder;
 
+/*
+ * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances
+ * consecutive, so that the pipe,transcoder,port -> power domain macros
+ * work correctly.
+ */
 enum intel_display_power_domain {
        POWER_DOMAIN_DISPLAY_CORE,
        POWER_DOMAIN_PIPE_A,
@@ -29,10 +34,12 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_D,
        POWER_DOMAIN_TRANSCODER_EDP,
-       /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
-       POWER_DOMAIN_TRANSCODER_VDSC_PW2,
        POWER_DOMAIN_TRANSCODER_DSI_A,
        POWER_DOMAIN_TRANSCODER_DSI_C,
+
+       /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
+       POWER_DOMAIN_TRANSCODER_VDSC_PW2,
+
        POWER_DOMAIN_PORT_DDI_A_LANES,
        POWER_DOMAIN_PORT_DDI_B_LANES,
        POWER_DOMAIN_PORT_DDI_C_LANES,
@@ -125,30 +132,6 @@ enum intel_display_power_domain {
        POWER_DOMAIN_NUM,
 };
 
-/*
- * i915_power_well_id:
- *
- * IDs used to look up power wells. Power wells accessed directly bypassing
- * the power domains framework must be assigned a unique ID. The rest of power
- * wells must be assigned DISP_PW_ID_NONE.
- */
-enum i915_power_well_id {
-       DISP_PW_ID_NONE,
-
-       VLV_DISP_PW_DISP2D,
-       BXT_DISP_PW_DPIO_CMN_A,
-       VLV_DISP_PW_DPIO_CMN_BC,
-       GLK_DISP_PW_DPIO_CMN_C,
-       CHV_DISP_PW_DPIO_CMN_D,
-       HSW_DISP_PW_GLOBAL,
-       SKL_DISP_PW_MISC_IO,
-       SKL_DISP_PW_1,
-       SKL_DISP_PW_2,
-       ICL_DISP_PW_3,
-       SKL_DISP_DC_OFF,
-       TGL_DISP_PW_TC_COLD_OFF,
-};
-
 #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
 #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
                ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
@@ -232,8 +215,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain);
 
 bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                    enum intel_display_power_domain domain);
-bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
-                                        enum i915_power_well_id power_well_id);
 bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                      enum intel_display_power_domain domain);
 intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
new file mode 100644 (file)
index 0000000..2a0fb9d
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_display_power_well.h"
+
+struct i915_power_well *
+lookup_power_well(struct drm_i915_private *i915,
+                 enum i915_power_well_id power_well_id)
+{
+       struct i915_power_well *power_well;
+
+       for_each_power_well(i915, power_well)
+               if (power_well->desc->id == power_well_id)
+                       return power_well;
+
+       /*
+        * It's not feasible to add error checking code to the callers since
+        * this condition really shouldn't happen and it doesn't even make sense
+        * to abort things like display initialization sequences. Just return
+        * the first power well and hope the WARN gets reported so we can fix
+        * our driver.
+        */
+       drm_WARN(&i915->drm, 1,
+                "Power well %d not defined for this platform\n",
+                power_well_id);
+       return &i915->power_domains.power_wells[0];
+}
+
+void intel_power_well_enable(struct drm_i915_private *i915,
+                            struct i915_power_well *power_well)
+{
+       drm_dbg_kms(&i915->drm, "enabling %s\n", power_well->desc->name);
+       power_well->desc->ops->enable(i915, power_well);
+       power_well->hw_enabled = true;
+}
+
+void intel_power_well_disable(struct drm_i915_private *i915,
+                             struct i915_power_well *power_well)
+{
+       drm_dbg_kms(&i915->drm, "disabling %s\n", power_well->desc->name);
+       power_well->hw_enabled = false;
+       power_well->desc->ops->disable(i915, power_well);
+}
+
+void intel_power_well_sync_hw(struct drm_i915_private *i915,
+                             struct i915_power_well *power_well)
+{
+       power_well->desc->ops->sync_hw(i915, power_well);
+       power_well->hw_enabled =
+               power_well->desc->ops->is_enabled(i915, power_well);
+}
+
+void intel_power_well_get(struct drm_i915_private *i915,
+                         struct i915_power_well *power_well)
+{
+       if (!power_well->count++)
+               intel_power_well_enable(i915, power_well);
+}
+
+void intel_power_well_put(struct drm_i915_private *i915,
+                         struct i915_power_well *power_well)
+{
+       drm_WARN(&i915->drm, !power_well->count,
+                "Use count on power well %s is already zero",
+                power_well->desc->name);
+
+       if (!--power_well->count)
+               intel_power_well_disable(i915, power_well);
+}
+
+bool intel_power_well_is_enabled(struct drm_i915_private *i915,
+                                struct i915_power_well *power_well)
+{
+       return power_well->desc->ops->is_enabled(i915, power_well);
+}
+
+bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well)
+{
+       return power_well->hw_enabled;
+}
+
+bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
+                                        enum i915_power_well_id power_well_id)
+{
+       struct i915_power_well *power_well;
+
+       power_well = lookup_power_well(dev_priv, power_well_id);
+
+       return intel_power_well_is_enabled(dev_priv, power_well);
+}
+
+bool intel_power_well_is_always_on(struct i915_power_well *power_well)
+{
+       return power_well->desc->always_on;
+}
+
+const char *intel_power_well_name(struct i915_power_well *power_well)
+{
+       return power_well->desc->name;
+}
+
+u64 intel_power_well_domains(struct i915_power_well *power_well)
+{
+       return power_well->desc->domains;
+}
+
+int intel_power_well_refcount(struct i915_power_well *power_well)
+{
+       return power_well->count;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h
new file mode 100644 (file)
index 0000000..9a3756f
--- /dev/null
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+#ifndef __INTEL_DISPLAY_POWER_WELL_H__
+#define __INTEL_DISPLAY_POWER_WELL_H__
+
+#include <linux/types.h>
+
+#include "intel_display.h"
+
+struct drm_i915_private;
+struct i915_power_well;
+
+/*
+ * i915_power_well_id:
+ *
+ * IDs used to look up power wells. Power wells accessed directly bypassing
+ * the power domains framework must be assigned a unique ID. The rest of power
+ * wells must be assigned DISP_PW_ID_NONE.
+ */
+enum i915_power_well_id {
+       DISP_PW_ID_NONE,
+
+       VLV_DISP_PW_DISP2D,
+       BXT_DISP_PW_DPIO_CMN_A,
+       VLV_DISP_PW_DPIO_CMN_BC,
+       GLK_DISP_PW_DPIO_CMN_C,
+       CHV_DISP_PW_DPIO_CMN_D,
+       HSW_DISP_PW_GLOBAL,
+       SKL_DISP_PW_MISC_IO,
+       SKL_DISP_PW_1,
+       SKL_DISP_PW_2,
+       ICL_DISP_PW_3,
+       SKL_DISP_DC_OFF,
+       TGL_DISP_PW_TC_COLD_OFF,
+};
+
+struct i915_power_well_regs {
+       i915_reg_t bios;
+       i915_reg_t driver;
+       i915_reg_t kvmr;
+       i915_reg_t debug;
+};
+
+struct i915_power_well_ops {
+       const struct i915_power_well_regs *regs;
+       /*
+        * Synchronize the well's hw state to match the current sw state, for
+        * example enable/disable it based on the current refcount. Called
+        * during driver init and resume time, possibly after first calling
+        * the enable/disable handlers.
+        */
+       void (*sync_hw)(struct drm_i915_private *i915,
+                       struct i915_power_well *power_well);
+       /*
+        * Enable the well and resources that depend on it (for example
+        * interrupts located on the well). Called after the 0->1 refcount
+        * transition.
+        */
+       void (*enable)(struct drm_i915_private *i915,
+                      struct i915_power_well *power_well);
+       /*
+        * Disable the well and resources that depend on it. Called after
+        * the 1->0 refcount transition.
+        */
+       void (*disable)(struct drm_i915_private *i915,
+                       struct i915_power_well *power_well);
+       /* Returns the hw enabled state. */
+       bool (*is_enabled)(struct drm_i915_private *i915,
+                          struct i915_power_well *power_well);
+};
+
+struct i915_power_well_desc {
+       const char *name;
+       bool always_on;
+       u64 domains;
+       /* unique identifier for this power well */
+       enum i915_power_well_id id;
+       /*
+        * Arbitraty data associated with this power well. Platform and power
+        * well specific.
+        */
+       union {
+               struct {
+                       /*
+                        * request/status flag index in the PUNIT power well
+                        * control/status registers.
+                        */
+                       u8 idx;
+               } vlv;
+               struct {
+                       enum dpio_phy phy;
+               } bxt;
+               struct {
+                       /*
+                        * request/status flag index in the power well
+                        * constrol/status registers.
+                        */
+                       u8 idx;
+                       /* Mask of pipes whose IRQ logic is backed by the pw */
+                       u8 irq_pipe_mask;
+                       /*
+                        * Instead of waiting for the status bit to ack enables,
+                        * just wait a specific amount of time and then consider
+                        * the well enabled.
+                        */
+                       u16 fixed_enable_delay;
+                       /* The pw is backing the VGA functionality */
+                       bool has_vga:1;
+                       bool has_fuses:1;
+                       /*
+                        * The pw is for an ICL+ TypeC PHY port in
+                        * Thunderbolt mode.
+                        */
+                       bool is_tc_tbt:1;
+               } hsw;
+       };
+       const struct i915_power_well_ops *ops;
+};
+
+struct i915_power_well {
+       const struct i915_power_well_desc *desc;
+       /* power well enable/disable usage count */
+       int count;
+       /* cached hw enabled state */
+       bool hw_enabled;
+};
+
+struct i915_power_well *lookup_power_well(struct drm_i915_private *i915,
+                                         enum i915_power_well_id id);
+
+void intel_power_well_enable(struct drm_i915_private *i915,
+                            struct i915_power_well *power_well);
+void intel_power_well_disable(struct drm_i915_private *i915,
+                             struct i915_power_well *power_well);
+void intel_power_well_sync_hw(struct drm_i915_private *i915,
+                             struct i915_power_well *power_well);
+void intel_power_well_get(struct drm_i915_private *i915,
+                         struct i915_power_well *power_well);
+void intel_power_well_put(struct drm_i915_private *i915,
+                         struct i915_power_well *power_well);
+bool intel_power_well_is_enabled(struct drm_i915_private *i915,
+                                struct i915_power_well *power_well);
+bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well);
+bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
+                                        enum i915_power_well_id power_well_id);
+bool intel_power_well_is_always_on(struct i915_power_well *power_well);
+const char *intel_power_well_name(struct i915_power_well *power_well);
+u64 intel_power_well_domains(struct i915_power_well *power_well);
+int intel_power_well_refcount(struct i915_power_well *power_well);
+
+#endif
index f05f0f9..2dd5a4b 100644 (file)
@@ -9,6 +9,7 @@
 #if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
 #define __INTEL_DISPLAY_TRACE_H__
 
+#include <linux/string_helpers.h>
 #include <linux/types.h>
 #include <linux/tracepoint.h>
 
@@ -161,7 +162,7 @@ TRACE_EVENT(intel_memory_cxsr,
                           ),
 
            TP_printk("%s->%s, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
-                     onoff(__entry->old), onoff(__entry->new),
+                     str_on_off(__entry->old), str_on_off(__entry->new),
                      __entry->frame[PIPE_A], __entry->scanline[PIPE_A],
                      __entry->frame[PIPE_B], __entry->scanline[PIPE_B],
                      __entry->frame[PIPE_C], __entry->scanline[PIPE_C])
@@ -210,9 +211,9 @@ TRACE_EVENT(g4x_wm,
            TP_printk("pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s",
                      pipe_name(__entry->pipe), __entry->frame, __entry->scanline,
                      __entry->primary, __entry->sprite, __entry->cursor,
-                     yesno(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
-                     yesno(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc,
-                     yesno(__entry->fbc))
+                     str_yes_no(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
+                     str_yes_no(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc,
+                     str_yes_no(__entry->fbc))
 );
 
 TRACE_EVENT(vlv_wm,
index 776b3e6..cfd0421 100644 (file)
@@ -280,8 +280,7 @@ struct intel_panel_bl_funcs {
 };
 
 struct intel_panel {
-       struct drm_display_mode *fixed_mode;
-       struct drm_display_mode *downclock_mode;
+       struct list_head fixed_modes;
 
        /* backlight */
        struct {
@@ -847,8 +846,13 @@ struct intel_crtc_wm_state {
                        /* gen9+ only needs 1-step wm programming */
                        struct skl_pipe_wm optimal;
                        struct skl_ddb_entry ddb;
+                       /*
+                        * pre-icl: for packed/planar CbCr
+                        * icl+: for everything
+                        */
+                       struct skl_ddb_entry plane_ddb[I915_MAX_PLANES];
+                       /* pre-icl: for planar Y */
                        struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES];
-                       struct skl_ddb_entry plane_ddb_uv[I915_MAX_PLANES];
                } skl;
 
                struct {
@@ -954,7 +958,7 @@ struct intel_crtc_state {
        /* Pipe source size (ie. panel fitter input size)
         * All planes will be positioned inside this space,
         * and get clipped at the edges. */
-       int pipe_src_w, pipe_src_h;
+       struct drm_rect pipe_src;
 
        /*
         * Pipe pixel rate, adjusted for
@@ -1125,11 +1129,14 @@ struct intel_crtc_state {
 
        int min_cdclk[I915_MAX_PLANES];
 
+       /* for packed/planar CbCr */
        u32 data_rate[I915_MAX_PLANES];
+       /* for planar Y */
+       u32 data_rate_y[I915_MAX_PLANES];
 
-       /* FIXME unify with data_rate[] */
-       u64 plane_data_rate[I915_MAX_PLANES];
-       u64 uv_plane_data_rate[I915_MAX_PLANES];
+       /* FIXME unify with data_rate[]? */
+       u64 rel_data_rate[I915_MAX_PLANES];
+       u64 rel_data_rate_y[I915_MAX_PLANES];
 
        /* Gamma mode programmed on the pipe */
        u32 gamma_mode;
@@ -1154,6 +1161,9 @@ struct intel_crtc_state {
        /* bitmask of planes that will be updated during the commit */
        u8 update_planes;
 
+       u8 framestart_delay; /* 1-4 */
+       u8 msa_timing_delay; /* 0-3 */
+
        struct {
                u32 enable;
                u32 gcp;
@@ -1179,9 +1189,6 @@ struct intel_crtc_state {
        /* enable pipe csc? */
        bool csc_enable;
 
-       /* enable pipe big joiner? */
-       bool bigjoiner;
-
        /* big joiner pipe bitmask */
        u8 bigjoiner_pipes;
 
@@ -1252,6 +1259,11 @@ enum intel_pipe_crc_source {
        INTEL_PIPE_CRC_SOURCE_MAX,
 };
 
+enum drrs_refresh_rate {
+       DRRS_REFRESH_RATE_HIGH,
+       DRRS_REFRESH_RATE_LOW,
+};
+
 #define INTEL_PIPE_CRC_ENTRIES_NR      128
 struct intel_pipe_crc {
        spinlock_t lock;
@@ -1294,6 +1306,16 @@ struct intel_crtc {
                } active;
        } wm;
 
+       struct {
+               struct mutex mutex;
+               struct delayed_work work;
+               enum drrs_refresh_rate refresh_rate;
+               unsigned int frontbuffer_bits;
+               unsigned int busy_frontbuffer_bits;
+               enum transcoder cpu_transcoder;
+               struct intel_link_m_n m_n, m2_n2;
+       } drrs;
+
        int scanline_offset;
 
        struct {
@@ -1503,6 +1525,7 @@ struct intel_psr {
        bool colorimetry_support;
        bool psr2_enabled;
        bool psr2_sel_fetch_enabled;
+       bool psr2_sel_fetch_cff_enabled;
        bool req_psr2_sdp_prior_scanline;
        u8 sink_sync_latency;
        ktime_t last_entry_attempt;
index 7616a39..257cf66 100644 (file)
@@ -28,6 +28,7 @@
 #include "i915_reg.h"
 #include "intel_de.h"
 #include "intel_dmc.h"
+#include "intel_dmc_regs.h"
 
 /**
  * DOC: DMC Firmware Support
  * low-power state and comes back to normal.
  */
 
+#define DMC_VERSION(major, minor)      ((major) << 16 | (minor))
+#define DMC_VERSION_MAJOR(version)     ((version) >> 16)
+#define DMC_VERSION_MINOR(version)     ((version) & 0xffff)
+
 #define DMC_PATH(platform, major, minor) \
        "i915/"                          \
        __stringify(platform) "_dmc_ver" \
@@ -47,8 +52,8 @@
 
 #define DISPLAY_VER12_DMC_MAX_FW_SIZE  ICL_DMC_MAX_FW_SIZE
 
-#define ADLP_DMC_PATH                  DMC_PATH(adlp, 2, 14)
-#define ADLP_DMC_VERSION_REQUIRED      DMC_VERSION(2, 14)
+#define ADLP_DMC_PATH                  DMC_PATH(adlp, 2, 16)
+#define ADLP_DMC_VERSION_REQUIRED      DMC_VERSION(2, 16)
 MODULE_FIRMWARE(ADLP_DMC_PATH);
 
 #define ADLS_DMC_PATH                  DMC_PATH(adls, 2, 01)
@@ -276,17 +281,8 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
        struct intel_dmc *dmc = &dev_priv->dmc;
        u32 id, i;
 
-       if (!HAS_DMC(dev_priv)) {
-               drm_err(&dev_priv->drm,
-                       "No DMC support available for this platform\n");
+       if (!intel_dmc_has_payload(dev_priv))
                return;
-       }
-
-       if (!dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload) {
-               drm_err(&dev_priv->drm,
-                       "Tried to program CSR with empty payload\n");
-               return;
-       }
 
        assert_rpm_wakelock_held(&dev_priv->runtime_pm);
 
@@ -314,6 +310,17 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
        gen9_set_dc_state_debugmask(dev_priv);
 }
 
+void assert_dmc_loaded(struct drm_i915_private *i915)
+{
+       drm_WARN_ONCE(&i915->drm,
+                     !intel_de_read(i915, DMC_PROGRAM(i915->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
+                     "DMC program storage start is NULL\n");
+       drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE),
+                     "DMC SSP Base Not fine\n");
+       drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_HTP_SKL),
+                     "DMC HTP Not fine\n");
+}
+
 static bool fw_info_matches_stepping(const struct intel_fw_info *fw_info,
                                     const struct stepping_info *si)
 {
@@ -697,7 +704,7 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
                dmc->fw_path = RKL_DMC_PATH;
                dmc->required_version = RKL_DMC_VERSION_REQUIRED;
                dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
-       } else if (DISPLAY_VER(dev_priv) >= 12) {
+       } else if (IS_TIGERLAKE(dev_priv)) {
                dmc->fw_path = TGL_DMC_PATH;
                dmc->required_version = TGL_DMC_VERSION_REQUIRED;
                dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
@@ -808,3 +815,101 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv)
        for (id = 0; id < DMC_FW_MAX; id++)
                kfree(dev_priv->dmc.dmc_info[id].payload);
 }
+
+void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
+                                struct drm_i915_private *i915)
+{
+       struct intel_dmc *dmc = &i915->dmc;
+
+       if (!HAS_DMC(i915))
+               return;
+
+       i915_error_printf(m, "DMC loaded: %s\n",
+                         str_yes_no(intel_dmc_has_payload(i915)));
+       i915_error_printf(m, "DMC fw version: %d.%d\n",
+                         DMC_VERSION_MAJOR(dmc->version),
+                         DMC_VERSION_MINOR(dmc->version));
+}
+
+static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
+{
+       struct drm_i915_private *i915 = m->private;
+       intel_wakeref_t wakeref;
+       struct intel_dmc *dmc;
+       i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG;
+
+       if (!HAS_DMC(i915))
+               return -ENODEV;
+
+       dmc = &i915->dmc;
+
+       wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+       seq_printf(m, "fw loaded: %s\n",
+                  str_yes_no(intel_dmc_has_payload(i915)));
+       seq_printf(m, "path: %s\n", dmc->fw_path);
+       seq_printf(m, "Pipe A fw support: %s\n",
+                  str_yes_no(GRAPHICS_VER(i915) >= 12));
+       seq_printf(m, "Pipe A fw loaded: %s\n",
+                  str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload));
+       seq_printf(m, "Pipe B fw support: %s\n",
+                  str_yes_no(IS_ALDERLAKE_P(i915)));
+       seq_printf(m, "Pipe B fw loaded: %s\n",
+                  str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload));
+
+       if (!intel_dmc_has_payload(i915))
+               goto out;
+
+       seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
+                  DMC_VERSION_MINOR(dmc->version));
+
+       if (DISPLAY_VER(i915) >= 12) {
+               if (IS_DGFX(i915)) {
+                       dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
+               } else {
+                       dc5_reg = TGL_DMC_DEBUG_DC5_COUNT;
+                       dc6_reg = TGL_DMC_DEBUG_DC6_COUNT;
+               }
+
+               /*
+                * NOTE: DMC_DEBUG3 is a general purpose reg.
+                * According to B.Specs:49196 DMC f/w reuses DC5/6 counter
+                * reg for DC3CO debugging and validation,
+                * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
+                */
+               seq_printf(m, "DC3CO count: %d\n",
+                          intel_de_read(i915, IS_DGFX(i915) ?
+                                        DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
+       } else {
+               dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT :
+                       SKL_DMC_DC3_DC5_COUNT;
+               if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915))
+                       dc6_reg = SKL_DMC_DC5_DC6_COUNT;
+       }
+
+       seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg));
+       if (i915_mmio_reg_valid(dc6_reg))
+               seq_printf(m, "DC5 -> DC6 count: %d\n",
+                          intel_de_read(i915, dc6_reg));
+
+out:
+       seq_printf(m, "program base: 0x%08x\n",
+                  intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
+       seq_printf(m, "ssp base: 0x%08x\n",
+                  intel_de_read(i915, DMC_SSP_BASE));
+       seq_printf(m, "htp: 0x%08x\n", intel_de_read(i915, DMC_HTP_SKL));
+
+       intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(intel_dmc_debugfs_status);
+
+void intel_dmc_debugfs_register(struct drm_i915_private *i915)
+{
+       struct drm_minor *minor = i915->drm.primary;
+
+       debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,
+                           i915, &intel_dmc_debugfs_status_fops);
+}
index 7c59030..41091ae 100644 (file)
 #include "intel_wakeref.h"
 #include <linux/workqueue.h>
 
+struct drm_i915_error_state_buf;
 struct drm_i915_private;
 
-#define DMC_VERSION(major, minor)      ((major) << 16 | (minor))
-#define DMC_VERSION_MAJOR(version)     ((version) >> 16)
-#define DMC_VERSION_MINOR(version)     ((version) & 0xffff)
-
 enum {
        DMC_FW_MAIN = 0,
        DMC_FW_PIPEA,
@@ -54,5 +51,10 @@ 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);
 bool intel_dmc_has_payload(struct drm_i915_private *i915);
+void intel_dmc_debugfs_register(struct drm_i915_private *i915);
+void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
+                                struct drm_i915_private *i915);
+
+void assert_dmc_loaded(struct drm_i915_private *i915);
 
 #endif /* __INTEL_DMC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
new file mode 100644 (file)
index 0000000..d65e698
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_DMC_REGS_H__
+#define __INTEL_DMC_REGS_H__
+
+#include "i915_reg_defs.h"
+
+#define DMC_PROGRAM(addr, i)   _MMIO((addr) + (i) * 4)
+#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
+#define DMC_HTP_ADDR_SKL       0x00500034
+#define DMC_SSP_BASE           _MMIO(0x8F074)
+#define DMC_HTP_SKL            _MMIO(0x8F004)
+#define DMC_LAST_WRITE         _MMIO(0x8F034)
+#define DMC_LAST_WRITE_VALUE   0xc003b400
+#define DMC_MMIO_START_RANGE   0x80000
+#define DMC_MMIO_END_RANGE     0x8FFFF
+#define SKL_DMC_DC3_DC5_COUNT  _MMIO(0x80030)
+#define SKL_DMC_DC5_DC6_COUNT  _MMIO(0x8002C)
+#define BXT_DMC_DC3_DC5_COUNT  _MMIO(0x80038)
+#define TGL_DMC_DEBUG_DC5_COUNT        _MMIO(0x101084)
+#define TGL_DMC_DEBUG_DC6_COUNT        _MMIO(0x101088)
+#define DG1_DMC_DEBUG_DC5_COUNT        _MMIO(0x134154)
+
+#define TGL_DMC_DEBUG3         _MMIO(0x101090)
+#define DG1_DMC_DEBUG3         _MMIO(0x13415c)
+
+#endif /* __INTEL_DMC_REGS_H__ */
index d667657..d55acc4 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/notifier.h>
 #include <linux/slab.h>
+#include <linux/string_helpers.h>
 #include <linux/timekeeping.h>
 #include <linux/types.h>
 
@@ -59,7 +60,6 @@
 #include "intel_dp_mst.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
-#include "intel_drrs.h"
 #include "intel_fifo_underrun.h"
 #include "intel_hdcp.h"
 #include "intel_hdmi.h"
@@ -67,6 +67,7 @@
 #include "intel_lspcon.h"
 #include "intel_lvds.h"
 #include "intel_panel.h"
+#include "intel_pch_display.h"
 #include "intel_pps.h"
 #include "intel_psr.h"
 #include "intel_tc.h"
@@ -386,23 +387,13 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp)
        return intel_dp_is_edp(intel_dp) ? 810000 : 1350000;
 }
 
-static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy)
-{
-       u32 voltage;
-
-       voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK;
-
-       return voltage == VOLTAGE_INFO_0_85V;
-}
-
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
 
-       if (intel_phy_is_combo(dev_priv, phy) &&
-           (is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp)))
+       if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
@@ -410,23 +401,7 @@ static int icl_max_source_rate(struct intel_dp *intel_dp)
 
 static int ehl_max_source_rate(struct intel_dp *intel_dp)
 {
-       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-       enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
-
-       if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy))
-               return 540000;
-
-       return 810000;
-}
-
-static int dg1_max_source_rate(struct intel_dp *intel_dp)
-{
-       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-       struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-       enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
-
-       if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy))
+       if (intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
@@ -469,7 +444,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
                        max_rate = dg2_max_source_rate(intel_dp);
                else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) ||
                         IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
-                       max_rate = dg1_max_source_rate(intel_dp);
+                       max_rate = 810000;
                else if (IS_JSL_EHL(dev_priv))
                        max_rate = ehl_max_source_rate(intel_dp);
                else
@@ -580,8 +555,9 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
                                                     int link_rate,
                                                     u8 lane_count)
 {
+       /* FIXME figure out what we actually want here */
        const struct drm_display_mode *fixed_mode =
-               intel_dp->attached_connector->panel.fixed_mode;
+               intel_panel_preferred_fixed_mode(intel_dp->attached_connector);
        int mode_rate, max_rate;
 
        mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
@@ -783,14 +759,12 @@ static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
 }
 
 static enum intel_output_format
-intel_dp_output_format(struct drm_connector *connector,
-                      const struct drm_display_mode *mode)
+intel_dp_output_format(struct intel_connector *connector,
+                      bool ycbcr_420_output)
 {
-       struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
-       const struct drm_display_info *info = &connector->display_info;
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
 
-       if (!connector->ycbcr_420_allowed ||
-           !drm_mode_is_420_only(info, mode))
+       if (!connector->base.ycbcr_420_allowed || !ycbcr_420_output)
                return INTEL_OUTPUT_FORMAT_RGB;
 
        if (intel_dp->dfp.rgb_to_ycbcr &&
@@ -825,11 +799,12 @@ static int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
 }
 
 static int
-intel_dp_mode_min_output_bpp(struct drm_connector *connector,
+intel_dp_mode_min_output_bpp(struct intel_connector *connector,
                             const struct drm_display_mode *mode)
 {
+       const struct drm_display_info *info = &connector->base.display_info;
        enum intel_output_format output_format =
-               intel_dp_output_format(connector, mode);
+               intel_dp_output_format(connector, drm_mode_is_420_only(info, mode));
 
        return intel_dp_output_bpp(output_format, intel_dp_min_bpp(output_format));
 }
@@ -853,6 +828,43 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
        return hdisplay == 4096 && !HAS_DDI(dev_priv);
 }
 
+static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp)
+{
+       struct intel_connector *connector = intel_dp->attached_connector;
+       const struct drm_display_info *info = &connector->base.display_info;
+       int max_tmds_clock = intel_dp->dfp.max_tmds_clock;
+
+       /* Only consider the sink's max TMDS clock if we know this is a HDMI DFP */
+       if (max_tmds_clock && info->max_tmds_clock)
+               max_tmds_clock = min(max_tmds_clock, info->max_tmds_clock);
+
+       return max_tmds_clock;
+}
+
+static enum drm_mode_status
+intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
+                         int clock, int bpc, bool ycbcr420_output,
+                         bool respect_downstream_limits)
+{
+       int tmds_clock, min_tmds_clock, max_tmds_clock;
+
+       if (!respect_downstream_limits)
+               return MODE_OK;
+
+       tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+
+       min_tmds_clock = intel_dp->dfp.min_tmds_clock;
+       max_tmds_clock = intel_dp_max_tmds_clock(intel_dp);
+
+       if (min_tmds_clock && tmds_clock < min_tmds_clock)
+               return MODE_CLOCK_LOW;
+
+       if (max_tmds_clock && tmds_clock > max_tmds_clock)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid_downstream(struct intel_connector *connector,
                               const struct drm_display_mode *mode,
@@ -860,13 +872,14 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
 {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        const struct drm_display_info *info = &connector->base.display_info;
-       int tmds_clock;
+       enum drm_mode_status status;
+       bool ycbcr_420_only;
 
        /* If PCON supports FRL MODE, check FRL bandwidth constraints */
        if (intel_dp->dfp.pcon_max_frl_bw) {
                int target_bw;
                int max_frl_bw;
-               int bpp = intel_dp_mode_min_output_bpp(&connector->base, mode);
+               int bpp = intel_dp_mode_min_output_bpp(connector, mode);
 
                target_bw = bpp * target_clock;
 
@@ -885,16 +898,23 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
            target_clock > intel_dp->dfp.max_dotclock)
                return MODE_CLOCK_HIGH;
 
+       ycbcr_420_only = drm_mode_is_420_only(info, mode);
+
        /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
-       tmds_clock = intel_hdmi_tmds_clock(target_clock, 8,
-                                          drm_mode_is_420_only(info, mode));
+       status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
+                                          8, ycbcr_420_only, true);
 
-       if (intel_dp->dfp.min_tmds_clock &&
-           tmds_clock < intel_dp->dfp.min_tmds_clock)
-               return MODE_CLOCK_LOW;
-       if (intel_dp->dfp.max_tmds_clock &&
-           tmds_clock > intel_dp->dfp.max_tmds_clock)
-               return MODE_CLOCK_HIGH;
+       if (status != MODE_OK) {
+               if (ycbcr_420_only ||
+                   !connector->base.ycbcr_420_allowed ||
+                   !drm_mode_is_420_also(info, mode))
+                       return status;
+
+               status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
+                                                  8, true, true);
+               if (status != MODE_OK)
+                       return status;
+       }
 
        return MODE_OK;
 }
@@ -911,13 +931,13 @@ static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
 }
 
 static enum drm_mode_status
-intel_dp_mode_valid(struct drm_connector *connector,
+intel_dp_mode_valid(struct drm_connector *_connector,
                    struct drm_display_mode *mode)
 {
-       struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
-       struct intel_connector *intel_connector = to_intel_connector(connector);
-       struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
-       struct drm_i915_private *dev_priv = to_i915(connector->dev);
+       struct intel_connector *connector = to_intel_connector(_connector);
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       const struct drm_display_mode *fixed_mode;
        int target_clock = mode->clock;
        int max_rate, mode_rate, max_lanes, max_link_clock;
        int max_dotclk = dev_priv->max_dotclk_freq;
@@ -932,8 +952,9 @@ intel_dp_mode_valid(struct drm_connector *connector,
        if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                return MODE_H_ILLEGAL;
 
+       fixed_mode = intel_panel_fixed_mode(connector, mode);
        if (intel_dp_is_edp(intel_dp) && fixed_mode) {
-               status = intel_panel_mode_valid(intel_connector, mode);
+               status = intel_panel_mode_valid(connector, mode);
                if (status != MODE_OK)
                        return status;
 
@@ -1007,8 +1028,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
        if (mode_rate > max_rate && !dsc)
                return MODE_CLOCK_HIGH;
 
-       status = intel_dp_mode_valid_downstream(intel_connector,
-                                               mode, target_clock);
+       status = intel_dp_mode_valid_downstream(connector, mode, target_clock);
        if (status != MODE_OK)
                return status;
 
@@ -1130,44 +1150,50 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
                drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
 }
 
-static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
-                                  const struct intel_crtc_state *crtc_state)
+static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp,
+                                const struct intel_crtc_state *crtc_state)
 {
        return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
                (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
                 intel_dp->dfp.ycbcr_444_to_420);
 }
 
-static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
-                                          const struct intel_crtc_state *crtc_state, int bpc)
+static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
+                                    const struct intel_crtc_state *crtc_state,
+                                    int bpc, bool respect_downstream_limits)
 {
+       bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state);
        int clock = crtc_state->hw.adjusted_mode.crtc_clock;
-       int tmds_clock = intel_hdmi_tmds_clock(clock, bpc,
-                                              intel_dp_hdmi_ycbcr420(intel_dp, crtc_state));
 
-       if (intel_dp->dfp.min_tmds_clock &&
-           tmds_clock < intel_dp->dfp.min_tmds_clock)
-               return false;
-
-       if (intel_dp->dfp.max_tmds_clock &&
-           tmds_clock > intel_dp->dfp.max_tmds_clock)
-               return false;
+       /*
+        * Current bpc could already be below 8bpc due to
+        * FDI bandwidth constraints or other limits.
+        * HDMI minimum is 8bpc however.
+        */
+       bpc = max(bpc, 8);
 
-       return true;
-}
+       /*
+        * We will never exceed downstream TMDS clock limits while
+        * attempting deep color. If the user insists on forcing an
+        * out of spec mode they will have to be satisfied with 8bpc.
+        */
+       if (!respect_downstream_limits)
+               bpc = 8;
 
-static bool intel_dp_hdmi_bpc_possible(struct intel_dp *intel_dp,
-                                      const struct intel_crtc_state *crtc_state,
-                                      int bpc)
-{
+       for (; bpc >= 8; bpc -= 2) {
+               if (intel_hdmi_bpc_possible(crtc_state, bpc,
+                                           intel_dp->has_hdmi_sink, ycbcr420_output) &&
+                   intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output,
+                                             respect_downstream_limits) == MODE_OK)
+                       return bpc;
+       }
 
-       return intel_hdmi_bpc_possible(crtc_state, bpc, intel_dp->has_hdmi_sink,
-                                      intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
-               intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
+       return -EINVAL;
 }
 
 static int intel_dp_max_bpp(struct intel_dp *intel_dp,
-                           const struct intel_crtc_state *crtc_state)
+                           const struct intel_crtc_state *crtc_state,
+                           bool respect_downstream_limits)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_connector *intel_connector = intel_dp->attached_connector;
@@ -1179,10 +1205,14 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
                bpc = min_t(int, bpc, intel_dp->dfp.max_bpc);
 
        if (intel_dp->dfp.min_tmds_clock) {
-               for (; bpc >= 10; bpc -= 2) {
-                       if (intel_dp_hdmi_bpc_possible(intel_dp, crtc_state, bpc))
-                               break;
-               }
+               int max_hdmi_bpc;
+
+               max_hdmi_bpc = intel_dp_hdmi_compute_bpc(intel_dp, crtc_state, bpc,
+                                                        respect_downstream_limits);
+               if (max_hdmi_bpc < 0)
+                       return 0;
+
+               bpc = min(bpc, max_hdmi_bpc);
        }
 
        bpp = bpc * 3;
@@ -1424,13 +1454,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                                                    pipe_config->lane_count,
                                                    adjusted_mode->crtc_clock,
                                                    adjusted_mode->crtc_hdisplay,
-                                                   pipe_config->bigjoiner,
+                                                   pipe_config->bigjoiner_pipes,
                                                    pipe_bpp);
                dsc_dp_slice_count =
                        intel_dp_dsc_get_slice_count(intel_dp,
                                                     adjusted_mode->crtc_clock,
                                                     adjusted_mode->crtc_hdisplay,
-                                                    pipe_config->bigjoiner);
+                                                    pipe_config->bigjoiner_pipes);
                if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
                        drm_dbg_kms(&dev_priv->drm,
                                    "Compressed BPP/Slice Count not supported\n");
@@ -1464,7 +1494,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
         * then we need to use 2 VDSC instances.
         */
        if (adjusted_mode->crtc_clock > dev_priv->max_cdclk_freq ||
-           pipe_config->bigjoiner) {
+           pipe_config->bigjoiner_pipes) {
                if (pipe_config->dsc.slice_count < 2) {
                        drm_dbg_kms(&dev_priv->drm,
                                    "Cannot split stream to use 2 VDSC instances\n");
@@ -1497,13 +1527,16 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 static int
 intel_dp_compute_link_config(struct intel_encoder *encoder,
                             struct intel_crtc_state *pipe_config,
-                            struct drm_connector_state *conn_state)
+                            struct drm_connector_state *conn_state,
+                            bool respect_downstream_limits)
 {
        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
        const struct drm_display_mode *adjusted_mode =
                &pipe_config->hw.adjusted_mode;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        struct link_config_limits limits;
+       bool joiner_needs_dsc = false;
        int ret;
 
        limits.min_rate = intel_dp_common_rate(intel_dp, 0);
@@ -1513,7 +1546,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
        limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
 
        limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
-       limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config);
+       limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config, respect_downstream_limits);
 
        if (intel_dp->use_max_params) {
                /*
@@ -1537,7 +1570,14 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 
        if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
                                    adjusted_mode->crtc_clock))
-               pipe_config->bigjoiner = true;
+               pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
+
+       /*
+        * Pipe joiner needs compression up to display 12 due to bandwidth
+        * limitation. DG2 onwards pipe joiner can be enabled without
+        * compression.
+        */
+       joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
 
        /*
         * Optimize for slow and wide for everything, because there are some
@@ -1545,13 +1585,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
         */
        ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
 
-       /*
-        * Pipe joiner needs compression upto display12 due to BW limitation. DG2
-        * onwards pipe joiner can be enabled without compression.
-        */
-       drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
-       if (ret || intel_dp->force_dsc_en || (DISPLAY_VER(i915) < 13 &&
-                                             pipe_config->bigjoiner)) {
+       if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) {
+               drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
+                           str_yes_no(ret), str_yes_no(joiner_needs_dsc),
+                           str_yes_no(intel_dp->force_dsc_en));
                ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
                                                  conn_state, &limits);
                if (ret < 0)
@@ -1786,6 +1823,137 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
                intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
 }
 
+static bool cpu_transcoder_has_drrs(struct drm_i915_private *i915,
+                                   enum transcoder cpu_transcoder)
+{
+       /* M1/N1 is double buffered */
+       if (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915))
+               return true;
+
+       return intel_cpu_transcoder_has_m2_n2(i915, cpu_transcoder);
+}
+
+static bool can_enable_drrs(struct intel_connector *connector,
+                           const struct intel_crtc_state *pipe_config,
+                           const struct drm_display_mode *downclock_mode)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+
+       if (pipe_config->vrr.enable)
+               return false;
+
+       /*
+        * DRRS and PSR can't be enable together, so giving preference to PSR
+        * as it allows more power-savings by complete shutting down display,
+        * so to guarantee this, intel_drrs_compute_config() must be called
+        * after intel_psr_compute_config().
+        */
+       if (pipe_config->has_psr)
+               return false;
+
+       /* FIXME missing FDI M2/N2 etc. */
+       if (pipe_config->has_pch_encoder)
+               return false;
+
+       if (!cpu_transcoder_has_drrs(i915, pipe_config->cpu_transcoder))
+               return false;
+
+       return downclock_mode &&
+               intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS;
+}
+
+static void
+intel_dp_drrs_compute_config(struct intel_connector *connector,
+                            struct intel_crtc_state *pipe_config,
+                            int output_bpp, bool constant_n)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       const struct drm_display_mode *downclock_mode =
+               intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
+       int pixel_clock;
+
+       if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
+               if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
+                       intel_zero_m_n(&pipe_config->dp_m2_n2);
+               return;
+       }
+
+       if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915))
+               pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay;
+
+       pipe_config->has_drrs = true;
+
+       pixel_clock = downclock_mode->clock;
+       if (pipe_config->splitter.enable)
+               pixel_clock /= pipe_config->splitter.link_count;
+
+       intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
+                              pipe_config->port_clock, &pipe_config->dp_m2_n2,
+                              constant_n, pipe_config->fec_enable);
+
+       /* FIXME: abstract this better */
+       if (pipe_config->splitter.enable)
+               pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count;
+}
+
+static bool intel_dp_has_audio(struct intel_encoder *encoder,
+                              const struct intel_crtc_state *crtc_state,
+                              const struct drm_connector_state *conn_state)
+{
+       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       const struct intel_digital_connector_state *intel_conn_state =
+               to_intel_digital_connector_state(conn_state);
+
+       if (!intel_dp_port_has_audio(i915, encoder->port))
+               return false;
+
+       if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
+               return intel_dp->has_audio;
+       else
+               return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+}
+
+static int
+intel_dp_compute_output_format(struct intel_encoder *encoder,
+                              struct intel_crtc_state *crtc_state,
+                              struct drm_connector_state *conn_state,
+                              bool respect_downstream_limits)
+{
+       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct intel_connector *connector = intel_dp->attached_connector;
+       const struct drm_display_info *info = &connector->base.display_info;
+       const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+       bool ycbcr_420_only;
+       int ret;
+
+       ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
+
+       crtc_state->output_format = intel_dp_output_format(connector, ycbcr_420_only);
+
+       if (ycbcr_420_only && !intel_dp_is_ycbcr420(intel_dp, crtc_state)) {
+               drm_dbg_kms(&i915->drm,
+                           "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
+               crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
+       }
+
+       ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
+                                          respect_downstream_limits);
+       if (ret) {
+               if (intel_dp_is_ycbcr420(intel_dp, crtc_state) ||
+                   !connector->base.ycbcr_420_allowed ||
+                   !drm_mode_is_420_also(info, adjusted_mode))
+                       return ret;
+
+               crtc_state->output_format = intel_dp_output_format(connector, true);
+               ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
+                                                  respect_downstream_limits);
+       }
+
+       return ret;
+}
+
 int
 intel_dp_compute_config(struct intel_encoder *encoder,
                        struct intel_crtc_state *pipe_config,
@@ -1794,38 +1962,19 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       enum port port = encoder->port;
-       struct intel_connector *intel_connector = intel_dp->attached_connector;
-       struct intel_digital_connector_state *intel_conn_state =
-               to_intel_digital_connector_state(conn_state);
+       const struct drm_display_mode *fixed_mode;
+       struct intel_connector *connector = intel_dp->attached_connector;
        bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N);
        int ret = 0, output_bpp;
 
-       if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
+       if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A)
                pipe_config->has_pch_encoder = true;
 
-       pipe_config->output_format = intel_dp_output_format(&intel_connector->base,
-                                                           adjusted_mode);
-
-       if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
-               ret = intel_panel_fitting(pipe_config, conn_state);
-               if (ret)
-                       return ret;
-       }
-
-       if (!intel_dp_port_has_audio(dev_priv, port))
-               pipe_config->has_audio = false;
-       else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
-               pipe_config->has_audio = intel_dp->has_audio;
-       else
-               pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON;
-
-       if (intel_dp_is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
-               ret = intel_panel_compute_config(intel_connector, adjusted_mode);
-               if (ret)
-                       return ret;
+       pipe_config->has_audio = intel_dp_has_audio(encoder, pipe_config, conn_state);
 
-               ret = intel_panel_fitting(pipe_config, conn_state);
+       fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode);
+       if (intel_dp_is_edp(intel_dp) && fixed_mode) {
+               ret = intel_panel_compute_config(connector, adjusted_mode);
                if (ret)
                        return ret;
        }
@@ -1843,10 +1992,23 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        if (intel_dp_hdisplay_bad(dev_priv, adjusted_mode->crtc_hdisplay))
                return -EINVAL;
 
-       ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state);
-       if (ret < 0)
+       /*
+        * Try to respect downstream TMDS clock limits first, if
+        * that fails assume the user might know something we don't.
+        */
+       ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, true);
+       if (ret)
+               ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, false);
+       if (ret)
                return ret;
 
+       if ((intel_dp_is_edp(intel_dp) && fixed_mode) ||
+           pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
+               ret = intel_panel_fitting(pipe_config, conn_state);
+               if (ret)
+                       return ret;
+       }
+
        pipe_config->limited_color_range =
                intel_dp_limited_color_range(pipe_config, conn_state);
 
@@ -1892,8 +2054,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        intel_vrr_compute_config(pipe_config, conn_state);
        intel_psr_compute_config(intel_dp, pipe_config, conn_state);
-       intel_drrs_compute_config(intel_dp, pipe_config, output_bpp,
-                                 constant_n);
+       intel_dp_drrs_compute_config(connector, pipe_config,
+                                    output_bpp, constant_n);
        intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
        intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
 
@@ -1976,7 +2138,7 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
        if (ret < 0)
                drm_dbg_kms(&i915->drm,
                            "Failed to %s sink decompression state\n",
-                           enabledisable(enable));
+                           str_enable_disable(enable));
 }
 
 static void
@@ -2452,7 +2614,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
        if (drm_dp_dpcd_writeb(&intel_dp->aux,
                               DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
                drm_dbg_kms(&i915->drm, "Failed to %s protocol converter HDMI mode\n",
-                           enabledisable(intel_dp->has_hdmi_sink));
+                           str_enable_disable(intel_dp->has_hdmi_sink));
 
        tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
                intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
@@ -2461,45 +2623,15 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
                               DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
                drm_dbg_kms(&i915->drm,
                            "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n",
-                           enabledisable(intel_dp->dfp.ycbcr_444_to_420));
-
-       tmp = 0;
-       if (intel_dp->dfp.rgb_to_ycbcr) {
-               bool bt2020, bt709;
+                           str_enable_disable(intel_dp->dfp.ycbcr_444_to_420));
 
-               /*
-                * FIXME: Currently if userspace selects BT2020 or BT709, but PCON supports only
-                * RGB->YCbCr for BT601 colorspace, we go ahead with BT601, as default.
-                *
-                */
-               tmp = DP_CONVERSION_BT601_RGB_YCBCR_ENABLE;
-
-               bt2020 = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
-                                                                  intel_dp->downstream_ports,
-                                                                  DP_DS_HDMI_BT2020_RGB_YCBCR_CONV);
-               bt709 = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
-                                                                 intel_dp->downstream_ports,
-                                                                 DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
-               switch (crtc_state->infoframes.vsc.colorimetry) {
-               case DP_COLORIMETRY_BT2020_RGB:
-               case DP_COLORIMETRY_BT2020_YCC:
-                       if (bt2020)
-                               tmp = DP_CONVERSION_BT2020_RGB_YCBCR_ENABLE;
-                       break;
-               case DP_COLORIMETRY_BT709_YCC:
-               case DP_COLORIMETRY_XVYCC_709:
-                       if (bt709)
-                               tmp = DP_CONVERSION_BT709_RGB_YCBCR_ENABLE;
-                       break;
-               default:
-                       break;
-               }
-       }
+       tmp = intel_dp->dfp.rgb_to_ycbcr ?
+               DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0;
 
        if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0)
                drm_dbg_kms(&i915->drm,
                           "Failed to %s protocol converter RGB->YCbCr conversion mode\n",
-                          enabledisable(tmp));
+                          str_enable_disable(tmp));
 }
 
 
@@ -2572,9 +2704,9 @@ static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
        drm_mode_set_name(mode);
 
        drm_dbg_kms(&i915->drm,
-                   "[CONNECTOR:%d:%s] using generated MSO mode: ",
-                   connector->base.base.id, connector->base.name);
-       drm_mode_debug_printmodeline(mode);
+                   "[CONNECTOR:%d:%s] using generated MSO mode: " DRM_MODE_FMT "\n",
+                   connector->base.base.id, connector->base.name,
+                   DRM_MODE_ARG(mode));
 }
 
 static void intel_edp_mso_init(struct intel_dp *intel_dp)
@@ -2787,8 +2919,9 @@ intel_dp_configure_mst(struct intel_dp *intel_dp)
        drm_dbg_kms(&i915->drm,
                    "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n",
                    encoder->base.base.id, encoder->base.name,
-                   yesno(intel_dp_mst_source_support(intel_dp)), yesno(sink_can_mst),
-                   yesno(i915->params.enable_dp_mst));
+                   str_yes_no(intel_dp_mst_source_support(intel_dp)),
+                   str_yes_no(sink_can_mst),
+                   str_yes_no(i915->params.enable_dp_mst));
 
        if (!intel_dp_mst_source_support(intel_dp))
                return;
@@ -4347,9 +4480,7 @@ intel_dp_update_420(struct intel_dp *intel_dp)
                                                        intel_dp->downstream_ports);
        rgb_to_ycbcr = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
                                                                 intel_dp->downstream_ports,
-                                                                DP_DS_HDMI_BT601_RGB_YCBCR_CONV |
-                                                                DP_DS_HDMI_BT709_RGB_YCBCR_CONV |
-                                                                DP_DS_HDMI_BT2020_RGB_YCBCR_CONV);
+                                                                DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
 
        if (DISPLAY_VER(i915) >= 11) {
                /* Let PCON convert from RGB->YCbCr if possible */
@@ -4375,21 +4506,28 @@ intel_dp_update_420(struct intel_dp *intel_dp)
        drm_dbg_kms(&i915->drm,
                    "[CONNECTOR:%d:%s] RGB->YcbCr conversion? %s, YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n",
                    connector->base.base.id, connector->base.name,
-                   yesno(intel_dp->dfp.rgb_to_ycbcr),
-                   yesno(connector->base.ycbcr_420_allowed),
-                   yesno(intel_dp->dfp.ycbcr_444_to_420));
+                   str_yes_no(intel_dp->dfp.rgb_to_ycbcr),
+                   str_yes_no(connector->base.ycbcr_420_allowed),
+                   str_yes_no(intel_dp->dfp.ycbcr_444_to_420));
 }
 
 static void
 intel_dp_set_edid(struct intel_dp *intel_dp)
 {
+       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
        struct intel_connector *connector = intel_dp->attached_connector;
        struct edid *edid;
+       bool vrr_capable;
 
        intel_dp_unset_edid(intel_dp);
        edid = intel_dp_get_edid(intel_dp);
        connector->detect_edid = edid;
 
+       vrr_capable = intel_vrr_is_capable(&connector->base);
+       drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] VRR capable: %s\n",
+                   connector->base.base.id, connector->base.name, str_yes_no(vrr_capable));
+       drm_connector_set_vrr_capable_property(&connector->base, vrr_capable);
+
        intel_dp_update_dfp(intel_dp, edid);
        intel_dp_update_420(intel_dp);
 
@@ -4422,6 +4560,9 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 
        intel_dp->dfp.ycbcr_444_to_420 = false;
        connector->base.ycbcr_420_allowed = false;
+
+       drm_connector_set_vrr_capable_property(&connector->base,
+                                              false);
 }
 
 static int
@@ -4572,26 +4713,12 @@ static int intel_dp_get_modes(struct drm_connector *connector)
        int num_modes = 0;
 
        edid = intel_connector->detect_edid;
-       if (edid) {
+       if (edid)
                num_modes = intel_connector_update_modes(connector, edid);
 
-               if (intel_vrr_is_capable(connector))
-                       drm_connector_set_vrr_capable_property(connector,
-                                                              true);
-       }
-
        /* Also add fixed mode, which may or may not be present in EDID */
-       if (intel_dp_is_edp(intel_attached_dp(intel_connector)) &&
-           intel_connector->panel.fixed_mode) {
-               struct drm_display_mode *mode;
-
-               mode = drm_mode_duplicate(connector->dev,
-                                         intel_connector->panel.fixed_mode);
-               if (mode) {
-                       drm_mode_probed_add(connector, mode);
-                       num_modes++;
-               }
-       }
+       if (intel_dp_is_edp(intel_attached_dp(intel_connector)))
+               num_modes += intel_panel_get_modes(intel_connector);
 
        if (num_modes)
                return num_modes;
@@ -4643,9 +4770,7 @@ intel_dp_connector_register(struct drm_connector *connector)
        if (lspcon_init(dig_port)) {
                lspcon_detect_hdr_capability(lspcon);
                if (lspcon->hdr_supported)
-                       drm_object_attach_property(&connector->base,
-                                                  connector->dev->mode_config.hdr_output_metadata_property,
-                                                  0);
+                       drm_connector_attach_hdr_output_metadata_property(connector);
        }
 
        return ret;
@@ -4914,6 +5039,25 @@ bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
        return intel_bios_is_port_edp(dev_priv, port);
 }
 
+static bool
+has_gamut_metadata_dip(struct drm_i915_private *i915, enum port port)
+{
+       if (intel_bios_is_lspcon_present(i915, port))
+               return false;
+
+       if (DISPLAY_VER(i915) >= 11)
+               return true;
+
+       if (port == PORT_A)
+               return false;
+
+       if (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
+           DISPLAY_VER(i915) >= 9)
+               return true;
+
+       return false;
+}
+
 static void
 intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
 {
@@ -4940,10 +5084,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
                intel_attach_dp_colorspace_property(connector);
        }
 
-       if (IS_GEMINILAKE(dev_priv) || DISPLAY_VER(dev_priv) >= 11)
-               drm_object_attach_property(&connector->base,
-                                          connector->dev->mode_config.hdr_output_metadata_property,
-                                          0);
+       if (has_gamut_metadata_dip(dev_priv, port))
+               drm_connector_attach_hdr_output_metadata_property(connector);
 
        if (intel_dp_is_edp(intel_dp)) {
                u32 allowed_scalers;
@@ -4962,14 +5104,30 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
                drm_connector_attach_vrr_capable_property(connector);
 }
 
+static void
+intel_edp_add_properties(struct intel_dp *intel_dp)
+{
+       struct intel_connector *connector = intel_dp->attached_connector;
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_preferred_fixed_mode(connector);
+
+       if (!fixed_mode)
+               return;
+
+       drm_connector_set_panel_orientation_with_quirk(&connector->base,
+                                                      i915->vbt.orientation,
+                                                      fixed_mode->hdisplay,
+                                                      fixed_mode->vdisplay);
+}
+
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                                     struct intel_connector *intel_connector)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct drm_device *dev = &dev_priv->drm;
        struct drm_connector *connector = &intel_connector->base;
-       struct drm_display_mode *fixed_mode = NULL;
-       struct drm_display_mode *downclock_mode = NULL;
+       struct drm_display_mode *fixed_mode;
        bool has_dpcd;
        enum pipe pipe = INVALID_PIPE;
        struct edid *edid;
@@ -5026,20 +5184,20 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        }
        intel_connector->edid = edid;
 
-       fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
-       if (fixed_mode)
-               downclock_mode = intel_drrs_init(intel_connector, fixed_mode);
+       intel_panel_add_edid_fixed_modes(intel_connector,
+                                        dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
 
        /* MSO requires information from the EDID */
        intel_edp_mso_init(intel_dp);
 
        /* multiply the mode clock and horizontal timings for MSO */
-       intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
-       intel_edp_mso_mode_fixup(intel_connector, downclock_mode);
+       list_for_each_entry(fixed_mode, &intel_connector->panel.fixed_modes, head)
+               intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
 
        /* fallback to VBT if available for eDP */
-       if (!fixed_mode)
-               fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
+       if (!intel_panel_preferred_fixed_mode(intel_connector))
+               intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
+
        mutex_unlock(&dev->mode_config.mutex);
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
@@ -5061,16 +5219,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                            pipe_name(pipe));
        }
 
-       intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+       intel_panel_init(intel_connector);
+
        if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
                intel_connector->panel.backlight.power = intel_pps_backlight_power;
        intel_backlight_setup(intel_connector, pipe);
 
-       if (fixed_mode) {
-               drm_connector_set_panel_orientation_with_quirk(connector,
-                               dev_priv->vbt.orientation,
-                               fixed_mode->hdisplay, fixed_mode->vdisplay);
-       }
+       intel_edp_add_properties(intel_dp);
 
        return true;
 
index 5d98773..26f9e2b 100644 (file)
@@ -55,6 +55,7 @@ static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp,
 }
 
 static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
+                                        const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                                         enum drm_dp_phy dp_phy)
 {
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
@@ -63,7 +64,7 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
 
        intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name));
 
-       if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) {
+       if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) {
                drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
                            "[ENCODER:%d:%s][%s] failed to read the PHY caps\n",
                            encoder->base.base.id, encoder->base.name, phy_name);
@@ -77,10 +78,12 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
                    phy_caps);
 }
 
-static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
+static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp,
+                                           const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       int ret;
 
        if (intel_dp_is_edp(intel_dp))
                return false;
@@ -92,8 +95,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
        if (DISPLAY_VER(i915) < 10 || IS_GEMINILAKE(i915))
                return false;
 
-       if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
-                                         intel_dp->lttpr_common_caps) < 0)
+       ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd,
+                                           intel_dp->lttpr_common_caps);
+       if (ret < 0)
                goto reset_caps;
 
        drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
@@ -122,14 +126,14 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
        return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
 }
 
-static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
+static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
        int lttpr_count;
        int i;
 
-       if (!intel_dp_read_lttpr_common_caps(intel_dp))
+       if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd))
                return 0;
 
        lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
@@ -168,7 +172,7 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
        }
 
        for (i = 0; i < lttpr_count; i++)
-               intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i));
+               intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
 
        return lttpr_count;
 }
@@ -193,9 +197,18 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
  */
 int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
 {
-       int lttpr_count = intel_dp_init_lttpr(intel_dp);
+       u8 dpcd[DP_RECEIVER_CAP_SIZE];
+       int lttpr_count;
+
+       if (drm_dp_read_dpcd_caps(&intel_dp->aux, dpcd))
+               return -EIO;
 
-       /* The DPTX shall read the DPRX caps after LTTPR detection. */
+       lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
+
+       /*
+        * The DPTX shall read the DPRX caps after LTTPR detection, so re-read
+        * it here.
+        */
        if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
                intel_dp_reset_lttpr_common_caps(intel_dp);
                return -EIO;
index e30e698..061b277 100644 (file)
@@ -398,9 +398,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
        if (ret) {
                drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret);
        }
-       if (old_crtc_state->has_audio)
-               intel_audio_codec_disable(encoder,
-                                         old_crtc_state, old_conn_state);
+
+       intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
 
 static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
@@ -599,8 +598,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
 
        intel_crtc_vblank_on(pipe_config);
 
-       if (pipe_config->has_audio)
-               intel_audio_codec_enable(encoder, pipe_config, conn_state);
+       intel_audio_codec_enable(encoder, pipe_config, conn_state);
 
        /* Enable hdcp if it's desired */
        if (conn_state->content_protection ==
index 14f5ffe..95b9d32 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/string_helpers.h>
 
 #include "intel_crtc.h"
 #include "intel_de.h"
@@ -253,12 +254,12 @@ static const struct intel_limit ilk_limits_dual_lvds_100m = {
 
 static const struct intel_limit intel_limits_vlv = {
         /*
-         * These are the data rate limits (measured in fast clocks)
+         * These are based on the data rate limits (measured in fast clocks)
          * since those are the strictest limits we have. The fast
          * clock and actual rate limits are more relaxed, so checking
          * them would make no difference.
          */
-       .dot = { .min = 25000 * 5, .max = 270000 * 5 },
+       .dot = { .min = 25000, .max = 270000 },
        .vco = { .min = 4000000, .max = 6000000 },
        .n = { .min = 1, .max = 7 },
        .m1 = { .min = 2, .max = 3 },
@@ -269,12 +270,12 @@ static const struct intel_limit intel_limits_vlv = {
 
 static const struct intel_limit intel_limits_chv = {
        /*
-        * These are the data rate limits (measured in fast clocks)
+        * These are based on the data rate limits (measured in fast clocks)
         * since those are the strictest limits we have.  The fast
         * clock and actual rate limits are more relaxed, so checking
         * them would make no difference.
         */
-       .dot = { .min = 25000 * 5, .max = 540000 * 5},
+       .dot = { .min = 25000, .max = 540000 },
        .vco = { .min = 4800000, .max = 6480000 },
        .n = { .min = 1, .max = 1 },
        .m1 = { .min = 2, .max = 2 },
@@ -284,8 +285,7 @@ static const struct intel_limit intel_limits_chv = {
 };
 
 static const struct intel_limit intel_limits_bxt = {
-       /* FIXME: find real dot limits */
-       .dot = { .min = 0, .max = INT_MAX },
+       .dot = { .min = 25000, .max = 594000 },
        .vco = { .min = 4800000, .max = 6700000 },
        .n = { .min = 1, .max = 1 },
        .m1 = { .min = 2, .max = 2 },
@@ -336,26 +336,26 @@ int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
 int vlv_calc_dpll_params(int refclk, struct dpll *clock)
 {
        clock->m = clock->m1 * clock->m2;
-       clock->p = clock->p1 * clock->p2;
+       clock->p = clock->p1 * clock->p2 * 5;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
                return 0;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 
-       return clock->dot / 5;
+       return clock->dot;
 }
 
 int chv_calc_dpll_params(int refclk, struct dpll *clock)
 {
        clock->m = clock->m1 * clock->m2;
-       clock->p = clock->p1 * clock->p2;
+       clock->p = clock->p1 * clock->p2 * 5;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
                return 0;
        clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
                                           clock->n << 22);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 
-       return clock->dot / 5;
+       return clock->dot;
 }
 
 /*
@@ -424,8 +424,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,
 
 /*
  * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ * refclk, or FALSE.
  *
  * Target and reference clocks are specified in kHz.
  *
@@ -483,8 +482,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit,
 
 /*
  * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ * refclk, or FALSE.
  *
  * Target and reference clocks are specified in kHz.
  *
@@ -540,8 +538,7 @@ pnv_find_best_dpll(const struct intel_limit *limit,
 
 /*
  * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ * refclk, or FALSE.
  *
  * Target and reference clocks are specified in kHz.
  *
@@ -640,8 +637,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
 
 /*
  * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ * refclk, or FALSE.
  */
 static bool
 vlv_find_best_dpll(const struct intel_limit *limit,
@@ -658,8 +654,6 @@ vlv_find_best_dpll(const struct intel_limit *limit,
        int max_n = min(limit->n.max, refclk / 19200);
        bool found = false;
 
-       target *= 5; /* fast clock */
-
        memset(best_clock, 0, sizeof(*best_clock));
 
        /* based on hardware requirement, prefer smaller n to precision */
@@ -667,7 +661,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,
                for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
                        for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow;
                             clock.p2 -= clock.p2 > 10 ? 2 : 1) {
-                               clock.p = clock.p1 * clock.p2;
+                               clock.p = clock.p1 * clock.p2 * 5;
                                /* based on hardware requirement, prefer bigger m1,m2 values */
                                for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
                                        unsigned int ppm;
@@ -701,8 +695,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,
 
 /*
  * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE.  The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ * refclk, or FALSE.
  */
 static bool
 chv_find_best_dpll(const struct intel_limit *limit,
@@ -728,7 +721,6 @@ chv_find_best_dpll(const struct intel_limit *limit,
         */
        clock.n = 1;
        clock.m1 = 2;
-       target *= 5;    /* fast clock */
 
        for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
                for (clock.p2 = limit->p2.p2_fast;
@@ -736,7 +728,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
                                clock.p2 -= clock.p2 > 10 ? 2 : 1) {
                        unsigned int error_ppm;
 
-                       clock.p = clock.p1 * clock.p2;
+                       clock.p = clock.p1 * clock.p2 * 5;
 
                        m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22,
                                                   refclk * clock.m1);
@@ -1945,7 +1937,7 @@ static void assert_pll(struct drm_i915_private *dev_priv,
        cur_state = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
        I915_STATE_WARN(cur_state != state,
                        "PLL state assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
index 569903d..b7071da 100644 (file)
@@ -21,6 +21,8 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/string_helpers.h>
+
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dpio_phy.h"
@@ -178,13 +180,14 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
        struct intel_dpll_hw_state hw_state;
 
        if (drm_WARN(&dev_priv->drm, !pll,
-                    "asserting DPLL %s with no DPLL\n", onoff(state)))
+                    "asserting DPLL %s with no DPLL\n", str_on_off(state)))
                return;
 
        cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state);
        I915_STATE_WARN(cur_state != state,
             "%s assertion failure (expected %s, current %s)\n",
-                       pll->info->name, onoff(state), onoff(cur_state));
+                       pll->info->name, str_on_off(state),
+                       str_on_off(cur_state));
 }
 
 static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
@@ -832,7 +835,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */,
 {
        u64 freq2k;
        unsigned p, n2, r2;
-       struct hsw_wrpll_rnp best = { 0, 0, 0 };
+       struct hsw_wrpll_rnp best = {};
        unsigned budget;
 
        freq2k = clock / 100;
@@ -1330,13 +1333,6 @@ struct skl_wrpll_context {
        unsigned int p;                 /* chosen divider */
 };
 
-static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
-{
-       memset(ctx, 0, sizeof(*ctx));
-
-       ctx->min_deviation = U64_MAX;
-}
-
 /* DCO freq must be within +1%/-6%  of the DCO central freq */
 #define SKL_DCO_MAX_PDEVIATION 100
 #define SKL_DCO_MAX_NDEVIATION 600
@@ -1502,28 +1498,28 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */,
                        int ref_clock,
                        struct skl_wrpll_params *wrpll_params)
 {
-       u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
-       u64 dco_central_freq[3] = { 8400000000ULL,
-                                   9000000000ULL,
-                                   9600000000ULL };
-       static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
-                                            24, 28, 30, 32, 36, 40, 42, 44,
-                                            48, 52, 54, 56, 60, 64, 66, 68,
-                                            70, 72, 76, 78, 80, 84, 88, 90,
-                                            92, 96, 98 };
-       static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
+       static const u64 dco_central_freq[3] = { 8400000000ULL,
+                                                9000000000ULL,
+                                                9600000000ULL };
+       static const u8 even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
+                                           24, 28, 30, 32, 36, 40, 42, 44,
+                                           48, 52, 54, 56, 60, 64, 66, 68,
+                                           70, 72, 76, 78, 80, 84, 88, 90,
+                                           92, 96, 98 };
+       static const u8 odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
        static const struct {
-               const int *list;
+               const u8 *list;
                int n_dividers;
        } dividers[] = {
                { even_dividers, ARRAY_SIZE(even_dividers) },
                { odd_dividers, ARRAY_SIZE(odd_dividers) },
        };
-       struct skl_wrpll_context ctx;
+       struct skl_wrpll_context ctx = {
+               .min_deviation = U64_MAX,
+       };
        unsigned int dco, d, i;
        unsigned int p0, p1, p2;
-
-       skl_wrpll_context_init(&ctx);
+       u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
 
        for (d = 0; d < ARRAY_SIZE(dividers); d++) {
                for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
@@ -1574,8 +1570,8 @@ skip_remaining_dividers:
 static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+       struct skl_wrpll_params wrpll_params = {};
        u32 ctrl1, cfgcr1, cfgcr2;
-       struct skl_wrpll_params wrpll_params = { 0, };
 
        /*
         * See comment in intel_dpll_hw_state to understand why we always use 0
@@ -1902,7 +1898,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
 
        /* Write M2 integer */
        temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0));
-       temp &= ~PORT_PLL_M2_MASK;
+       temp &= ~PORT_PLL_M2_INT_MASK;
        temp |= pll->state.hw_state.pll0;
        intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 0), temp);
 
@@ -2038,7 +2034,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
 
        hw_state->pll0 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0));
-       hw_state->pll0 &= PORT_PLL_M2_MASK;
+       hw_state->pll0 &= PORT_PLL_M2_INT_MASK;
 
        hw_state->pll1 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 1));
        hw_state->pll1 &= PORT_PLL_N_MASK;
@@ -2087,82 +2083,64 @@ out:
        return ret;
 }
 
-/* bxt clock parameters */
-struct bxt_clk_div {
-       int clock;
-       u32 p1;
-       u32 p2;
-       u32 m2_int;
-       u32 m2_frac;
-       bool m2_frac_en;
-       u32 n;
-
-       int vco;
-};
-
 /* pre-calculated values for DP linkrates */
-static const struct bxt_clk_div bxt_dp_clk_val[] = {
-       {162000, 4, 2, 32, 1677722, 1, 1},
-       {270000, 4, 1, 27,       0, 0, 1},
-       {540000, 2, 1, 27,       0, 0, 1},
-       {216000, 3, 2, 32, 1677722, 1, 1},
-       {243000, 4, 1, 24, 1258291, 1, 1},
-       {324000, 4, 1, 32, 1677722, 1, 1},
-       {432000, 3, 1, 32, 1677722, 1, 1}
+static const struct dpll bxt_dp_clk_val[] = {
+       /* m2 is .22 binary fixed point */
+       { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
+       { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
+       { .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
+       { .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
+       { .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6133333 /* 24.3 */ },
+       { .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
+       { .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ },
 };
 
 static bool
 bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state,
-                         struct bxt_clk_div *clk_div)
+                         struct dpll *clk_div)
 {
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-       struct dpll best_clock;
 
        /* Calculate HDMI div */
        /*
         * FIXME: tie the following calculation into
         * i9xx_crtc_compute_clock
         */
-       if (!bxt_find_best_dpll(crtc_state, &best_clock)) {
+       if (!bxt_find_best_dpll(crtc_state, clk_div)) {
                drm_dbg(&i915->drm, "no PLL dividers found for clock %d pipe %c\n",
                        crtc_state->port_clock,
                        pipe_name(crtc->pipe));
                return false;
        }
 
-       clk_div->p1 = best_clock.p1;
-       clk_div->p2 = best_clock.p2;
-       drm_WARN_ON(&i915->drm, best_clock.m1 != 2);
-       clk_div->n = best_clock.n;
-       clk_div->m2_int = best_clock.m2 >> 22;
-       clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
-       clk_div->m2_frac_en = clk_div->m2_frac != 0;
-
-       clk_div->vco = best_clock.vco;
+       drm_WARN_ON(&i915->drm, clk_div->m1 != 2);
 
        return true;
 }
 
 static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state,
-                                   struct bxt_clk_div *clk_div)
+                                   struct dpll *clk_div)
 {
-       int clock = crtc_state->port_clock;
+       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
        int i;
 
        *clk_div = bxt_dp_clk_val[0];
        for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
-               if (bxt_dp_clk_val[i].clock == clock) {
+               if (crtc_state->port_clock == bxt_dp_clk_val[i].dot) {
                        *clk_div = bxt_dp_clk_val[i];
                        break;
                }
        }
 
-       clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
+       chv_calc_dpll_params(i915->dpll.ref_clks.nssc, clk_div);
+
+       drm_WARN_ON(&i915->drm, clk_div->vco == 0 ||
+                   clk_div->dot != crtc_state->port_clock);
 }
 
 static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
-                                     const struct bxt_clk_div *clk_div)
+                                     const struct dpll *clk_div)
 {
        struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
        struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state;
@@ -2206,23 +2184,23 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
                lanestagger = 0x02;
 
        dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
-       dpll_hw_state->pll0 = clk_div->m2_int;
+       dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22);
        dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
-       dpll_hw_state->pll2 = clk_div->m2_frac;
+       dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff);
 
-       if (clk_div->m2_frac_en)
+       if (clk_div->m2 & 0x3fffff)
                dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
 
-       dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
-       dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
+       dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) |
+               PORT_PLL_INT_COEFF(int_coef) |
+               PORT_PLL_GAIN_CTL(gain_ctl);
 
-       dpll_hw_state->pll8 = targ_cnt;
+       dpll_hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt);
 
-       dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
+       dpll_hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5);
 
-       dpll_hw_state->pll10 =
-               PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
-               | PORT_PLL_DCO_AMP_OVR_EN_H;
+       dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(15) |
+               PORT_PLL_DCO_AMP_OVR_EN_H;
 
        dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
 
@@ -2234,7 +2212,7 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
 static bool
 bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
 {
-       struct bxt_clk_div clk_div = {};
+       struct dpll clk_div = {};
 
        bxt_ddi_dp_pll_dividers(crtc_state, &clk_div);
 
@@ -2244,7 +2222,7 @@ bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
 static bool
 bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
 {
-       struct bxt_clk_div clk_div = {};
+       struct dpll clk_div = {};
 
        bxt_ddi_hdmi_pll_dividers(crtc_state, &clk_div);
 
@@ -2258,12 +2236,12 @@ static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915,
        struct dpll clock;
 
        clock.m1 = 2;
-       clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22;
+       clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, pll_state->pll0) << 22;
        if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
-               clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK;
-       clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
-       clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
-       clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
+               clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, pll_state->pll2);
+       clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, pll_state->pll1);
+       clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0);
+       clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0);
 
        return chv_calc_dpll_params(i915->dpll.ref_clks.nssc, &clock);
 }
@@ -2758,8 +2736,8 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
                                     struct intel_dpll_hw_state *state,
                                     bool is_dkl)
 {
+       static const u8 div1_vals[] = { 7, 5, 3, 2 };
        u32 dco_min_freq, dco_max_freq;
-       int div1_vals[] = {7, 5, 3, 2};
        unsigned int i;
        int div2;
 
index 05dd7db..15b2716 100644 (file)
@@ -249,7 +249,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
        size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
 
        if (HAS_LMEM(i915))
-               dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
+               dpt_obj = i915_gem_object_create_lmem(i915, size, I915_BO_ALLOC_CONTIGUOUS);
        else
                dpt_obj = i915_gem_object_create_stolen(i915, size);
        if (IS_ERR(dpt_obj))
index fa715b8..166caf2 100644 (file)
  * requested by userspace.
  */
 
-static bool can_enable_drrs(struct intel_connector *connector,
-                           const struct intel_crtc_state *pipe_config)
+const char *intel_drrs_type_str(enum drrs_type drrs_type)
 {
-       const struct drm_i915_private *i915 = to_i915(connector->base.dev);
-
-       if (pipe_config->vrr.enable)
-               return false;
-
-       /*
-        * DRRS and PSR can't be enable together, so giving preference to PSR
-        * as it allows more power-savings by complete shutting down display,
-        * so to guarantee this, intel_drrs_compute_config() must be called
-        * after intel_psr_compute_config().
-        */
-       if (pipe_config->has_psr)
-               return false;
-
-       return connector->panel.downclock_mode &&
-               i915->drrs.type == SEAMLESS_DRRS_SUPPORT;
-}
-
-void
-intel_drrs_compute_config(struct intel_dp *intel_dp,
-                         struct intel_crtc_state *pipe_config,
-                         int output_bpp, bool constant_n)
-{
-       struct intel_connector *connector = intel_dp->attached_connector;
-       struct drm_i915_private *i915 = to_i915(connector->base.dev);
-       int pixel_clock;
-
-       if (!can_enable_drrs(connector, pipe_config)) {
-               if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
-                       intel_zero_m_n(&pipe_config->dp_m2_n2);
-               return;
-       }
-
-       pipe_config->has_drrs = true;
-
-       pixel_clock = connector->panel.downclock_mode->clock;
-       if (pipe_config->splitter.enable)
-               pixel_clock /= pipe_config->splitter.link_count;
+       static const char * const str[] = {
+               [DRRS_TYPE_NONE] = "none",
+               [DRRS_TYPE_STATIC] = "static",
+               [DRRS_TYPE_SEAMLESS] = "seamless",
+       };
 
-       intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
-                              pipe_config->port_clock, &pipe_config->dp_m2_n2,
-                              constant_n, pipe_config->fec_enable);
+       if (drrs_type >= ARRAY_SIZE(str))
+               return "<invalid>";
 
-       /* FIXME: abstract this better */
-       if (pipe_config->splitter.enable)
-               pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count;
+       return str[drrs_type];
 }
 
 static void
-intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
-                                    enum drrs_refresh_rate_type refresh_type)
+intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc,
+                                    enum drrs_refresh_rate refresh_rate)
 {
-       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;
+       enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder;
        u32 val, bit;
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               bit = PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+               bit = PIPECONF_REFRESH_RATE_ALT_VLV;
        else
-               bit = PIPECONF_EDP_RR_MODE_SWITCH;
+               bit = PIPECONF_REFRESH_RATE_ALT_ILK;
 
        val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder));
 
-       if (refresh_type == DRRS_LOW_RR)
+       if (refresh_rate == DRRS_REFRESH_RATE_LOW)
                val |= bit;
        else
                val &= ~bit;
@@ -123,244 +85,171 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
 }
 
 static void
-intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state,
-                               enum drrs_refresh_rate_type refresh_type)
+intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc,
+                               enum drrs_refresh_rate refresh_rate)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-       intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder,
-                                      refresh_type == DRRS_LOW_RR ?
-                                      &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n);
+       intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder,
+                                      refresh_rate == DRRS_REFRESH_RATE_LOW ?
+                                      &crtc->drrs.m2_n2 : &crtc->drrs.m_n);
 }
 
-static void intel_drrs_set_state(struct drm_i915_private *dev_priv,
-                                const struct intel_crtc_state *crtc_state,
-                                enum drrs_refresh_rate_type refresh_type)
+bool intel_drrs_is_active(struct intel_crtc *crtc)
 {
-       struct intel_dp *intel_dp = dev_priv->drrs.dp;
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-       struct drm_display_mode *mode;
-
-       if (!intel_dp) {
-               drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
-               return;
-       }
-
-       if (!crtc) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "DRRS: intel_crtc not initialized\n");
-               return;
-       }
-
-       if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
-               drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
-               return;
-       }
+       return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER;
+}
 
-       if (refresh_type == dev_priv->drrs.refresh_rate_type)
-               return;
+static void intel_drrs_set_state(struct intel_crtc *crtc,
+                                enum drrs_refresh_rate refresh_rate)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       if (!crtc_state->hw.active) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "eDP encoder disabled. CRTC not Active\n");
+       if (refresh_rate == crtc->drrs.refresh_rate)
                return;
-       }
 
-       if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv))
-               intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_type);
-       else if (DISPLAY_VER(dev_priv) > 6)
-               intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_type);
+       if (intel_cpu_transcoder_has_m2_n2(dev_priv, crtc->drrs.cpu_transcoder))
+               intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate);
+       else
+               intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate);
 
-       dev_priv->drrs.refresh_rate_type = refresh_type;
+       crtc->drrs.refresh_rate = refresh_rate;
+}
 
-       if (refresh_type == DRRS_LOW_RR)
-               mode = intel_dp->attached_connector->panel.downclock_mode;
-       else
-               mode = intel_dp->attached_connector->panel.fixed_mode;
-       drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
-                   drm_mode_vrefresh(mode));
+static void intel_drrs_schedule_work(struct intel_crtc *crtc)
+{
+       mod_delayed_work(system_wq, &crtc->drrs.work, msecs_to_jiffies(1000));
 }
 
-static void
-intel_drrs_enable_locked(struct intel_dp *intel_dp)
+static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+       unsigned int frontbuffer_bits;
+
+       frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
 
-       dev_priv->drrs.busy_frontbuffer_bits = 0;
-       dev_priv->drrs.dp = intel_dp;
+       for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc,
+                                        crtc_state->bigjoiner_pipes)
+               frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
+
+       return frontbuffer_bits;
 }
 
 /**
- * intel_drrs_enable - init drrs struct if supported
- * @intel_dp: DP struct
- * @crtc_state: A pointer to the active crtc state.
+ * intel_drrs_activate - activate DRRS
+ * @crtc_state: the crtc state
  *
- * Initializes frontbuffer_bits and drrs.dp
+ * Activates DRRS on the crtc.
  */
-void intel_drrs_enable(struct intel_dp *intel_dp,
-                      const struct intel_crtc_state *crtc_state)
+void intel_drrs_activate(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 
        if (!crtc_state->has_drrs)
                return;
 
-       drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
+       if (!crtc_state->hw.active)
+               return;
 
-       mutex_lock(&dev_priv->drrs.mutex);
+       if (intel_crtc_is_bigjoiner_slave(crtc_state))
+               return;
 
-       if (dev_priv->drrs.dp) {
-               drm_warn(&dev_priv->drm, "DRRS already enabled\n");
-               goto unlock;
-       }
+       mutex_lock(&crtc->drrs.mutex);
 
-       intel_drrs_enable_locked(intel_dp);
+       crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder;
+       crtc->drrs.m_n = crtc_state->dp_m_n;
+       crtc->drrs.m2_n2 = crtc_state->dp_m2_n2;
+       crtc->drrs.frontbuffer_bits = intel_drrs_frontbuffer_bits(crtc_state);
+       crtc->drrs.busy_frontbuffer_bits = 0;
 
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
-}
+       intel_drrs_schedule_work(crtc);
 
-static void
-intel_drrs_disable_locked(struct intel_dp *intel_dp,
-                         const struct intel_crtc_state *crtc_state)
-{
-       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-       intel_drrs_set_state(dev_priv, crtc_state, DRRS_HIGH_RR);
-       dev_priv->drrs.dp = NULL;
+       mutex_unlock(&crtc->drrs.mutex);
 }
 
 /**
- * intel_drrs_disable - Disable DRRS
- * @intel_dp: DP struct
- * @old_crtc_state: Pointer to old crtc_state.
+ * intel_drrs_deactivate - deactivate DRRS
+ * @old_crtc_state: the old crtc state
  *
+ * Deactivates DRRS on the crtc.
  */
-void intel_drrs_disable(struct intel_dp *intel_dp,
-                       const struct intel_crtc_state *old_crtc_state)
+void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state)
 {
-       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
 
        if (!old_crtc_state->has_drrs)
                return;
 
-       mutex_lock(&dev_priv->drrs.mutex);
-       if (!dev_priv->drrs.dp) {
-               mutex_unlock(&dev_priv->drrs.mutex);
+       if (!old_crtc_state->hw.active)
                return;
-       }
-
-       intel_drrs_disable_locked(intel_dp, old_crtc_state);
-       mutex_unlock(&dev_priv->drrs.mutex);
-
-       cancel_delayed_work_sync(&dev_priv->drrs.work);
-}
-
-/**
- * intel_drrs_update - Update DRRS state
- * @intel_dp: Intel DP
- * @crtc_state: new CRTC state
- *
- * This function will update DRRS states, disabling or enabling DRRS when
- * executing fastsets. For full modeset, intel_drrs_disable() and
- * intel_drrs_enable() should be called instead.
- */
-void
-intel_drrs_update(struct intel_dp *intel_dp,
-                 const struct intel_crtc_state *crtc_state)
-{
-       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
-       if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
+       if (intel_crtc_is_bigjoiner_slave(old_crtc_state))
                return;
 
-       mutex_lock(&dev_priv->drrs.mutex);
+       mutex_lock(&crtc->drrs.mutex);
 
-       /* New state matches current one? */
-       if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
-               goto unlock;
+       if (intel_drrs_is_active(crtc))
+               intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
 
-       if (crtc_state->has_drrs)
-               intel_drrs_enable_locked(intel_dp);
-       else
-               intel_drrs_disable_locked(intel_dp, crtc_state);
+       crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
+       crtc->drrs.frontbuffer_bits = 0;
+       crtc->drrs.busy_frontbuffer_bits = 0;
+
+       mutex_unlock(&crtc->drrs.mutex);
 
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
+       cancel_delayed_work_sync(&crtc->drrs.work);
 }
 
 static void intel_drrs_downclock_work(struct work_struct *work)
 {
-       struct drm_i915_private *dev_priv =
-               container_of(work, typeof(*dev_priv), drrs.work.work);
-       struct intel_dp *intel_dp;
-       struct drm_crtc *crtc;
-
-       mutex_lock(&dev_priv->drrs.mutex);
-
-       intel_dp = dev_priv->drrs.dp;
+       struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work);
 
-       if (!intel_dp)
-               goto unlock;
+       mutex_lock(&crtc->drrs.mutex);
 
-       /*
-        * The delayed work can race with an invalidate hence we need to
-        * recheck.
-        */
+       if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits)
+               intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW);
 
-       if (dev_priv->drrs.busy_frontbuffer_bits)
-               goto unlock;
-
-       crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
-       intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, DRRS_LOW_RR);
-
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
+       mutex_unlock(&crtc->drrs.mutex);
 }
 
 static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv,
-                                         unsigned int frontbuffer_bits,
+                                         unsigned int all_frontbuffer_bits,
                                          bool invalidate)
 {
-       struct intel_dp *intel_dp;
-       struct drm_crtc *crtc;
-       enum pipe pipe;
+       struct intel_crtc *crtc;
 
-       if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
+       if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
                return;
 
-       cancel_delayed_work(&dev_priv->drrs.work);
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               unsigned int frontbuffer_bits;
 
-       mutex_lock(&dev_priv->drrs.mutex);
+               mutex_lock(&crtc->drrs.mutex);
 
-       intel_dp = dev_priv->drrs.dp;
-       if (!intel_dp) {
-               mutex_unlock(&dev_priv->drrs.mutex);
-               return;
-       }
+               frontbuffer_bits = all_frontbuffer_bits & crtc->drrs.frontbuffer_bits;
+               if (!frontbuffer_bits) {
+                       mutex_unlock(&crtc->drrs.mutex);
+                       continue;
+               }
 
-       crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
-       pipe = to_intel_crtc(crtc)->pipe;
+               if (invalidate)
+                       crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
+               else
+                       crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
 
-       frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
-       if (invalidate)
-               dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
-       else
-               dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
-
-       /* flush/invalidate means busy screen hence upclock */
-       if (frontbuffer_bits)
-               intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config,
-                                    DRRS_HIGH_RR);
-
-       /*
-        * flush also means no more activity hence schedule downclock, if all
-        * other fbs are quiescent too
-        */
-       if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits)
-               schedule_delayed_work(&dev_priv->drrs.work,
-                                     msecs_to_jiffies(1000));
-       mutex_unlock(&dev_priv->drrs.mutex);
+               /* flush/invalidate means busy screen hence upclock */
+               intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
+
+               /*
+                * flush also means no more activity hence schedule downclock, if all
+                * other fbs are quiescent too
+                */
+               if (!crtc->drrs.busy_frontbuffer_bits)
+                       intel_drrs_schedule_work(crtc);
+               else
+                       cancel_delayed_work(&crtc->drrs.work);
+
+               mutex_unlock(&crtc->drrs.mutex);
+       }
 }
 
 /**
@@ -397,68 +286,17 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv,
        intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
 }
 
-void intel_drrs_page_flip(struct intel_atomic_state *state,
-                         struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
-
-       intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
-}
-
 /**
- * intel_drrs_init - Init basic DRRS work and mutex.
- * @connector: eDP connector
- * @fixed_mode: preferred mode of panel
+ * intel_crtc_drrs_init - Init DRRS for CRTC
+ * @crtc: crtc
  *
- * This function is  called only once at driver load to initialize basic
+ * This function is called only once at driver load to initialize basic
  * DRRS stuff.
  *
- * Returns:
- * Downclock mode if panel supports it, else return NULL.
- * DRRS support is determined by the presence of downclock mode (apart
- * from VBT setting).
  */
-struct drm_display_mode *
-intel_drrs_init(struct intel_connector *connector,
-               struct drm_display_mode *fixed_mode)
+void intel_crtc_drrs_init(struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       struct intel_encoder *encoder = connector->encoder;
-       struct drm_display_mode *downclock_mode = NULL;
-
-       INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work);
-       mutex_init(&dev_priv->drrs.mutex);
-
-       if (DISPLAY_VER(dev_priv) <= 6) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "DRRS supported for Gen7 and above\n");
-               return NULL;
-       }
-
-       if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) &&
-           encoder->port != PORT_A) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "DRRS only supported on eDP port A\n");
-               return NULL;
-       }
-
-       if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
-               drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
-               return NULL;
-       }
-
-       downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
-       if (!downclock_mode) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "Downclock mode is not found. DRRS not supported\n");
-               return NULL;
-       }
-
-       dev_priv->drrs.type = dev_priv->vbt.drrs_type;
-
-       dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
-       drm_dbg_kms(&dev_priv->drm,
-                   "seamless DRRS supported for eDP panel.\n");
-       return downclock_mode;
+       INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work);
+       mutex_init(&crtc->drrs.mutex);
+       crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
 }
index 9ec9c44..3ad1be1 100644 (file)
@@ -8,29 +8,21 @@
 
 #include <linux/types.h>
 
+enum drrs_type;
 struct drm_i915_private;
 struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_connector;
-struct intel_dp;
 
-void intel_drrs_enable(struct intel_dp *intel_dp,
-                      const struct intel_crtc_state *crtc_state);
-void intel_drrs_disable(struct intel_dp *intel_dp,
-                       const struct intel_crtc_state *crtc_state);
-void intel_drrs_update(struct intel_dp *intel_dp,
-                      const struct intel_crtc_state *crtc_state);
+const char *intel_drrs_type_str(enum drrs_type drrs_type);
+bool intel_drrs_is_active(struct intel_crtc *crtc);
+void intel_drrs_activate(const struct intel_crtc_state *crtc_state);
+void intel_drrs_deactivate(const struct intel_crtc_state *crtc_state);
 void intel_drrs_invalidate(struct drm_i915_private *dev_priv,
                           unsigned int frontbuffer_bits);
 void intel_drrs_flush(struct drm_i915_private *dev_priv,
                      unsigned int frontbuffer_bits);
-void intel_drrs_page_flip(struct intel_atomic_state *state,
-                         struct intel_crtc *crtc);
-void intel_drrs_compute_config(struct intel_dp *intel_dp,
-                              struct intel_crtc_state *pipe_config,
-                              int output_bpp, bool constant_n);
-struct drm_display_mode *intel_drrs_init(struct intel_connector *connector,
-                                        struct drm_display_mode *fixed_mode);
+void intel_crtc_drrs_init(struct intel_crtc *crtc);
 
 #endif /* __INTEL_DRRS_H__ */
index b34a673..c4affcb 100644 (file)
@@ -283,14 +283,12 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
 
        obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
        if (IS_ERR(obj)) {
-               drm_err(&i915->drm, "Gem object creation failed\n");
                kfree(dsb);
                goto out;
        }
 
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
        if (IS_ERR(vma)) {
-               drm_err(&i915->drm, "Vma creation failed\n");
                i915_gem_object_put(obj);
                kfree(dsb);
                goto out;
@@ -298,7 +296,6 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
 
        buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
        if (IS_ERR(buf)) {
-               drm_err(&i915->drm, "Command buffer creation failed\n");
                i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
                kfree(dsb);
                goto out;
@@ -311,6 +308,10 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
        dsb->ins_start_offset = 0;
        crtc_state->dsb = dsb;
 out:
+       if (!crtc_state->dsb)
+               drm_info(&i915->drm,
+                        "DSB queue setup failed, will fallback to MMIO for display HW programming\n");
+
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
 
index a50422e..389a8c2 100644 (file)
@@ -34,26 +34,7 @@ int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi)
 
 int intel_dsi_get_modes(struct drm_connector *connector)
 {
-       struct drm_i915_private *i915 = to_i915(connector->dev);
-       struct intel_connector *intel_connector = to_intel_connector(connector);
-       struct drm_display_mode *mode;
-
-       drm_dbg_kms(&i915->drm, "\n");
-
-       if (!intel_connector->panel.fixed_mode) {
-               drm_dbg_kms(&i915->drm, "no fixed mode\n");
-               return 0;
-       }
-
-       mode = drm_mode_duplicate(connector->dev,
-                                 intel_connector->panel.fixed_mode);
-       if (!mode) {
-               drm_dbg_kms(&i915->drm, "drm_mode_duplicate failed\n");
-               return 0;
-       }
-
-       drm_mode_probed_add(connector, mode);
-       return 1;
+       return intel_panel_get_modes(to_intel_connector(connector));
 }
 
 enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
@@ -61,7 +42,8 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
 {
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
        struct intel_connector *intel_connector = to_intel_connector(connector);
-       const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_fixed_mode(intel_connector, mode);
        int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
        enum drm_mode_status status;
 
index 6b4a273..f370e9c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/slab.h>
+#include <linux/string_helpers.h>
 
 #include <asm/unaligned.h>
 
@@ -686,9 +687,9 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
                    intel_dsi->burst_mode_ratio);
        drm_dbg_kms(&i915->drm, "Reset timer %d\n", intel_dsi->rst_timer_val);
        drm_dbg_kms(&i915->drm, "Eot %s\n",
-                   enableddisabled(intel_dsi->eotp_pkt));
+                   str_enabled_disabled(intel_dsi->eotp_pkt));
        drm_dbg_kms(&i915->drm, "Clockstop %s\n",
-                   enableddisabled(!intel_dsi->clock_stop));
+                   str_enabled_disabled(!intel_dsi->clock_stop));
        drm_dbg_kms(&i915->drm, "Mode %s\n",
                    intel_dsi->operation_mode ? "command" : "video");
        if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
@@ -715,7 +716,7 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
        drm_dbg_kms(&i915->drm, "HS to LP Clock Count 0x%x\n",
                    intel_dsi->clk_hs_to_lp_count);
        drm_dbg_kms(&i915->drm, "BTA %s\n",
-                   enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
+                   str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
 }
 
 bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
index 2eeb209..5572e43 100644 (file)
@@ -226,7 +226,7 @@ intel_dvo_mode_valid(struct drm_connector *connector,
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector);
        const struct drm_display_mode *fixed_mode =
-               intel_connector->panel.fixed_mode;
+               intel_panel_fixed_mode(intel_connector, mode);
        int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
        int target_clock = mode->clock;
 
@@ -257,9 +257,9 @@ static int intel_dvo_compute_config(struct intel_encoder *encoder,
 {
        struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
        struct intel_connector *connector = to_intel_connector(conn_state->connector);
-       const struct drm_display_mode *fixed_mode =
-               intel_dvo->attached_connector->panel.fixed_mode;
        struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_fixed_mode(intel_dvo->attached_connector, adjusted_mode);
 
        /*
         * If we have timings from the BIOS for the panel, put them in
@@ -333,8 +333,6 @@ intel_dvo_detect(struct drm_connector *connector, bool force)
 static int intel_dvo_get_modes(struct drm_connector *connector)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
-       const struct drm_display_mode *fixed_mode =
-               to_intel_connector(connector)->panel.fixed_mode;
        int num_modes;
 
        /*
@@ -348,17 +346,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
        if (num_modes)
                return num_modes;
 
-       if (fixed_mode) {
-               struct drm_display_mode *mode;
-
-               mode = drm_mode_duplicate(connector->dev, fixed_mode);
-               if (mode) {
-                       drm_mode_probed_add(connector, mode);
-                       num_modes++;
-               }
-       }
-
-       return num_modes;
+       return intel_panel_get_modes(to_intel_connector(connector));
 }
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
@@ -390,27 +378,6 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
        .destroy = intel_dvo_enc_destroy,
 };
 
-/*
- * Attempts to get a fixed panel timing for LVDS (currently only the i830).
- *
- * Other chips with DVO LVDS will need to extend this to deal with the LVDS
- * chip being on DVOB/C and having multiple pipes.
- */
-static struct drm_display_mode *
-intel_dvo_get_current_mode(struct intel_encoder *encoder)
-{
-       struct drm_display_mode *mode;
-
-       mode = intel_encoder_current_mode(encoder);
-       if (mode) {
-               DRM_DEBUG_KMS("using current (BIOS) mode: ");
-               drm_mode_debug_printmodeline(mode);
-               mode->type |= DRM_MODE_TYPE_PREFERRED;
-       }
-
-       return mode;
-}
-
 static enum port intel_dvo_port(i915_reg_t dvo_reg)
 {
        if (i915_mmio_reg_equal(dvo_reg, DVOA))
@@ -561,9 +528,11 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
                         * headers, likely), so for now, just get the current
                         * mode being output through DVO.
                         */
-                       intel_panel_init(&intel_connector->panel,
-                                        intel_dvo_get_current_mode(intel_encoder),
-                                        NULL);
+                       intel_panel_add_encoder_fixed_mode(intel_connector,
+                                                          intel_encoder);
+
+                       intel_panel_init(intel_connector);
+
                        intel_dvo->panel_wants_dither = true;
                }
 
index 23cfe2e..e94923e 100644 (file)
@@ -107,6 +107,21 @@ static const struct drm_format_info gen12_ccs_cc_formats[] = {
          .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
+static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
+       { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
+         .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+         .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
+         .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+         .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
+         .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+         .hsub = 1, .vsub = 1, .has_alpha = true },
+       { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
+         .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+         .hsub = 1, .vsub = 1, .has_alpha = true },
+};
+
 struct intel_modifier_desc {
        u64 modifier;
        struct {
@@ -135,11 +150,32 @@ struct intel_modifier_desc {
                                         INTEL_PLANE_CAP_CCS_MC)
 #define INTEL_PLANE_CAP_TILING_MASK    (INTEL_PLANE_CAP_TILING_X | \
                                         INTEL_PLANE_CAP_TILING_Y | \
-                                        INTEL_PLANE_CAP_TILING_Yf)
+                                        INTEL_PLANE_CAP_TILING_Yf | \
+                                        INTEL_PLANE_CAP_TILING_4)
 #define INTEL_PLANE_CAP_TILING_NONE    0
 
 static const struct intel_modifier_desc intel_modifiers[] = {
        {
+               .modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS,
+               .display_ver = { 13, 13 },
+               .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC,
+       }, {
+               .modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC,
+               .display_ver = { 13, 13 },
+               .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC_CC,
+
+               .ccs.cc_planes = BIT(1),
+
+               FORMAT_OVERRIDE(gen12_flat_ccs_cc_formats),
+       }, {
+               .modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS,
+               .display_ver = { 13, 13 },
+               .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC,
+       }, {
+               .modifier = I915_FORMAT_MOD_4_TILED,
+               .display_ver = { 13, 13 },
+               .plane_caps = INTEL_PLANE_CAP_TILING_4,
+       }, {
                .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
                .display_ver = { 12, 13 },
                .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC,
@@ -380,17 +416,13 @@ bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier)
 static bool format_is_yuv_semiplanar(const struct intel_modifier_desc *md,
                                     const struct drm_format_info *info)
 {
-       int yuv_planes;
-
        if (!info->is_yuv)
                return false;
 
-       if (plane_caps_contain_any(md->plane_caps, INTEL_PLANE_CAP_CCS_MASK))
-               yuv_planes = 4;
+       if (hweight8(md->ccs.planar_aux_planes) == 2)
+               return info->num_planes == 4;
        else
-               yuv_planes = 2;
-
-       return info->num_planes == yuv_planes;
+               return info->num_planes == 2;
 }
 
 /**
@@ -515,12 +547,13 @@ static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_p
 
 int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
 {
+       const struct intel_modifier_desc *md = lookup_modifier(fb->modifier);
        struct drm_i915_private *i915 = to_i915(fb->dev);
 
-       if (intel_fb_is_ccs_modifier(fb->modifier))
+       if (md->ccs.packed_aux_planes | md->ccs.planar_aux_planes)
                return main_to_ccs_plane(fb, main_plane);
        else if (DISPLAY_VER(i915) < 11 &&
-                intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
+                format_is_yuv_semiplanar(md, fb->format))
                return 1;
        else
                return 0;
@@ -545,6 +578,15 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
                        return 128;
                else
                        return 512;
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
+       case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
+       case I915_FORMAT_MOD_4_TILED:
+               /*
+                * Each 4K tile consists of 64B(8*8) subtiles, with
+                * same shape as Y Tile(i.e 4*16B OWords)
+                */
+               return 128;
        case I915_FORMAT_MOD_Y_TILED_CCS:
                if (intel_fb_is_ccs_aux_plane(fb, color_plane))
                        return 128;
@@ -650,6 +692,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
                return I915_TILING_Y;
        case INTEL_PLANE_CAP_TILING_X:
                return I915_TILING_X;
+       case INTEL_PLANE_CAP_TILING_4:
        case INTEL_PLANE_CAP_TILING_Yf:
        case INTEL_PLANE_CAP_TILING_NONE:
                return I915_TILING_NONE;
@@ -737,8 +780,13 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
        case I915_FORMAT_MOD_Y_TILED_CCS:
        case I915_FORMAT_MOD_Yf_TILED_CCS:
        case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_4_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
                return 1 * 1024 * 1024;
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
+       case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
+               return 16 * 1024;
        default:
                MISSING_CASE(fb->modifier);
                return 0;
index ba9df89..12386f1 100644 (file)
@@ -27,6 +27,7 @@ struct intel_plane_state;
 #define INTEL_PLANE_CAP_TILING_X       BIT(3)
 #define INTEL_PLANE_CAP_TILING_Y       BIT(4)
 #define INTEL_PLANE_CAP_TILING_Yf      BIT(5)
+#define INTEL_PLANE_CAP_TILING_4       BIT(6)
 
 bool intel_fb_is_ccs_modifier(u64 modifier);
 bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier);
index 87f4af3..6708353 100644 (file)
  * forcibly disable it to allow proper screen updates.
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_fourcc.h>
 
 #include "i915_drv.h"
+#include "i915_utils.h"
 #include "i915_vgpu.h"
 #include "intel_cdclk.h"
 #include "intel_de.h"
@@ -87,7 +90,6 @@ struct intel_fbc {
         * with stolen_lock.
         */
        struct mutex lock;
-       unsigned int possible_framebuffer_bits;
        unsigned int busy_bits;
 
        struct drm_mm_node compressed_fb;
@@ -665,6 +667,10 @@ static bool intel_fbc_is_compressing(struct intel_fbc *fbc)
 
 static void intel_fbc_nuke(struct intel_fbc *fbc)
 {
+       struct drm_i915_private *i915 = fbc->i915;
+
+       drm_WARN_ON(&i915->drm, fbc->flip_pending);
+
        trace_intel_fbc_nuke(fbc->state.plane);
 
        fbc->funcs->nuke(fbc);
@@ -946,6 +952,7 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state)
        case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
                return DISPLAY_VER(i915) >= 9;
+       case I915_FORMAT_MOD_4_TILED:
        case I915_FORMAT_MOD_X_TILED:
                return true;
        default:
@@ -966,6 +973,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
        struct intel_fbc_state *fbc_state = &fbc->state;
 
        WARN_ON(plane_state->no_fbc_reason);
+       WARN_ON(fbc_state->plane && fbc_state->plane != plane);
 
        fbc_state->plane = plane;
 
@@ -1270,6 +1278,8 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
        __intel_fbc_cleanup_cfb(fbc);
 
        fbc->state.plane = NULL;
+       fbc->flip_pending = false;
+       fbc->busy_bits = 0;
 }
 
 static void __intel_fbc_post_update(struct intel_fbc *fbc)
@@ -1313,7 +1323,7 @@ static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)
        if (fbc->state.plane)
                return fbc->state.plane->frontbuffer_bit;
        else
-               return fbc->possible_framebuffer_bits;
+               return 0;
 }
 
 static void __intel_fbc_invalidate(struct intel_fbc *fbc,
@@ -1325,11 +1335,14 @@ static void __intel_fbc_invalidate(struct intel_fbc *fbc,
 
        mutex_lock(&fbc->lock);
 
-       fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits;
+       frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc);
+       if (!frontbuffer_bits)
+               goto out;
 
-       if (fbc->state.plane && fbc->busy_bits)
-               intel_fbc_deactivate(fbc, "frontbuffer write");
+       fbc->busy_bits |= frontbuffer_bits;
+       intel_fbc_deactivate(fbc, "frontbuffer write");
 
+out:
        mutex_unlock(&fbc->lock);
 }
 
@@ -1351,18 +1364,22 @@ static void __intel_fbc_flush(struct intel_fbc *fbc,
 {
        mutex_lock(&fbc->lock);
 
+       frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc);
+       if (!frontbuffer_bits)
+               goto out;
+
        fbc->busy_bits &= ~frontbuffer_bits;
 
        if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE)
                goto out;
 
-       if (!fbc->busy_bits && fbc->state.plane &&
-           (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
-               if (fbc->active)
-                       intel_fbc_nuke(fbc);
-               else if (!fbc->flip_pending)
-                       __intel_fbc_post_update(fbc);
-       }
+       if (fbc->busy_bits || fbc->flip_pending)
+               goto out;
+
+       if (fbc->active)
+               intel_fbc_nuke(fbc);
+       else
+               intel_fbc_activate(fbc);
 
 out:
        mutex_unlock(&fbc->lock);
@@ -1500,25 +1517,6 @@ void intel_fbc_update(struct intel_atomic_state *state,
        }
 }
 
-/**
- * intel_fbc_global_disable - globally disable FBC
- * @i915: i915 device instance
- *
- * This function disables FBC regardless of which CRTC is associated with it.
- */
-void intel_fbc_global_disable(struct drm_i915_private *i915)
-{
-       struct intel_fbc *fbc;
-       enum intel_fbc_id fbc_id;
-
-       for_each_intel_fbc(i915, fbc, fbc_id) {
-               mutex_lock(&fbc->lock);
-               if (fbc->state.plane)
-                       __intel_fbc_disable(fbc);
-               mutex_unlock(&fbc->lock);
-       }
-}
-
 static void intel_fbc_underrun_work_fn(struct work_struct *work)
 {
        struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work);
@@ -1640,7 +1638,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *i915)
 static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
 {
        /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
-       if (intel_vtd_active(i915) &&
+       if (i915_vtd_active(i915) &&
            (IS_SKYLAKE(i915) || IS_BROXTON(i915))) {
                drm_info(&i915->drm,
                         "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
@@ -1652,11 +1650,7 @@ static bool need_fbc_vtd_wa(struct drm_i915_private *i915)
 
 void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
 {
-       if (!fbc)
-               return;
-
        plane->fbc = fbc;
-       fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
 }
 
 static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915,
@@ -1709,22 +1703,26 @@ void intel_fbc_init(struct drm_i915_private *i915)
        drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",
                    i915->params.enable_fbc);
 
-       for_each_fbc_id(i915, fbc_id) {
-               struct intel_fbc *fbc;
+       for_each_fbc_id(i915, fbc_id)
+               i915->fbc[fbc_id] = intel_fbc_create(i915, fbc_id);
+}
 
-               fbc = intel_fbc_create(i915, fbc_id);
-               if (!fbc)
-                       continue;
+/**
+ * intel_fbc_sanitize - Sanitize FBC
+ * @i915: the i915 device
+ *
+ * Make sure FBC is initially disabled since we have no
+ * idea eg. into which parts of stolen it might be scribbling
+ * into.
+ */
+void intel_fbc_sanitize(struct drm_i915_private *i915)
+{
+       struct intel_fbc *fbc;
+       enum intel_fbc_id fbc_id;
 
-               /*
-                * We still don't have any sort of hardware state readout
-                * for FBC, so deactivate it in case the BIOS activated it
-                * to make sure software matches the hardware state.
-                */
+       for_each_intel_fbc(i915, fbc, fbc_id) {
                if (intel_fbc_hw_is_active(fbc))
                        intel_fbc_hw_deactivate(fbc);
-
-               i915->fbc[fbc->id] = fbc;
        }
 }
 
@@ -1743,7 +1741,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
        if (fbc->active) {
                seq_puts(m, "FBC enabled\n");
                seq_printf(m, "Compressing: %s\n",
-                          yesno(intel_fbc_is_compressing(fbc)));
+                          str_yes_no(intel_fbc_is_compressing(fbc)));
        } else {
                seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason);
        }
index 8c5a733..db60143 100644 (file)
@@ -30,10 +30,10 @@ void intel_fbc_post_update(struct intel_atomic_state *state,
                           struct intel_crtc *crtc);
 void intel_fbc_init(struct drm_i915_private *dev_priv);
 void intel_fbc_cleanup(struct drm_i915_private *dev_priv);
+void intel_fbc_sanitize(struct drm_i915_private *dev_priv);
 void intel_fbc_update(struct intel_atomic_state *state,
                      struct intel_crtc *crtc);
 void intel_fbc_disable(struct intel_crtc *crtc);
-void intel_fbc_global_disable(struct drm_i915_private *dev_priv);
 void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
                          unsigned int frontbuffer_bits,
                          enum fb_op_origin origin);
index 4e4b436..67d2484 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "intel_atomic.h"
 #include "intel_crtc.h"
 #include "intel_ddi.h"
@@ -34,7 +36,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
        }
        I915_STATE_WARN(cur_state != state,
                        "FDI TX state assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe)
@@ -55,7 +57,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
        cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;
        I915_STATE_WARN(cur_state != state,
                        "FDI RX state assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe)
@@ -93,7 +95,7 @@ static void assert_fdi_rx_pll(struct drm_i915_private *i915,
        cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
        I915_STATE_WARN(cur_state != state,
                        "FDI RX PLL assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
index 2fad032..21281a7 100644 (file)
 #include "intel_display_types.h"
 #include "intel_gmbus.h"
 
+struct intel_gmbus {
+       struct i2c_adapter adapter;
+#define GMBUS_FORCE_BIT_RETRY (1U << 31)
+       u32 force_bit;
+       u32 reg0;
+       i915_reg_t gpio_reg;
+       struct i2c_algo_bit_data bit_algo;
+       struct drm_i915_private *dev_priv;
+};
+
 struct gmbus_pin {
        const char *name;
        enum i915_gpio gpio;
@@ -106,51 +116,47 @@ static const struct gmbus_pin gmbus_pins_dg2[] = {
        [GMBUS_PIN_9_TC1_ICP] = { "tc1", GPIOJ },
 };
 
-/* pin is expected to be valid */
-static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
+static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
                                             unsigned int pin)
 {
-       if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2)
-               return &gmbus_pins_dg2[pin];
-       else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
-               return &gmbus_pins_dg1[pin];
-       else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
-               return &gmbus_pins_icp[pin];
-       else if (HAS_PCH_CNP(dev_priv))
-               return &gmbus_pins_cnp[pin];
-       else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
-               return &gmbus_pins_bxt[pin];
-       else if (DISPLAY_VER(dev_priv) == 9)
-               return &gmbus_pins_skl[pin];
-       else if (IS_BROADWELL(dev_priv))
-               return &gmbus_pins_bdw[pin];
-       else
-               return &gmbus_pins[pin];
-}
-
-bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
-                             unsigned int pin)
-{
-       unsigned int size;
+       const struct gmbus_pin *pins;
+       size_t size;
 
-       if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2)
+       if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
+               pins = gmbus_pins_dg2;
                size = ARRAY_SIZE(gmbus_pins_dg2);
-       else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
+       } else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
+               pins = gmbus_pins_dg1;
                size = ARRAY_SIZE(gmbus_pins_dg1);
-       else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+       } else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
+               pins = gmbus_pins_icp;
                size = ARRAY_SIZE(gmbus_pins_icp);
-       else if (HAS_PCH_CNP(dev_priv))
+       } else if (HAS_PCH_CNP(i915)) {
+               pins = gmbus_pins_cnp;
                size = ARRAY_SIZE(gmbus_pins_cnp);
-       else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+       } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
+               pins = gmbus_pins_bxt;
                size = ARRAY_SIZE(gmbus_pins_bxt);
-       else if (DISPLAY_VER(dev_priv) == 9)
+       } else if (DISPLAY_VER(i915) == 9) {
+               pins = gmbus_pins_skl;
                size = ARRAY_SIZE(gmbus_pins_skl);
-       else if (IS_BROADWELL(dev_priv))
+       } else if (IS_BROADWELL(i915)) {
+               pins = gmbus_pins_bdw;
                size = ARRAY_SIZE(gmbus_pins_bdw);
-       else
+       } else {
+               pins = gmbus_pins;
                size = ARRAY_SIZE(gmbus_pins);
+       }
+
+       if (pin >= size || !pins[pin].name)
+               return NULL;
+
+       return &pins[pin];
+}
 
-       return pin < size && get_gmbus_pin(dev_priv, pin)->name;
+bool intel_gmbus_is_valid_pin(struct drm_i915_private *i915, unsigned int pin)
+{
+       return get_gmbus_pin(i915, pin);
 }
 
 /* Intel GPIO access functions */
@@ -294,9 +300,7 @@ static void set_data(void *data, int state_high)
 static int
 intel_gpio_pre_xfer(struct i2c_adapter *adapter)
 {
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
+       struct intel_gmbus *bus = to_intel_gmbus(adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
 
        intel_gmbus_reset(dev_priv);
@@ -313,9 +317,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
 static void
 intel_gpio_post_xfer(struct i2c_adapter *adapter)
 {
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
+       struct intel_gmbus *bus = to_intel_gmbus(adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
 
        set_data(bus, 1);
@@ -326,14 +328,13 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
 }
 
 static void
-intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin)
+intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg)
 {
-       struct drm_i915_private *dev_priv = bus->dev_priv;
        struct i2c_algo_bit_data *algo;
 
        algo = &bus->bit_algo;
 
-       bus->gpio_reg = GPIO(get_gmbus_pin(dev_priv, pin)->gpio);
+       bus->gpio_reg = gpio_reg;
        bus->adapter.algo_data = algo;
        algo->setsda = set_data;
        algo->setscl = set_clock;
@@ -614,9 +615,7 @@ static int
 do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
              u32 gmbus0_source)
 {
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
+       struct intel_gmbus *bus = to_intel_gmbus(adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
        int i = 0, inc, try = 0;
        int ret = 0;
@@ -746,8 +745,7 @@ out:
 static int
 gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 {
-       struct intel_gmbus *bus =
-               container_of(adapter, struct intel_gmbus, adapter);
+       struct intel_gmbus *bus = to_intel_gmbus(adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
        intel_wakeref_t wakeref;
        int ret;
@@ -771,8 +769,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 
 int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 {
-       struct intel_gmbus *bus =
-               container_of(adapter, struct intel_gmbus, adapter);
+       struct intel_gmbus *bus = to_intel_gmbus(adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
        u8 cmd = DRM_HDCP_DDC_AKSV;
        u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
@@ -863,7 +860,6 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
 int intel_gmbus_setup(struct drm_i915_private *dev_priv)
 {
        struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
-       struct intel_gmbus *bus;
        unsigned int pin;
        int ret;
 
@@ -880,17 +876,24 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
        init_waitqueue_head(&dev_priv->gmbus_wait_queue);
 
        for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) {
-               if (!intel_gmbus_is_valid_pin(dev_priv, pin))
+               const struct gmbus_pin *gmbus_pin;
+               struct intel_gmbus *bus;
+
+               gmbus_pin = get_gmbus_pin(dev_priv, pin);
+               if (!gmbus_pin)
                        continue;
 
-               bus = &dev_priv->gmbus[pin];
+               bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+               if (!bus) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
 
                bus->adapter.owner = THIS_MODULE;
                bus->adapter.class = I2C_CLASS_DDC;
                snprintf(bus->adapter.name,
                         sizeof(bus->adapter.name),
-                        "i915 gmbus %s",
-                        get_gmbus_pin(dev_priv, pin)->name);
+                        "i915 gmbus %s", gmbus_pin->name);
 
                bus->adapter.dev.parent = &pdev->dev;
                bus->dev_priv = dev_priv;
@@ -911,11 +914,15 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
                if (IS_I830(dev_priv))
                        bus->force_bit = 1;
 
-               intel_gpio_setup(bus, pin);
+               intel_gpio_setup(bus, GPIO(gmbus_pin->gpio));
 
                ret = i2c_add_adapter(&bus->adapter);
-               if (ret)
+               if (ret) {
+                       kfree(bus);
                        goto err;
+               }
+
+               dev_priv->gmbus[pin] = bus;
        }
 
        intel_gmbus_reset(dev_priv);
@@ -923,24 +930,19 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
        return 0;
 
 err:
-       while (pin--) {
-               if (!intel_gmbus_is_valid_pin(dev_priv, pin))
-                       continue;
+       intel_gmbus_teardown(dev_priv);
 
-               bus = &dev_priv->gmbus[pin];
-               i2c_del_adapter(&bus->adapter);
-       }
        return ret;
 }
 
 struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv,
                                            unsigned int pin)
 {
-       if (drm_WARN_ON(&dev_priv->drm,
-                       !intel_gmbus_is_valid_pin(dev_priv, pin)))
+       if (drm_WARN_ON(&dev_priv->drm, pin >= ARRAY_SIZE(dev_priv->gmbus) ||
+                       !dev_priv->gmbus[pin]))
                return NULL;
 
-       return &dev_priv->gmbus[pin].adapter;
+       return &dev_priv->gmbus[pin]->adapter;
 }
 
 void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
@@ -968,14 +970,18 @@ bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
 
 void intel_gmbus_teardown(struct drm_i915_private *dev_priv)
 {
-       struct intel_gmbus *bus;
        unsigned int pin;
 
        for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) {
-               if (!intel_gmbus_is_valid_pin(dev_priv, pin))
+               struct intel_gmbus *bus;
+
+               bus = dev_priv->gmbus[pin];
+               if (!bus)
                        continue;
 
-               bus = &dev_priv->gmbus[pin];
                i2c_del_adapter(&bus->adapter);
+
+               kfree(bus);
+               dev_priv->gmbus[pin] = NULL;
        }
 }
index e1ecf38..4de4c17 100644 (file)
@@ -20,6 +20,7 @@
 #include "intel_connector.h"
 #include "intel_de.h"
 #include "intel_display_power.h"
+#include "intel_display_power_well.h"
 #include "intel_display_types.h"
 #include "intel_hdcp.h"
 #include "intel_pcode.h"
index 6512f01..a4a6f8b 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/hdmi.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/string_helpers.h>
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -2637,7 +2638,7 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
        drm_dbg_kms(&dev_priv->drm,
                    "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n",
                    connector->base.id, connector->name,
-                   yesno(scrambling), high_tmds_clock_ratio ? 40 : 10);
+                   str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10);
 
        /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */
        return drm_scdc_set_high_tmds_clock_ratio(adapter,
index 9fced37..e847816 100644 (file)
@@ -389,7 +389,8 @@ intel_lvds_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
-       struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_fixed_mode(intel_connector, mode);
        int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
        enum drm_mode_status status;
 
@@ -475,19 +476,12 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 static int intel_lvds_get_modes(struct drm_connector *connector)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
-       struct drm_device *dev = connector->dev;
-       struct drm_display_mode *mode;
 
        /* use cached edid if we have one */
        if (!IS_ERR_OR_NULL(intel_connector->edid))
                return drm_add_edid_modes(connector, intel_connector->edid);
 
-       mode = drm_mode_duplicate(dev, intel_connector->panel.fixed_mode);
-       if (mode == NULL)
-               return 0;
-
-       drm_mode_probed_add(connector, mode);
-       return 1;
+       return intel_panel_get_modes(intel_connector);
 }
 
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
@@ -786,16 +780,18 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv)
 
 static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
 {
-       struct drm_device *dev = lvds_encoder->base.base.dev;
+       struct drm_i915_private *dev_priv = to_i915(lvds_encoder->base.base.dev);
+       struct intel_connector *connector = lvds_encoder->attached_connector;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_preferred_fixed_mode(connector);
        unsigned int val;
-       struct drm_i915_private *dev_priv = to_i915(dev);
 
        /* use the module option value if specified */
        if (dev_priv->params.lvds_channel_mode > 0)
                return dev_priv->params.lvds_channel_mode == 2;
 
        /* single channel LVDS is limited to 112 MHz */
-       if (lvds_encoder->attached_connector->panel.fixed_mode->clock > 112999)
+       if (fixed_mode->clock > 112999)
                return true;
 
        if (dmi_check_system(intel_dual_link_lvds))
@@ -833,8 +829,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
        struct drm_encoder *encoder;
-       struct drm_display_mode *fixed_mode = NULL;
-       struct drm_display_mode *downclock_mode = NULL;
        struct edid *edid;
        i915_reg_t lvds_reg;
        u32 lvds;
@@ -973,35 +967,30 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        }
        intel_connector->edid = edid;
 
-       fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
-       if (fixed_mode)
-               goto out;
+       /* Try EDID first */
+       intel_panel_add_edid_fixed_modes(intel_connector,
+                                        dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
 
        /* Failed to get EDID, what about VBT? */
-       fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
-       if (fixed_mode)
-               goto out;
+       if (!intel_panel_preferred_fixed_mode(intel_connector))
+               intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
 
        /*
-        * If we didn't get EDID, try checking if the panel is already turned
-        * on.  If so, assume that whatever is currently programmed is the
-        * correct mode.
+        * If we didn't get a fixed mode from EDID or VBT, try checking
+        * if the panel is already turned on.  If so, assume that
+        * whatever is currently programmed is the correct mode.
         */
-       fixed_mode = intel_encoder_current_mode(intel_encoder);
-       if (fixed_mode) {
-               drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: ");
-               drm_mode_debug_printmodeline(fixed_mode);
-               fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
-       }
+       if (!intel_panel_preferred_fixed_mode(intel_connector))
+               intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder);
+
+       mutex_unlock(&dev->mode_config.mutex);
 
        /* If we still don't have a mode after all that, give up. */
-       if (!fixed_mode)
+       if (!intel_panel_preferred_fixed_mode(intel_connector))
                goto failed;
 
-out:
-       mutex_unlock(&dev->mode_config.mutex);
+       intel_panel_init(intel_connector);
 
-       intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
        intel_backlight_setup(intel_connector, INVALID_PIPE);
 
        lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
@@ -1013,8 +1002,6 @@ out:
        return;
 
 failed:
-       mutex_unlock(&dev->mode_config.mutex);
-
        drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n");
        drm_connector_cleanup(connector);
        drm_encoder_cleanup(encoder);
index 76845d3..ee46561 100644 (file)
@@ -958,19 +958,21 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
 static int check_overlay_dst(struct intel_overlay *overlay,
                             struct drm_intel_overlay_put_image *rec)
 {
-       const struct intel_crtc_state *pipe_config =
+       const struct intel_crtc_state *crtc_state =
                overlay->crtc->config;
+       struct drm_rect req, clipped;
 
-       if (rec->dst_height == 0 || rec->dst_width == 0)
-               return -EINVAL;
+       drm_rect_init(&req, rec->dst_x, rec->dst_y,
+                     rec->dst_width, rec->dst_height);
 
-       if (rec->dst_x < pipe_config->pipe_src_w &&
-           rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w &&
-           rec->dst_y < pipe_config->pipe_src_h &&
-           rec->dst_y + rec->dst_height <= pipe_config->pipe_src_h)
-               return 0;
-       else
+       clipped = req;
+       drm_rect_intersect(&clipped, &crtc_state->pipe_src);
+
+       if (!drm_rect_visible(&clipped) ||
+           !drm_rect_equals(&clipped, &req))
                return -EINVAL;
+
+       return 0;
 }
 
 static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
@@ -1160,7 +1162,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
                crtc->overlay = overlay;
 
                /* line too wide, i.e. one-line-mode */
-               if (crtc->config->pipe_src_w > 1024 &&
+               if (drm_rect_width(&crtc->config->pipe_src) > 1024 &&
                    crtc->config->gmch_pfit.control & PFIT_ENABLE) {
                        overlay->pfit_active = true;
                        update_pfit_vscale_ratio(overlay);
index a0c8e43..03398fe 100644 (file)
@@ -35,6 +35,7 @@
 #include "intel_connector.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
+#include "intel_drrs.h"
 #include "intel_panel.h"
 
 bool intel_panel_use_ssc(struct drm_i915_private *i915)
@@ -45,10 +46,83 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915)
                && !(i915->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
+const struct drm_display_mode *
+intel_panel_preferred_fixed_mode(struct intel_connector *connector)
+{
+       return list_first_entry_or_null(&connector->panel.fixed_modes,
+                                       struct drm_display_mode, head);
+}
+
+const struct drm_display_mode *
+intel_panel_fixed_mode(struct intel_connector *connector,
+                      const struct drm_display_mode *mode)
+{
+       const struct drm_display_mode *fixed_mode, *best_mode = NULL;
+       int vrefresh = drm_mode_vrefresh(mode);
+
+       /* pick the fixed_mode that is closest in terms of vrefresh */
+       list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
+               if (!best_mode ||
+                   abs(drm_mode_vrefresh(fixed_mode) - vrefresh) <
+                   abs(drm_mode_vrefresh(best_mode) - vrefresh))
+                       best_mode = fixed_mode;
+       }
+
+       return best_mode;
+}
+
+const struct drm_display_mode *
+intel_panel_downclock_mode(struct intel_connector *connector,
+                          const struct drm_display_mode *adjusted_mode)
+{
+       const struct drm_display_mode *fixed_mode, *best_mode = NULL;
+       int vrefresh = drm_mode_vrefresh(adjusted_mode);
+
+       /* pick the fixed_mode with the lowest refresh rate */
+       list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
+               if (drm_mode_vrefresh(fixed_mode) < vrefresh) {
+                       vrefresh = drm_mode_vrefresh(fixed_mode);
+                       best_mode = fixed_mode;
+               }
+       }
+
+       return best_mode;
+}
+
+int intel_panel_get_modes(struct intel_connector *connector)
+{
+       const struct drm_display_mode *fixed_mode;
+       int num_modes = 0;
+
+       list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
+               struct drm_display_mode *mode;
+
+               mode = drm_mode_duplicate(connector->base.dev, fixed_mode);
+               if (mode) {
+                       drm_mode_probed_add(&connector->base, mode);
+                       num_modes++;
+               }
+       }
+
+       return num_modes;
+}
+
+enum drrs_type intel_panel_drrs_type(struct intel_connector *connector)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+
+       if (list_empty(&connector->panel.fixed_modes) ||
+           list_is_singular(&connector->panel.fixed_modes))
+               return DRRS_TYPE_NONE;
+
+       return i915->vbt.drrs_type;
+}
+
 int intel_panel_compute_config(struct intel_connector *connector,
                               struct drm_display_mode *adjusted_mode)
 {
-       const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_fixed_mode(connector, adjusted_mode);
 
        if (!fixed_mode)
                return 0;
@@ -75,128 +149,142 @@ int intel_panel_compute_config(struct intel_connector *connector,
        return 0;
 }
 
-static bool is_downclock_mode(const struct drm_display_mode *downclock_mode,
-                             const struct drm_display_mode *fixed_mode)
+static bool is_alt_fixed_mode(const struct drm_display_mode *mode,
+                             const struct drm_display_mode *preferred_mode)
 {
-       return drm_mode_match(downclock_mode, fixed_mode,
+       return drm_mode_match(mode, preferred_mode,
                              DRM_MODE_MATCH_TIMINGS |
                              DRM_MODE_MATCH_FLAGS |
                              DRM_MODE_MATCH_3D_FLAGS) &&
-               downclock_mode->clock < fixed_mode->clock;
+               mode->clock != preferred_mode->clock;
 }
 
-struct drm_display_mode *
-intel_panel_edid_downclock_mode(struct intel_connector *connector,
-                               const struct drm_display_mode *fixed_mode)
+static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       const struct drm_display_mode *scan, *best_mode = NULL;
-       struct drm_display_mode *downclock_mode;
-       int best_clock = fixed_mode->clock;
+       const struct drm_display_mode *preferred_mode =
+               intel_panel_preferred_fixed_mode(connector);
+       struct drm_display_mode *mode, *next;
 
-       list_for_each_entry(scan, &connector->base.probed_modes, head) {
-               /*
-                * If one mode has the same resolution with the fixed_panel
-                * mode while they have the different refresh rate, it means
-                * that the reduced downclock is found. In such
-                * case we can set the different FPx0/1 to dynamically select
-                * between low and high frequency.
-                */
-               if (is_downclock_mode(scan, fixed_mode) &&
-                   scan->clock < best_clock) {
-                       /*
-                        * The downclock is already found. But we
-                        * expect to find the lower downclock.
-                        */
-                       best_clock = scan->clock;
-                       best_mode = scan;
-               }
-       }
-
-       if (!best_mode)
-               return NULL;
-
-       downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode);
-       if (!downclock_mode)
-               return NULL;
+       list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
+               if (!is_alt_fixed_mode(mode, preferred_mode))
+                       continue;
 
-       drm_dbg_kms(&dev_priv->drm,
-                   "[CONNECTOR:%d:%s] using downclock mode from EDID: ",
-                   connector->base.base.id, connector->base.name);
-       drm_mode_debug_printmodeline(downclock_mode);
+               drm_dbg_kms(&dev_priv->drm,
+                           "[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n",
+                           connector->base.base.id, connector->base.name,
+                           DRM_MODE_ARG(mode));
 
-       return downclock_mode;
+               list_move_tail(&mode->head, &connector->panel.fixed_modes);
+       }
 }
 
-struct drm_display_mode *
-intel_panel_edid_fixed_mode(struct intel_connector *connector)
+static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       const struct drm_display_mode *scan;
-       struct drm_display_mode *fixed_mode;
+       struct drm_display_mode *scan, *fixed_mode = NULL;
 
        if (list_empty(&connector->base.probed_modes))
-               return NULL;
+               return;
 
-       /* prefer fixed mode from EDID if available */
+       /* make sure the preferred mode is first */
        list_for_each_entry(scan, &connector->base.probed_modes, head) {
-               if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0)
-                       continue;
+               if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+                       fixed_mode = scan;
+                       break;
+               }
+       }
 
-               fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
-               if (!fixed_mode)
-                       return NULL;
+       if (!fixed_mode)
+               fixed_mode = list_first_entry(&connector->base.probed_modes,
+                                             typeof(*fixed_mode), head);
 
-               drm_dbg_kms(&dev_priv->drm,
-                           "[CONNECTOR:%d:%s] using preferred mode from EDID: ",
-                           connector->base.base.id, connector->base.name);
-               drm_mode_debug_printmodeline(fixed_mode);
+       drm_dbg_kms(&dev_priv->drm,
+                   "[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n",
+                   connector->base.base.id, connector->base.name,
+                   fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first",
+                   DRM_MODE_ARG(fixed_mode));
+
+       fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 
-               return fixed_mode;
+       list_move_tail(&fixed_mode->head, &connector->panel.fixed_modes);
+}
+
+static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       struct drm_display_mode *mode, *next;
+
+       list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
+               list_del(&mode->head);
+               drm_mode_destroy(&i915->drm, mode);
        }
+}
 
-       scan = list_first_entry(&connector->base.probed_modes,
-                               typeof(*scan), head);
+void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs)
+{
+       intel_panel_add_edid_preferred_mode(connector);
+       if (intel_panel_preferred_fixed_mode(connector) && has_drrs)
+               intel_panel_add_edid_alt_fixed_modes(connector);
+       intel_panel_destroy_probed_modes(connector);
+}
+
+static void intel_panel_add_fixed_mode(struct intel_connector *connector,
+                                      struct drm_display_mode *fixed_mode,
+                                      const char *type)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       struct drm_display_info *info = &connector->base.display_info;
 
-       fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
        if (!fixed_mode)
-               return NULL;
+               return;
 
-       fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+       fixed_mode->type |= DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
 
-       drm_dbg_kms(&dev_priv->drm,
-                   "[CONNECTOR:%d:%s] using first mode from EDID: ",
-                   connector->base.base.id, connector->base.name);
-       drm_mode_debug_printmodeline(fixed_mode);
+       info->width_mm = fixed_mode->width_mm;
+       info->height_mm = fixed_mode->height_mm;
 
-       return fixed_mode;
+       drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n",
+                   connector->base.base.id, connector->base.name, type,
+                   DRM_MODE_ARG(fixed_mode));
+
+       list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes);
 }
 
-struct drm_display_mode *
-intel_panel_vbt_fixed_mode(struct intel_connector *connector)
+void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector)
 {
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       struct drm_display_info *info = &connector->base.display_info;
-       struct drm_display_mode *fixed_mode;
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       const struct drm_display_mode *mode;
 
-       if (!dev_priv->vbt.lfp_lvds_vbt_mode)
-               return NULL;
+       mode = i915->vbt.lfp_lvds_vbt_mode;
+       if (!mode)
+               return;
 
-       fixed_mode = drm_mode_duplicate(&dev_priv->drm,
-                                       dev_priv->vbt.lfp_lvds_vbt_mode);
-       if (!fixed_mode)
-               return NULL;
+       intel_panel_add_fixed_mode(connector,
+                                  drm_mode_duplicate(&i915->drm, mode),
+                                  "VBT LFP");
+}
 
-       fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector)
+{
+       struct drm_i915_private *i915 = to_i915(connector->base.dev);
+       const struct drm_display_mode *mode;
 
-       drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: ",
-                   connector->base.base.id, connector->base.name);
-       drm_mode_debug_printmodeline(fixed_mode);
+       mode = i915->vbt.sdvo_lvds_vbt_mode;
+       if (!mode)
+               return;
 
-       info->width_mm = fixed_mode->width_mm;
-       info->height_mm = fixed_mode->height_mm;
+       intel_panel_add_fixed_mode(connector,
+                                  drm_mode_duplicate(&i915->drm, mode),
+                                  "VBT SDVO");
+}
 
-       return fixed_mode;
+void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
+                                       struct intel_encoder *encoder)
+{
+       intel_panel_add_fixed_mode(connector,
+                                  intel_encoder_current_mode(encoder),
+                                  "current (BIOS)");
 }
 
 /* adjusted_mode has been preset to be the panel's fixed mode */
@@ -205,18 +293,20 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
 {
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->hw.adjusted_mode;
+       int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+       int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
        int x, y, width, height;
 
        /* Native modes don't need fitting */
-       if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w &&
-           adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h &&
+       if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
+           adjusted_mode->crtc_vdisplay == pipe_src_h &&
            crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
                return 0;
 
        switch (conn_state->scaling_mode) {
        case DRM_MODE_SCALE_CENTER:
-               width = crtc_state->pipe_src_w;
-               height = crtc_state->pipe_src_h;
+               width = pipe_src_w;
+               height = pipe_src_h;
                x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
                y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
                break;
@@ -224,19 +314,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
        case DRM_MODE_SCALE_ASPECT:
                /* Scale but preserve the aspect ratio */
                {
-                       u32 scaled_width = adjusted_mode->crtc_hdisplay
-                               * crtc_state->pipe_src_h;
-                       u32 scaled_height = crtc_state->pipe_src_w
-                               * adjusted_mode->crtc_vdisplay;
+                       u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+                       u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
                        if (scaled_width > scaled_height) { /* pillar */
-                               width = scaled_height / crtc_state->pipe_src_h;
+                               width = scaled_height / pipe_src_h;
                                if (width & 1)
                                        width++;
                                x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
                                y = 0;
                                height = adjusted_mode->crtc_vdisplay;
                        } else if (scaled_width < scaled_height) { /* letter */
-                               height = scaled_width / crtc_state->pipe_src_w;
+                               height = scaled_width / pipe_src_w;
                                if (height & 1)
                                    height++;
                                y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
@@ -251,8 +339,8 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
                break;
 
        case DRM_MODE_SCALE_NONE:
-               WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w);
-               WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h);
+               WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w);
+               WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h);
                fallthrough;
        case DRM_MODE_SCALE_FULLSCREEN:
                x = y = 0;
@@ -333,10 +421,10 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
 {
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->hw.adjusted_mode;
-       u32 scaled_width = adjusted_mode->crtc_hdisplay *
-               crtc_state->pipe_src_h;
-       u32 scaled_height = crtc_state->pipe_src_w *
-               adjusted_mode->crtc_vdisplay;
+       int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+       int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+       u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+       u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
 
        /* 965+ is easy, it does everything in hw */
        if (scaled_width > scaled_height)
@@ -345,7 +433,7 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
        else if (scaled_width < scaled_height)
                *pfit_control |= PFIT_ENABLE |
                        PFIT_SCALING_LETTER;
-       else if (adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w)
+       else if (adjusted_mode->crtc_hdisplay != pipe_src_w)
                *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
 }
 
@@ -354,10 +442,10 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
                              u32 *border)
 {
        struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
-       u32 scaled_width = adjusted_mode->crtc_hdisplay *
-               crtc_state->pipe_src_h;
-       u32 scaled_height = crtc_state->pipe_src_w *
-               adjusted_mode->crtc_vdisplay;
+       int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+       int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+       u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+       u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
        u32 bits;
 
        /*
@@ -367,12 +455,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
         */
        if (scaled_width > scaled_height) { /* pillar */
                centre_horizontally(adjusted_mode,
-                                   scaled_height /
-                                   crtc_state->pipe_src_h);
+                                   scaled_height / pipe_src_h);
 
                *border = LVDS_BORDER_ENABLE;
-               if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay) {
-                       bits = panel_fitter_scaling(crtc_state->pipe_src_h,
+               if (pipe_src_h != adjusted_mode->crtc_vdisplay) {
+                       bits = panel_fitter_scaling(pipe_src_h,
                                                    adjusted_mode->crtc_vdisplay);
 
                        *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
@@ -383,12 +470,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
                }
        } else if (scaled_width < scaled_height) { /* letter */
                centre_vertically(adjusted_mode,
-                                 scaled_width /
-                                 crtc_state->pipe_src_w);
+                                 scaled_width / pipe_src_w);
 
                *border = LVDS_BORDER_ENABLE;
-               if (crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) {
-                       bits = panel_fitter_scaling(crtc_state->pipe_src_w,
+               if (pipe_src_w != adjusted_mode->crtc_hdisplay) {
+                       bits = panel_fitter_scaling(pipe_src_w,
                                                    adjusted_mode->crtc_hdisplay);
 
                        *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
@@ -413,10 +499,12 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
        struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+       int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+       int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
 
        /* Native modes don't need fitting */
-       if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w &&
-           adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h)
+       if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
+           adjusted_mode->crtc_vdisplay == pipe_src_h)
                goto out;
 
        switch (conn_state->scaling_mode) {
@@ -425,8 +513,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
                 * For centered modes, we have to calculate border widths &
                 * heights and modify the values programmed into the CRTC.
                 */
-               centre_horizontally(adjusted_mode, crtc_state->pipe_src_w);
-               centre_vertically(adjusted_mode, crtc_state->pipe_src_h);
+               centre_horizontally(adjusted_mode, pipe_src_w);
+               centre_vertically(adjusted_mode, pipe_src_h);
                border = LVDS_BORDER_ENABLE;
                break;
        case DRM_MODE_SCALE_ASPECT:
@@ -442,8 +530,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
                 * Full scaling, even if it changes the aspect ratio.
                 * Fortunately this is all done for us in hw.
                 */
-               if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay ||
-                   crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) {
+               if (pipe_src_h != adjusted_mode->crtc_vdisplay ||
+                   pipe_src_w != adjusted_mode->crtc_hdisplay) {
                        pfit_control |= PFIT_ENABLE;
                        if (DISPLAY_VER(dev_priv) >= 4)
                                pfit_control |= PFIT_SCALING_AUTO;
@@ -508,7 +596,8 @@ enum drm_mode_status
 intel_panel_mode_valid(struct intel_connector *connector,
                       const struct drm_display_mode *mode)
 {
-       const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode;
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_fixed_mode(connector, mode);
 
        if (!fixed_mode)
                return MODE_OK;
@@ -525,29 +614,29 @@ intel_panel_mode_valid(struct intel_connector *connector,
        return MODE_OK;
 }
 
-int intel_panel_init(struct intel_panel *panel,
-                    struct drm_display_mode *fixed_mode,
-                    struct drm_display_mode *downclock_mode)
+int intel_panel_init(struct intel_connector *connector)
 {
+       struct intel_panel *panel = &connector->panel;
+
        intel_backlight_init_funcs(panel);
 
-       panel->fixed_mode = fixed_mode;
-       panel->downclock_mode = downclock_mode;
+       drm_dbg_kms(connector->base.dev,
+                   "[CONNECTOR:%d:%s] DRRS type: %s\n",
+                   connector->base.base.id, connector->base.name,
+                   intel_drrs_type_str(intel_panel_drrs_type(connector)));
 
        return 0;
 }
 
-void intel_panel_fini(struct intel_panel *panel)
+void intel_panel_fini(struct intel_connector *connector)
 {
-       struct intel_connector *intel_connector =
-               container_of(panel, struct intel_connector, panel);
+       struct intel_panel *panel = &connector->panel;
+       struct drm_display_mode *fixed_mode, *next;
 
        intel_backlight_destroy(panel);
 
-       if (panel->fixed_mode)
-               drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
-
-       if (panel->downclock_mode)
-               drm_mode_destroy(intel_connector->base.dev,
-                               panel->downclock_mode);
+       list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) {
+               list_del(&fixed_mode->head);
+               drm_mode_destroy(connector->base.dev, fixed_mode);
+       }
 }
index d50b3f7..2e32bb7 100644 (file)
@@ -9,23 +9,30 @@
 #include <linux/types.h>
 
 enum drm_connector_status;
+enum drrs_type;
 struct drm_connector;
 struct drm_connector_state;
 struct drm_display_mode;
 struct drm_i915_private;
 struct intel_connector;
 struct intel_crtc_state;
-struct intel_panel;
+struct intel_encoder;
 
-int intel_panel_init(struct intel_panel *panel,
-                    struct drm_display_mode *fixed_mode,
-                    struct drm_display_mode *downclock_mode);
-void intel_panel_fini(struct intel_panel *panel);
+int intel_panel_init(struct intel_connector *connector);
+void intel_panel_fini(struct intel_connector *connector);
 enum drm_connector_status
 intel_panel_detect(struct drm_connector *connector, bool force);
 bool intel_panel_use_ssc(struct drm_i915_private *i915);
-void intel_panel_fixed_mode(const struct drm_display_mode *fixed_mode,
-                           struct drm_display_mode *adjusted_mode);
+const struct drm_display_mode *
+intel_panel_preferred_fixed_mode(struct intel_connector *connector);
+const struct drm_display_mode *
+intel_panel_fixed_mode(struct intel_connector *connector,
+                      const struct drm_display_mode *mode);
+const struct drm_display_mode *
+intel_panel_downclock_mode(struct intel_connector *connector,
+                          const struct drm_display_mode *adjusted_mode);
+int intel_panel_get_modes(struct intel_connector *connector);
+enum drrs_type intel_panel_drrs_type(struct intel_connector *connector);
 enum drm_mode_status
 intel_panel_mode_valid(struct intel_connector *connector,
                       const struct drm_display_mode *mode);
@@ -33,12 +40,10 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state,
                        const struct drm_connector_state *conn_state);
 int intel_panel_compute_config(struct intel_connector *connector,
                               struct drm_display_mode *adjusted_mode);
-struct drm_display_mode *
-intel_panel_edid_downclock_mode(struct intel_connector *connector,
-                               const struct drm_display_mode *fixed_mode);
-struct drm_display_mode *
-intel_panel_edid_fixed_mode(struct intel_connector *connector);
-struct drm_display_mode *
-intel_panel_vbt_fixed_mode(struct intel_connector *connector);
+void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs);
+void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector);
+void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector);
+void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
+                                       struct intel_encoder *encoder);
 
 #endif /* __INTEL_PANEL_H__ */
index 9192769..837152d 100644 (file)
 #include "intel_pps.h"
 #include "intel_sdvo.h"
 
+bool intel_has_pch_trancoder(struct drm_i915_private *i915,
+                            enum pipe pch_transcoder)
+{
+       return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) ||
+               (HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A);
+}
+
+enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+       if (HAS_PCH_LPT(i915))
+               return PIPE_A;
+       else
+               return crtc->pipe;
+}
+
 static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
                                   enum pipe pipe, enum port port,
                                   i915_reg_t dp_reg)
@@ -88,6 +105,67 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
                        pipe_name(pipe));
 }
 
+static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
+                                      enum port port, i915_reg_t hdmi_reg)
+{
+       u32 val = intel_de_read(dev_priv, hdmi_reg);
+
+       if (val & SDVO_ENABLE ||
+           (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A))
+               return;
+
+       drm_dbg_kms(&dev_priv->drm,
+                   "Sanitizing transcoder select for HDMI %c\n",
+                   port_name(port));
+
+       val &= ~SDVO_PIPE_SEL_MASK;
+       val |= SDVO_PIPE_SEL(PIPE_A);
+
+       intel_de_write(dev_priv, hdmi_reg, val);
+}
+
+static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv,
+                                    enum port port, i915_reg_t dp_reg)
+{
+       u32 val = intel_de_read(dev_priv, dp_reg);
+
+       if (val & DP_PORT_EN ||
+           (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A))
+               return;
+
+       drm_dbg_kms(&dev_priv->drm,
+                   "Sanitizing transcoder select for DP %c\n",
+                   port_name(port));
+
+       val &= ~DP_PIPE_SEL_MASK;
+       val |= DP_PIPE_SEL(PIPE_A);
+
+       intel_de_write(dev_priv, dp_reg, val);
+}
+
+static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv)
+{
+       /*
+        * The BIOS may select transcoder B on some of the PCH
+        * ports even it doesn't enable the port. This would trip
+        * assert_pch_dp_disabled() and assert_pch_hdmi_disabled().
+        * Sanitize the transcoder select bits to prevent that. We
+        * assume that the BIOS never actually enabled the port,
+        * because if it did we'd actually have to toggle the port
+        * on and back off to make the transcoder A select stick
+        * (see. intel_dp_link_down(), intel_disable_hdmi(),
+        * intel_disable_sdvo()).
+        */
+       ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B);
+       ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C);
+       ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D);
+
+       /* PCH SDVOB multiplex with HDMIB */
+       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB);
+       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC);
+       ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID);
+}
+
 static void intel_pch_transcoder_set_m1_n1(struct intel_crtc *crtc,
                                           const struct intel_link_m_n *m_n)
 {
@@ -181,7 +259,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
                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);
+               val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
                intel_de_write(dev_priv, reg, val);
        }
 
@@ -192,7 +270,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
        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);
+               val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
 
                /*
                 * Make the BPC in transcoder be consistent with
@@ -466,9 +544,11 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
        ilk_pch_clock_get(crtc_state);
 }
 
-static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
-                                     enum transcoder cpu_transcoder)
+static void lpt_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 transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        u32 val, pipeconf_val;
 
        /* FDI must be feeding us bits for PCH ports */
@@ -480,7 +560,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        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);
+       val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
        intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
 
        val = TRANS_ENABLE;
@@ -521,7 +601,6 @@ void lpt_pch_enable(struct intel_atomic_state *state,
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_crtc_state *crtc_state =
                intel_atomic_get_new_crtc_state(state, crtc);
-       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
        assert_pch_transcoder_disabled(dev_priv, PIPE_A);
 
@@ -530,7 +609,7 @@ void lpt_pch_enable(struct intel_atomic_state *state,
        /* Set transcoder timing. */
        ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);
 
-       lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
+       lpt_enable_pch_transcoder(crtc_state);
 }
 
 void lpt_pch_disable(struct intel_atomic_state *state,
@@ -563,3 +642,9 @@ void lpt_pch_get_config(struct intel_crtc_state *crtc_state)
 
        crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
 }
+
+void intel_pch_sanitize(struct drm_i915_private *i915)
+{
+       if (HAS_PCH_IBX(i915))
+               ibx_sanitize_pch_ports(i915);
+}
index 749473d..41a6341 100644 (file)
@@ -6,11 +6,19 @@
 #ifndef _INTEL_PCH_DISPLAY_H_
 #define _INTEL_PCH_DISPLAY_H_
 
+#include <linux/types.h>
+
+enum pipe;
+struct drm_i915_private;
 struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_link_m_n;
 
+bool intel_has_pch_trancoder(struct drm_i915_private *i915,
+                            enum pipe pch_transcoder);
+enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
+
 void ilk_pch_pre_enable(struct intel_atomic_state *state,
                        struct intel_crtc *crtc);
 void ilk_pch_enable(struct intel_atomic_state *state,
@@ -32,4 +40,6 @@ void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc,
 void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc,
                                    struct intel_link_m_n *m_n);
 
+void intel_pch_sanitize(struct drm_i915_private *i915);
+
 #endif
index d7b1de4..e207d12 100644 (file)
@@ -127,6 +127,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
        case DRM_FORMAT_MOD_LINEAR:
        case I915_FORMAT_MOD_X_TILED:
        case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_4_TILED:
                break;
        default:
                drm_dbg(&dev_priv->drm,
index bff8c2d..5a55010 100644 (file)
@@ -100,11 +100,15 @@ static bool psr_global_enabled(struct intel_dp *intel_dp)
 
 static bool psr2_global_enabled(struct intel_dp *intel_dp)
 {
+       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
        switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
        case I915_PSR_DEBUG_DISABLE:
        case I915_PSR_DEBUG_FORCE_PSR1:
                return false;
        default:
+               if (i915->params.enable_psr == 1)
+                       return false;
                return true;
        }
 }
@@ -1217,6 +1221,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
        intel_dp->psr.dc3co_exit_delay = val;
        intel_dp->psr.dc3co_exitline = crtc_state->dc3co_exitline;
        intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
+       intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
        intel_dp->psr.req_psr2_sdp_prior_scanline =
                crtc_state->req_psr2_sdp_prior_scanline;
 
@@ -1432,28 +1437,42 @@ unlock:
        mutex_unlock(&psr->lock);
 }
 
-static inline u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv)
+static u32 man_trk_ctl_enable_bit_get(struct drm_i915_private *dev_priv)
+{
+       return IS_ALDERLAKE_P(dev_priv) ? 0 : PSR2_MAN_TRK_CTL_ENABLE;
+}
+
+static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv)
 {
        return IS_ALDERLAKE_P(dev_priv) ?
               ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME :
               PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
 }
 
-static inline u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
+static u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
 {
        return IS_ALDERLAKE_P(dev_priv) ?
               ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE :
               PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
 }
 
+static u32 man_trk_ctl_continuos_full_frame(struct drm_i915_private *dev_priv)
+{
+       return IS_ALDERLAKE_P(dev_priv) ?
+              ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME :
+              PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME;
+}
+
 static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
        if (intel_dp->psr.psr2_sel_fetch_enabled)
-               intel_de_rmw(dev_priv,
-                            PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), 0,
-                            man_trk_ctl_single_full_frame_bit_get(dev_priv));
+               intel_de_write(dev_priv,
+                              PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+                              man_trk_ctl_enable_bit_get(dev_priv) |
+                              man_trk_ctl_partial_frame_bit_get(dev_priv) |
+                              man_trk_ctl_single_full_frame_bit_get(dev_priv));
 
        /*
         * Display WA #0884: skl+
@@ -1537,10 +1556,21 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
 void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       struct intel_encoder *encoder;
 
        if (!crtc_state->enable_psr2_sel_fetch)
                return;
 
+       for_each_intel_encoder_mask_with_psr(&dev_priv->drm, encoder,
+                                            crtc_state->uapi.encoder_mask) {
+               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+               lockdep_assert_held(&intel_dp->psr.lock);
+               if (intel_dp->psr.psr2_sel_fetch_cff_enabled)
+                       return;
+               break;
+       }
+
        intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(crtc_state->cpu_transcoder),
                       crtc_state->psr2_man_track_ctl);
 }
@@ -1550,10 +1580,7 @@ static void psr2_man_trk_ctl_calc(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);
-       u32 val = 0;
-
-       if (!IS_ALDERLAKE_P(dev_priv))
-               val = PSR2_MAN_TRK_CTL_ENABLE;
+       u32 val = man_trk_ctl_enable_bit_get(dev_priv);
 
        /* SF partial frame enable has to be set even on full update */
        val |= man_trk_ctl_partial_frame_bit_get(dev_priv);
@@ -1911,13 +1938,13 @@ static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
 }
 
 /**
- * intel_psr_wait_for_idle - wait for PSR be ready for a pipe update
+ * intel_psr_wait_for_idle_locked - wait for PSR be ready for a pipe update
  * @new_crtc_state: new CRTC state
  *
  * This function is expected to be called from pipe_update_start() where it is
  * not expected to race with PSR enable or disable.
  */
-void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
+void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev);
        struct intel_encoder *encoder;
@@ -1930,12 +1957,10 @@ void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
                int ret;
 
-               mutex_lock(&intel_dp->psr.lock);
+               lockdep_assert_held(&intel_dp->psr.lock);
 
-               if (!intel_dp->psr.enabled) {
-                       mutex_unlock(&intel_dp->psr.lock);
+               if (!intel_dp->psr.enabled)
                        continue;
-               }
 
                if (intel_dp->psr.psr2_enabled)
                        ret = _psr2_ready_for_pipe_update_locked(intel_dp);
@@ -1944,8 +1969,6 @@ void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
 
                if (ret)
                        drm_err(&dev_priv->drm, "PSR wait timed out, atomic update may fail\n");
-
-               mutex_unlock(&intel_dp->psr.lock);
        }
 }
 
@@ -2122,6 +2145,27 @@ unlock:
        mutex_unlock(&intel_dp->psr.lock);
 }
 
+static void _psr_invalidate_handle(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+       if (intel_dp->psr.psr2_sel_fetch_enabled) {
+               u32 val;
+
+               if (intel_dp->psr.psr2_sel_fetch_cff_enabled)
+                       return;
+
+               val = man_trk_ctl_enable_bit_get(dev_priv) |
+                     man_trk_ctl_partial_frame_bit_get(dev_priv) |
+                     man_trk_ctl_continuos_full_frame(dev_priv);
+               intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), val);
+               intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
+               intel_dp->psr.psr2_sel_fetch_cff_enabled = true;
+       } else {
+               intel_psr_exit(intel_dp);
+       }
+}
+
 /**
  * intel_psr_invalidate - Invalidade PSR
  * @dev_priv: i915 device
@@ -2158,7 +2202,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
                intel_dp->psr.busy_frontbuffer_bits |= pipe_frontbuffer_bits;
 
                if (pipe_frontbuffer_bits)
-                       intel_psr_exit(intel_dp);
+                       _psr_invalidate_handle(intel_dp);
 
                mutex_unlock(&intel_dp->psr.lock);
        }
@@ -2190,6 +2234,42 @@ tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
                         intel_dp->psr.dc3co_exit_delay);
 }
 
+static void _psr_flush_handle(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+       if (intel_dp->psr.psr2_sel_fetch_enabled) {
+               if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {
+                       /* can we turn CFF off? */
+                       if (intel_dp->psr.busy_frontbuffer_bits == 0) {
+                               u32 val = man_trk_ctl_enable_bit_get(dev_priv) |
+                                         man_trk_ctl_partial_frame_bit_get(dev_priv) |
+                                         man_trk_ctl_single_full_frame_bit_get(dev_priv);
+
+                               /*
+                                * turn continuous full frame off and do a single
+                                * full frame
+                                */
+                               intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+                                              val);
+                               intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
+                               intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
+                       }
+               } else {
+                       /*
+                        * continuous full frame is disabled, only a single full
+                        * frame is required
+                        */
+                       psr_force_hw_tracking_exit(intel_dp);
+               }
+       } else {
+               psr_force_hw_tracking_exit(intel_dp);
+
+               if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
+                       schedule_work(&intel_dp->psr.work);
+       }
+}
+
 /**
  * intel_psr_flush - Flush PSR
  * @dev_priv: i915 device
@@ -2227,25 +2307,22 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
                 * we have to ensure that the PSR is not activated until
                 * intel_psr_resume() is called.
                 */
-               if (intel_dp->psr.paused) {
-                       mutex_unlock(&intel_dp->psr.lock);
-                       continue;
-               }
+               if (intel_dp->psr.paused)
+                       goto unlock;
 
                if (origin == ORIGIN_FLIP ||
                    (origin == ORIGIN_CURSOR_UPDATE &&
                     !intel_dp->psr.psr2_sel_fetch_enabled)) {
                        tgl_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
-                       mutex_unlock(&intel_dp->psr.lock);
-                       continue;
+                       goto unlock;
                }
 
-               /* By definition flush = invalidate + flush */
-               if (pipe_frontbuffer_bits)
-                       psr_force_hw_tracking_exit(intel_dp);
+               if (pipe_frontbuffer_bits == 0)
+                       goto unlock;
 
-               if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
-                       schedule_work(&intel_dp->psr.work);
+               /* By definition flush = invalidate + flush */
+               _psr_flush_handle(intel_dp);
+unlock:
                mutex_unlock(&intel_dp->psr.lock);
        }
 }
@@ -2436,3 +2513,51 @@ bool intel_psr_enabled(struct intel_dp *intel_dp)
 
        return ret;
 }
+
+/**
+ * intel_psr_lock - grab PSR lock
+ * @crtc_state: the crtc state
+ *
+ * This is initially meant to be used by around CRTC update, when
+ * vblank sensitive registers are updated and we need grab the lock
+ * before it to avoid vblank evasion.
+ */
+void intel_psr_lock(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+       struct intel_encoder *encoder;
+
+       if (!crtc_state->has_psr)
+               return;
+
+       for_each_intel_encoder_mask_with_psr(&i915->drm, encoder,
+                                            crtc_state->uapi.encoder_mask) {
+               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+               mutex_lock(&intel_dp->psr.lock);
+               break;
+       }
+}
+
+/**
+ * intel_psr_unlock - release PSR lock
+ * @crtc_state: the crtc state
+ *
+ * Release the PSR lock that was held during pipe update.
+ */
+void intel_psr_unlock(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+       struct intel_encoder *encoder;
+
+       if (!crtc_state->has_psr)
+               return;
+
+       for_each_intel_encoder_mask_with_psr(&i915->drm, encoder,
+                                            crtc_state->uapi.encoder_mask) {
+               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+               mutex_unlock(&intel_dp->psr.lock);
+               break;
+       }
+}
index f6526d9..2ac3a46 100644 (file)
@@ -41,7 +41,7 @@ void intel_psr_get_config(struct intel_encoder *encoder,
                          struct intel_crtc_state *pipe_config);
 void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir);
 void intel_psr_short_pulse(struct intel_dp *intel_dp);
-void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state);
+void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_state);
 bool intel_psr_enabled(struct intel_dp *intel_dp);
 int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
                                struct intel_crtc *crtc);
@@ -55,4 +55,7 @@ void intel_psr2_disable_plane_sel_fetch(struct intel_plane *plane,
 void intel_psr_pause(struct intel_dp *intel_dp);
 void intel_psr_resume(struct intel_dp *intel_dp);
 
+void intel_psr_lock(const struct intel_crtc_state *crtc_state);
+void intel_psr_unlock(const struct intel_crtc_state *crtc_state);
+
 #endif /* __INTEL_PSR_H__ */
index 76e1188..ab88d8b 100644 (file)
@@ -283,7 +283,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
 static const struct {
        u8 cmd;
        const char *name;
-} __attribute__ ((packed)) sdvo_cmd_names[] = {
+} __packed sdvo_cmd_names[] = {
        SDVO_CMD_NAME_ENTRY(RESET),
        SDVO_CMD_NAME_ENTRY(GET_DEVICE_CAPS),
        SDVO_CMD_NAME_ENTRY(GET_FIRMWARE_REV),
@@ -783,24 +783,22 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
 static bool
 intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
                                         struct intel_sdvo_connector *intel_sdvo_connector,
-                                        u16 clock,
-                                        u16 width,
-                                        u16 height)
+                                        const struct drm_display_mode *mode)
 {
        struct intel_sdvo_preferred_input_timing_args args;
 
        memset(&args, 0, sizeof(args));
-       args.clock = clock;
-       args.width = width;
-       args.height = height;
+       args.clock = mode->clock / 10;
+       args.width = mode->hdisplay;
+       args.height = mode->vdisplay;
        args.interlace = 0;
 
        if (IS_LVDS(intel_sdvo_connector)) {
                const struct drm_display_mode *fixed_mode =
-                       intel_sdvo_connector->base.panel.fixed_mode;
+                       intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
 
-               if (fixed_mode->hdisplay != width ||
-                   fixed_mode->vdisplay != height)
+               if (fixed_mode->hdisplay != args.width ||
+                   fixed_mode->vdisplay != args.height)
                        args.scaled = 1;
        }
 
@@ -1236,9 +1234,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
 
        if (!intel_sdvo_create_preferred_input_timing(intel_sdvo,
                                                      intel_sdvo_connector,
-                                                     mode->clock / 10,
-                                                     mode->hdisplay,
-                                                     mode->vdisplay))
+                                                     mode))
                return false;
 
        if (!intel_sdvo_get_preferred_input_timing(intel_sdvo,
@@ -1335,6 +1331,8 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
                                                           adjusted_mode);
                pipe_config->sdvo_tv_clock = true;
        } else if (IS_LVDS(intel_sdvo_connector)) {
+               const struct drm_display_mode *fixed_mode =
+                       intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
                int ret;
 
                ret = intel_panel_compute_config(&intel_sdvo_connector->base,
@@ -1342,8 +1340,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
                if (ret)
                        return ret;
 
-               if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
-                                                            intel_sdvo_connector->base.panel.fixed_mode))
+               if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, fixed_mode))
                        return -EINVAL;
 
                (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
@@ -1465,7 +1462,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
        const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
        const struct intel_sdvo_connector_state *sdvo_state =
                to_intel_sdvo_connector_state(conn_state);
-       const struct intel_sdvo_connector *intel_sdvo_connector =
+       struct intel_sdvo_connector *intel_sdvo_connector =
                to_intel_sdvo_connector(conn_state->connector);
        const struct drm_display_mode *mode = &crtc_state->hw.mode;
        struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder);
@@ -1496,11 +1493,14 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
                return;
 
        /* lvds has a special fixed output timing. */
-       if (IS_LVDS(intel_sdvo_connector))
-               intel_sdvo_get_dtd_from_mode(&output_dtd,
-                                            intel_sdvo_connector->base.panel.fixed_mode);
-       else
+       if (IS_LVDS(intel_sdvo_connector)) {
+               const struct drm_display_mode *fixed_mode =
+                       intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
+
+               intel_sdvo_get_dtd_from_mode(&output_dtd, fixed_mode);
+       } else {
                intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
+       }
        if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd))
                drm_info(&dev_priv->drm,
                         "Setting output timings on %s failed\n",
@@ -2291,33 +2291,12 @@ static int intel_sdvo_get_lvds_modes(struct drm_connector *connector)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
-       struct drm_display_mode *newmode;
        int num_modes = 0;
 
        drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
                    connector->base.id, connector->name);
 
-       /*
-        * Fetch modes from VBT. For SDVO prefer the VBT mode since some
-        * SDVO->LVDS transcoders can't cope with the EDID mode.
-        */
-       if (dev_priv->vbt.sdvo_lvds_vbt_mode != NULL) {
-               newmode = drm_mode_duplicate(connector->dev,
-                                            dev_priv->vbt.sdvo_lvds_vbt_mode);
-               if (newmode != NULL) {
-                       /* Guarantee the mode is preferred */
-                       newmode->type = (DRM_MODE_TYPE_PREFERRED |
-                                        DRM_MODE_TYPE_DRIVER);
-                       drm_mode_probed_add(connector, newmode);
-                       num_modes++;
-               }
-       }
-
-       /*
-        * Attempt to get the mode list from DDC.
-        * Assume that the preferred modes are
-        * arranged in priority order.
-        */
+       num_modes += intel_panel_get_modes(to_intel_connector(connector));
        num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc);
 
        return num_modes;
@@ -2747,6 +2726,8 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
        __drm_atomic_helper_connector_reset(&sdvo_connector->base.base,
                                            &conn_state->base.base);
 
+       INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes);
+
        return sdvo_connector;
 }
 
@@ -2890,7 +2871,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        struct drm_connector *connector;
        struct intel_connector *intel_connector;
        struct intel_sdvo_connector *intel_sdvo_connector;
-       struct drm_display_mode *mode;
 
        DRM_DEBUG_KMS("initialising LVDS device %d\n", device);
 
@@ -2919,20 +2899,20 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
                goto err;
 
-       intel_sdvo_get_lvds_modes(connector);
-
-       list_for_each_entry(mode, &connector->probed_modes, head) {
-               if (mode->type & DRM_MODE_TYPE_PREFERRED) {
-                       struct drm_display_mode *fixed_mode =
-                               drm_mode_duplicate(connector->dev, mode);
+       /*
+        * Fetch modes from VBT. For SDVO prefer the VBT mode since some
+        * SDVO->LVDS transcoders can't cope with the EDID mode.
+        */
+       intel_panel_add_vbt_sdvo_fixed_mode(intel_connector);
 
-                       intel_panel_init(&intel_connector->panel,
-                                        fixed_mode, NULL);
-                       break;
-               }
+       if (!intel_panel_preferred_fixed_mode(intel_connector)) {
+               intel_ddc_get_modes(connector, &intel_sdvo->ddc);
+               intel_panel_add_edid_fixed_modes(intel_connector, false);
        }
 
-       if (!intel_connector->panel.fixed_mode)
+       intel_panel_init(intel_connector);
+
+       if (!intel_panel_preferred_fixed_mode(intel_connector))
                goto err;
 
        return true;
index 7e6245b..0dd4775 100644 (file)
@@ -32,10 +32,14 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915)
                if (!intel_phy_is_snps(i915, phy))
                        continue;
 
+               /*
+                * If calibration does not complete successfully, we'll remember
+                * which phy was affected and skip setup of the corresponding
+                * output later.
+                */
                if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy),
                                            DG2_PHY_DP_TX_ACK_MASK, 25))
-                       drm_err(&i915->drm, "SNPS PHY %c failed to calibrate after 25ms.\n",
-                               phy_name(phy));
+                       i915->snps_phy_failed_calibration |= BIT(phy);
        }
 }
 
index 2d71294..7c0df80 100644 (file)
@@ -30,6 +30,8 @@
  * support.
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_color_mgmt.h>
@@ -96,13 +98,13 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 
        if (src_x % hsub || src_w % hsub) {
                drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
-                           src_x, src_w, hsub, yesno(rotated));
+                           src_x, src_w, hsub, str_yes_no(rotated));
                return -EINVAL;
        }
 
        if (src_y % vsub || src_h % vsub) {
                drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
-                           src_y, src_h, vsub, yesno(rotated));
+                           src_y, src_h, vsub, str_yes_no(rotated));
                return -EINVAL;
        }
 
@@ -430,9 +432,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane,
        int crtc_y = plane_state->uapi.dst.y1;
        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
                          plane_state->view.color_plane[0].mapping_stride);
@@ -440,8 +439,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane,
                          SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
        intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
                          SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -457,14 +454,11 @@ vlv_sprite_update_arm(struct intel_plane *plane,
        u32 x = plane_state->view.color_plane[0].x;
        u32 y = plane_state->view.color_plane[0].y;
        u32 sprctl, linear_offset;
-       unsigned long irqflags;
 
        sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
 
        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
                chv_sprite_update_csc(plane_state);
 
@@ -494,8 +488,6 @@ vlv_sprite_update_arm(struct intel_plane *plane,
 
        vlv_sprite_update_clrc(plane_state);
        vlv_sprite_update_gamma(plane_state);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -505,14 +497,9 @@ vlv_sprite_disable_arm(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
        enum plane_id plane_id = plane->id;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
        intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static bool
@@ -862,15 +849,12 @@ ivb_sprite_update_noarm(struct intel_plane *plane,
        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
        u32 sprscale = 0;
-       unsigned long irqflags;
 
        if (crtc_w != src_w || crtc_h != src_h)
                sprscale = SPRITE_SCALE_ENABLE |
                        SPRITE_SRC_WIDTH(src_w - 1) |
                        SPRITE_SRC_HEIGHT(src_h - 1);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
                          plane_state->view.color_plane[0].mapping_stride);
        intel_de_write_fw(dev_priv, SPRPOS(pipe),
@@ -879,8 +863,6 @@ ivb_sprite_update_noarm(struct intel_plane *plane,
                          SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
        if (IS_IVYBRIDGE(dev_priv))
                intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -895,14 +877,11 @@ ivb_sprite_update_arm(struct intel_plane *plane,
        u32 x = plane_state->view.color_plane[0].x;
        u32 y = plane_state->view.color_plane[0].y;
        u32 sprctl, linear_offset;
-       unsigned long irqflags;
 
        sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
 
        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        if (key->flags) {
                intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
                intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
@@ -931,8 +910,6 @@ ivb_sprite_update_arm(struct intel_plane *plane,
                          intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 
        ivb_sprite_update_gamma(plane_state);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -941,17 +918,12 @@ ivb_sprite_disable_arm(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
        /* Disable the scaler */
        if (IS_IVYBRIDGE(dev_priv))
                intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
        intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static bool
@@ -1204,15 +1176,12 @@ g4x_sprite_update_noarm(struct intel_plane *plane,
        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
        u32 dvsscale = 0;
-       unsigned long irqflags;
 
        if (crtc_w != src_w || crtc_h != src_h)
                dvsscale = DVS_SCALE_ENABLE |
                        DVS_SRC_WIDTH(src_w - 1) |
                        DVS_SRC_HEIGHT(src_h - 1);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
                          plane_state->view.color_plane[0].mapping_stride);
        intel_de_write_fw(dev_priv, DVSPOS(pipe),
@@ -1220,8 +1189,6 @@ g4x_sprite_update_noarm(struct intel_plane *plane,
        intel_de_write_fw(dev_priv, DVSSIZE(pipe),
                          DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
        intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -1236,14 +1203,11 @@ g4x_sprite_update_arm(struct intel_plane *plane,
        u32 x = plane_state->view.color_plane[0].x;
        u32 y = plane_state->view.color_plane[0].y;
        u32 dvscntr, linear_offset;
-       unsigned long irqflags;
 
        dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
 
        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        if (key->flags) {
                intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
                intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
@@ -1267,8 +1231,6 @@ g4x_sprite_update_arm(struct intel_plane *plane,
                g4x_sprite_update_gamma(plane_state);
        else
                ilk_sprite_update_gamma(plane_state);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -1277,16 +1239,11 @@ g4x_sprite_disable_arm(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
        /* Disable the scaler */
        intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
        intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static bool
index 8a39989..9379f34 100644 (file)
@@ -1145,8 +1145,8 @@ intel_tv_get_config(struct intel_encoder *encoder,
 
        intel_tv_mode_to_mode(&mode, &tv_mode);
 
-       drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
-       drm_mode_debug_printmodeline(&mode);
+       drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(&mode));
 
        intel_tv_scale_mode_horiz(&mode, hdisplay,
                                  xpos, mode.hdisplay - xsize - xpos);
@@ -1250,8 +1250,8 @@ intel_tv_compute_config(struct intel_encoder *encoder,
                tv_conn_state->bypass_vfilter = false;
        }
 
-       drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
-       drm_mode_debug_printmodeline(adjusted_mode);
+       drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
+                   DRM_MODE_ARG(adjusted_mode));
 
        /*
         * The pipe scanline counter behaviour looks as follows when
@@ -1806,8 +1806,8 @@ intel_tv_get_modes(struct drm_connector *connector)
                 */
                intel_tv_mode_to_mode(mode, tv_mode);
                if (count == 0) {
-                       drm_dbg_kms(&dev_priv->drm, "TV mode:\n");
-                       drm_mode_debug_printmodeline(mode);
+                       drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",
+                                   DRM_MODE_ARG(mode));
                }
                intel_tv_scale_mode_horiz(mode, input->w, 0, 0);
                intel_tv_scale_mode_vert(mode, input->h, 0, 0);
index b9397d9..e4a11c3 100644 (file)
@@ -289,6 +289,9 @@ struct bdb_general_features {
 #define HDMI_MAX_DATA_RATE_PLATFORM    0                       /* 204 */
 #define HDMI_MAX_DATA_RATE_297         1                       /* 204 */
 #define HDMI_MAX_DATA_RATE_165         2                       /* 204 */
+#define HDMI_MAX_DATA_RATE_594         3                       /* 249 */
+#define HDMI_MAX_DATA_RATE_340         4                       /* 249 */
+#define HDMI_MAX_DATA_RATE_300         5                       /* 249 */
 
 #define LEGACY_CHILD_DEVICE_CONFIG_SIZE                33
 
@@ -719,20 +722,22 @@ struct bdb_lvds_options {
 /*
  * Block 41 - LFP Data Table Pointers
  */
+struct lvds_lfp_data_ptr_table {
+       u16 offset; /* offsets are from start of bdb */
+       u8 table_size;
+} __packed;
 
 /* LFP pointer table contains entries to the struct below */
 struct lvds_lfp_data_ptr {
-       u16 fp_timing_offset; /* offsets are from start of bdb */
-       u8 fp_table_size;
-       u16 dvo_timing_offset;
-       u8 dvo_table_size;
-       u16 panel_pnp_id_offset;
-       u8 pnp_table_size;
+       struct lvds_lfp_data_ptr_table fp_timing;
+       struct lvds_lfp_data_ptr_table dvo_timing;
+       struct lvds_lfp_data_ptr_table panel_pnp_id;
 } __packed;
 
 struct bdb_lvds_lfp_data_ptrs {
        u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
        struct lvds_lfp_data_ptr ptr[16];
+       struct lvds_lfp_data_ptr_table panel_name; /* 156-163? */
 } __packed;
 
 /*
@@ -774,6 +779,10 @@ struct bdb_lvds_lfp_data {
        struct lvds_lfp_data_entry data[16];
 } __packed;
 
+struct lvds_lfp_panel_name {
+       u8 name[13];
+} __packed;
+
 /*
  * Block 43 - LFP Backlight Control Data Block
  */
index 545eff5..e59c29a 100644 (file)
@@ -378,10 +378,18 @@ calculate_rc_params(struct rc_parameters *rc,
 {
        int bpc = vdsc_cfg->bits_per_component;
        int bpp = vdsc_cfg->bits_per_pixel >> 4;
-       int ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
-       int ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
-       int ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
-       int ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
+       static const s8 ofs_und6[] = {
+               0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+       };
+       static const s8 ofs_und8[] = {
+               2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12
+       };
+       static const s8 ofs_und12[] = {
+               2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12
+       };
+       static const s8 ofs_und15[] = {
+               10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12
+       };
        int qp_bpc_modifier = (bpc - 8) * 2;
        u32 res, buf_i, bpp_i;
 
@@ -579,7 +587,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
        u8 num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1;
        int i = 0;
 
-       if (crtc_state->bigjoiner)
+       if (crtc_state->bigjoiner_pipes)
                num_vdsc_instances *= 2;
 
        /* Populate PICTURE_PARAMETER_SET_0 registers */
@@ -1113,7 +1121,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 dss_ctl1_val = 0;
 
-       if (crtc_state->bigjoiner && !crtc_state->dsc.compression_enable) {
+       if (crtc_state->bigjoiner_pipes && !crtc_state->dsc.compression_enable) {
                if (intel_crtc_is_bigjoiner_slave(crtc_state))
                        dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE;
                else
@@ -1140,7 +1148,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
                dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
                dss_ctl1_val |= JOINER_ENABLE;
        }
-       if (crtc_state->bigjoiner) {
+       if (crtc_state->bigjoiner_pipes) {
                dss_ctl1_val |= BIG_JOINER_ENABLE;
                if (!intel_crtc_is_bigjoiner_slave(crtc_state))
                        dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE;
@@ -1156,7 +1164,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
 
        /* Disable only if either of them is enabled */
        if (old_crtc_state->dsc.compression_enable ||
-           old_crtc_state->bigjoiner) {
+           old_crtc_state->bigjoiner_pipes) {
                intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0);
                intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0);
        }
index 139e893..396f2f9 100644 (file)
@@ -69,9 +69,9 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat
 
        /* The hw imposes the extra scanline before frame start */
        if (DISPLAY_VER(i915) >= 13)
-               return crtc_state->vrr.guardband + i915->framestart_delay + 1;
+               return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1;
        else
-               return crtc_state->vrr.pipeline_full + i915->framestart_delay + 1;
+               return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1;
 }
 
 int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state)
index c2e9411..4092679 100644 (file)
@@ -197,7 +197,8 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
        return skl_update_scaler(crtc_state, !crtc_state->hw.active,
                                 SKL_CRTC_INDEX,
                                 &crtc_state->scaler_state.scaler_id,
-                                crtc_state->pipe_src_w, crtc_state->pipe_src_h,
+                                drm_rect_width(&crtc_state->pipe_src),
+                                drm_rect_height(&crtc_state->pipe_src),
                                 width, height, NULL, 0,
                                 crtc_state->pch_pfit.enabled);
 }
@@ -400,10 +401,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_crtc_scaler_state *scaler_state =
                &crtc_state->scaler_state;
-       struct drm_rect src = {
-               .x2 = crtc_state->pipe_src_w << 16,
-               .y2 = crtc_state->pipe_src_h << 16,
-       };
        const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
        u16 uv_rgb_hphase, uv_rgb_vphase;
        enum pipe pipe = crtc->pipe;
@@ -412,7 +409,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
        int x = dst->x1;
        int y = dst->y1;
        int hscale, vscale;
-       unsigned long irqflags;
+       struct drm_rect src;
        int id;
        u32 ps_ctrl;
 
@@ -423,6 +420,10 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
                        crtc_state->scaler_state.scaler_id < 0))
                return;
 
+       drm_rect_init(&src, 0, 0,
+                     drm_rect_width(&crtc_state->pipe_src) << 16,
+                     drm_rect_height(&crtc_state->pipe_src) << 16);
+
        hscale = drm_rect_calc_hscale(&src, dst, 0, INT_MAX);
        vscale = drm_rect_calc_vscale(&src, dst, 0, INT_MAX);
 
@@ -434,8 +435,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
        ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
        ps_ctrl |=  PS_SCALER_EN | scaler_state->scalers[id].mode;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        skl_scaler_setup_filter(dev_priv, pipe, id, 0,
                                crtc_state->hw.scaling_filter);
 
@@ -449,8 +448,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
                          x << 16 | y);
        intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id),
                          width << 16 | height);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 void
@@ -519,15 +516,10 @@ static void skl_detach_scaler(struct intel_crtc *crtc, int id)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0);
        intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0);
        intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 /*
index 1223075..caa0332 100644 (file)
@@ -615,9 +615,20 @@ skl_plane_disable_arm(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
-       unsigned long irqflags;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       skl_write_plane_wm(plane, crtc_state);
+
+       intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
+       intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
+}
+
+static void
+icl_plane_disable_arm(struct intel_plane *plane,
+                     const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
 
        if (icl_is_hdr_plane(dev_priv, plane_id))
                intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
@@ -627,8 +638,6 @@ skl_plane_disable_arm(struct intel_plane *plane,
        intel_psr2_disable_plane_sel_fetch(plane, crtc_state);
        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static bool
@@ -762,6 +771,18 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier)
                return PLANE_CTL_TILED_X;
        case I915_FORMAT_MOD_Y_TILED:
                return PLANE_CTL_TILED_Y;
+       case I915_FORMAT_MOD_4_TILED:
+               return PLANE_CTL_TILED_4;
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
+               return PLANE_CTL_TILED_4 |
+                       PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
+                       PLANE_CTL_CLEAR_COLOR_DISABLE;
+       case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
+               return PLANE_CTL_TILED_4 |
+                       PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
+                       PLANE_CTL_CLEAR_COLOR_DISABLE;
+       case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
+               return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
        case I915_FORMAT_MOD_Y_TILED_CCS:
        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
                return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
@@ -1065,7 +1086,7 @@ static void icl_plane_csc_load_black(struct intel_plane *plane)
        intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
 }
 
-static int skl_plane_color_plane(const struct intel_plane_state *plane_state)
+static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
 {
        /* Program the UV plane on planar master */
        if (plane_state->planar_linked_plane && !plane_state->planar_slave)
@@ -1082,14 +1103,11 @@ skl_plane_update_noarm(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
-       int color_plane = skl_plane_color_plane(plane_state);
-       u32 stride = skl_plane_stride(plane_state, color_plane);
-       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       u32 stride = skl_plane_stride(plane_state, 0);
        int crtc_x = plane_state->uapi.dst.x1;
        int crtc_y = plane_state->uapi.dst.y1;
        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
-       unsigned long irqflags;
 
        /* The scaler will handle the output position */
        if (plane_state->scaler_id >= 0) {
@@ -1097,14 +1115,99 @@ skl_plane_update_noarm(struct intel_plane *plane,
                crtc_y = 0;
        }
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
+                         PLANE_STRIDE_(stride));
+       intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
+                         PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
+       intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
+                         PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
+
+       skl_write_plane_wm(plane, crtc_state);
+}
+
+static void
+skl_plane_update_arm(struct intel_plane *plane,
+                    const struct intel_crtc_state *crtc_state,
+                    const struct intel_plane_state *plane_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
+       u32 x = plane_state->view.color_plane[0].x;
+       u32 y = plane_state->view.color_plane[0].y;
+       u32 plane_ctl, plane_color_ctl = 0;
+
+       plane_ctl = plane_state->ctl |
+               skl_plane_ctl_crtc(crtc_state);
+
+       if (DISPLAY_VER(dev_priv) >= 10)
+               plane_color_ctl = plane_state->color_ctl |
+                       glk_plane_color_ctl_crtc(crtc_state);
+
+       intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
+       intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
+       intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
+
+       intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
+                         PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
+
+       intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
+                         skl_plane_aux_dist(plane_state, 0));
+
+       intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
+                         PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
+                         PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
+
+       if (DISPLAY_VER(dev_priv) >= 10)
+               intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
 
        /*
-        * FIXME: pxp session invalidation can hit any time even at time of commit
-        * or after the commit, display content will be garbage.
+        * Enable the scaler before the plane so that we don't
+        * get a catastrophic underrun even if the two operations
+        * end up happening in two different frames.
+        *
+        * TODO: split into noarm+arm pair
         */
-       if (plane_state->force_black)
-               icl_plane_csc_load_black(plane);
+       if (plane_state->scaler_id >= 0)
+               skl_program_plane_scaler(plane, crtc_state, plane_state);
+
+       /*
+        * The control register self-arms if the plane was previously
+        * disabled. Try to make the plane enable atomic by writing
+        * the control register just before the surface register.
+        */
+       intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
+       intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
+                         skl_plane_surf(plane_state, 0));
+}
+
+static void
+icl_plane_update_noarm(struct intel_plane *plane,
+                      const struct intel_crtc_state *crtc_state,
+                      const struct intel_plane_state *plane_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
+       int color_plane = icl_plane_color_plane(plane_state);
+       u32 stride = skl_plane_stride(plane_state, color_plane);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       int crtc_x = plane_state->uapi.dst.x1;
+       int crtc_y = plane_state->uapi.dst.y1;
+       int x = plane_state->view.color_plane[color_plane].x;
+       int y = plane_state->view.color_plane[color_plane].y;
+       int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+       int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
+       u32 plane_color_ctl;
+
+       plane_color_ctl = plane_state->color_ctl |
+               glk_plane_color_ctl_crtc(crtc_state);
+
+       /* The scaler will handle the output position */
+       if (plane_state->scaler_id >= 0) {
+               crtc_x = 0;
+               crtc_y = 0;
+       }
 
        intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
                          PLANE_STRIDE_(stride));
@@ -1113,6 +1216,13 @@ skl_plane_update_noarm(struct intel_plane *plane,
        intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
                          PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
 
+       intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
+       intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
+       intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
+
+       intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
+                         PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
+
        if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
                intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0),
                                  lower_32_bits(plane_state->ccval));
@@ -1120,60 +1230,45 @@ skl_plane_update_noarm(struct intel_plane *plane,
                                  upper_32_bits(plane_state->ccval));
        }
 
+       /* FLAT CCS doesn't need to program AUX_DIST */
+       if (!HAS_FLAT_CCS(dev_priv))
+               intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
+                                 skl_plane_aux_dist(plane_state, color_plane));
+
        if (icl_is_hdr_plane(dev_priv, plane_id))
                intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
                                  plane_state->cus_ctl);
 
+       intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
+
        if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
                icl_program_input_csc(plane, crtc_state, plane_state);
 
        skl_write_plane_wm(plane, crtc_state);
 
-       intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
+       /*
+        * FIXME: pxp session invalidation can hit any time even at time of commit
+        * or after the commit, display content will be garbage.
+        */
+       if (plane_state->force_black)
+               icl_plane_csc_load_black(plane);
 
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+       intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
 }
 
 static void
-skl_plane_update_arm(struct intel_plane *plane,
+icl_plane_update_arm(struct intel_plane *plane,
                     const struct intel_crtc_state *crtc_state,
                     const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
-       int color_plane = skl_plane_color_plane(plane_state);
-       u32 x = plane_state->view.color_plane[color_plane].x;
-       u32 y = plane_state->view.color_plane[color_plane].y;
-       u32 plane_color_ctl = 0;
-       u32 plane_ctl = plane_state->ctl;
-       unsigned long irqflags;
-
-       plane_ctl |= skl_plane_ctl_crtc(crtc_state);
-
-       if (DISPLAY_VER(dev_priv) >= 10)
-               plane_color_ctl = plane_state->color_ctl |
-                       glk_plane_color_ctl_crtc(crtc_state);
-
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-       intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
-       intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
-       intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
-
-       intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
-                         PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
-
-       intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
-                         skl_plane_aux_dist(plane_state, color_plane));
-
-       if (DISPLAY_VER(dev_priv) < 11)
-               intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
-                                 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
-                                 PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
+       int color_plane = icl_plane_color_plane(plane_state);
+       u32 plane_ctl;
 
-       if (DISPLAY_VER(dev_priv) >= 10)
-               intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
+       plane_ctl = plane_state->ctl |
+               skl_plane_ctl_crtc(crtc_state);
 
        /*
         * Enable the scaler before the plane so that we don't
@@ -1193,8 +1288,6 @@ skl_plane_update_arm(struct intel_plane *plane,
        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
                          skl_plane_surf(plane_state, color_plane));
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void
@@ -1204,7 +1297,6 @@ skl_plane_async_flip(struct intel_plane *plane,
                     bool async_flip)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       unsigned long irqflags;
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
        u32 plane_ctl = plane_state->ctl;
@@ -1214,13 +1306,9 @@ skl_plane_async_flip(struct intel_plane *plane,
        if (async_flip)
                plane_ctl |= PLANE_CTL_ASYNC_FLIP;
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
        intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
        intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
                          skl_plane_surf(plane_state, 0));
-
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static bool intel_format_is_p01x(u32 format)
@@ -1325,7 +1413,7 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s
                to_i915(plane_state->uapi.plane->dev);
        int crtc_x = plane_state->uapi.dst.x1;
        int crtc_w = drm_rect_width(&plane_state->uapi.dst);
-       int pipe_src_w = crtc_state->pipe_src_w;
+       int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
 
        /*
         * Display WA #1175: glk
@@ -1545,9 +1633,10 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
 
        /*
         * CCS AUX surface doesn't have its own x/y offsets, we must make sure
-        * they match with the main surface x/y offsets.
+        * they match with the main surface x/y offsets. On DG2
+        * there's no aux plane on fb so skip this checking.
         */
-       if (intel_fb_is_ccs_modifier(fb->modifier)) {
+       if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
                while (!skl_check_main_ccs_coordinates(plane_state, x, y,
                                                       offset, aux_plane)) {
                        if (offset == 0)
@@ -1591,6 +1680,8 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
        const struct drm_framebuffer *fb = plane_state->hw.fb;
        unsigned int rotation = plane_state->hw.rotation;
        int uv_plane = 1;
+       int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
+                       skl_main_to_aux_plane(fb, uv_plane) : 0;
        int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
        int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
        int x = plane_state->uapi.src.x1 >> 17;
@@ -1611,8 +1702,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
        offset = intel_plane_compute_aligned_offset(&x, &y,
                                                    plane_state, uv_plane);
 
-       if (intel_fb_is_ccs_modifier(fb->modifier)) {
-               int ccs_plane = main_to_ccs_plane(fb, uv_plane);
+       if (ccs_plane) {
                u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
                u32 alignment = intel_surf_alignment(fb, uv_plane);
 
@@ -2011,9 +2101,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
        case DRM_FORMAT_Y216:
        case DRM_FORMAT_XVYU12_16161616:
        case DRM_FORMAT_XVYU16161616:
-               if (modifier == DRM_FORMAT_MOD_LINEAR ||
-                   modifier == I915_FORMAT_MOD_X_TILED ||
-                   modifier == I915_FORMAT_MOD_Y_TILED)
+               if (!intel_fb_is_ccs_modifier(modifier))
                        return true;
                fallthrough;
        default:
@@ -2094,6 +2182,10 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
        if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
                return false;
 
+       /* Wa_14013215631 */
+       if (IS_DG2_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
+               return false;
+
        return plane_id < PLANE_SPRITE4;
 }
 
@@ -2106,6 +2198,8 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915,
                caps |= INTEL_PLANE_CAP_TILING_Y;
        if (DISPLAY_VER(i915) < 12)
                caps |= INTEL_PLANE_CAP_TILING_Yf;
+       if (HAS_4TILE(i915))
+               caps |= INTEL_PLANE_CAP_TILING_4;
 
        if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
                caps |= INTEL_PLANE_CAP_CCS_RC;
@@ -2162,9 +2256,15 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
        }
 
        plane->max_stride = skl_plane_max_stride;
-       plane->update_noarm = skl_plane_update_noarm;
-       plane->update_arm = skl_plane_update_arm;
-       plane->disable_arm = skl_plane_disable_arm;
+       if (DISPLAY_VER(dev_priv) >= 11) {
+               plane->update_noarm = icl_plane_update_noarm;
+               plane->update_arm = icl_plane_update_arm;
+               plane->disable_arm = icl_plane_disable_arm;
+       } else {
+               plane->update_noarm = skl_plane_update_noarm;
+               plane->update_arm = skl_plane_update_arm;
+               plane->disable_arm = skl_plane_disable_arm;
+       }
        plane->get_hw_state = skl_plane_get_hw_state;
        plane->check_plane = skl_plane_check;
 
@@ -2278,13 +2378,14 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
        unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
+       static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
 
        if (!plane->get_hw_state(plane, &pipe))
                return;
 
        drm_WARN_ON(dev, pipe != crtc->pipe);
 
-       if (crtc_state->bigjoiner) {
+       if (crtc_state->bigjoiner_pipes) {
                drm_dbg_kms(&dev_priv->drm,
                            "Unsupported bigjoiner configuration for initial FB\n");
                return;
@@ -2332,19 +2433,34 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
        case PLANE_CTL_TILED_Y:
                plane_config->tiling = I915_TILING_Y;
                if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
-                       fb->modifier = DISPLAY_VER(dev_priv) >= 12 ?
-                               I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
-                               I915_FORMAT_MOD_Y_TILED_CCS;
+                       if (DISPLAY_VER(dev_priv) >= 12)
+                               fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
                else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
                        fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
                else
                        fb->modifier = I915_FORMAT_MOD_Y_TILED;
                break;
-       case PLANE_CTL_TILED_YF:
-               if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
-                       fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
-               else
-                       fb->modifier = I915_FORMAT_MOD_Yf_TILED;
+       case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
+               if (HAS_4TILE(dev_priv)) {
+                       u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
+                                     PLANE_CTL_CLEAR_COLOR_DISABLE;
+
+                       if ((val & rc_mask) == rc_mask)
+                               fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
+                       else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
+                               fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
+                       else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
+                               fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_4_TILED;
+               } else {
+                       if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
+                               fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_Yf_TILED;
+               }
                break;
        default:
                MISSING_CASE(tiling);
index 0d936f6..1954f07 100644 (file)
@@ -1660,6 +1660,8 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
 static void vlv_dsi_add_properties(struct intel_connector *connector)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       const struct drm_display_mode *fixed_mode =
+               intel_panel_preferred_fixed_mode(connector);
        u32 allowed_scalers;
 
        allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN);
@@ -1673,8 +1675,8 @@ static void vlv_dsi_add_properties(struct intel_connector *connector)
 
        drm_connector_set_panel_orientation_with_quirk(&connector->base,
                                                       intel_dsi_get_panel_orientation(connector),
-                                                      connector->panel.fixed_mode->hdisplay,
-                                                      connector->panel.fixed_mode->vdisplay);
+                                                      fixed_mode->hdisplay,
+                                                      fixed_mode->vdisplay);
 }
 
 #define NS_KHZ_RATIO           1000000
@@ -1857,7 +1859,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
        struct drm_encoder *encoder;
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
-       struct drm_display_mode *current_mode, *fixed_mode;
+       struct drm_display_mode *current_mode;
        enum port port;
        enum pipe pipe;
 
@@ -1978,15 +1980,16 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
        intel_connector_attach_encoder(intel_connector, intel_encoder);
 
        mutex_lock(&dev->mode_config.mutex);
-       fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
+       intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
        mutex_unlock(&dev->mode_config.mutex);
 
-       if (!fixed_mode) {
+       if (!intel_panel_preferred_fixed_mode(intel_connector)) {
                drm_dbg_kms(&dev_priv->drm, "no fixed mode\n");
                goto err_cleanup_connector;
        }
 
-       intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+       intel_panel_init(intel_connector);
+
        intel_backlight_setup(intel_connector, INVALID_PIPE);
 
        vlv_dsi_add_properties(intel_connector);
index df880f4..5894b01 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/string_helpers.h>
 
 #include "i915_drv.h"
 #include "intel_de.h"
@@ -393,10 +394,7 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev,
        /* Calculate TXESC2 divider */
        div2_value = DIV_ROUND_UP(div1_value, txesc1_div);
 
-       if (div2_value < 10)
-               txesc2_div = div2_value;
-       else
-               txesc2_div = 10;
+       txesc2_div = min_t(u32, div2_value, 10);
 
        intel_de_write(dev_priv, MIPIO_TXESC_CLK_DIV1,
                       (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
@@ -581,7 +579,7 @@ static void assert_dsi_pll(struct drm_i915_private *i915, bool state)
 
        I915_STATE_WARN(cur_state != state,
                        "DSI PLL state assertion failure (expected %s, current %s)\n",
-                       onoff(state), onoff(cur_state));
+                       str_on_off(state), str_on_off(cur_state));
 }
 
 void assert_dsi_pll_enabled(struct drm_i915_private *i915)
index 9ae294e..5db83aa 100644 (file)
@@ -64,6 +64,7 @@
  *
  */
 
+#include <linux/highmem.h>
 #include <linux/log2.h>
 #include <linux/nospec.h>
 
index 78f8797..fd0e15d 100644 (file)
@@ -4,8 +4,9 @@
  * Copyright © 2008,2010 Intel Corporation
  */
 
-#include <linux/intel-iommu.h>
 #include <linux/dma-resv.h>
+#include <linux/highmem.h>
+#include <linux/intel-iommu.h>
 #include <linux/sync_file.h>
 #include <linux/uaccess.h>
 
index 444f826..ede084f 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <uapi/drm/i915_drm.h>
+
 #include "intel_memory_region.h"
 #include "gem/i915_gem_region.h"
 #include "gem/i915_gem_lmem.h"
index 372bc22..c1c3b51 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/highmem.h>
 #include <linux/sched/mm.h>
 
 #include <drm/drm_cache.h>
index ca6faff..0d0e46d 100644 (file)
@@ -14,6 +14,7 @@
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 #include "i915_gem_region.h"
+#include "i915_gem_tiling.h"
 #include "i915_scatterlist.h"
 
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
index 6cf9446..5866c88 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <uapi/drm/i915_drm.h>
+
 #include "intel_memory_region.h"
 #include "i915_gem_region.h"
 #include "i915_drv.h"
index 3a1c782..c7541dc 100644 (file)
@@ -12,8 +12,9 @@
 
 #include "gem/i915_gem_region.h"
 #include "i915_drv.h"
-#include "i915_gemfs.h"
 #include "i915_gem_object.h"
+#include "i915_gem_tiling.h"
+#include "i915_gemfs.h"
 #include "i915_scatterlist.h"
 #include "i915_trace.h"
 
index 0bf8f61..2a225da 100644 (file)
@@ -15,6 +15,7 @@
 #include "i915_drv.h"
 #include "i915_gem_stolen.h"
 #include "i915_reg.h"
+#include "i915_utils.h"
 #include "i915_vgpu.h"
 #include "intel_mchbar_regs.h"
 
@@ -401,7 +402,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
                return 0;
        }
 
-       if (intel_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
+       if (i915_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
                drm_notice(&i915->drm,
                           "%s, disabling use of stolen memory\n",
                           "DMAR active");
index d6adda5..80ac0db 100644 (file)
@@ -219,6 +219,14 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj,
        return ret;
 }
 
+bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
+       return to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
+               i915_gem_object_is_tiled(obj);
+}
+
 int
 i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
                           unsigned int tiling, unsigned int stride)
index 9924196..6bd5751 100644 (file)
@@ -8,8 +8,10 @@
 
 #include <linux/types.h>
 
+struct drm_i915_gem_object;
 struct drm_i915_private;
 
+bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj);
 u32 i915_gem_fence_size(struct drm_i915_private *i915, u32 size,
                        unsigned int tiling, unsigned int stride);
 u32 i915_gem_fence_alignment(struct drm_i915_private *i915, u32 size,
index 7271fbf..ee87874 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "i915_drv.h"
 #include "i915_gemfs.h"
+#include "i915_utils.h"
 
 int i915_gemfs_init(struct drm_i915_private *i915)
 {
@@ -32,7 +33,7 @@ int i915_gemfs_init(struct drm_i915_private *i915)
         */
 
        opts = NULL;
-       if (intel_vtd_active(i915)) {
+       if (i915_vtd_active(i915)) {
                if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
                        opts = huge_opt;
                        drm_info(&i915->drm,
index 7a84fa6..ef15967 100644 (file)
@@ -5,6 +5,8 @@
  */
 
 #include <linux/prime_numbers.h>
+#include <linux/string_helpers.h>
+#include <linux/swap.h>
 
 #include "i915_selftest.h"
 
@@ -804,7 +806,7 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
                if (vma->resource->page_sizes_gtt != expected_gtt) {
                        pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n",
                               vma->resource->page_sizes_gtt, expected_gtt,
-                              obj->base.size, yesno(!!single));
+                              obj->base.size, str_yes_no(!!single));
                        err = -EINVAL;
                        break;
                }
@@ -960,7 +962,7 @@ static int igt_mock_ppgtt_64K(void *arg)
                        if (vma->resource->page_sizes_gtt != expected_gtt) {
                                pr_err("gtt=%u, expected=%u, i=%d, single=%s\n",
                                       vma->resource->page_sizes_gtt,
-                                      expected_gtt, i, yesno(!!single));
+                                      expected_gtt, i, str_yes_no(!!single));
                                err = -EINVAL;
                                goto out_vma_unpin;
                        }
@@ -1706,14 +1708,14 @@ static int igt_shrink_thp(void *arg)
                        I915_SHRINK_WRITEBACK);
        if (should_swap == i915_gem_object_has_pages(obj)) {
                pr_err("unexpected pages mismatch, should_swap=%s\n",
-                      yesno(should_swap));
+                      str_yes_no(should_swap));
                err = -EINVAL;
                goto out_put;
        }
 
        if (should_swap == (obj->mm.page_sizes.sg || obj->mm.page_sizes.phys)) {
                pr_err("unexpected residual page-size bits, should_swap=%s\n",
-                      yesno(should_swap));
+                      str_yes_no(should_swap));
                err = -EINVAL;
                goto out_put;
        }
index 7609db8..93a6742 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/prime_numbers.h>
+#include <linux/string_helpers.h>
 
 #include "gem/i915_gem_internal.h"
 #include "gem/i915_gem_pm.h"
@@ -700,7 +701,7 @@ static int igt_ctx_exec(void *arg)
                                pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
                                       ndwords, dw, max_dwords(obj),
                                       engine->name,
-                                      yesno(i915_gem_context_has_full_ppgtt(ctx)),
+                                      str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
                                       err);
                                intel_context_put(ce);
                                kernel_context_close(ctx);
@@ -834,7 +835,7 @@ static int igt_shared_ctx_exec(void *arg)
                                pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
                                       ndwords, dw, max_dwords(obj),
                                       engine->name,
-                                      yesno(i915_gem_context_has_full_ppgtt(ctx)),
+                                      str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
                                       err);
                                intel_context_put(ce);
                                kernel_context_close(ctx);
@@ -1415,7 +1416,7 @@ static int igt_ctx_readonly(void *arg)
                                pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
                                       ndwords, dw, max_dwords(obj),
                                       ce->engine->name,
-                                      yesno(i915_gem_context_has_full_ppgtt(ctx)),
+                                      str_yes_no(i915_gem_context_has_full_ppgtt(ctx)),
                                       err);
                                i915_gem_context_unlock_engines(ctx);
                                goto out_file;
index a132e24..c4c2c91 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright © 2016 Intel Corporation
  */
 
+#include <linux/highmem.h>
 #include <linux/prime_numbers.h>
 
 #include "gem/i915_gem_internal.h"
index 209cf26..9dc9dcc 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/string_helpers.h>
 #include <trace/events/dma_fence.h>
 #include <uapi/linux/sched/types.h>
 
@@ -512,7 +513,7 @@ void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine,
        if (!b)
                return;
 
-       drm_printf(p, "IRQ: %s\n", enableddisabled(b->irq_armed));
+       drm_printf(p, "IRQ: %s\n", str_enabled_disabled(b->irq_armed));
        if (!list_empty(&b->signalers))
                print_signals(b, p);
 }
index e1aa78b..7447411 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2016 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_print.h>
 
 #include "gem/i915_gem_context.h"
@@ -1706,9 +1708,8 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
                u8 read, write;
 
                drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, timeslice? %s\n",
-                          yesno(test_bit(TASKLET_STATE_SCHED,
-                                         &engine->sched_engine->tasklet.state)),
-                          enableddisabled(!atomic_read(&engine->sched_engine->tasklet.count)),
+                          str_yes_no(test_bit(TASKLET_STATE_SCHED, &engine->sched_engine->tasklet.state)),
+                          str_enabled_disabled(!atomic_read(&engine->sched_engine->tasklet.count)),
                           repr_timer(&engine->execlists.preempt),
                           repr_timer(&engine->execlists.timer));
 
@@ -1969,7 +1970,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 
        drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count));
        drm_printf(m, "\tBarriers?: %s\n",
-                  yesno(!llist_empty(&engine->barrier_tasks)));
+                  str_yes_no(!llist_empty(&engine->barrier_tasks)));
        drm_printf(m, "\tLatency: %luus\n",
                   ewma__engine_latency_read(&engine->latency));
        if (intel_engine_supports_stats(engine))
@@ -2011,7 +2012,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
        drm_printf(m, "HWSP:\n");
        hexdump(m, engine->status_page.addr, PAGE_SIZE);
 
-       drm_printf(m, "Idle? %s\n", yesno(intel_engine_is_idle(engine)));
+       drm_printf(m, "Idle? %s\n", str_yes_no(intel_engine_is_idle(engine)));
 
        intel_engine_print_breadcrumbs(engine, m);
 }
index 3e0c81f..1c602d4 100644 (file)
  *
  */
 #include <linux/interrupt.h>
+#include <linux/string_helpers.h>
 
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -1335,11 +1336,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                } else if (timeslice_expired(engine, last)) {
                        ENGINE_TRACE(engine,
                                     "expired:%s last=%llx:%lld, prio=%d, hint=%d, yield?=%s\n",
-                                    yesno(timer_expired(&execlists->timer)),
+                                    str_yes_no(timer_expired(&execlists->timer)),
                                     last->fence.context, last->fence.seqno,
                                     rq_prio(last),
                                     sched_engine->queue_priority_hint,
-                                    yesno(timeslice_yield(execlists, last)));
+                                    str_yes_no(timeslice_yield(execlists, last)));
 
                        /*
                         * Consume this timeslice; ensure we start a new one.
@@ -1427,7 +1428,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                             __i915_request_is_complete(rq) ? "!" :
                             __i915_request_has_started(rq) ? "*" :
                             "",
-                            yesno(engine != ve->siblings[0]));
+                            str_yes_no(engine != ve->siblings[0]));
 
                WRITE_ONCE(ve->request, NULL);
                WRITE_ONCE(ve->base.sched_engine->queue_priority_hint, INT_MIN);
index 8850d4e..e164f30 100644 (file)
@@ -18,6 +18,7 @@
 #include "intel_gt_regs.h"
 #include "i915_drv.h"
 #include "i915_scatterlist.h"
+#include "i915_utils.h"
 #include "i915_vgpu.h"
 
 #include "intel_gtt.h"
@@ -104,7 +105,7 @@ static bool needs_idle_maps(struct drm_i915_private *i915)
         * Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
         */
-       if (!intel_vtd_active(i915))
+       if (!i915_vtd_active(i915))
                return false;
 
        if (GRAPHICS_VER(i915) == 5 && IS_MOBILE(i915))
@@ -1256,7 +1257,7 @@ int i915_ggtt_probe_hw(struct drm_i915_private *i915)
        if (ret)
                return ret;
 
-       if (intel_vtd_active(i915))
+       if (i915_vtd_active(i915))
                drm_info(&i915->drm, "VT-d active for gfx access\n");
 
        return 0;
index 76880fb..6ebda3d 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2008-2015 Intel Corporation
  */
 
+#include <linux/highmem.h>
+
 #include "i915_drv.h"
 #include "i915_reg.h"
 #include "i915_scatterlist.h"
index c0fa41e..e4ecc17 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
 #include <linux/suspend.h>
 
 #include "i915_drv.h"
@@ -157,7 +158,7 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
        enum intel_engine_id id;
        intel_wakeref_t wakeref;
 
-       GT_TRACE(gt, "force:%s", yesno(force));
+       GT_TRACE(gt, "force:%s", str_yes_no(force));
 
        /* Use a raw wakeref to avoid calling intel_display_power_get early */
        wakeref = intel_runtime_pm_get(gt->uncore->rpm);
index 3776591..437e96b 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/seq_file.h>
+#include <linux/string_helpers.h>
 
 #include "i915_drv.h"
 #include "i915_reg.h"
@@ -105,14 +106,14 @@ static int vlv_drpc(struct seq_file *m)
        rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL);
 
        seq_printf(m, "RC6 Enabled: %s\n",
-                  yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE |
+                  str_yes_no(rcctl1 & (GEN7_RC_CTL_TO_MODE |
                                        GEN6_RC_CTL_EI_MODE(1))));
        seq_printf(m, "Render Power Well: %s\n",
                   (pw_status & VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down");
        seq_printf(m, "Media Power Well: %s\n",
                   (pw_status & VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
 
-       print_rc6_res(m, "Render RC6 residency since boot:", VLV_GT_RENDER_RC6);
+       print_rc6_res(m, "Render RC6 residency since boot:", GEN6_GT_GFX_RC6);
        print_rc6_res(m, "Media RC6 residency since boot:", VLV_GT_MEDIA_RC6);
 
        return fw_domains_show(m, NULL);
@@ -140,19 +141,19 @@ static int gen6_drpc(struct seq_file *m)
                snb_pcode_read(i915, GEN6_PCODE_READ_RC6VIDS, &rc6vids, NULL);
 
        seq_printf(m, "RC1e Enabled: %s\n",
-                  yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
+                  str_yes_no(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
        seq_printf(m, "RC6 Enabled: %s\n",
-                  yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
+                  str_yes_no(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
        if (GRAPHICS_VER(i915) >= 9) {
                seq_printf(m, "Render Well Gating Enabled: %s\n",
-                          yesno(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE));
+                          str_yes_no(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE));
                seq_printf(m, "Media Well Gating Enabled: %s\n",
-                          yesno(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE));
+                          str_yes_no(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE));
        }
        seq_printf(m, "Deep RC6 Enabled: %s\n",
-                  yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE));
+                  str_yes_no(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE));
        seq_printf(m, "Deepest RC6 Enabled: %s\n",
-                  yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE));
+                  str_yes_no(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE));
        seq_puts(m, "Current RC state: ");
        switch (gt_core_status & GEN6_RCn_MASK) {
        case GEN6_RC0:
@@ -176,7 +177,7 @@ static int gen6_drpc(struct seq_file *m)
        }
 
        seq_printf(m, "Core Power Down: %s\n",
-                  yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
+                  str_yes_no(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
        if (GRAPHICS_VER(i915) >= 9) {
                seq_printf(m, "Render Power Well: %s\n",
                           (gen9_powergate_status &
@@ -216,16 +217,17 @@ static int ilk_drpc(struct seq_file *m)
        rstdbyctl = intel_uncore_read(uncore, RSTDBYCTL);
        crstandvid = intel_uncore_read16(uncore, CRSTANDVID);
 
-       seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
+       seq_printf(m, "HD boost: %s\n",
+                  str_yes_no(rgvmodectl & MEMMODE_BOOST_EN));
        seq_printf(m, "Boost freq: %d\n",
                   (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
                   MEMMODE_BOOST_FREQ_SHIFT);
        seq_printf(m, "HW control enabled: %s\n",
-                  yesno(rgvmodectl & MEMMODE_HWIDLE_EN));
+                  str_yes_no(rgvmodectl & MEMMODE_HWIDLE_EN));
        seq_printf(m, "SW control enabled: %s\n",
-                  yesno(rgvmodectl & MEMMODE_SWMODE_EN));
+                  str_yes_no(rgvmodectl & MEMMODE_SWMODE_EN));
        seq_printf(m, "Gated voltage change: %s\n",
-                  yesno(rgvmodectl & MEMMODE_RCLK_GATE));
+                  str_yes_no(rgvmodectl & MEMMODE_RCLK_GATE));
        seq_printf(m, "Starting frequency: P%d\n",
                   (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
        seq_printf(m, "Max P-state: P%d\n",
@@ -234,7 +236,7 @@ static int ilk_drpc(struct seq_file *m)
        seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
        seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
        seq_printf(m, "Render standby enabled: %s\n",
-                  yesno(!(rstdbyctl & RCX_SW_EXIT)));
+                  str_yes_no(!(rstdbyctl & RCX_SW_EXIT)));
        seq_puts(m, "Current RS state: ");
        switch (rstdbyctl & RSX_STATUS_MASK) {
        case RSX_STATUS_ON:
@@ -307,12 +309,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
 
                rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL);
                drm_printf(p, "Video Turbo Mode: %s\n",
-                          yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
+                          str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
                drm_printf(p, "HW control enabled: %s\n",
-                          yesno(rpmodectl & GEN6_RP_ENABLE));
+                          str_yes_no(rpmodectl & GEN6_RP_ENABLE));
                drm_printf(p, "SW control enabled: %s\n",
-                          yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
-                                GEN6_RP_MEDIA_SW_MODE));
+                          str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
 
                vlv_punit_get(i915);
                freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
@@ -417,12 +418,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
                pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
 
                drm_printf(p, "Video Turbo Mode: %s\n",
-                          yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
+                          str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
                drm_printf(p, "HW control enabled: %s\n",
-                          yesno(rpmodectl & GEN6_RP_ENABLE));
+                          str_yes_no(rpmodectl & GEN6_RP_ENABLE));
                drm_printf(p, "SW control enabled: %s\n",
-                          yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
-                                GEN6_RP_MEDIA_SW_MODE));
+                          str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
 
                drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
                           pm_ier, pm_imr, pm_mask);
@@ -542,7 +542,7 @@ static int llc_show(struct seq_file *m, void *data)
        intel_wakeref_t wakeref;
        int gpu_freq, ia_freq;
 
-       seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(i915)));
+       seq_printf(m, "LLC: %s\n", str_yes_no(HAS_LLC(i915)));
        seq_printf(m, "%s: %uMB\n", edram ? "eDRAM" : "eLLC",
                   i915->edram_size_mb);
 
@@ -604,10 +604,12 @@ static int rps_boost_show(struct seq_file *m, void *data)
        struct drm_i915_private *i915 = gt->i915;
        struct intel_rps *rps = &gt->rps;
 
-       seq_printf(m, "RPS enabled? %s\n", yesno(intel_rps_is_enabled(rps)));
-       seq_printf(m, "RPS active? %s\n", yesno(intel_rps_is_active(rps)));
+       seq_printf(m, "RPS enabled? %s\n",
+                  str_yes_no(intel_rps_is_enabled(rps)));
+       seq_printf(m, "RPS active? %s\n",
+                  str_yes_no(intel_rps_is_active(rps)));
        seq_printf(m, "GPU busy? %s, %llums\n",
-                  yesno(gt->awake),
+                  str_yes_no(gt->awake),
                   ktime_to_ms(intel_gt_get_awake_time(gt)));
        seq_printf(m, "Boosts outstanding? %d\n",
                   atomic_read(&rps->num_waiters));
index 19cd34f..201b507 100644 (file)
 #define   VLV_MEDIA_RC6_COUNT_EN               (1 << 1)
 #define   VLV_RENDER_RC6_COUNT_EN              (1 << 0)
 #define GEN6_GT_GFX_RC6                                _MMIO(0x138108)
-#define VLV_GT_RENDER_RC6                      _MMIO(0x138108)
 #define VLV_GT_MEDIA_RC6                       _MMIO(0x13810c)
 
 #define GEN6_GT_GFX_RC6p                       _MMIO(0x13810c)
index a5f5b2d..cc53b48 100644 (file)
 #include "gem/i915_gem_internal.h"
 #include "gem/i915_gem_lmem.h"
 #include "i915_trace.h"
+#include "i915_utils.h"
 #include "intel_gt.h"
 #include "intel_gt_regs.h"
 #include "intel_gtt.h"
 
+
+static bool intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915)
+{
+       return IS_BROXTON(i915) && i915_vtd_active(i915);
+}
+
+bool intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915)
+{
+       return IS_CHERRYVIEW(i915) || intel_ggtt_update_needs_vtd_wa(i915);
+}
+
 struct drm_i915_gem_object *alloc_pt_lmem(struct i915_address_space *vm, int sz)
 {
        struct drm_i915_gem_object *obj;
index 9d83c2d..ba70253 100644 (file)
@@ -383,6 +383,8 @@ struct i915_ppgtt {
 #define i915_is_dpt(vm) ((vm)->is_dpt)
 #define i915_is_ggtt_or_dpt(vm) (i915_is_ggtt(vm) || i915_is_dpt(vm))
 
+bool intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915);
+
 int __must_check
 i915_vm_lock_objects(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww);
 
index 6df359c..63db136 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/pm_runtime.h>
+#include <linux/string_helpers.h>
 
 #include "i915_drv.h"
 #include "i915_reg.h"
@@ -430,8 +431,8 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6)
        rc_sw_target >>= RC_SW_TARGET_STATE_SHIFT;
        drm_dbg(&i915->drm, "BIOS enabled RC states: "
                         "HW_CTRL %s HW_RC6 %s SW_TARGET_STATE %x\n",
-                        onoff(rc_ctl & GEN6_RC_CTL_HW_ENABLE),
-                        onoff(rc_ctl & GEN6_RC_CTL_RC6_ENABLE),
+                        str_on_off(rc_ctl & GEN6_RC_CTL_HW_ENABLE),
+                        str_on_off(rc_ctl & GEN6_RC_CTL_RC6_ENABLE),
                         rc_sw_target);
 
        if (!(intel_uncore_read(uncore, RC6_LOCATION) & RC6_CTX_IN_DRAM)) {
index 8271326..a6ae213 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/sched/mm.h>
 #include <linux/stop_machine.h>
+#include <linux/string_helpers.h>
 
 #include "display/intel_display.h"
 #include "display/intel_overlay.h"
@@ -137,7 +138,7 @@ void __i915_request_reset(struct i915_request *rq, bool guilty)
 {
        bool banned = false;
 
-       RQ_TRACE(rq, "guilty? %s\n", yesno(guilty));
+       RQ_TRACE(rq, "guilty? %s\n", str_yes_no(guilty));
        GEM_BUG_ON(__i915_request_is_complete(rq));
 
        rcu_read_lock(); /* protect the GEM context */
index c812410..a9c13b1 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
@@ -772,7 +774,8 @@ static void gen6_rps_set_thresholds(struct intel_rps *rps, u8 val)
 
 void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive)
 {
-       GT_TRACE(rps_to_gt(rps), "mark interactive: %s\n", yesno(interactive));
+       GT_TRACE(rps_to_gt(rps), "mark interactive: %s\n",
+                str_yes_no(interactive));
 
        mutex_lock(&rps->power.mutex);
        if (interactive) {
@@ -1279,7 +1282,8 @@ static bool chv_rps_enable(struct intel_rps *rps)
        drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0,
                      "GPLL not enabled\n");
 
-       drm_dbg(&i915->drm, "GPLL enabled? %s\n", yesno(val & GPLLENABLE));
+       drm_dbg(&i915->drm, "GPLL enabled? %s\n",
+               str_yes_no(val & GPLLENABLE));
        drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val);
 
        return rps_reset(rps);
@@ -1380,7 +1384,8 @@ static bool vlv_rps_enable(struct intel_rps *rps)
        drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0,
                      "GPLL not enabled\n");
 
-       drm_dbg(&i915->drm, "GPLL enabled? %s\n", yesno(val & GPLLENABLE));
+       drm_dbg(&i915->drm, "GPLL enabled? %s\n",
+               str_yes_no(val & GPLLENABLE));
        drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val);
 
        return rps_reset(rps);
@@ -1772,7 +1777,7 @@ static void rps_work(struct work_struct *work)
 
        GT_TRACE(gt,
                 "pm_iir:%x, client_boost:%s, last:%d, cur:%x, min:%x, max:%x\n",
-                pm_iir, yesno(client_boost),
+                pm_iir, str_yes_no(client_boost),
                 adj, new_freq, min, max);
 
        if (client_boost && new_freq < rps->boost_freq) {
index 4ac0bba..614915f 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "i915_drv.h"
 #include "intel_engine_regs.h"
 #include "intel_gt_regs.h"
@@ -711,10 +713,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
        drm_printf(p, "EU total: %u\n", sseu->eu_total);
        drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
        drm_printf(p, "has slice power gating: %s\n",
-                  yesno(sseu->has_slice_pg));
+                  str_yes_no(sseu->has_slice_pg));
        drm_printf(p, "has subslice power gating: %s\n",
-                  yesno(sseu->has_subslice_pg));
-       drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg));
+                  str_yes_no(sseu->has_subslice_pg));
+       drm_printf(p, "has EU power gating: %s\n",
+                  str_yes_no(sseu->has_eu_pg));
 }
 
 void intel_sseu_print_topology(const struct sseu_dev_info *sseu,
index 903626f..a9d5bc4 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "i915_drv.h"
 #include "intel_gt_debugfs.h"
 #include "intel_gt_regs.h"
@@ -226,16 +228,16 @@ static void i915_print_sseu_info(struct seq_file *m,
        if (!is_available_info)
                return;
 
-       seq_printf(m, "  Has Pooled EU: %s\n", yesno(has_pooled_eu));
+       seq_printf(m, "  Has Pooled EU: %s\n", str_yes_no(has_pooled_eu));
        if (has_pooled_eu)
                seq_printf(m, "  Min EU in pool: %u\n", sseu->min_eu_in_pool);
 
        seq_printf(m, "  Has Slice Power Gating: %s\n",
-                  yesno(sseu->has_slice_pg));
+                  str_yes_no(sseu->has_slice_pg));
        seq_printf(m, "  Has Subslice Power Gating: %s\n",
-                  yesno(sseu->has_subslice_pg));
+                  str_yes_no(sseu->has_subslice_pg));
        seq_printf(m, "  Has EU Power Gating: %s\n",
-                  yesno(sseu->has_eu_pg));
+                  str_yes_no(sseu->has_eu_pg));
 }
 
 /*
index 0410c40..522d019 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/prime_numbers.h>
+#include <linux/string_helpers.h>
 
 #include "intel_context.h"
 #include "intel_engine_heartbeat.h"
@@ -209,7 +210,7 @@ static int __igt_sync(struct intel_timeline *tl,
 
        if (__intel_timeline_sync_is_later(tl, ctx, p->seqno) != p->expected) {
                pr_err("%s: %s(ctx=%llu, seqno=%u) expected passed %s but failed\n",
-                      name, p->name, ctx, p->seqno, yesno(p->expected));
+                      name, p->name, ctx, p->seqno, str_yes_no(p->expected));
                return -EINVAL;
        }
 
index 2f7fc87..f01325c 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/circ_buf.h>
 #include <linux/ktime.h>
 #include <linux/time64.h>
+#include <linux/string_helpers.h>
 #include <linux/timekeeping.h>
 
 #include "i915_drv.h"
@@ -170,7 +171,7 @@ static int ct_control_enable(struct intel_guc_ct *ct, bool enable)
                                     GUC_CTB_CONTROL_ENABLE : GUC_CTB_CONTROL_DISABLE);
        if (unlikely(err))
                CT_PROBE_ERROR(ct, "Failed to control/%s CTB (%pe)\n",
-                              enabledisable(enable), ERR_PTR(err));
+                              str_enable_disable(enable), ERR_PTR(err));
 
        return err;
 }
@@ -1202,7 +1203,7 @@ void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
 void intel_guc_ct_print_info(struct intel_guc_ct *ct,
                             struct drm_printer *p)
 {
-       drm_printf(p, "CT %s\n", enableddisabled(ct->enabled));
+       drm_printf(p, "CT %s\n", str_enabled_disabled(ct->enabled));
 
        if (!ct->enabled)
                return;
index b53f61f..a24dc64 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/string_helpers.h>
 
 #include "gt/intel_gt.h"
 #include "i915_drv.h"
@@ -476,8 +477,8 @@ int intel_guc_log_create(struct intel_guc_log *log)
 
        log->level = __get_default_log_level(log);
        DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n",
-                        log->level, enableddisabled(log->level),
-                        yesno(GUC_LOG_LEVEL_IS_VERBOSE(log->level)),
+                        log->level, str_enabled_disabled(log->level),
+                        str_yes_no(GUC_LOG_LEVEL_IS_VERBOSE(log->level)),
                         GUC_LOG_LEVEL_TO_VERBOSITY(log->level));
 
        return 0;
index fc805d4..e00661f 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2021 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "intel_guc_rc.h"
 #include "gt/intel_gt.h"
 #include "i915_drv.h"
@@ -59,12 +61,12 @@ static int __guc_rc_control(struct intel_guc *guc, bool enable)
        ret = guc_action_control_gucrc(guc, enable);
        if (ret) {
                drm_err(drm, "Failed to %s GuC RC (%pe)\n",
-                       enabledisable(enable), ERR_PTR(ret));
+                       str_enable_disable(enable), ERR_PTR(ret));
                return ret;
        }
 
        drm_info(&gt->i915->drm, "GuC RC: %s\n",
-                enableddisabled(enable));
+                str_enabled_disabled(enable));
 
        return 0;
 }
index ac749ab..9f032c6 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <drm/drm_cache.h>
+#include <linux/string_helpers.h>
 
 #include "i915_drv.h"
 #include "i915_reg.h"
@@ -719,7 +720,7 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p
 
                        drm_printf(p, "\tSLPC state: %s\n", slpc_get_state_string(slpc));
                        drm_printf(p, "\tGTPERF task active: %s\n",
-                                  yesno(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED));
+                                  str_yes_no(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED));
                        drm_printf(p, "\tMax freq: %u MHz\n",
                                   slpc_decode_max_freq(slpc));
                        drm_printf(p, "\tMin freq: %u MHz\n",
index da199aa..8c9ef69 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2016-2019 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "gt/intel_gt.h"
 #include "gt/intel_reset.h"
 #include "intel_guc.h"
@@ -78,10 +80,10 @@ static void __confirm_options(struct intel_uc *uc)
        drm_dbg(&i915->drm,
                "enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
                i915->params.enable_guc,
-               yesno(intel_uc_wants_guc(uc)),
-               yesno(intel_uc_wants_guc_submission(uc)),
-               yesno(intel_uc_wants_huc(uc)),
-               yesno(intel_uc_wants_guc_slpc(uc)));
+               str_yes_no(intel_uc_wants_guc(uc)),
+               str_yes_no(intel_uc_wants_guc_submission(uc)),
+               str_yes_no(intel_uc_wants_huc(uc)),
+               str_yes_no(intel_uc_wants_guc_slpc(uc)));
 
        if (i915->params.enable_guc == 0) {
                GEM_BUG_ON(intel_uc_wants_guc(uc));
@@ -522,9 +524,9 @@ static int __uc_init_hw(struct intel_uc *uc)
        }
 
        drm_info(&i915->drm, "GuC submission %s\n",
-                enableddisabled(intel_uc_uses_guc_submission(uc)));
+                str_enabled_disabled(intel_uc_uses_guc_submission(uc)));
        drm_info(&i915->drm, "GuC SLPC %s\n",
-                enableddisabled(intel_uc_uses_guc_slpc(uc)));
+                str_enabled_disabled(intel_uc_uses_guc_slpc(uc)));
 
        return 0;
 
index c2f7924..284d6fb 100644 (file)
@@ -4,6 +4,8 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/string_helpers.h>
+
 #include <drm/drm_print.h>
 
 #include "gt/intel_gt_debugfs.h"
@@ -18,17 +20,17 @@ static int uc_usage_show(struct seq_file *m, void *data)
        struct drm_printer p = drm_seq_file_printer(m);
 
        drm_printf(&p, "[guc] supported:%s wanted:%s used:%s\n",
-                  yesno(intel_uc_supports_guc(uc)),
-                  yesno(intel_uc_wants_guc(uc)),
-                  yesno(intel_uc_uses_guc(uc)));
+                  str_yes_no(intel_uc_supports_guc(uc)),
+                  str_yes_no(intel_uc_wants_guc(uc)),
+                  str_yes_no(intel_uc_uses_guc(uc)));
        drm_printf(&p, "[huc] supported:%s wanted:%s used:%s\n",
-                  yesno(intel_uc_supports_huc(uc)),
-                  yesno(intel_uc_wants_huc(uc)),
-                  yesno(intel_uc_uses_huc(uc)));
+                  str_yes_no(intel_uc_supports_huc(uc)),
+                  str_yes_no(intel_uc_wants_huc(uc)),
+                  str_yes_no(intel_uc_uses_huc(uc)));
        drm_printf(&p, "[submission] supported:%s wanted:%s used:%s\n",
-                  yesno(intel_uc_supports_guc_submission(uc)),
-                  yesno(intel_uc_wants_guc_submission(uc)),
-                  yesno(intel_uc_uses_guc_submission(uc)));
+                  str_yes_no(intel_uc_supports_guc_submission(uc)),
+                  str_yes_no(intel_uc_wants_guc_submission(uc)),
+                  str_yes_no(intel_uc_uses_guc_submission(uc)));
 
        return 0;
 }
index c881130..541f180 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/firmware.h>
+#include <linux/highmem.h>
 
 #include <drm/drm_cache.h>
 #include <drm/drm_print.h>
index 520a7e1..57b0f49 100644 (file)
@@ -42,6 +42,7 @@
 #include "i915_pvinfo.h"
 #include "intel_mchbar_regs.h"
 #include "display/intel_display_types.h"
+#include "display/intel_dmc_regs.h"
 #include "display/intel_fbc.h"
 #include "display/vlv_dsi_pll_regs.h"
 #include "gt/intel_gt_regs.h"
@@ -576,14 +577,19 @@ static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port)
        }
 
        clock.m1 = 2;
-       clock.m2 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 0)) & PORT_PLL_M2_MASK) << 22;
+       clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK,
+                                vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 0))) << 22;
        if (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 3)) & PORT_PLL_M2_FRAC_ENABLE)
-               clock.m2 |= vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 2)) & PORT_PLL_M2_FRAC_MASK;
-       clock.n = (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 1)) & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
-       clock.p1 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
-       clock.p2 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
+               clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK,
+                                         vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 2)));
+       clock.n = REG_FIELD_GET(PORT_PLL_N_MASK,
+                               vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 1)));
+       clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK,
+                                vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)));
+       clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK,
+                                vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)));
        clock.m = clock.m1 * clock.m2;
-       clock.p = clock.p1 * clock.p2;
+       clock.p = clock.p1 * clock.p2 * 5;
 
        if (clock.n == 0 || clock.p == 0) {
                gvt_dbg_dpy("vgpu-%d PORT_%c PLL has invalid divider\n", vgpu->id, port_name(port));
@@ -593,7 +599,7 @@ static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port)
        clock.vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock.m), clock.n << 22);
        clock.dot = DIV_ROUND_CLOSEST(clock.vco, clock.p);
 
-       dp_br = clock.dot / 5;
+       dp_br = clock.dot;
 
 out:
        return dp_br;
index 5f6e416..f93e612 100644 (file)
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/highmem.h>
+
 #include <drm/drm_cache.h>
 
 #include "gt/intel_engine.h"
index 946bbe5..0223939 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <linux/sched/mm.h>
 #include <linux/sort.h>
+#include <linux/string_helpers.h>
 
 #include <drm/drm_debugfs.h>
 
@@ -47,6 +48,7 @@
 
 #include "i915_debugfs.h"
 #include "i915_debugfs_params.h"
+#include "i915_driver.h"
 #include "i915_irq.h"
 #include "i915_scheduler.h"
 #include "intel_mchbar_regs.h"
@@ -455,9 +457,11 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_rps *rps = &to_gt(dev_priv)->rps;
 
-       seq_printf(m, "RPS enabled? %s\n", yesno(intel_rps_is_enabled(rps)));
-       seq_printf(m, "RPS active? %s\n", yesno(intel_rps_is_active(rps)));
-       seq_printf(m, "GPU busy? %s\n", yesno(to_gt(dev_priv)->awake));
+       seq_printf(m, "RPS enabled? %s\n",
+                  str_yes_no(intel_rps_is_enabled(rps)));
+       seq_printf(m, "RPS active? %s\n",
+                  str_yes_no(intel_rps_is_active(rps)));
+       seq_printf(m, "GPU busy? %s\n", str_yes_no(to_gt(dev_priv)->awake));
        seq_printf(m, "Boosts outstanding? %d\n",
                   atomic_read(&rps->num_waiters));
        seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive));
@@ -488,11 +492,11 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
                seq_puts(m, "Runtime power management not supported\n");
 
        seq_printf(m, "Runtime power status: %s\n",
-                  enableddisabled(!dev_priv->power_domains.init_wakeref));
+                  str_enabled_disabled(!dev_priv->power_domains.init_wakeref));
 
-       seq_printf(m, "GPU idle: %s\n", yesno(!to_gt(dev_priv)->awake));
+       seq_printf(m, "GPU idle: %s\n", str_yes_no(!to_gt(dev_priv)->awake));
        seq_printf(m, "IRQs disabled: %s\n",
-                  yesno(!intel_irqs_enabled(dev_priv)));
+                  str_yes_no(!intel_irqs_enabled(dev_priv)));
 #ifdef CONFIG_PM
        seq_printf(m, "Usage count: %d\n",
                   atomic_read(&dev_priv->drm.dev->power.usage_count));
@@ -522,7 +526,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
        wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 
        seq_printf(m, "GT awake? %s [%d], %llums\n",
-                  yesno(to_gt(i915)->awake),
+                  str_yes_no(to_gt(i915)->awake),
                   atomic_read(&to_gt(i915)->wakeref.count),
                   ktime_to_ms(intel_gt_get_awake_time(to_gt(i915))));
        seq_printf(m, "CS timestamp frequency: %u Hz, %d ns\n",
index 62b3f33..09de45d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pnp.h>
 #include <linux/slab.h>
+#include <linux/string_helpers.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/vt.h>
 
@@ -87,6 +88,7 @@
 #include "i915_suspend.h"
 #include "i915_switcheroo.h"
 #include "i915_sysfs.h"
+#include "i915_utils.h"
 #include "i915_vgpu.h"
 #include "intel_dram.h"
 #include "intel_gvt.h"
@@ -752,7 +754,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 void
 i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p)
 {
-       drm_printf(p, "iommu: %s\n", enableddisabled(intel_vtd_active(i915)));
+       drm_printf(p, "iommu: %s\n",
+                  str_enabled_disabled(i915_vtd_active(i915)));
 }
 
 static void i915_welcome_messages(struct drm_i915_private *dev_priv)
index 9d11de6..44ec543 100644 (file)
@@ -11,6 +11,7 @@
 struct pci_dev;
 struct pci_device_id;
 struct drm_i915_private;
+struct drm_printer;
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
@@ -26,4 +27,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915);
 int i915_driver_resume_switcheroo(struct drm_i915_private *i915);
 int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state);
 
+void
+i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p);
+
 #endif /* __I915_DRIVER_H__ */
index fa14da8..ce2cd64 100644 (file)
 
 #include <uapi/drm/i915_drm.h>
 
-#include <asm/hypervisor.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/intel-iommu.h>
 #include <linux/pm_qos.h>
 
 #include <drm/drm_connector.h>
@@ -99,6 +94,7 @@ struct intel_dpll_funcs;
 struct intel_encoder;
 struct intel_fbdev;
 struct intel_fdi_funcs;
+struct intel_gmbus;
 struct intel_hotplug_funcs;
 struct intel_initial_plane_config;
 struct intel_limit;
@@ -197,30 +193,10 @@ struct drm_i915_display_funcs {
 
 #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */
 
-/*
- * HIGH_RR is the highest eDP panel refresh rate read from EDID
- * LOW_RR is the lowest eDP panel refresh rate found from EDID
- * parsing for same resolution.
- */
-enum drrs_refresh_rate_type {
-       DRRS_HIGH_RR,
-       DRRS_LOW_RR,
-       DRRS_MAX_RR, /* RR count */
-};
-
-enum drrs_support_type {
-       DRRS_NOT_SUPPORTED = 0,
-       STATIC_DRRS_SUPPORT = 1,
-       SEAMLESS_DRRS_SUPPORT = 2
-};
-
-struct i915_drrs {
-       struct mutex mutex;
-       struct delayed_work work;
-       struct intel_dp *dp;
-       unsigned busy_frontbuffer_bits;
-       enum drrs_refresh_rate_type refresh_rate_type;
-       enum drrs_support_type type;
+enum drrs_type {
+       DRRS_TYPE_NONE,
+       DRRS_TYPE_STATIC,
+       DRRS_TYPE_SEAMLESS,
 };
 
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
@@ -231,16 +207,6 @@ struct i915_drrs {
 #define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7)
 #define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8)
 
-struct intel_gmbus {
-       struct i2c_adapter adapter;
-#define GMBUS_FORCE_BIT_RETRY (1U << 31)
-       u32 force_bit;
-       u32 reg0;
-       i915_reg_t gpio_reg;
-       struct i2c_algo_bit_data bit_algo;
-       struct drm_i915_private *dev_priv;
-};
-
 struct i915_suspend_saved_registers {
        u32 saveDSPARB;
        u32 saveSWF0[16];
@@ -360,17 +326,18 @@ struct intel_vbt_data {
        bool override_afc_startup;
        u8 override_afc_startup_val;
 
-       enum drrs_support_type drrs_type;
+       enum drrs_type drrs_type;
 
        struct {
                int rate;
                int lanes;
                int preemphasis;
                int vswing;
-               bool low_vswing;
-               bool initialized;
                int bpp;
                struct edp_power_seq pps;
+               u8 drrs_msa_timing_delay;
+               bool low_vswing;
+               bool initialized;
                bool hobl;
        } edp;
 
@@ -412,6 +379,7 @@ struct intel_vbt_data {
        int crt_ddc_pin;
 
        struct list_head display_devices;
+       struct list_head bdb_blocks;
 
        struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
        struct sdvo_device_mapping sdvo_mappings[2];
@@ -510,7 +478,7 @@ struct drm_i915_private {
 
        struct intel_dmc dmc;
 
-       struct intel_gmbus gmbus[GMBUS_NUM_PINS];
+       struct intel_gmbus *gmbus[GMBUS_NUM_PINS];
 
        /** gmbus_mutex protects against concurrent usage of the single hw gmbus
         * controller on different i2c buses. */
@@ -553,7 +521,6 @@ struct drm_i915_private {
 
        struct i915_hotplug hotplug;
        struct intel_fbc *fbc[I915_MAX_FBCS];
-       struct i915_drrs drrs;
        struct intel_opregion opregion;
        struct intel_vbt_data vbt;
 
@@ -666,12 +633,6 @@ struct drm_i915_private {
 
        struct list_head global_obj_list;
 
-       /*
-        * For reading active_pipes holding any crtc lock is
-        * sufficient, for writing must hold all of them.
-        */
-       u8 active_pipes;
-
        struct i915_frontbuffer_tracking fb_tracking;
 
        struct intel_atomic_helper {
@@ -701,8 +662,6 @@ struct drm_i915_private {
 
        struct i915_gpu_error gpu_error;
 
-       struct drm_i915_gem_object *vlv_pctx;
-
        /* list of fbdev register on this device */
        struct intel_fbdev *fbdev;
        struct work_struct fbdev_suspend_work;
@@ -723,7 +682,6 @@ struct drm_i915_private {
        u32 bxt_phy_grc;
 
        u32 suspend_count;
-       bool power_domains_suspended;
        struct i915_suspend_saved_registers regfile;
        struct vlv_s0ix_state *vlv_s0ix_state;
 
@@ -825,8 +783,6 @@ struct drm_i915_private {
                struct file *mmap_singleton;
        } gem;
 
-       u8 framestart_delay;
-
        /* Window2 specifies time required to program DSB (Window2) in number of scan lines */
        u8 window2_delay;
 
@@ -837,8 +793,16 @@ struct drm_i915_private {
 
        bool irq_enabled;
 
-       /* perform PHY state sanity checks? */
-       bool chv_phy_assert[2];
+       union {
+               /* perform PHY state sanity checks? */
+               bool chv_phy_assert[2];
+
+               /*
+                * DG2: Mask of PHYs that were not calibrated by the firmware
+                * and should not be used.
+                */
+               u8 snps_phy_failed_calibration;
+       };
 
        bool ipc_enabled;
 
@@ -1251,6 +1215,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
 #define CMDPARSER_USES_GGTT(dev_priv) (GRAPHICS_VER(dev_priv) == 7)
 
 #define HAS_LLC(dev_priv)      (INTEL_INFO(dev_priv)->has_llc)
+#define HAS_4TILE(dev_priv)    (INTEL_INFO(dev_priv)->has_4tile)
 #define HAS_SNOOP(dev_priv)    (INTEL_INFO(dev_priv)->has_snoop)
 #define HAS_EDRAM(dev_priv)    ((dev_priv)->edram_size_mb)
 #define HAS_SECURE_BATCHES(dev_priv) (GRAPHICS_VER(dev_priv) < 6)
@@ -1398,42 +1363,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
 #define HAS_GUC_DEPRIVILEGE(dev_priv) \
        (INTEL_INFO(dev_priv)->has_guc_deprivilege)
 
-static inline bool run_as_guest(void)
-{
-       return !hypervisor_is_type(X86_HYPER_NATIVE);
-}
-
 #define HAS_D12_PLANE_MINIMIZATION(dev_priv) (IS_ROCKETLAKE(dev_priv) || \
                                              IS_ALDERLAKE_S(dev_priv))
 
-static inline bool intel_vtd_active(struct drm_i915_private *i915)
-{
-       if (device_iommu_mapped(i915->drm.dev))
-               return true;
-
-       /* Running as a guest, we assume the host is enforcing VT'd */
-       return run_as_guest();
-}
-
-void
-i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p);
-
-static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
-{
-       return DISPLAY_VER(dev_priv) >= 6 && intel_vtd_active(dev_priv);
-}
-
-static inline bool
-intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915)
-{
-       return IS_BROXTON(i915) && intel_vtd_active(i915);
-}
-
-static inline bool
-intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915)
-{
-       return IS_CHERRYVIEW(i915) || intel_ggtt_update_needs_vtd_wa(i915);
-}
+#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915))
 
 /* i915_gem.c */
 void i915_gem_init_early(struct drm_i915_private *dev_priv);
@@ -1508,15 +1441,6 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv);
 
 int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file);
 
-/* i915_gem_tiling.c */
-static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
-{
-       struct drm_i915_private *i915 = to_i915(obj->base.dev);
-
-       return to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
-               i915_gem_object_is_tiled(obj);
-}
-
 /* intel_device_info.c */
 static inline struct intel_device_info *
 mkwrite_device_info(struct drm_i915_private *dev_priv)
index 1d04255..d0e7ee7 100644 (file)
  */
 
 #include <linux/ascii85.h>
+#include <linux/highmem.h>
 #include <linux/nmi.h>
 #include <linux/pagevec.h>
 #include <linux/scatterlist.h>
+#include <linux/string_helpers.h>
 #include <linux/utsname.h>
 #include <linux/zlib.h>
 
@@ -52,6 +54,7 @@
 #include "i915_gpu_error.h"
 #include "i915_memcpy.h"
 #include "i915_scatterlist.h"
+#include "i915_utils.h"
 
 #define ALLOW_FAIL (__GFP_KSWAPD_RECLAIM | __GFP_RETRY_MAYFAIL | __GFP_NOWARN)
 #define ATOMIC_MAYFAIL (GFP_ATOMIC | __GFP_NOWARN)
@@ -719,7 +722,7 @@ static void err_print_gt(struct drm_i915_error_state_buf *m,
        const struct intel_engine_coredump *ee;
        int i;
 
-       err_printf(m, "GT awake: %s\n", yesno(gt->awake));
+       err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake));
        err_printf(m, "EIR: 0x%08x\n", gt->eir);
        err_printf(m, "IER: 0x%08x\n", gt->ier);
        for (i = 0; i < gt->ngtier; i++)
@@ -823,18 +826,10 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
 
        err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
 
-       if (HAS_DMC(m->i915)) {
-               struct intel_dmc *dmc = &m->i915->dmc;
+       intel_dmc_print_error_state(m, m->i915);
 
-               err_printf(m, "DMC loaded: %s\n",
-                          yesno(intel_dmc_has_payload(m->i915) != 0));
-               err_printf(m, "DMC fw version: %d.%d\n",
-                          DMC_VERSION_MAJOR(dmc->version),
-                          DMC_VERSION_MINOR(dmc->version));
-       }
-
-       err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock));
-       err_printf(m, "PM suspended: %s\n", yesno(error->suspended));
+       err_printf(m, "RPM wakelock: %s\n", str_yes_no(error->wakelock));
+       err_printf(m, "PM suspended: %s\n", str_yes_no(error->suspended));
 
        if (error->gt)
                err_print_gt(m, error->gt);
@@ -1812,7 +1807,7 @@ static void capture_gen(struct i915_gpu_coredump *error)
        error->wakelock = atomic_read(&i915->runtime_pm.wakeref_count);
        error->suspended = i915->runtime_pm.suspended;
 
-       error->iommu = intel_vtd_active(i915);
+       error->iommu = i915_vtd_active(i915);
        error->reset_count = i915_reset_count(&i915->gpu_error);
        error->suspend_count = i915->suspend_count;
 
index 903d838..88ce3a0 100644 (file)
@@ -281,6 +281,12 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err);
 
 #else
 
+__printf(2, 3)
+static inline void
+i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
+{
+}
+
 static inline void
 i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask)
 {
index eea355c..5ad071e 100644 (file)
@@ -22,6 +22,8 @@
  * IN THE SOFTWARE.
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_print.h>
 
 #include "i915_params.h"
@@ -94,7 +96,7 @@ i915_param_named_unsafe(enable_hangcheck, bool, 0400,
 
 i915_param_named_unsafe(enable_psr, int, 0400,
        "Enable PSR "
-       "(0=disabled, 1=enabled) "
+       "(0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) "
        "Default: -1 (use per-chip default)");
 
 i915_param_named(psr_safest_params, bool, 0400,
@@ -206,7 +208,8 @@ static __always_inline void _print_param(struct drm_printer *p,
                                         const void *x)
 {
        if (!__builtin_strcmp(type, "bool"))
-               drm_printf(p, "i915.%s=%s\n", name, yesno(*(const bool *)x));
+               drm_printf(p, "i915.%s=%s\n", name,
+                          str_yes_no(*(const bool *)x));
        else if (!__builtin_strcmp(type, "int"))
                drm_printf(p, "i915.%s=%d\n", name, *(const int *)x);
        else if (!__builtin_strcmp(type, "unsigned int"))
index c32c0c6..9e07792 100644 (file)
@@ -1040,25 +1040,36 @@ static const struct intel_device_info xehpsdv_info = {
        .require_force_probe = 1,
 };
 
+#define DG2_FEATURES \
+       XE_HP_FEATURES, \
+       XE_HPM_FEATURES, \
+       DGFX_FEATURES, \
+       .graphics.rel = 55, \
+       .media.rel = 55, \
+       PLATFORM(INTEL_DG2), \
+       .has_4tile = 1, \
+       .has_64k_pages = 1, \
+       .has_guc_deprivilege = 1, \
+       .needs_compact_pt = 1, \
+       .platform_engine_mask = \
+               BIT(RCS0) | BIT(BCS0) | \
+               BIT(VECS0) | BIT(VECS1) | \
+               BIT(VCS0) | BIT(VCS2)
+
 __maybe_unused
 static const struct intel_device_info dg2_info = {
-       XE_HP_FEATURES,
-       XE_HPM_FEATURES,
+       DG2_FEATURES,
        XE_LPD_FEATURES,
-       DGFX_FEATURES,
-       .graphics.rel = 55,
-       .media.rel = 55,
-       PLATFORM(INTEL_DG2),
-       .has_guc_deprivilege = 1,
-       .has_64k_pages = 1,
-       .needs_compact_pt = 1,
-       .platform_engine_mask =
-               BIT(RCS0) | BIT(BCS0) |
-               BIT(VECS0) | BIT(VECS1) |
-               BIT(VCS0) | BIT(VCS2),
-       .require_force_probe = 1,
        .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
                               BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
+       .require_force_probe = 1,
+};
+
+__maybe_unused
+static const struct intel_device_info ats_m_info = {
+       DG2_FEATURES,
+       .display = { 0 },
+       .require_force_probe = 1,
 };
 
 #undef PLATFORM
index cfc2104..3e3b095 100644 (file)
@@ -148,10 +148,7 @@ static u64 __get_rc6(struct intel_gt *gt)
        struct drm_i915_private *i915 = gt->i915;
        u64 val;
 
-       val = intel_rc6_residency_ns(&gt->rc6,
-                                    IS_VALLEYVIEW(i915) ?
-                                    VLV_GT_RENDER_RC6 :
-                                    GEN6_GT_GFX_RC6);
+       val = intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6);
 
        if (HAS_RC6p(i915))
                val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6p);
index 3c87d77..51f46fe 100644 (file)
 #define _PORT_PLL_A                    0x46074
 #define _PORT_PLL_B                    0x46078
 #define _PORT_PLL_C                    0x4607c
-#define   PORT_PLL_ENABLE              (1 << 31)
-#define   PORT_PLL_LOCK                        (1 << 30)
-#define   PORT_PLL_REF_SEL             (1 << 27)
-#define   PORT_PLL_POWER_ENABLE                (1 << 26)
-#define   PORT_PLL_POWER_STATE         (1 << 25)
+#define   PORT_PLL_ENABLE              REG_BIT(31)
+#define   PORT_PLL_LOCK                        REG_BIT(30)
+#define   PORT_PLL_REF_SEL             REG_BIT(27)
+#define   PORT_PLL_POWER_ENABLE                REG_BIT(26)
+#define   PORT_PLL_POWER_STATE         REG_BIT(25)
 #define BXT_PORT_PLL_ENABLE(port)      _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B)
 
 #define _PORT_PLL_EBB_0_A              0x162034
 #define _PORT_PLL_EBB_0_B              0x6C034
 #define _PORT_PLL_EBB_0_C              0x6C340
-#define   PORT_PLL_P1_SHIFT            13
-#define   PORT_PLL_P1_MASK             (0x07 << PORT_PLL_P1_SHIFT)
-#define   PORT_PLL_P1(x)               ((x)  << PORT_PLL_P1_SHIFT)
-#define   PORT_PLL_P2_SHIFT            8
-#define   PORT_PLL_P2_MASK             (0x1f << PORT_PLL_P2_SHIFT)
-#define   PORT_PLL_P2(x)               ((x)  << PORT_PLL_P2_SHIFT)
+#define   PORT_PLL_P1_MASK             REG_GENMASK(15, 13)
+#define   PORT_PLL_P1(p1)              REG_FIELD_PREP(PORT_PLL_P1_MASK, (p1))
+#define   PORT_PLL_P2_MASK             REG_GENMASK(12, 8)
+#define   PORT_PLL_P2(p2)              REG_FIELD_PREP(PORT_PLL_P2_MASK, (p2))
 #define BXT_PORT_PLL_EBB_0(phy, ch)    _MMIO_BXT_PHY_CH(phy, ch, \
                                                         _PORT_PLL_EBB_0_B, \
                                                         _PORT_PLL_EBB_0_C)
 #define _PORT_PLL_EBB_4_A              0x162038
 #define _PORT_PLL_EBB_4_B              0x6C038
 #define _PORT_PLL_EBB_4_C              0x6C344
-#define   PORT_PLL_10BIT_CLK_ENABLE    (1 << 13)
-#define   PORT_PLL_RECALIBRATE         (1 << 14)
+#define   PORT_PLL_RECALIBRATE         REG_BIT(14)
+#define   PORT_PLL_10BIT_CLK_ENABLE    REG_BIT(13)
 #define BXT_PORT_PLL_EBB_4(phy, ch)    _MMIO_BXT_PHY_CH(phy, ch, \
                                                         _PORT_PLL_EBB_4_B, \
                                                         _PORT_PLL_EBB_4_C)
 #define _PORT_PLL_0_B                  0x6C100
 #define _PORT_PLL_0_C                  0x6C380
 /* PORT_PLL_0_A */
-#define   PORT_PLL_M2_MASK             0xFF
+#define   PORT_PLL_M2_INT_MASK         REG_GENMASK(7, 0)
+#define   PORT_PLL_M2_INT(m2_int)      REG_FIELD_PREP(PORT_PLL_M2_INT_MASK, (m2_int))
 /* PORT_PLL_1_A */
-#define   PORT_PLL_N_SHIFT             8
-#define   PORT_PLL_N_MASK              (0x0F << PORT_PLL_N_SHIFT)
-#define   PORT_PLL_N(x)                        ((x) << PORT_PLL_N_SHIFT)
+#define   PORT_PLL_N_MASK              REG_GENMASK(11, 8)
+#define   PORT_PLL_N(n)                        REG_FIELD_PREP(PORT_PLL_N_MASK, (n))
 /* PORT_PLL_2_A */
-#define   PORT_PLL_M2_FRAC_MASK                0x3FFFFF
+#define   PORT_PLL_M2_FRAC_MASK                REG_GENMASK(21, 0)
+#define   PORT_PLL_M2_FRAC(m2_frac)    REG_FIELD_PREP(PORT_PLL_M2_FRAC_MASK, (m2_frac))
 /* PORT_PLL_3_A */
-#define   PORT_PLL_M2_FRAC_ENABLE      (1 << 16)
+#define   PORT_PLL_M2_FRAC_ENABLE      REG_BIT(16)
 /* PORT_PLL_6_A */
-#define   PORT_PLL_PROP_COEFF_MASK     0xF
-#define   PORT_PLL_INT_COEFF_MASK      (0x1F << 8)
-#define   PORT_PLL_INT_COEFF(x)                ((x)  << 8)
-#define   PORT_PLL_GAIN_CTL_MASK       (0x07 << 16)
-#define   PORT_PLL_GAIN_CTL(x)         ((x)  << 16)
+#define   PORT_PLL_GAIN_CTL_MASK       REG_GENMASK(18, 16)
+#define   PORT_PLL_GAIN_CTL(x)         REG_FIELD_PREP(PORT_PLL_GAIN_CTL_MASK, (x))
+#define   PORT_PLL_INT_COEFF_MASK      REG_GENMASK(12, 8)
+#define   PORT_PLL_INT_COEFF(x)                REG_FIELD_PREP(PORT_PLL_INT_COEFF_MASK, (x))
+#define   PORT_PLL_PROP_COEFF_MASK     REG_GENMASK(3, 0)
+#define   PORT_PLL_PROP_COEFF(x)       REG_FIELD_PREP(PORT_PLL_PROP_COEFF_MASK, (x))
 /* PORT_PLL_8_A */
-#define   PORT_PLL_TARGET_CNT_MASK     0x3FF
+#define   PORT_PLL_TARGET_CNT_MASK     REG_GENMASK(9, 0)
+#define   PORT_PLL_TARGET_CNT(x)       REG_FIELD_PREP(PORT_PLL_TARGET_CNT_MASK, (x))
 /* PORT_PLL_9_A */
-#define  PORT_PLL_LOCK_THRESHOLD_SHIFT 1
-#define  PORT_PLL_LOCK_THRESHOLD_MASK  (0x7 << PORT_PLL_LOCK_THRESHOLD_SHIFT)
+#define  PORT_PLL_LOCK_THRESHOLD_MASK  REG_GENMASK(3, 1)
+#define  PORT_PLL_LOCK_THRESHOLD(x)    REG_FIELD_PREP(PORT_PLL_LOCK_THRESHOLD_MASK, (x))
 /* PORT_PLL_10_A */
-#define  PORT_PLL_DCO_AMP_OVR_EN_H     (1 << 27)
-#define  PORT_PLL_DCO_AMP_DEFAULT      15
-#define  PORT_PLL_DCO_AMP_MASK         0x3c00
-#define  PORT_PLL_DCO_AMP(x)           ((x) << 10)
+#define  PORT_PLL_DCO_AMP_OVR_EN_H     REG_BIT(27)
+#define  PORT_PLL_DCO_AMP_MASK         REG_GENMASK(13, 10)
+#define  PORT_PLL_DCO_AMP(x)           REG_FIELD_PREP(PORT_PLL_DCO_AMP_MASK, (x))
 #define _PORT_PLL_BASE(phy, ch)                _BXT_PHY_CH(phy, ch, \
                                                    _PORT_PLL_0_B, \
                                                    _PORT_PLL_0_C)
 #define MBUS_ABOX_BT_CREDIT_POOL1_MASK (0x1F << 0)
 #define MBUS_ABOX_BT_CREDIT_POOL1(x)   ((x) << 0)
 
-#define _PIPEA_MBUS_DBOX_CTL           0x7003C
-#define _PIPEB_MBUS_DBOX_CTL           0x7103C
-#define PIPE_MBUS_DBOX_CTL(pipe)       _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \
-                                                  _PIPEB_MBUS_DBOX_CTL)
-#define MBUS_DBOX_BW_CREDIT_MASK       (3 << 14)
-#define MBUS_DBOX_BW_CREDIT(x)         ((x) << 14)
-#define MBUS_DBOX_B_CREDIT_MASK                (0x1F << 8)
-#define MBUS_DBOX_B_CREDIT(x)          ((x) << 8)
-#define MBUS_DBOX_A_CREDIT_MASK                (0xF << 0)
-#define MBUS_DBOX_A_CREDIT(x)          ((x) << 0)
+#define _PIPEA_MBUS_DBOX_CTL                   0x7003C
+#define _PIPEB_MBUS_DBOX_CTL                   0x7103C
+#define PIPE_MBUS_DBOX_CTL(pipe)               _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \
+                                                          _PIPEB_MBUS_DBOX_CTL)
+#define MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK    REG_GENMASK(24, 20) /* tgl+ */
+#define MBUS_DBOX_B2B_TRANSACTIONS_MAX(x)      REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK, x)
+#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK  REG_GENMASK(19, 17) /* tgl+ */
+#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY(x)    REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK, x)
+#define MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN REG_BIT(16) /* tgl+ */
+#define MBUS_DBOX_BW_CREDIT_MASK               REG_GENMASK(15, 14)
+#define MBUS_DBOX_BW_CREDIT(x)                 REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, x)
+#define MBUS_DBOX_B_CREDIT_MASK                        REG_GENMASK(12, 8)
+#define MBUS_DBOX_B_CREDIT(x)                  REG_FIELD_PREP(MBUS_DBOX_B_CREDIT_MASK, x)
+#define MBUS_DBOX_A_CREDIT_MASK                        REG_GENMASK(3, 0)
+#define MBUS_DBOX_A_CREDIT(x)                  REG_FIELD_PREP(MBUS_DBOX_A_CREDIT_MASK, x)
 
 #define MBUS_UBOX_CTL                  _MMIO(0x4503C)
 #define MBUS_BBOX_CTL_S1               _MMIO(0x45040)
 #define   PIPECONF_INTERLACE_IF_ID_ILK         REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 3)
 #define   PIPECONF_INTERLACE_IF_ID_DBL_ILK     REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 4) /* ilk/snb only */
 #define   PIPECONF_INTERLACE_PF_ID_DBL_ILK     REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 5) /* ilk/snb only */
-#define   PIPECONF_EDP_RR_MODE_SWITCH          REG_BIT(20)
+#define   PIPECONF_REFRESH_RATE_ALT_ILK                REG_BIT(20)
+#define   PIPECONF_MSA_TIMING_DELAY_MASK       REG_GENMASK(19, 18) /* ilk/snb/ivb */
+#define   PIPECONF_MSA_TIMING_DELAY(x)         REG_FIELD_PREP(PIPECONF_MSA_TIMING_DELAY_MASK, (x))
 #define   PIPECONF_CXSR_DOWNCLOCK              REG_BIT(16)
-#define   PIPECONF_EDP_RR_MODE_SWITCH_VLV      REG_BIT(14)
+#define   PIPECONF_REFRESH_RATE_ALT_VLV                REG_BIT(14)
 #define   PIPECONF_COLOR_RANGE_SELECT          REG_BIT(13)
 #define   PIPECONF_OUTPUT_COLORSPACE_MASK      REG_GENMASK(12, 11) /* ilk-ivb */
 #define   PIPECONF_OUTPUT_COLORSPACE_RGB       REG_FIELD_PREP(PIPECONF_OUTPUT_COLORSPACE_MASK, 0) /* ilk-ivb */
 #define   PLANE_CTL_TILED_X                    REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 1)
 #define   PLANE_CTL_TILED_Y                    REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 4)
 #define   PLANE_CTL_TILED_YF                   REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5)
+#define   PLANE_CTL_TILED_4                     REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5)
 #define   PLANE_CTL_ASYNC_FLIP                 REG_BIT(9)
 #define   PLANE_CTL_FLIP_HORIZONTAL            REG_BIT(8)
 #define   PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE REG_BIT(4) /* TGL+ */
 #define  GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */
 #define  GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */
 
-/* DMC */
-#define DMC_PROGRAM(addr, i)   _MMIO((addr) + (i) * 4)
-#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
-#define DMC_HTP_ADDR_SKL       0x00500034
-#define DMC_SSP_BASE           _MMIO(0x8F074)
-#define DMC_HTP_SKL            _MMIO(0x8F004)
-#define DMC_LAST_WRITE         _MMIO(0x8F034)
-#define DMC_LAST_WRITE_VALUE   0xc003b400
-/* MMIO address range for DMC program (0x80000 - 0x82FFF) */
-#define DMC_MMIO_START_RANGE   0x80000
-#define DMC_MMIO_END_RANGE     0x8FFFF
-#define SKL_DMC_DC3_DC5_COUNT  _MMIO(0x80030)
-#define SKL_DMC_DC5_DC6_COUNT  _MMIO(0x8002C)
-#define BXT_DMC_DC3_DC5_COUNT  _MMIO(0x80038)
-#define TGL_DMC_DEBUG_DC5_COUNT        _MMIO(0x101084)
-#define TGL_DMC_DEBUG_DC6_COUNT        _MMIO(0x101088)
-#define DG1_DMC_DEBUG_DC5_COUNT        _MMIO(0x134154)
-
-#define TGL_DMC_DEBUG3         _MMIO(0x101090)
-#define DG1_DMC_DEBUG3         _MMIO(0x13415c)
-
 /* Display Internal Timeout Register */
 #define RM_TIMEOUT             _MMIO(0x42060)
 #define  MMIO_TIMEOUT_US(us)   ((us) << 0)
 #define   ICL_DELAY_PMRSP                      REG_BIT(22)
 #define   DISABLE_FLR_SRC                      REG_BIT(15)
 #define   MASK_WAKEMEM                         REG_BIT(13)
+#define   DDI_CLOCK_REG_ACCESS                 REG_BIT(7)
 
 #define GEN11_CHICKEN_DCPR_2                   _MMIO(0x46434)
 #define   DCPR_MASK_MAXLATENCY_MEMUP_CLR       REG_BIT(27)
 #define     ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point)        (((point) << 16) | (0x1 << 8))
 #define     ADL_PCODE_MEM_SS_READ_PSF_GV_INFO  ((0) | (0x2 << 8))
 #define   ICL_PCODE_SAGV_DE_MEM_SS_CONFIG      0xe
-#define     ICL_PCODE_POINTS_RESTRICTED                0x0
-#define     ICL_PCODE_POINTS_RESTRICTED_MASK   0xf
-#define   ADLS_PSF_PT_SHIFT                    8
-#define   ADLS_QGV_PT_MASK                     REG_GENMASK(7, 0)
-#define   ADLS_PSF_PT_MASK                     REG_GENMASK(10, 8)
+#define     ICL_PCODE_REP_QGV_MASK             REG_GENMASK(1, 0)
+#define     ICL_PCODE_REP_QGV_SAFE             REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 0)
+#define     ICL_PCODE_REP_QGV_POLL             REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 1)
+#define     ICL_PCODE_REP_QGV_REJECTED         REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 2)
+#define     ADLS_PCODE_REP_PSF_MASK            REG_GENMASK(3, 2)
+#define     ADLS_PCODE_REP_PSF_SAFE            REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 0)
+#define     ADLS_PCODE_REP_PSF_POLL            REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 1)
+#define     ADLS_PCODE_REP_PSF_REJECTED                REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 2)
+#define     ICL_PCODE_REQ_QGV_PT_MASK          REG_GENMASK(7, 0)
+#define     ICL_PCODE_REQ_QGV_PT(x)            REG_FIELD_PREP(ICL_PCODE_REQ_QGV_PT_MASK, (x))
+#define     ADLS_PCODE_REQ_PSF_PT_MASK         REG_GENMASK(10, 8)
+#define     ADLS_PCODE_REQ_PSF_PT(x)           REG_FIELD_PREP(ADLS_PCODE_REQ_PSF_PT_MASK, (x))
 #define   GEN6_PCODE_READ_D_COMP               0x10
 #define   GEN6_PCODE_WRITE_D_COMP              0x11
 #define   ICL_PCODE_EXIT_TCCOLD                        0x12
index 889f5b7..81def10 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include "display/intel_de.h"
-#include "display/intel_fbc.h"
 #include "display/intel_gmbus.h"
 #include "display/intel_vga.h"
 
@@ -119,9 +118,6 @@ void i915_restore_display(struct drm_i915_private *dev_priv)
        if (GRAPHICS_VER(dev_priv) <= 4)
                intel_de_write(dev_priv, DSPARB, dev_priv->regfile.saveDSPARB);
 
-       /* only restore FBC info on the platform that supports FBC*/
-       intel_fbc_global_disable(dev_priv);
-
        intel_vga_redisable(dev_priv);
 
        intel_gmbus_reset(dev_priv);
index f9e780d..29fd02b 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2019 Intel Corporation
  */
 
+#include <linux/device.h>
+
 #include <drm/drm_drv.h>
 
 #include "i915_drv.h"
@@ -114,3 +116,12 @@ void set_timer_ms(struct timer_list *t, unsigned long timeout)
        /* Keep t->expires = 0 reserved to indicate a canceled timer. */
        mod_timer(t, jiffies + timeout ?: 1);
 }
+
+bool i915_vtd_active(struct drm_i915_private *i915)
+{
+       if (device_iommu_mapped(i915->drm.dev))
+               return true;
+
+       /* Running as a guest, we assume the host is enforcing VT'd */
+       return i915_run_as_guest();
+}
index bfafd0a..ea7648e 100644 (file)
 #include <linux/list.h>
 #include <linux/overflow.h>
 #include <linux/sched.h>
+#include <linux/string_helpers.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/sched/clock.h>
 
+#ifdef CONFIG_X86
+#include <asm/hypervisor.h>
+#endif
+
 struct drm_i915_private;
 struct timer_list;
 
@@ -399,26 +404,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
 #define MBps(x) KBps(1000 * (x))
 #define GBps(x) ((u64)1000 * MBps((x)))
 
-static inline const char *yesno(bool v)
-{
-       return v ? "yes" : "no";
-}
-
-static inline const char *onoff(bool v)
-{
-       return v ? "on" : "off";
-}
-
-static inline const char *enabledisable(bool v)
-{
-       return v ? "enable" : "disable";
-}
-
-static inline const char *enableddisabled(bool v)
-{
-       return v ? "enabled" : "disabled";
-}
-
 void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint);
 static inline void __add_taint_for_CI(unsigned int taint)
 {
@@ -444,4 +429,16 @@ static inline bool timer_expired(const struct timer_list *t)
        return timer_active(t) && !timer_pending(t);
 }
 
+static inline bool i915_run_as_guest(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+       return !hypervisor_is_type(X86_HYPER_NATIVE);
+#else
+       /* Not supported yet */
+       return false;
+#endif
+}
+
+bool i915_vtd_active(struct drm_i915_private *i915);
+
 #endif /* !__I915_UTILS_H */
index 32c5f10..41a5b98 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#include <linux/string_helpers.h>
+
 #include <drm/drm_print.h>
 #include <drm/i915_pciids.h>
 
@@ -29,6 +31,7 @@
 #include "display/intel_de.h"
 #include "intel_device_info.h"
 #include "i915_drv.h"
+#include "i915_utils.h"
 
 #define PLATFORM_NAME(x) [INTEL_##x] = #x
 static const char * const platform_names[] = {
@@ -110,11 +113,11 @@ void intel_device_info_print_static(const struct intel_device_info *info,
        drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type);
        drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size);
 
-#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name))
+#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name))
        DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
 #undef PRINT_FLAG
 
-#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name))
+#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display.name))
        DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG);
 #undef PRINT_FLAG
 }
@@ -366,7 +369,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
                        info->display.has_dsc = 0;
        }
 
-       if (GRAPHICS_VER(dev_priv) == 6 && intel_vtd_active(dev_priv)) {
+       if (GRAPHICS_VER(dev_priv) == 6 && i915_vtd_active(dev_priv)) {
                drm_info(&dev_priv->drm,
                         "Disabling ppGTT for VT-d support\n");
                info->ppgtt_type = INTEL_PPGTT_NONE;
@@ -388,6 +391,6 @@ void intel_driver_caps_print(const struct intel_driver_caps *caps,
                             struct drm_printer *p)
 {
        drm_printf(p, "Has logical contexts? %s\n",
-                  yesno(caps->has_logical_contexts));
+                  str_yes_no(caps->has_logical_contexts));
        drm_printf(p, "scheduler: %x\n", caps->scheduler);
 }
index 291215d..f9b9558 100644 (file)
@@ -137,6 +137,7 @@ enum intel_ppgtt_type {
        func(needs_compact_pt); \
        func(gpu_reset_clobbers_display); \
        func(has_reset_engine); \
+       func(has_4tile); \
        func(has_flat_ccs); \
        func(has_global_mocs); \
        func(has_gt_uc); \
index 174c95c..2b9e783 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
+
 #include "i915_drv.h"
 #include "i915_reg.h"
 #include "intel_dram.h"
@@ -136,7 +138,7 @@ skl_dram_get_dimm_info(struct drm_i915_private *i915,
        drm_dbg_kms(&i915->drm,
                    "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n",
                    channel, dimm_name, dimm->size, dimm->width, dimm->ranks,
-                   yesno(skl_is_16gb_dimm(dimm)));
+                   str_yes_no(skl_is_16gb_dimm(dimm)));
 }
 
 static int
@@ -165,7 +167,7 @@ skl_dram_get_channel_info(struct drm_i915_private *i915,
                skl_is_16gb_dimm(&ch->dimm_s);
 
        drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n",
-                   channel, ch->ranks, yesno(ch->is_16gb_dimm));
+                   channel, ch->ranks, str_yes_no(ch->is_16gb_dimm));
 
        return 0;
 }
@@ -214,7 +216,7 @@ skl_dram_get_channels_info(struct drm_i915_private *i915)
        dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1);
 
        drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n",
-                   yesno(dram_info->symmetric_memory));
+                   str_yes_no(dram_info->symmetric_memory));
 
        return 0;
 }
@@ -492,7 +494,7 @@ void intel_dram_detect(struct drm_i915_private *i915)
        drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels);
 
        drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n",
-                   yesno(dram_info->wm_lv_0_adjust_needed));
+                   str_yes_no(dram_info->wm_lv_0_adjust_needed));
 }
 
 static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap)
index 1c841f6..ded78b8 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <linux/prandom.h>
 
+#include <uapi/drm/i915_drm.h>
+
 #include "intel_memory_region.h"
 #include "i915_drv.h"
 #include "i915_ttm_buddy_manager.h"
index 21dcbd6..bbc35ec 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/mutex.h>
 #include <linux/io-mapping.h>
 #include <drm/drm_mm.h>
-#include <drm/i915_drm.h>
+#include <uapi/drm/i915_drm.h>
 
 struct drm_i915_private;
 struct drm_i915_gem_object;
index 4cce044..e2b2bbd 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include "i915_drv.h"
+#include "i915_utils.h"
 #include "intel_pch.h"
 
 /* Map PCH device id to PCH type, or PCH_NONE if unknown. */
@@ -256,7 +257,7 @@ void intel_detect_pch(struct drm_i915_private *dev_priv)
                dev_priv->pch_type = PCH_NOP;
                dev_priv->pch_id = 0;
        } else if (!pch) {
-               if (run_as_guest() && HAS_DISPLAY(dev_priv)) {
+               if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) {
                        intel_virt_detect_pch(dev_priv, &id, &pch_type);
                        dev_priv->pch_type = pch_type;
                        dev_priv->pch_id = id;
index 391a374..ac72754 100644 (file)
@@ -136,7 +136,7 @@ static bool skl_pcode_try_request(struct drm_i915_private *i915, u32 mbox,
 {
        *status = __snb_pcode_rw(i915, mbox, &request, NULL, 500, 0, true);
 
-       return *status || ((request & reply_mask) == reply);
+       return (*status == 0) && ((request & reply_mask) == reply);
 }
 
 /**
@@ -202,7 +202,7 @@ int skl_pcode_request(struct drm_i915_private *i915, u32 mbox, u32 request,
 
 out:
        mutex_unlock(&i915->sb_lock);
-       return ret ? ret : status;
+       return status ? status : ret;
 #undef COND
 }
 
index 9333f73..594ab59 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/string_helpers.h>
 #include <linux/pm_runtime.h>
 
 #include <drm/drm_atomic_helper.h>
@@ -56,6 +57,8 @@
 #include "vlv_sideband.h"
 #include "../../../platform/x86/intel_ips.h"
 
+static void skl_sagv_disable(struct drm_i915_private *dev_priv);
+
 struct drm_i915_clock_gating_funcs {
        void (*init_clock_gating)(struct drm_i915_private *i915);
 };
@@ -418,8 +421,8 @@ static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl
        trace_intel_memory_cxsr(dev_priv, was_enabled, enable);
 
        drm_dbg_kms(&dev_priv->drm, "memory self-refresh is %s (was %s)\n",
-                   enableddisabled(enable),
-                   enableddisabled(was_enabled));
+                   str_enabled_disabled(enable),
+                   str_enabled_disabled(was_enabled));
 
        return was_enabled;
 }
@@ -3669,8 +3672,8 @@ intel_has_sagv(struct drm_i915_private *dev_priv)
                dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED;
 }
 
-static void
-skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
+static u32
+intel_sagv_block_time(struct drm_i915_private *dev_priv)
 {
        if (DISPLAY_VER(dev_priv) >= 12) {
                u32 val = 0;
@@ -3679,26 +3682,48 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
                ret = snb_pcode_read(dev_priv,
                                     GEN12_PCODE_READ_SAGV_BLOCK_TIME_US,
                                     &val, NULL);
-               if (!ret) {
-                       dev_priv->sagv_block_time_us = val;
-                       return;
+               if (ret) {
+                       drm_dbg_kms(&dev_priv->drm, "Couldn't read SAGV block time!\n");
+                       return 0;
                }
 
-               drm_dbg(&dev_priv->drm, "Couldn't read SAGV block time!\n");
+               return val;
        } else if (DISPLAY_VER(dev_priv) == 11) {
-               dev_priv->sagv_block_time_us = 10;
-               return;
-       } else if (DISPLAY_VER(dev_priv) == 10) {
-               dev_priv->sagv_block_time_us = 20;
-               return;
-       } else if (DISPLAY_VER(dev_priv) == 9) {
-               dev_priv->sagv_block_time_us = 30;
-               return;
+               return 10;
+       } else if (DISPLAY_VER(dev_priv) == 9 && !IS_LP(dev_priv)) {
+               return 30;
        } else {
-               MISSING_CASE(DISPLAY_VER(dev_priv));
+               return 0;
        }
+}
+
+static void intel_sagv_init(struct drm_i915_private *i915)
+{
+       if (!intel_has_sagv(i915))
+               i915->sagv_status = I915_SAGV_NOT_CONTROLLED;
 
-       dev_priv->sagv_block_time_us = 0;
+       /*
+        * Probe to see if we have working SAGV control.
+        * For icl+ this was already determined by intel_bw_init_hw().
+        */
+       if (DISPLAY_VER(i915) < 11)
+               skl_sagv_disable(i915);
+
+       drm_WARN_ON(&i915->drm, i915->sagv_status == I915_SAGV_UNKNOWN);
+
+       i915->sagv_block_time_us = intel_sagv_block_time(i915);
+
+       drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n",
+                   str_yes_no(intel_has_sagv(i915)), i915->sagv_block_time_us);
+
+       /* avoid overflow when adding with wm0 latency/etc. */
+       if (drm_WARN(&i915->drm, i915->sagv_block_time_us > U16_MAX,
+                    "Excessive SAGV block time %u, ignoring\n",
+                    i915->sagv_block_time_us))
+               i915->sagv_block_time_us = 0;
+
+       if (!intel_has_sagv(i915))
+               i915->sagv_block_time_us = 0;
 }
 
 /*
@@ -3712,16 +3737,15 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
  *  - All planes can enable watermarks for latencies >= SAGV engine block time
  *  - We're not using an interlaced display configuration
  */
-static int
-intel_enable_sagv(struct drm_i915_private *dev_priv)
+static void skl_sagv_enable(struct drm_i915_private *dev_priv)
 {
        int ret;
 
        if (!intel_has_sagv(dev_priv))
-               return 0;
+               return;
 
        if (dev_priv->sagv_status == I915_SAGV_ENABLED)
-               return 0;
+               return;
 
        drm_dbg_kms(&dev_priv->drm, "Enabling SAGV\n");
        ret = snb_pcode_write(dev_priv, GEN9_PCODE_SAGV_CONTROL,
@@ -3736,26 +3760,24 @@ intel_enable_sagv(struct drm_i915_private *dev_priv)
        if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) {
                drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n");
                dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED;
-               return 0;
+               return;
        } else if (ret < 0) {
                drm_err(&dev_priv->drm, "Failed to enable SAGV\n");
-               return ret;
+               return;
        }
 
        dev_priv->sagv_status = I915_SAGV_ENABLED;
-       return 0;
 }
 
-static int
-intel_disable_sagv(struct drm_i915_private *dev_priv)
+static void skl_sagv_disable(struct drm_i915_private *dev_priv)
 {
        int ret;
 
        if (!intel_has_sagv(dev_priv))
-               return 0;
+               return;
 
        if (dev_priv->sagv_status == I915_SAGV_DISABLED)
-               return 0;
+               return;
 
        drm_dbg_kms(&dev_priv->drm, "Disabling SAGV\n");
        /* bspec says to keep retrying for at least 1 ms */
@@ -3770,14 +3792,13 @@ intel_disable_sagv(struct drm_i915_private *dev_priv)
        if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) {
                drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n");
                dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED;
-               return 0;
+               return;
        } else if (ret < 0) {
                drm_err(&dev_priv->drm, "Failed to disable SAGV (%d)\n", ret);
-               return ret;
+               return;
        }
 
        dev_priv->sagv_status = I915_SAGV_DISABLED;
-       return 0;
 }
 
 static void skl_sagv_pre_plane_update(struct intel_atomic_state *state)
@@ -3790,7 +3811,7 @@ static void skl_sagv_pre_plane_update(struct intel_atomic_state *state)
                return;
 
        if (!intel_can_enable_sagv(i915, new_bw_state))
-               intel_disable_sagv(i915);
+               skl_sagv_disable(i915);
 }
 
 static void skl_sagv_post_plane_update(struct intel_atomic_state *state)
@@ -3803,7 +3824,7 @@ static void skl_sagv_post_plane_update(struct intel_atomic_state *state)
                return;
 
        if (intel_can_enable_sagv(i915, new_bw_state))
-               intel_enable_sagv(i915);
+               skl_sagv_enable(i915);
 }
 
 static void icl_sagv_pre_plane_update(struct intel_atomic_state *state)
@@ -4325,46 +4346,31 @@ static void
 skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv,
                           const enum pipe pipe,
                           const enum plane_id plane_id,
-                          struct skl_ddb_entry *ddb_y,
-                          struct skl_ddb_entry *ddb_uv)
+                          struct skl_ddb_entry *ddb,
+                          struct skl_ddb_entry *ddb_y)
 {
-       u32 val, val2;
-       u32 fourcc = 0;
+       u32 val;
 
        /* Cursor doesn't support NV12/planar, so no extra calculation needed */
        if (plane_id == PLANE_CURSOR) {
                val = intel_uncore_read(&dev_priv->uncore, CUR_BUF_CFG(pipe));
-               skl_ddb_entry_init_from_hw(ddb_y, val);
+               skl_ddb_entry_init_from_hw(ddb, val);
                return;
        }
 
-       val = intel_uncore_read(&dev_priv->uncore, PLANE_CTL(pipe, plane_id));
-
-       /* No DDB allocated for disabled planes */
-       if (val & PLANE_CTL_ENABLE)
-               fourcc = skl_format_to_fourcc(val & PLANE_CTL_FORMAT_MASK_SKL,
-                                             val & PLANE_CTL_ORDER_RGBX,
-                                             val & PLANE_CTL_ALPHA_MASK);
-
-       if (DISPLAY_VER(dev_priv) >= 11) {
-               val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id));
-               skl_ddb_entry_init_from_hw(ddb_y, val);
-       } else {
-               val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id));
-               val2 = intel_uncore_read(&dev_priv->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id));
+       val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id));
+       skl_ddb_entry_init_from_hw(ddb, val);
 
-               if (fourcc &&
-                   drm_format_info_is_yuv_semiplanar(drm_format_info(fourcc)))
-                       swap(val, val2);
+       if (DISPLAY_VER(dev_priv) >= 11)
+               return;
 
-               skl_ddb_entry_init_from_hw(ddb_y, val);
-               skl_ddb_entry_init_from_hw(ddb_uv, val2);
-       }
+       val = intel_uncore_read(&dev_priv->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id));
+       skl_ddb_entry_init_from_hw(ddb_y, val);
 }
 
 void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
-                              struct skl_ddb_entry *ddb_y,
-                              struct skl_ddb_entry *ddb_uv)
+                              struct skl_ddb_entry *ddb,
+                              struct skl_ddb_entry *ddb_y)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum intel_display_power_domain power_domain;
@@ -4380,8 +4386,8 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
        for_each_plane_id_on_crtc(crtc, plane_id)
                skl_ddb_get_hw_plane_state(dev_priv, pipe,
                                           plane_id,
-                                          &ddb_y[plane_id],
-                                          &ddb_uv[plane_id]);
+                                          &ddb[plane_id],
+                                          &ddb_y[plane_id]);
 
        intel_display_power_put(dev_priv, power_domain, wakeref);
 }
@@ -4912,17 +4918,6 @@ static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool
        return active_pipes & BIT(pipe) ? BIT(DBUF_S1) : 0;
 }
 
-static bool
-use_min_ddb(const struct intel_crtc_state *crtc_state,
-           struct intel_plane *plane)
-{
-       struct drm_i915_private *i915 = to_i915(plane->base.dev);
-
-       return DISPLAY_VER(i915) >= 13 &&
-              crtc_state->uapi.async_flip &&
-              plane->async_flip;
-}
-
 static bool
 use_minimal_wm0_only(const struct intel_crtc_state *crtc_state,
                     struct intel_plane *plane)
@@ -4935,134 +4930,24 @@ use_minimal_wm0_only(const struct intel_crtc_state *crtc_state,
 }
 
 static u64
-skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
-                            const struct intel_plane_state *plane_state,
-                            int color_plane)
+skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-       const struct drm_framebuffer *fb = plane_state->hw.fb;
-       int width, height;
-
-       if (!plane_state->uapi.visible)
-               return 0;
-
-       if (plane->id == PLANE_CURSOR)
-               return 0;
-
-       /*
-        * We calculate extra ddb based on ratio plane rate/total data rate
-        * in case, in some cases we should not allocate extra ddb for the plane,
-        * so do not count its data rate, if this is the case.
-        */
-       if (use_min_ddb(crtc_state, plane))
-               return 0;
-
-       if (color_plane == 1 &&
-           !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
-               return 0;
-
-       /*
-        * Src coordinates are already rotated by 270 degrees for
-        * the 90/270 degree plane rotation cases (to match the
-        * GTT mapping), hence no need to account for rotation here.
-        */
-       width = drm_rect_width(&plane_state->uapi.src) >> 16;
-       height = drm_rect_height(&plane_state->uapi.src) >> 16;
-
-       /* UV plane does 1/2 pixel sub-sampling */
-       if (color_plane == 1) {
-               width /= 2;
-               height /= 2;
-       }
-
-       return width * height * fb->format->cpp[color_plane];
-}
-
-static u64
-skl_get_total_relative_data_rate(struct intel_atomic_state *state,
-                                struct intel_crtc *crtc)
-{
-       struct intel_crtc_state *crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       const struct intel_plane_state *plane_state;
-       struct intel_plane *plane;
-       u64 total_data_rate = 0;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
        enum plane_id plane_id;
-       int i;
-
-       /* Calculate and cache data rate for each plane */
-       for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               if (plane->pipe != crtc->pipe)
-                       continue;
-
-               plane_id = plane->id;
-
-               /* packed/y */
-               crtc_state->plane_data_rate[plane_id] =
-                       skl_plane_relative_data_rate(crtc_state, plane_state, 0);
-
-               /* uv-plane */
-               crtc_state->uv_plane_data_rate[plane_id] =
-                       skl_plane_relative_data_rate(crtc_state, plane_state, 1);
-       }
+       u64 data_rate = 0;
 
        for_each_plane_id_on_crtc(crtc, plane_id) {
-               total_data_rate += crtc_state->plane_data_rate[plane_id];
-               total_data_rate += crtc_state->uv_plane_data_rate[plane_id];
-       }
-
-       return total_data_rate;
-}
-
-static u64
-icl_get_total_relative_data_rate(struct intel_atomic_state *state,
-                                struct intel_crtc *crtc)
-{
-       struct intel_crtc_state *crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       const struct intel_plane_state *plane_state;
-       struct intel_plane *plane;
-       u64 total_data_rate = 0;
-       enum plane_id plane_id;
-       int i;
-
-       /* Calculate and cache data rate for each plane */
-       for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               if (plane->pipe != crtc->pipe)
+               if (plane_id == PLANE_CURSOR)
                        continue;
 
-               plane_id = plane->id;
-
-               if (!plane_state->planar_linked_plane) {
-                       crtc_state->plane_data_rate[plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 0);
-               } else {
-                       enum plane_id y_plane_id;
-
-                       /*
-                        * The slave plane might not iterate in
-                        * intel_atomic_crtc_state_for_each_plane_state(),
-                        * and needs the master plane state which may be
-                        * NULL if we try get_new_plane_state(), so we
-                        * always calculate from the master.
-                        */
-                       if (plane_state->planar_slave)
-                               continue;
-
-                       /* Y plane rate is calculated on the slave */
-                       y_plane_id = plane_state->planar_linked_plane->id;
-                       crtc_state->plane_data_rate[y_plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 0);
+               data_rate += crtc_state->rel_data_rate[plane_id];
 
-                       crtc_state->plane_data_rate[plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 1);
-               }
+               if (DISPLAY_VER(i915) < 11)
+                       data_rate += crtc_state->rel_data_rate_y[plane_id];
        }
 
-       for_each_plane_id_on_crtc(crtc, plane_id)
-               total_data_rate += crtc_state->plane_data_rate[plane_id];
-
-       return total_data_rate;
+       return data_rate;
 }
 
 const struct skl_wm_level *
@@ -5103,18 +4988,18 @@ skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm,
  * So this is actually safe to do.
  */
 static void
-skl_check_wm_level(struct skl_wm_level *wm, u64 total)
+skl_check_wm_level(struct skl_wm_level *wm, const struct skl_ddb_entry *ddb)
 {
-       if (wm->min_ddb_alloc > total)
+       if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb))
                memset(wm, 0, sizeof(*wm));
 }
 
 static void
 skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm,
-                       u64 total, u64 uv_total)
+                       const struct skl_ddb_entry *ddb_y, const struct skl_ddb_entry *ddb)
 {
-       if (wm->min_ddb_alloc > total ||
-           uv_wm->min_ddb_alloc > uv_total) {
+       if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb_y) ||
+           uv_wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) {
                memset(wm, 0, sizeof(*wm));
                memset(uv_wm, 0, sizeof(*uv_wm));
        }
@@ -5134,17 +5019,16 @@ static bool icl_need_wm1_wa(struct drm_i915_private *i915,
 
 struct skl_plane_ddb_iter {
        u64 data_rate;
-       u16 total[I915_MAX_PLANES];
-       u16 uv_total[I915_MAX_PLANES];
        u16 start, size;
 };
 
-static u16
+static void
 skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
+                      struct skl_ddb_entry *ddb,
                       const struct skl_wm_level *wm,
                       u64 data_rate)
 {
-       u16 extra = 0;
+       u16 size, extra = 0;
 
        if (data_rate) {
                extra = min_t(u16, iter->size,
@@ -5154,7 +5038,15 @@ skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter,
                iter->data_rate -= data_rate;
        }
 
-       return wm->min_ddb_alloc + extra;
+       /*
+        * Keep ddb entry of all disabled planes explicitly zeroed
+        * to avoid skl_ddb_add_affected_planes() adding them to
+        * the state when other planes change their allocations.
+        */
+       size = wm->min_ddb_alloc + extra;
+       if (size)
+               iter->start = skl_ddb_entry_init(ddb, iter->start,
+                                                iter->start + size);
 }
 
 static int
@@ -5168,32 +5060,31 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
                intel_atomic_get_new_dbuf_state(state);
        const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe];
        int num_active = hweight8(dbuf_state->active_pipes);
-       struct skl_plane_ddb_iter iter = {};
+       struct skl_plane_ddb_iter iter;
        enum plane_id plane_id;
+       u16 cursor_size;
        u32 blocks;
        int level;
 
        /* Clear the partitioning for disabled planes. */
+       memset(crtc_state->wm.skl.plane_ddb, 0, sizeof(crtc_state->wm.skl.plane_ddb));
        memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y));
-       memset(crtc_state->wm.skl.plane_ddb_uv, 0, sizeof(crtc_state->wm.skl.plane_ddb_uv));
 
        if (!crtc_state->hw.active)
                return 0;
 
-       if (DISPLAY_VER(dev_priv) >= 11)
-               iter.data_rate = icl_get_total_relative_data_rate(state, crtc);
-       else
-               iter.data_rate = skl_get_total_relative_data_rate(state, crtc);
-
+       iter.start = alloc->start;
        iter.size = skl_ddb_entry_size(alloc);
        if (iter.size == 0)
                return 0;
 
        /* Allocate fixed number of blocks for cursor. */
-       iter.total[PLANE_CURSOR] = skl_cursor_allocation(crtc_state, num_active);
-       iter.size -= iter.total[PLANE_CURSOR];
-       skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR],
-                          alloc->end - iter.total[PLANE_CURSOR], alloc->end);
+       cursor_size = skl_cursor_allocation(crtc_state, num_active);
+       iter.size -= cursor_size;
+       skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
+                          alloc->end - cursor_size, alloc->end);
+
+       iter.data_rate = skl_total_relative_data_rate(crtc_state);
 
        /*
         * Find the highest watermark level for which we can satisfy the block
@@ -5206,7 +5097,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
                                &crtc_state->wm.skl.optimal.planes[plane_id];
 
                        if (plane_id == PLANE_CURSOR) {
-                               if (wm->wm[level].min_ddb_alloc > iter.total[PLANE_CURSOR]) {
+                               const struct skl_ddb_entry *ddb =
+                                       &crtc_state->wm.skl.plane_ddb[plane_id];
+
+                               if (wm->wm[level].min_ddb_alloc > skl_ddb_entry_size(ddb)) {
                                        drm_WARN_ON(&dev_priv->drm,
                                                    wm->wm[level].min_ddb_alloc != U16_MAX);
                                        blocks = U32_MAX;
@@ -5243,47 +5137,29 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
         * proportional to its relative data rate.
         */
        for_each_plane_id_on_crtc(crtc, plane_id) {
+               struct skl_ddb_entry *ddb =
+                       &crtc_state->wm.skl.plane_ddb[plane_id];
+               struct skl_ddb_entry *ddb_y =
+                       &crtc_state->wm.skl.plane_ddb_y[plane_id];
                const struct skl_plane_wm *wm =
                        &crtc_state->wm.skl.optimal.planes[plane_id];
 
                if (plane_id == PLANE_CURSOR)
                        continue;
 
-               iter.total[plane_id] =
-                       skl_allocate_plane_ddb(&iter, &wm->wm[level],
-                                              crtc_state->plane_data_rate[plane_id]);
-
-               iter.uv_total[plane_id] =
-                       skl_allocate_plane_ddb(&iter, &wm->uv_wm[level],
-                                              crtc_state->uv_plane_data_rate[plane_id]);
+               if (DISPLAY_VER(dev_priv) < 11 &&
+                   crtc_state->nv12_planes & BIT(plane_id)) {
+                       skl_allocate_plane_ddb(&iter, ddb_y, &wm->wm[level],
+                                              crtc_state->rel_data_rate_y[plane_id]);
+                       skl_allocate_plane_ddb(&iter, ddb, &wm->uv_wm[level],
+                                              crtc_state->rel_data_rate[plane_id]);
+               } else {
+                       skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level],
+                                              crtc_state->rel_data_rate[plane_id]);
+               }
        }
        drm_WARN_ON(&dev_priv->drm, iter.size != 0 || iter.data_rate != 0);
 
-       /* Set the actual DDB start/end points for each plane */
-       iter.start = alloc->start;
-       for_each_plane_id_on_crtc(crtc, plane_id) {
-               struct skl_ddb_entry *plane_alloc =
-                       &crtc_state->wm.skl.plane_ddb_y[plane_id];
-               struct skl_ddb_entry *uv_plane_alloc =
-                       &crtc_state->wm.skl.plane_ddb_uv[plane_id];
-
-               if (plane_id == PLANE_CURSOR)
-                       continue;
-
-               /* Gen11+ uses a separate plane for UV watermarks */
-               drm_WARN_ON(&dev_priv->drm,
-                           DISPLAY_VER(dev_priv) >= 11 && iter.uv_total[plane_id]);
-
-               /* Leave disabled planes at (0,0) */
-               if (iter.total[plane_id])
-                       iter.start = skl_ddb_entry_init(plane_alloc, iter.start,
-                                                       iter.start + iter.total[plane_id]);
-
-               if (iter.uv_total[plane_id])
-                       iter.start = skl_ddb_entry_init(uv_plane_alloc, iter.start,
-                                                       iter.start + iter.uv_total[plane_id]);
-       }
-
        /*
         * When we calculated watermark values we didn't know how high
         * of a level we'd actually be able to hit, so we just marked
@@ -5292,12 +5168,20 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
         */
        for (level++; level <= ilk_wm_max_level(dev_priv); level++) {
                for_each_plane_id_on_crtc(crtc, plane_id) {
+                       const struct skl_ddb_entry *ddb =
+                               &crtc_state->wm.skl.plane_ddb[plane_id];
+                       const struct skl_ddb_entry *ddb_y =
+                               &crtc_state->wm.skl.plane_ddb_y[plane_id];
                        struct skl_plane_wm *wm =
                                &crtc_state->wm.skl.optimal.planes[plane_id];
 
-                       skl_check_nv12_wm_level(&wm->wm[level], &wm->uv_wm[level],
-                                               iter.total[plane_id],
-                                               iter.uv_total[plane_id]);
+                       if (DISPLAY_VER(dev_priv) < 11 &&
+                           crtc_state->nv12_planes & BIT(plane_id))
+                               skl_check_nv12_wm_level(&wm->wm[level],
+                                                       &wm->uv_wm[level],
+                                                       ddb_y, ddb);
+                       else
+                               skl_check_wm_level(&wm->wm[level], ddb);
 
                        if (icl_need_wm1_wa(dev_priv, plane_id) &&
                            level == 1 && wm->wm[0].enable) {
@@ -5313,12 +5197,24 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
         * if it turns out we don't have enough DDB blocks for them.
         */
        for_each_plane_id_on_crtc(crtc, plane_id) {
+               const struct skl_ddb_entry *ddb =
+                       &crtc_state->wm.skl.plane_ddb[plane_id];
+               const struct skl_ddb_entry *ddb_y =
+                       &crtc_state->wm.skl.plane_ddb_y[plane_id];
                struct skl_plane_wm *wm =
                        &crtc_state->wm.skl.optimal.planes[plane_id];
 
-               skl_check_wm_level(&wm->trans_wm, iter.total[plane_id]);
-               skl_check_wm_level(&wm->sagv.wm0, iter.total[plane_id]);
-               skl_check_wm_level(&wm->sagv.trans_wm, iter.total[plane_id]);
+               if (DISPLAY_VER(dev_priv) < 11 &&
+                   crtc_state->nv12_planes & BIT(plane_id)) {
+                       skl_check_wm_level(&wm->trans_wm, ddb_y);
+               } else {
+                       WARN_ON(skl_ddb_entry_size(ddb_y));
+
+                       skl_check_wm_level(&wm->trans_wm, ddb);
+               }
+
+               skl_check_wm_level(&wm->sagv.wm0, ddb);
+               skl_check_wm_level(&wm->sagv.trans_wm, ddb);
        }
 
        return 0;
@@ -5408,6 +5304,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
        }
 
        wp->y_tiled = modifier == I915_FORMAT_MOD_Y_TILED ||
+                     modifier == I915_FORMAT_MOD_4_TILED ||
                      modifier == I915_FORMAT_MOD_Yf_TILED ||
                      modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
                      modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
@@ -5926,7 +5823,7 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv,
                val |= PLANE_WM_EN;
        if (level->ignore_lines)
                val |= PLANE_WM_IGNORE_LINES;
-       val |= level->blocks;
+       val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks);
        val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines);
 
        intel_de_write_fw(dev_priv, reg, val);
@@ -5940,11 +5837,10 @@ void skl_write_plane_wm(struct intel_plane *plane,
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
        const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
-       const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
+       const struct skl_ddb_entry *ddb =
+               &crtc_state->wm.skl.plane_ddb[plane_id];
        const struct skl_ddb_entry *ddb_y =
                &crtc_state->wm.skl.plane_ddb_y[plane_id];
-       const struct skl_ddb_entry *ddb_uv =
-               &crtc_state->wm.skl.plane_ddb_uv[plane_id];
 
        for (level = 0; level <= max_level; level++)
                skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane_id, level),
@@ -5954,25 +5850,20 @@ void skl_write_plane_wm(struct intel_plane *plane,
                           skl_plane_trans_wm(pipe_wm, plane_id));
 
        if (HAS_HW_SAGV_WM(dev_priv)) {
+               const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
+
                skl_write_wm_level(dev_priv, PLANE_WM_SAGV(pipe, plane_id),
                                   &wm->sagv.wm0);
                skl_write_wm_level(dev_priv, PLANE_WM_SAGV_TRANS(pipe, plane_id),
                                   &wm->sagv.trans_wm);
        }
 
-       if (DISPLAY_VER(dev_priv) >= 11) {
-               skl_ddb_entry_write(dev_priv,
-                                   PLANE_BUF_CFG(pipe, plane_id), ddb_y);
-               return;
-       }
-
-       if (wm->is_planar)
-               swap(ddb_y, ddb_uv);
-
-       skl_ddb_entry_write(dev_priv,
-                           PLANE_BUF_CFG(pipe, plane_id), ddb_y);
        skl_ddb_entry_write(dev_priv,
-                           PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_uv);
+                           PLANE_BUF_CFG(pipe, plane_id), ddb);
+
+       if (DISPLAY_VER(dev_priv) < 11)
+               skl_ddb_entry_write(dev_priv,
+                                   PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_y);
 }
 
 void skl_write_cursor_wm(struct intel_plane *plane,
@@ -5984,7 +5875,7 @@ void skl_write_cursor_wm(struct intel_plane *plane,
        enum pipe pipe = plane->pipe;
        const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
        const struct skl_ddb_entry *ddb =
-               &crtc_state->wm.skl.plane_ddb_y[plane_id];
+               &crtc_state->wm.skl.plane_ddb[plane_id];
 
        for (level = 0; level <= max_level; level++)
                skl_write_wm_level(dev_priv, CUR_WM(pipe, level),
@@ -6081,10 +5972,10 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
                struct intel_plane_state *plane_state;
                enum plane_id plane_id = plane->id;
 
-               if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id],
-                                       &new_crtc_state->wm.skl.plane_ddb_y[plane_id]) &&
-                   skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_uv[plane_id],
-                                       &new_crtc_state->wm.skl.plane_ddb_uv[plane_id]))
+               if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb[plane_id],
+                                       &new_crtc_state->wm.skl.plane_ddb[plane_id]) &&
+                   skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id],
+                                       &new_crtc_state->wm.skl.plane_ddb_y[plane_id]))
                        continue;
 
                plane_state = intel_atomic_get_plane_state(state, plane);
@@ -6147,7 +6038,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
                        return ret;
        }
 
-       if (IS_ALDERLAKE_P(dev_priv))
+       if (HAS_MBUS_JOINING(dev_priv))
                new_dbuf_state->joined_mbus =
                        adlp_check_mbus_joined(new_dbuf_state->active_pipes);
 
@@ -6186,8 +6077,8 @@ skl_compute_ddb(struct intel_atomic_state *state)
                            old_dbuf_state->enabled_slices,
                            new_dbuf_state->enabled_slices,
                            INTEL_INFO(dev_priv)->dbuf.slice_mask,
-                           yesno(old_dbuf_state->joined_mbus),
-                           yesno(new_dbuf_state->joined_mbus));
+                           str_yes_no(old_dbuf_state->joined_mbus),
+                           str_yes_no(new_dbuf_state->joined_mbus));
        }
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
@@ -6253,8 +6144,8 @@ skl_print_wm_changes(struct intel_atomic_state *state)
                        enum plane_id plane_id = plane->id;
                        const struct skl_ddb_entry *old, *new;
 
-                       old = &old_crtc_state->wm.skl.plane_ddb_y[plane_id];
-                       new = &new_crtc_state->wm.skl.plane_ddb_y[plane_id];
+                       old = &old_crtc_state->wm.skl.plane_ddb[plane_id];
+                       new = &new_crtc_state->wm.skl.plane_ddb[plane_id];
 
                        if (skl_ddb_entry_equal(old, new))
                                continue;
@@ -6574,7 +6465,7 @@ static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level)
 {
        level->enable = val & PLANE_WM_EN;
        level->ignore_lines = val & PLANE_WM_IGNORE_LINES;
-       level->blocks = val & PLANE_WM_BLOCKS_MASK;
+       level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val);
        level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val);
 }
 
@@ -6639,7 +6530,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
                to_intel_dbuf_state(dev_priv->dbuf.obj.state);
        struct intel_crtc *crtc;
 
-       if (IS_ALDERLAKE_P(dev_priv))
+       if (HAS_MBUS_JOINING(dev_priv))
                dbuf_state->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN;
 
        for_each_intel_crtc(&dev_priv->drm, crtc) {
@@ -6656,16 +6547,16 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
                memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe]));
 
                for_each_plane_id_on_crtc(crtc, plane_id) {
+                       struct skl_ddb_entry *ddb =
+                               &crtc_state->wm.skl.plane_ddb[plane_id];
                        struct skl_ddb_entry *ddb_y =
                                &crtc_state->wm.skl.plane_ddb_y[plane_id];
-                       struct skl_ddb_entry *ddb_uv =
-                               &crtc_state->wm.skl.plane_ddb_uv[plane_id];
 
                        skl_ddb_get_hw_plane_state(dev_priv, crtc->pipe,
-                                                  plane_id, ddb_y, ddb_uv);
+                                                  plane_id, ddb, ddb_y);
 
+                       skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb);
                        skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_y);
-                       skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_uv);
                }
 
                dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state);
@@ -6689,7 +6580,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
                            crtc->base.base.id, crtc->base.name,
                            dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start,
                            dbuf_state->ddb[pipe].end, dbuf_state->active_pipes,
-                           yesno(dbuf_state->joined_mbus));
+                           str_yes_no(dbuf_state->joined_mbus));
        }
 
        dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices;
@@ -7000,7 +6891,8 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv)
                    "Initial HPLL watermarks: plane=%d, SR cursor=%d fbc=%d\n",
                    wm->hpll.plane, wm->hpll.cursor, wm->hpll.fbc);
        drm_dbg_kms(&dev_priv->drm, "Initial SR=%s HPLL=%s FBC=%s\n",
-                   yesno(wm->cxsr), yesno(wm->hpll_en), yesno(wm->fbc_en));
+                   str_yes_no(wm->cxsr), str_yes_no(wm->hpll_en),
+                   str_yes_no(wm->fbc_en));
 }
 
 void g4x_wm_sanitize(struct drm_i915_private *dev_priv)
@@ -7578,6 +7470,9 @@ static void adlp_init_clock_gating(struct drm_i915_private *dev_priv)
 
        /* Wa_22011091694:adlp */
        intel_de_rmw(dev_priv, GEN9_CLKGATE_DIS_5, 0, DPCE_GATING_DIS);
+
+       /* Bspec/49189 Initialize Sequence */
+       intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0);
 }
 
 static void dg1_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -8175,8 +8070,7 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
        else if (GRAPHICS_VER(dev_priv) == 5)
                ilk_get_mem_freq(dev_priv);
 
-       if (intel_has_sagv(dev_priv))
-               skl_setup_sagv_block_time(dev_priv);
+       intel_sagv_init(dev_priv);
 
        /* For FIFO watermark updates */
        if (DISPLAY_VER(dev_priv) >= 9) {
@@ -8301,7 +8195,7 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state)
        const struct intel_dbuf_state *dbuf_state =
                intel_atomic_get_new_dbuf_state(state);
 
-       if (!IS_ALDERLAKE_P(dev_priv))
+       if (!HAS_MBUS_JOINING(dev_priv))
                return;
 
        /*
@@ -8367,3 +8261,55 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state)
        gen9_dbuf_slices_update(dev_priv,
                                new_dbuf_state->enabled_slices);
 }
+
+void intel_mbus_dbox_update(struct intel_atomic_state *state)
+{
+       struct drm_i915_private *i915 = to_i915(state->base.dev);
+       const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state;
+       const struct intel_crtc_state *new_crtc_state;
+       const struct intel_crtc *crtc;
+       u32 val = 0;
+       int i;
+
+       if (DISPLAY_VER(i915) < 11)
+               return;
+
+       new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
+       old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
+       if (!new_dbuf_state ||
+           (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus &&
+            new_dbuf_state->active_pipes == old_dbuf_state->active_pipes))
+               return;
+
+       if (DISPLAY_VER(i915) >= 12) {
+               val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16);
+               val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1);
+               val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN;
+       }
+
+       /* Wa_22010947358:adl-p */
+       if (IS_ALDERLAKE_P(i915))
+               val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) :
+                                                    MBUS_DBOX_A_CREDIT(4);
+       else
+               val |= MBUS_DBOX_A_CREDIT(2);
+
+       if (IS_ALDERLAKE_P(i915)) {
+               val |= MBUS_DBOX_BW_CREDIT(2);
+               val |= MBUS_DBOX_B_CREDIT(8);
+       } else if (DISPLAY_VER(i915) >= 12) {
+               val |= MBUS_DBOX_BW_CREDIT(2);
+               val |= MBUS_DBOX_B_CREDIT(12);
+       } else {
+               val |= MBUS_DBOX_BW_CREDIT(1);
+               val |= MBUS_DBOX_B_CREDIT(8);
+       }
+
+       for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+               if (!new_crtc_state->hw.active ||
+                   !intel_crtc_needs_modeset(new_crtc_state))
+                       continue;
+
+               intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), val);
+       }
+}
index 5170515..50604cf 100644 (file)
@@ -94,5 +94,6 @@ intel_atomic_get_dbuf_state(struct intel_atomic_state *state);
 int intel_dbuf_init(struct drm_i915_private *dev_priv);
 void intel_dbuf_pre_plane_update(struct intel_atomic_state *state);
 void intel_dbuf_post_plane_update(struct intel_atomic_state *state);
+void intel_mbus_dbox_update(struct intel_atomic_state *state);
 
 #endif /* __INTEL_PM_H__ */
index 4fd69ec..74e8e46 100644 (file)
@@ -131,6 +131,10 @@ static const struct intel_step_info adls_rpls_revids[] = {
        [0xC] = { COMMON_GT_MEDIA_STEP(D0), .display_step = STEP_C0 },
 };
 
+static const struct intel_step_info adlp_n_revids[] = {
+       [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_D0 },
+};
+
 void intel_step_init(struct drm_i915_private *i915)
 {
        const struct intel_step_info *revids = NULL;
@@ -150,6 +154,9 @@ void intel_step_init(struct drm_i915_private *i915)
        } else if (IS_XEHPSDV(i915)) {
                revids = xehpsdv_revids;
                size = ARRAY_SIZE(xehpsdv_revids);
+       } else if (IS_ADLP_N(i915)) {
+               revids = adlp_n_revids;
+               size = ARRAY_SIZE(adlp_n_revids);
        } else if (IS_ALDERLAKE_P(i915)) {
                revids = adlp_revids;
                size = ARRAY_SIZE(adlp_revids);
index dd8fdd5..24cd3c3 100644 (file)
@@ -1502,11 +1502,10 @@ ilk_dummy_write(struct intel_uncore *uncore)
 static void
 __unclaimed_reg_debug(struct intel_uncore *uncore,
                      const i915_reg_t reg,
-                     const bool read,
-                     const bool before)
+                     const bool read)
 {
        if (drm_WARN(&uncore->i915->drm,
-                    check_for_unclaimed_mmio(uncore) && !before,
+                    check_for_unclaimed_mmio(uncore),
                     "Unclaimed %s register 0x%x\n",
                     read ? "read from" : "write to",
                     i915_mmio_reg_offset(reg)))
@@ -1514,6 +1513,18 @@ __unclaimed_reg_debug(struct intel_uncore *uncore,
                uncore->i915->params.mmio_debug--;
 }
 
+static void
+__unclaimed_previous_reg_debug(struct intel_uncore *uncore,
+                              const i915_reg_t reg,
+                              const bool read)
+{
+       if (check_for_unclaimed_mmio(uncore))
+               drm_dbg(&uncore->i915->drm,
+                       "Unclaimed access detected before %s register 0x%x\n",
+                       read ? "read from" : "write to",
+                       i915_mmio_reg_offset(reg));
+}
+
 static inline void
 unclaimed_reg_debug(struct intel_uncore *uncore,
                    const i915_reg_t reg,
@@ -1526,13 +1537,13 @@ unclaimed_reg_debug(struct intel_uncore *uncore,
        /* interrupts are disabled and re-enabled around uncore->lock usage */
        lockdep_assert_held(&uncore->lock);
 
-       if (before)
+       if (before) {
                spin_lock(&uncore->debug->lock);
-
-       __unclaimed_reg_debug(uncore, reg, read, before);
-
-       if (!before)
+               __unclaimed_previous_reg_debug(uncore, reg, read);
+       } else {
+               __unclaimed_reg_debug(uncore, reg, read);
                spin_unlock(&uncore->debug->lock);
+       }
 }
 
 #define __vgpu_read(x) \
index 10e1e45..c9da101 100644 (file)
@@ -4,6 +4,8 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/string_helpers.h>
+
 #include <drm/drm_print.h>
 
 #include "gt/intel_gt_debugfs.h"
@@ -22,7 +24,7 @@ static int pxp_info_show(struct seq_file *m, void *data)
                return 0;
        }
 
-       drm_printf(&p, "active: %s\n", yesno(intel_pxp_is_active(pxp)));
+       drm_printf(&p, "active: %s\n", str_yes_no(intel_pxp_is_active(pxp)));
        drm_printf(&p, "instance counter: %u\n", pxp->key_instance);
 
        return 0;
index 598840b..92b00b4 100644 (file)
@@ -3,8 +3,6 @@
  * Copyright(c) 2020, Intel Corporation. All rights reserved.
  */
 
-#include <drm/i915_drm.h>
-
 #include "i915_drv.h"
 
 #include "intel_pxp.h"
index 2dac9be..b61fe85 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kref.h>
+#include <linux/string_helpers.h>
 
 #include "gem/i915_gem_pm.h"
 #include "gt/intel_gt.h"
@@ -280,7 +281,7 @@ void i915_active_print(struct i915_active *ref, struct drm_printer *m)
        drm_printf(m, "active %ps:%ps\n", ref->active, ref->retire);
        drm_printf(m, "\tcount: %d\n", atomic_read(&ref->count));
        drm_printf(m, "\tpreallocated barriers? %s\n",
-                  yesno(!llist_empty(&ref->preallocated_barriers)));
+                  str_yes_no(!llist_empty(&ref->preallocated_barriers)));
 
        if (i915_active_acquire_if_busy(ref)) {
                struct active_node *it, *n;
index 1d9da32..664fde2 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/string_helpers.h>
 #include <linux/kernel.h>
 
 #include <drm/drm_print.h>
@@ -375,7 +376,7 @@ static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
        if (vlv_wait_for_pw_status(dev_priv, mask, val))
                drm_dbg(&dev_priv->drm,
                        "timeout waiting for GT wells to go %s\n",
-                       onoff(wait_for_on));
+                       str_on_off(wait_for_on));
 }
 
 static void vlv_check_no_gt_access(struct drm_i915_private *i915)
index df5c62e..2200e3c 100644 (file)
@@ -5010,7 +5010,7 @@ static void quirk_igfx_skip_te_disable(struct pci_dev *dev)
        ver = (dev->device >> 8) & 0xff;
        if (ver != 0x45 && ver != 0x46 && ver != 0x4c &&
            ver != 0x4e && ver != 0x8a && ver != 0x98 &&
-           ver != 0x9a)
+           ver != 0x9a && ver != 0xa7)
                return;
 
        if (risky_device(dev))
index 51e02cf..1eccd97 100644 (file)
@@ -2148,8 +2148,10 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
 int drm_dp_read_sink_count(struct drm_dp_aux *aux);
 
 int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+                                 const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                                  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
 int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+                              const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                               enum drm_dp_phy dp_phy,
                               u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
 int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
index 6722005..7adce32 100644 (file)
@@ -26,8 +26,7 @@
 #ifndef _I915_DRM_H_
 #define _I915_DRM_H_
 
-#include <drm/i915_pciids.h>
-#include <uapi/drm/i915_drm.h>
+#include <linux/types.h>
 
 /* For use by IPS driver */
 unsigned long i915_read_mch_val(void);
index 533890d..0800dc8 100644 (file)
        INTEL_VGA_DEVICE(0xA782, info), \
        INTEL_VGA_DEVICE(0xA783, info), \
        INTEL_VGA_DEVICE(0xA788, info), \
-       INTEL_VGA_DEVICE(0xA789, info)
+       INTEL_VGA_DEVICE(0xA789, info), \
+       INTEL_VGA_DEVICE(0xA78A, info), \
+       INTEL_VGA_DEVICE(0xA78B, info)
 
 #endif /* _I915_PCIIDS_H */
index fc0c145..e507416 100644 (file)
@@ -572,6 +572,53 @@ extern "C" {
  */
 #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8)
 
+/*
+ * Intel Tile 4 layout
+ *
+ * This is a tiled layout using 4KB tiles in a row-major layout. It has the same
+ * shape as Tile Y at two granularities: 4KB (128B x 32) and 64B (16B x 4). It
+ * only differs from Tile Y at the 256B granularity in between. At this
+ * granularity, Tile Y has a shape of 16B x 32 rows, but this tiling has a shape
+ * of 64B x 8 rows.
+ */
+#define I915_FORMAT_MOD_4_TILED         fourcc_mod_code(INTEL, 9)
+
+/*
+ * Intel color control surfaces (CCS) for DG2 render compression.
+ *
+ * The main surface is Tile 4 and at plane index 0. The CCS data is stored
+ * outside of the GEM object in a reserved memory area dedicated for the
+ * storage of the CCS data for all RC/RC_CC/MC compressible GEM objects. The
+ * main surface pitch is required to be a multiple of four Tile 4 widths.
+ */
+#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS fourcc_mod_code(INTEL, 10)
+
+/*
+ * Intel color control surfaces (CCS) for DG2 media compression.
+ *
+ * The main surface is Tile 4 and at plane index 0. For semi-planar formats
+ * like NV12, the Y and UV planes are Tile 4 and are located at plane indices
+ * 0 and 1, respectively. The CCS for all planes are stored outside of the
+ * GEM object in a reserved memory area dedicated for the storage of the
+ * CCS data for all RC/RC_CC/MC compressible GEM objects. The main surface
+ * pitch is required to be a multiple of four Tile 4 widths.
+ */
+#define I915_FORMAT_MOD_4_TILED_DG2_MC_CCS fourcc_mod_code(INTEL, 11)
+
+/*
+ * Intel Color Control Surface with Clear Color (CCS) for DG2 render compression.
+ *
+ * The main surface is Tile 4 and at plane index 0. The CCS data is stored
+ * outside of the GEM object in a reserved memory area dedicated for the
+ * storage of the CCS data for all RC/RC_CC/MC compressible GEM objects. The
+ * main surface pitch is required to be a multiple of four Tile 4 widths. The
+ * clear color is stored at plane index 1 and the pitch should be ignored. The
+ * format of the 256 bits of clear color data matches the one used for the
+ * I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC modifier, see its description
+ * for details.
+ */
+#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC fourcc_mod_code(INTEL, 12)
+
 /*
  * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
  *