summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-01-16 12:57:20 +1000
committerDave Airlie <airlied@redhat.com>2026-01-16 12:57:29 +1000
commit9d10cd526111a989eb353c3a4df9d4c79695ea8d (patch)
tree2e6c5370871c747752d1e09602deaa1374a28f27
parent37b812b7fdc2f1c7cb9e22c888776be7347097b0 (diff)
parentd30f75d2dba913754dbacb982b19b783a30253ea (diff)
Merge tag 'drm-intel-next-2026-01-15' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
Beyond Display: - Make 'guc_hw_reg_state' static as it isn't exported (Ben) - Fix doc build on mei related interface header (Jani) Display related: - Fix ggtt fb alignment on Xe display (Tvrtko) - More display clean-up towards deduplication and full separation (Jani) - Use the consolidated HDMI tables (Suraj) - Account for DSC slice overhead (Ankit) - Prepare GVT for display modularization (Ankit, Jani) - Enable/Disable DC balance along with VRR DSB (Mitul, Ville) - Protection against unsupported modes in LT PHY (Suraj) - Display W/a addition and fixes (Gustavo) - Fix many SPDX identifier comments (Ankit) - Incorporate Xe3_LPD changes for CD2X divider (Gustavo) - Clean up link BW/DSC slice config computation (Imre) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patch.msgid.link/aWkNThVRSkGAfUVv@intel.com
-rw-r--r--drivers/gpu/drm/i915/Makefile6
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.c17
-rw-r--r--drivers/gpu/drm/i915/display/intel_alpm.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c60
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc_state_dump.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c46
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h18
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_params.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reg_defs.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_utils.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.h12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c25
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc_regs.h60
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c513
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h17
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_dram.c42
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c31
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb_buffer.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_gvt_api.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_gvt_api.h21
-rw-r--r--drivers/gpu/drm/i915/display/intel_initial_plane.c193
-rw-r--r--drivers/gpu/drm/i915/display/intel_initial_plane.h (renamed from drivers/gpu/drm/i915/display/intel_plane_initial.h)6
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.c54
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy_regs.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane_initial.c442
-rw-r--r--drivers/gpu/drm/i915/display/intel_rom.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.c46
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c35
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c281
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr_regs.h68
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_clflush.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/aperture_gm.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/cfg_space.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c22
-rw-r--r--drivers/gpu/drm/i915/gvt/debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/gvt/display.c23
-rw-r--r--drivers/gpu/drm/i915/gvt/display.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/display_helpers.h37
-rw-r--r--drivers/gpu/drm/i915/gvt/dmabuf.c6
-rw-r--r--drivers/gpu/drm/i915/gvt/dmabuf.h7
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/execlist.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/fb_decoder.c14
-rw-r--r--drivers/gpu/drm/i915/gvt/fb_decoder.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/firmware.c4
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c9
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.h24
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c21
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c18
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.c11
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio_context.h5
-rw-r--r--drivers/gpu/drm/i915/gvt/opregion.c3
-rw-r--r--drivers/gpu/drm/i915/gvt/page_track.c3
-rw-r--r--drivers/gpu/drm/i915/gvt/sched_policy.c3
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c8
-rw-r--r--drivers/gpu/drm/i915/gvt/trace.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/trace_points.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/vgpu.c6
-rw-r--r--drivers/gpu/drm/i915/i915_config.c3
-rw-r--r--drivers/gpu/drm/i915/i915_config.h10
-rw-r--r--drivers/gpu/drm/i915/i915_driver.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c2
-rw-r--r--drivers/gpu/drm/i915/i915_initial_plane.c290
-rw-r--r--drivers/gpu/drm/i915/i915_initial_plane.h9
-rw-r--r--drivers/gpu/drm/i915/i915_request.c3
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h4
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.c11
-rw-r--r--drivers/gpu/drm/i915/intel_gvt_mmio_table.c4
-rw-r--r--drivers/gpu/drm/xe/Makefile6
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_config.h5
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h22
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h7
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h11
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.c2
-rw-r--r--drivers/gpu/drm/xe/display/xe_fb_pin.c2
-rw-r--r--drivers/gpu/drm/xe/display/xe_initial_plane.c189
-rw-r--r--drivers/gpu/drm/xe/display/xe_initial_plane.h9
-rw-r--r--drivers/gpu/drm/xe/display/xe_plane_initial.c321
-rw-r--r--include/drm/intel/display_parent_interface.h17
-rw-r--r--include/drm/intel/intel_lb_mei_interface.h3
95 files changed, 2008 insertions, 1434 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5f7b2bbe448c..241b1d2e2603 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -78,6 +78,7 @@ i915-$(CONFIG_PERF_EVENTS) += \
i915-y += \
i915_display_pc8.o \
i915_hdcp_gsc.o \
+ i915_initial_plane.o \
i915_panic.o
# "Graphics Technology" (aka we talk to the gpu)
@@ -288,6 +289,7 @@ i915-y += \
display/intel_hotplug.o \
display/intel_hotplug_irq.o \
display/intel_hti.o \
+ display/intel_initial_plane.o \
display/intel_link_bw.o \
display/intel_load_detect.o \
display/intel_lpe_audio.o \
@@ -300,7 +302,6 @@ i915-y += \
display/intel_pch_display.o \
display/intel_pch_refclk.o \
display/intel_plane.o \
- display/intel_plane_initial.o \
display/intel_pmdemand.o \
display/intel_psr.o \
display/intel_quirks.o \
@@ -381,6 +382,9 @@ i915-y += \
i915-$(CONFIG_DRM_I915_DP_TUNNEL) += \
display/intel_dp_tunnel.o
+i915-$(CONFIG_DRM_I915_GVT) += \
+ display/intel_gvt_api.o
+
i915-y += \
i915_perf.o
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c
index 167277cd8877..39dfceb438ae 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -7,7 +7,6 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "i9xx_wm_regs.h"
@@ -17,6 +16,7 @@
#include "intel_display.h"
#include "intel_display_regs.h"
#include "intel_display_trace.h"
+#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_fb.h"
#include "intel_mchbar_regs.h"
@@ -1863,8 +1863,7 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_uncore *uncore = &dev_priv->uncore;
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct vlv_fifo_state *fifo_state =
@@ -2743,12 +2742,12 @@ static void ilk_compute_wm_level(struct intel_display *display,
static void hsw_read_wm_latency(struct intel_display *display, u16 wm[])
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u64 sskpd;
display->wm.num_levels = 5;
- sskpd = intel_uncore_read64(&i915->uncore, MCH_SSKPD);
+ sskpd = intel_uncore_read64(uncore, MCH_SSKPD);
wm[0] = REG_FIELD_GET64(SSKPD_NEW_WM0_MASK_HSW, sskpd);
if (wm[0] == 0)
@@ -2761,12 +2760,12 @@ static void hsw_read_wm_latency(struct intel_display *display, u16 wm[])
static void snb_read_wm_latency(struct intel_display *display, u16 wm[])
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 sskpd;
display->wm.num_levels = 4;
- sskpd = intel_uncore_read(&i915->uncore, MCH_SSKPD);
+ sskpd = intel_uncore_read(uncore, MCH_SSKPD);
wm[0] = REG_FIELD_GET(SSKPD_WM0_MASK_SNB, sskpd);
wm[1] = REG_FIELD_GET(SSKPD_WM1_MASK_SNB, sskpd);
@@ -2776,12 +2775,12 @@ static void snb_read_wm_latency(struct intel_display *display, u16 wm[])
static void ilk_read_wm_latency(struct intel_display *display, u16 wm[])
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 mltr;
display->wm.num_levels = 3;
- mltr = intel_uncore_read(&i915->uncore, MLTR_ILK);
+ mltr = intel_uncore_read(uncore, MLTR_ILK);
/* ILK primary LP0 latency is 700 ns */
wm[0] = 7;
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h
index 53599b464dea..c6a4ec5b9561 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2024 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index d27835ed49c2..4ee3f5172f4e 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -6,7 +6,6 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_bw.h"
#include "intel_crtc.h"
@@ -75,11 +74,11 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp,
int point)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 dclk_ratio, dclk_reference;
u32 val;
- val = intel_uncore_read(&i915->uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
+ val = intel_uncore_read(uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
if (val & DG1_QCLK_REFERENCE)
dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
@@ -87,18 +86,18 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000);
- val = intel_uncore_read(&i915->uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
+ val = intel_uncore_read(uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
if (val & DG1_GEAR_TYPE)
sp->dclk *= 2;
if (sp->dclk == 0)
return -EINVAL;
- val = intel_uncore_read(&i915->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
+ val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
sp->t_rp = REG_FIELD_GET(DG1_DRAM_T_RP_MASK, val);
sp->t_rdpre = REG_FIELD_GET(DG1_DRAM_T_RDPRE_MASK, val);
- val = intel_uncore_read(&i915->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
+ val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
sp->t_rcd = REG_FIELD_GET(DG1_DRAM_T_RCD_MASK, val);
sp->t_ras = REG_FIELD_GET(DG1_DRAM_T_RAS_MASK, val);
@@ -212,14 +211,12 @@ static int icl_pcode_restrict_qgv_points(struct intel_display *display,
static int mtl_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp, int point)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val, val2;
u16 dclk;
- val = intel_uncore_read(&i915->uncore,
- MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
- val2 = intel_uncore_read(&i915->uncore,
- MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
+ val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
+ val2 = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
dclk = REG_FIELD_GET(MTL_DCLK_MASK, val);
sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000);
sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val);
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 0aa59d624095..9bfbfbf34dc0 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -39,6 +39,7 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
+#include "intel_display_wa.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
@@ -1858,6 +1859,20 @@ static void bxt_de_pll_enable(struct intel_display *display, int vco)
static void icl_cdclk_pll_disable(struct intel_display *display)
{
+ /*
+ * Wa_13012396614:
+ * Fixes: A sporadic race condition between MDCLK selection and PLL
+ * enabling.
+ * Workaround:
+ * Change programming of MDCLK source selection in CDCLK_CTL:
+ * - When disabling the CDCLK PLL, first set MDCLK source to be CD2XCLK.
+ * - When enabling the CDCLK PLL, update MDCLK source selection only
+ * after the PLL is enabled (which is already done as part of the
+ * normal flow of _bxt_set_cdclk()).
+ */
+ if (intel_display_wa(display, 13012396614))
+ intel_de_rmw(display, CDCLK_CTL, MDCLK_SOURCE_SEL_MASK, MDCLK_SOURCE_SEL_CD2XCLK);
+
intel_de_rmw(display, BXT_DE_PLL_ENABLE,
BXT_DE_PLL_PLL_ENABLE, 0);
@@ -1933,6 +1948,8 @@ static u32 bxt_cdclk_cd2x_pipe(struct intel_display *display, enum pipe pipe)
static u32 bxt_cdclk_cd2x_div_sel(struct intel_display *display,
int cdclk, int vco, u16 waveform)
{
+ u32 ret;
+
/* cdclk = vco / 2 / div{1,1.5,2,4} */
switch (cdclk_divider(cdclk, vco, waveform)) {
default:
@@ -1941,14 +1958,27 @@ static u32 bxt_cdclk_cd2x_div_sel(struct intel_display *display,
drm_WARN_ON(display->drm, vco != 0);
fallthrough;
case 2:
- return BXT_CDCLK_CD2X_DIV_SEL_1;
+ ret = BXT_CDCLK_CD2X_DIV_SEL_1;
+ break;
case 3:
- return BXT_CDCLK_CD2X_DIV_SEL_1_5;
+ ret = BXT_CDCLK_CD2X_DIV_SEL_1_5;
+ break;
case 4:
- return BXT_CDCLK_CD2X_DIV_SEL_2;
+ ret = BXT_CDCLK_CD2X_DIV_SEL_2;
+ break;
case 8:
- return BXT_CDCLK_CD2X_DIV_SEL_4;
+ ret = BXT_CDCLK_CD2X_DIV_SEL_4;
+ break;
}
+
+ /*
+ * On Xe3_LPD onward, the expectation is to always have
+ * BXT_CDCLK_CD2X_DIV_SEL_1 as the default.
+ */
+ if (DISPLAY_VER(display) >= 30)
+ drm_WARN_ON(display->drm, ret != BXT_CDCLK_CD2X_DIV_SEL_1);
+
+ return ret;
}
static u16 cdclk_squash_waveform(struct intel_display *display,
@@ -2136,8 +2166,10 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
waveform = cdclk_squash_waveform(display, cdclk);
- val = bxt_cdclk_cd2x_div_sel(display, cdclk, vco, waveform) |
- bxt_cdclk_cd2x_pipe(display, pipe);
+ val = bxt_cdclk_cd2x_div_sel(display, cdclk, vco, waveform);
+
+ if (DISPLAY_VER(display) < 30)
+ val |= bxt_cdclk_cd2x_pipe(display, pipe);
/*
* Disable SSA Precharge when CD clock frequency < 500 MHz,
@@ -2147,10 +2179,20 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
cdclk >= 500000)
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
- if (DISPLAY_VER(display) >= 20)
- val |= xe2lpd_mdclk_source_sel(display);
- else
+ if (DISPLAY_VER(display) >= 20) {
+ /*
+ * Wa_13012396614 requires selecting CD2XCLK as MDCLK source
+ * prior to disabling the PLL, which is already handled by
+ * icl_cdclk_pll_disable(). Here we are just making sure
+ * we keep the expected value.
+ */
+ if (intel_display_wa(display, 13012396614) && vco == 0)
+ val |= MDCLK_SOURCE_SEL_CD2XCLK;
+ else
+ val |= xe2lpd_mdclk_source_sel(display);
+ } else {
val |= skl_cdclk_decimal(cdclk);
+ }
return val;
}
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index c128bc4215c4..682bf1be350d 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -31,8 +31,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include "i915_drv.h"
-#include "i915_utils.h" /* for i915_inject_probe_failure() */
#include "intel_connector.h"
#include "intel_display_core.h"
#include "intel_display_debugfs.h"
diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
index c2a6217c2262..234843b8f83a 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -303,6 +303,14 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
drm_printf(&p, "vrr: vmin vblank: %d, vmax vblank: %d, vmin vtotal: %d, vmax vtotal: %d\n",
intel_vrr_vmin_vblank_start(pipe_config), intel_vrr_vmax_vblank_start(pipe_config),
intel_vrr_vmin_vtotal(pipe_config), intel_vrr_vmax_vtotal(pipe_config));
+ drm_printf(&p, "vrr: dc balance: %s, vmin: %d vmax: %d guardband: %d, slope: %d max increase: %d max decrease: %d vblank target: %d\n",
+ str_yes_no(pipe_config->vrr.dc_balance.enable),
+ pipe_config->vrr.dc_balance.vmin, pipe_config->vrr.dc_balance.vmax,
+ pipe_config->vrr.dc_balance.guardband,
+ pipe_config->vrr.dc_balance.slope,
+ pipe_config->vrr.dc_balance.max_increase,
+ pipe_config->vrr.dc_balance.max_decrease,
+ pipe_config->vrr.dc_balance.vblank_target);
drm_printf(&p, "requested mode: " DRM_MODE_FMT "\n",
DRM_MODE_ARG(&pipe_config->hw.mode));
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 2c87c58812da..7288065d2461 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2671,15 +2671,18 @@ static int intel_c20pll_calc_state(const struct intel_crtc_state *crtc_state,
hw_state->cx0pll.use_c10 = false;
hw_state->cx0pll.lane_count = crtc_state->lane_count;
- /* try computed C20 HDMI tables before using consolidated tables */
- if (!is_dp)
- /* TODO: Update SSC state for HDMI as well */
- err = intel_c20_compute_hdmi_tmds_pll(crtc_state, &hw_state->cx0pll.c20);
-
+ /*
+ * Try the ideal C20 HDMI tables before computing them, since the calculated
+ * values, although correct, may not be optimal.
+ */
if (err)
err = intel_c20pll_calc_state_from_table(crtc_state, encoder,
&hw_state->cx0pll);
+ /* TODO: Update SSC state for HDMI as well */
+ if (!is_dp && err)
+ err = intel_c20_compute_hdmi_tmds_pll(crtc_state, &hw_state->cx0pll.c20);
+
if (err)
return err;
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9f10113e2d18..ae98ac23ea22 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: MIT
+/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index 8df5cd5ce418..658890f73515 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2023 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index d5947cc9b94c..81b3a6692ca2 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -50,7 +50,6 @@
#include "g4x_hdmi.h"
#include "hsw_ips.h"
#include "i915_config.h"
-#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_plane.h"
#include "i9xx_plane_regs.h"
@@ -100,6 +99,7 @@
#include "intel_frontbuffer.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
+#include "intel_initial_plane.h"
#include "intel_link_bw.h"
#include "intel_lt_phy.h"
#include "intel_lvds.h"
@@ -113,7 +113,6 @@
#include "intel_pfit.h"
#include "intel_pipe_crc.h"
#include "intel_plane.h"
-#include "intel_plane_initial.h"
#include "intel_pmdemand.h"
#include "intel_pps.h"
#include "intel_psr.h"
@@ -639,7 +638,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 &&
hsw_ips_disable(crtc_state)) {
crtc_state->ips_enabled = false;
- intel_plane_initial_vblank_wait(crtc);
+ intel_initial_plane_vblank_wait(crtc);
}
/*
@@ -653,7 +652,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
*/
if (HAS_GMCH(display) &&
intel_set_memory_cxsr(display, false))
- intel_plane_initial_vblank_wait(crtc);
+ intel_initial_plane_vblank_wait(crtc);
/*
* Gen2 reports pipe underruns whenever all planes are disabled.
@@ -663,7 +662,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
intel_set_cpu_fifo_underrun_reporting(display, crtc->pipe, false);
intel_plane_disable_arm(NULL, plane, crtc_state);
- intel_plane_initial_vblank_wait(crtc);
+ intel_initial_plane_vblank_wait(crtc);
}
unsigned int
@@ -1158,6 +1157,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
if (intel_crtc_vrr_disabling(state, crtc)) {
intel_vrr_disable(old_crtc_state);
+ intel_vrr_dcb_reset(old_crtc_state, crtc);
intel_crtc_update_active_timings(old_crtc_state, false);
}
@@ -5476,6 +5476,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_LLI(cmrr.cmrr_m);
PIPE_CONF_CHECK_LLI(cmrr.cmrr_n);
PIPE_CONF_CHECK_BOOL(cmrr.enable);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.vmin);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.vmax);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.guardband);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.slope);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.max_increase);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.max_decrease);
+ PIPE_CONF_CHECK_I(vrr.dc_balance.vblank_target);
}
if (!fastset || intel_vrr_always_use_vrr_tg(display)) {
@@ -6856,6 +6863,9 @@ static void intel_update_crtc(struct intel_atomic_state *state,
intel_crtc_update_active_timings(new_crtc_state,
new_crtc_state->vrr.enable);
+ if (new_crtc_state->vrr.dc_balance.enable)
+ intel_vrr_dcb_increment_flip_count(new_crtc_state, crtc);
+
/*
* We usually enable FIFO underrun interrupts as part of the
* CRTC enable sequence during modesets. But when we inherit a
@@ -7154,7 +7164,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
{
- struct drm_i915_private *i915 = to_i915(intel_state->base.dev);
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;
long ret;
@@ -7163,7 +7172,7 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat
for_each_new_plane_in_state(&intel_state->base, plane, new_plane_state, i) {
if (new_plane_state->fence) {
ret = dma_fence_wait_timeout(new_plane_state->fence, false,
- i915_fence_timeout(i915));
+ i915_fence_timeout());
if (ret <= 0)
break;
@@ -7319,6 +7328,21 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
if (new_crtc_state->use_flipq)
intel_flipq_wait_dmc_halt(new_crtc_state->dsb_commit, crtc);
+ if (new_crtc_state->vrr.dc_balance.enable) {
+ /*
+ * Pause the DMC DC balancing for the remainder of
+ * the commit so that vmin/vmax won't change after
+ * we've baked them into the DSB vblank evasion
+ * commands.
+ *
+ * FIXME maybe need a small delay here to make sure
+ * DMC has finished updating the values? Or we need
+ * a better DMC<->driver protocol that gives is real
+ * guarantees about that...
+ */
+ intel_pipedmc_dcb_disable(NULL, crtc);
+ }
+
if (intel_crtc_needs_color_update(new_crtc_state))
intel_color_commit_noarm(new_crtc_state->dsb_commit,
new_crtc_state);
@@ -7372,6 +7396,10 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
intel_dsb_wait_for_delayed_vblank(state, new_crtc_state->dsb_commit);
intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
new_crtc_state);
+
+ if (new_crtc_state->vrr.dc_balance.enable)
+ intel_pipedmc_dcb_enable(new_crtc_state->dsb_commit, crtc);
+
intel_dsb_interrupt(new_crtc_state->dsb_commit);
}
@@ -7381,7 +7409,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
static void intel_atomic_commit_tail(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
- struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
@@ -7591,7 +7619,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* so enable debugging for the next modeset - and hope we catch
* the culprit.
*/
- intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
+ intel_uncore_arm_unclaimed_mmio_detection(uncore);
}
/*
* Delay re-enabling DC states by 17 ms to avoid the off->on->off
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index 50b2e9ae2c18..6c74d6b0cc48 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -205,6 +205,7 @@ struct intel_display_platforms {
#define HAS_ULTRAJOINER(__display) (((__display)->platform.dgfx && \
DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
#define HAS_VRR(__display) (DISPLAY_VER(__display) >= 11)
+#define HAS_VRR_DC_BALANCE(__display) (DISPLAY_VER(__display) >= 30)
#define INTEL_NUM_PIPES(__display) (hweight8(DISPLAY_RUNTIME_INFO(__display)->pipe_mask))
#define OVERLAY_NEEDS_PHYSICAL(__display) (DISPLAY_INFO(__display)->overlay_needs_physical)
#define SUPPORTS_TV(__display) (DISPLAY_INFO(__display)->supports_tv)
@@ -260,6 +261,23 @@ struct intel_display_platforms {
((id) == ARLS_HOST_BRIDGE_PCI_ID3) || \
((id) == ARLS_HOST_BRIDGE_PCI_ID4))
+#define INTEL_DISPLAY_DEVICE_PIPE_OFFSET(display, pipe) \
+ (DISPLAY_INFO((display))->pipe_offsets[(pipe)] - \
+ DISPLAY_INFO((display))->pipe_offsets[PIPE_A] + \
+ DISPLAY_MMIO_BASE((display)))
+
+#define INTEL_DISPLAY_DEVICE_TRANS_OFFSET(display, trans) \
+ (DISPLAY_INFO((display))->trans_offsets[(trans)] - \
+ DISPLAY_INFO((display))->trans_offsets[TRANSCODER_A] + \
+ DISPLAY_MMIO_BASE((display)))
+
+#define INTEL_DISPLAY_DEVICE_CURSOR_OFFSET(display, pipe) \
+ (DISPLAY_INFO((display))->cursor_offsets[(pipe)] - \
+ DISPLAY_INFO((display))->cursor_offsets[PIPE_A] + \
+ DISPLAY_MMIO_BASE((display)))
+
+#define DISPLAY_MMIO_BASE(display) (DISPLAY_INFO((display))->mmio_offset)
+
struct intel_display_runtime_info {
struct intel_display_ip_ver {
u16 ver;
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index e1d29aea0ddc..268b1de45b81 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -18,8 +18,6 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
-#include "i915_drv.h"
-#include "i915_utils.h" /* for i915_inject_probe_failure() */
#include "i9xx_wm.h"
#include "intel_acpi.h"
#include "intel_atomic.h"
@@ -54,11 +52,11 @@
#include "intel_hdcp.h"
#include "intel_hotplug.h"
#include "intel_hti.h"
+#include "intel_initial_plane.h"
#include "intel_modeset_lock.h"
#include "intel_modeset_setup.h"
#include "intel_opregion.h"
#include "intel_overlay.h"
-#include "intel_plane_initial.h"
#include "intel_pmdemand.h"
#include "intel_pps.h"
#include "intel_psr.h"
diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h
index b01bc5700c52..b95ecf728daa 100644
--- a/drivers/gpu/drm/i915/display/intel_display_params.h
+++ b/drivers/gpu/drm/i915/display/intel_display_params.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: MIT
+/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 47042a4c3a30..d27397f43863 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -8,7 +8,6 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_cdclk.h"
@@ -31,6 +30,7 @@
#include "intel_pmdemand.h"
#include "intel_pps_regs.h"
#include "intel_snps_phy.h"
+#include "intel_step.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
#include "vlv_sideband.h"
@@ -1328,7 +1328,6 @@ static void hsw_disable_lcpll(struct intel_display *display,
*/
static void hsw_restore_lcpll(struct intel_display *display)
{
- struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm);
u32 val;
int ret;
diff --git a/drivers/gpu/drm/i915/display/intel_display_reg_defs.h b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
index b83ad06f2ea7..175334b41bba 100644
--- a/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
@@ -8,8 +8,6 @@
#include "i915_reg_defs.h"
-#define DISPLAY_MMIO_BASE(dev_priv) (DISPLAY_INFO(dev_priv)->mmio_offset)
-
#define VLV_DISPLAY_BASE 0x180000
/*
@@ -36,14 +34,9 @@
* Device info offset array based helpers for groups of registers with unevenly
* spaced base offsets.
*/
-#define _MMIO_PIPE2(display, pipe, reg) _MMIO(DISPLAY_INFO(display)->pipe_offsets[(pipe)] - \
- DISPLAY_INFO(display)->pipe_offsets[PIPE_A] + \
- DISPLAY_MMIO_BASE(display) + (reg))
-#define _MMIO_TRANS2(display, tran, reg) _MMIO(DISPLAY_INFO(display)->trans_offsets[(tran)] - \
- DISPLAY_INFO(display)->trans_offsets[TRANSCODER_A] + \
- DISPLAY_MMIO_BASE(display) + (reg))
-#define _MMIO_CURSOR2(display, pipe, reg) _MMIO(DISPLAY_INFO(display)->cursor_offsets[(pipe)] - \
- DISPLAY_INFO(display)->cursor_offsets[PIPE_A] + \
- DISPLAY_MMIO_BASE(display) + (reg))
+
+#define _MMIO_PIPE2(display, pipe, reg) _MMIO(INTEL_DISPLAY_DEVICE_PIPE_OFFSET((display), (pipe)) + (reg))
+#define _MMIO_TRANS2(display, trans, reg) _MMIO(INTEL_DISPLAY_DEVICE_TRANS_OFFSET((display), (trans)) + (reg))
+#define _MMIO_CURSOR2(display, pipe, reg) _MMIO(INTEL_DISPLAY_DEVICE_CURSOR_OFFSET((display), (pipe)) + (reg))
#endif /* __INTEL_DISPLAY_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index eb2e3f1e83c9..6b92f333e18b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1385,6 +1385,13 @@ struct intel_crtc_state {
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
+ struct {
+ bool enable;
+ u16 vmin, vmax;
+ u16 guardband, slope;
+ u16 max_increase, max_decrease;
+ u16 vblank_target;
+ } dc_balance;
} vrr;
/* Content Match Refresh Rate state */
@@ -1525,6 +1532,10 @@ struct intel_crtc {
struct intel_link_m_n m_n, m2_n2;
} drrs;
+ struct {
+ u64 flip_count;
+ } dc_balance;
+
int scanline_offset;
struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_utils.h b/drivers/gpu/drm/i915/display/intel_display_utils.h
index 2a18f160320c..affa3179f52c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_utils.h
+++ b/drivers/gpu/drm/i915/display/intel_display_utils.h
@@ -9,18 +9,14 @@
struct intel_display;
-#ifndef MISSING_CASE
#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
__stringify(x), (long)(x))
-#endif
-#ifndef fetch_and_zero
#define fetch_and_zero(ptr) ({ \
typeof(*ptr) __T = *(ptr); \
*(ptr) = (typeof(*ptr))0; \
__T; \
})
-#endif
#define KHz(x) (1000 * (x))
#define MHz(x) KHz(1000 * (x))
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c
index a00af39f7538..581d943b9bdc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.c
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.c
@@ -62,18 +62,20 @@ static bool intel_display_needs_wa_16025573575(struct intel_display *display)
bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name)
{
switch (wa) {
+ case INTEL_DISPLAY_WA_13012396614:
+ return DISPLAY_VERx100(display) == 3000;
+ case INTEL_DISPLAY_WA_14011503117:
+ return DISPLAY_VER(display) == 13;
+ case INTEL_DISPLAY_WA_14025769978:
+ return DISPLAY_VER(display) == 35;
+ case INTEL_DISPLAY_WA_15018326506:
+ return display->platform.battlemage;
case INTEL_DISPLAY_WA_16023588340:
return intel_display_needs_wa_16023588340(display);
case INTEL_DISPLAY_WA_16025573575:
return intel_display_needs_wa_16025573575(display);
- case INTEL_DISPLAY_WA_14011503117:
- return DISPLAY_VER(display) == 13;
case INTEL_DISPLAY_WA_22014263786:
return IS_DISPLAY_VERx100(display, 1100, 1400);
- case INTEL_DISPLAY_WA_15018326506:
- return display->platform.battlemage;
- case INTEL_DISPLAY_WA_14025769978:
- return DISPLAY_VER(display) == 35;
default:
drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name);
break;
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h
index a68c0bb7e516..40f989f19df1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.h
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.h
@@ -21,13 +21,19 @@ static inline bool intel_display_needs_wa_16023588340(struct intel_display *disp
bool intel_display_needs_wa_16023588340(struct intel_display *display);
#endif
+/*
+ * This enum lists display workarounds; each entry here must have a
+ * corresponding case in __intel_display_wa(). Keep both sorted by lineage
+ * number.
+ */
enum intel_display_wa {
+ INTEL_DISPLAY_WA_13012396614,
+ INTEL_DISPLAY_WA_14011503117,
+ INTEL_DISPLAY_WA_14025769978,
+ INTEL_DISPLAY_WA_15018326506,
INTEL_DISPLAY_WA_16023588340,
INTEL_DISPLAY_WA_16025573575,
- INTEL_DISPLAY_WA_14011503117,
INTEL_DISPLAY_WA_22014263786,
- INTEL_DISPLAY_WA_15018326506,
- INTEL_DISPLAY_WA_14025769978,
};
bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name);
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 2fb6fec6dc99..1182bc9a2e6d 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -859,6 +859,14 @@ static void dmc_configure_event(struct intel_display *display,
dmc_id, num_handlers, event_id);
}
+void intel_dmc_configure_dc_balance_event(struct intel_display *display,
+ enum pipe pipe, bool enable)
+{
+ enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
+
+ dmc_configure_event(display, dmc_id, PIPEDMC_EVENT_ADAPTIVE_DCB_TRIGGER, enable);
+}
+
/**
* intel_dmc_block_pkgc() - block PKG C-state
* @display: display instance
@@ -1755,3 +1763,20 @@ u32 intel_pipedmc_start_mmioaddr(struct intel_crtc *crtc)
return dmc ? dmc->dmc_info[dmc_id].start_mmioaddr : 0;
}
+
+void intel_pipedmc_dcb_enable(struct intel_dsb *dsb, struct intel_crtc *crtc)
+{
+ struct intel_display *display = to_intel_display(crtc);
+ enum pipe pipe = crtc->pipe;
+
+ intel_de_write_dsb(display, dsb, PIPEDMC_DCB_CTL(pipe),
+ PIPEDMC_ADAPTIVE_DCB_ENABLE);
+}
+
+void intel_pipedmc_dcb_disable(struct intel_dsb *dsb, struct intel_crtc *crtc)
+{
+ struct intel_display *display = to_intel_display(crtc);
+ enum pipe pipe = crtc->pipe;
+
+ intel_de_write_dsb(display, dsb, PIPEDMC_DCB_CTL(pipe), 0);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h
index 40e9dcb033cc..3d8a9a593319 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc.h
@@ -15,6 +15,7 @@ struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_dmc_snapshot;
+struct intel_dsb;
void intel_dmc_init(struct intel_display *display);
void intel_dmc_load_program(struct intel_display *display);
@@ -24,6 +25,8 @@ void intel_dmc_enable_pipe(const struct intel_crtc_state *crtc_state);
void intel_dmc_disable_pipe(const struct intel_crtc_state *crtc_state);
void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe,
bool block);
+void intel_dmc_configure_dc_balance_event(struct intel_display *display,
+ enum pipe pipe, bool enable);
void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display,
enum pipe pipe, bool enable);
void intel_dmc_fini(struct intel_display *display);
@@ -39,6 +42,8 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display, bool star
void assert_main_dmc_loaded(struct intel_display *display);
void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe);
+void intel_pipedmc_dcb_enable(struct intel_dsb *dsb, struct intel_crtc *crtc);
+void intel_pipedmc_dcb_disable(struct intel_dsb *dsb, struct intel_crtc *crtc);
u32 intel_pipedmc_start_mmioaddr(struct intel_crtc *crtc);
void intel_pipedmc_enable_event(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
index c5aa49921cb9..38e342b45af0 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
@@ -584,4 +584,64 @@ enum pipedmc_event_id {
#define PTL_PIPEDMC_EXEC_TIME_LINES(start_mmioaddr) _MMIO((start_mmioaddr) + 0x6b8)
#define PTL_PIPEDMC_END_OF_EXEC_GB(start_mmioaddr) _MMIO((start_mmioaddr) + 0x6c0)
+#define _PIPEDMC_DCB_CTL_A 0x5f1a0
+#define _PIPEDMC_DCB_CTL_B 0x5f5a0
+#define PIPEDMC_DCB_CTL(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_CTL_A,\
+ _PIPEDMC_DCB_CTL_B)
+#define PIPEDMC_ADAPTIVE_DCB_ENABLE REG_BIT(31)
+
+#define _PIPEDMC_DCB_VBLANK_A 0x5f1bc
+#define _PIPEDMC_DCB_VBLANK_B 0x5f5bc
+#define PIPEDMC_DCB_VBLANK(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_VBLANK_A,\
+ _PIPEDMC_DCB_VBLANK_B)
+
+#define _PIPEDMC_DCB_SLOPE_A 0x5f1b8
+#define _PIPEDMC_DCB_SLOPE_B 0x5f5b8
+#define PIPEDMC_DCB_SLOPE(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_SLOPE_A,\
+ _PIPEDMC_DCB_SLOPE_B)
+
+#define _PIPEDMC_DCB_GUARDBAND_A 0x5f1b4
+#define _PIPEDMC_DCB_GUARDBAND_B 0x5f5b4
+#define PIPEDMC_DCB_GUARDBAND(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_GUARDBAND_A,\
+ _PIPEDMC_DCB_GUARDBAND_B)
+
+#define _PIPEDMC_DCB_MAX_INCREASE_A 0x5f1ac
+#define _PIPEDMC_DCB_MAX_INCREASE_B 0x5f5ac
+#define PIPEDMC_DCB_MAX_INCREASE(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_MAX_INCREASE_A,\
+ _PIPEDMC_DCB_MAX_INCREASE_B)
+
+#define _PIPEDMC_DCB_MAX_DECREASE_A 0x5f1b0
+#define _PIPEDMC_DCB_MAX_DECREASE_B 0x5f5b0
+#define PIPEDMC_DCB_MAX_DECREASE(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_MAX_DECREASE_A,\
+ _PIPEDMC_DCB_MAX_DECREASE_B)
+
+#define _PIPEDMC_DCB_VMIN_A 0x5f1a4
+#define _PIPEDMC_DCB_VMIN_B 0x5f5a4
+#define PIPEDMC_DCB_VMIN(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_VMIN_A,\
+ _PIPEDMC_DCB_VMIN_B)
+
+#define _PIPEDMC_DCB_VMAX_A 0x5f1a8
+#define _PIPEDMC_DCB_VMAX_B 0x5f5a8
+#define PIPEDMC_DCB_VMAX(pipe) _MMIO_PIPE((pipe), _PIPEDMC_DCB_VMAX_A,\
+ _PIPEDMC_DCB_VMAX_B)
+
+#define _PIPEDMC_DCB_DEBUG_A 0x5f1c0
+#define _PIPEDMC_DCB_DEBUG_B 0x5f5c0
+#define PIPEDMC_DCB_DEBUG(pipe) _MMIO_PIPE(pipe, _PIPEDMC_DCB_DEBUG_A,\
+ _PIPEDMC_DCB_DEBUG_B)
+
+#define _PIPEDMC_EVT_CTL_3_A 0x5f040
+#define _PIPEDMC_EVT_CTL_3_B 0x5f440
+#define PIPEDMC_EVT_CTL_3(pipe) _MMIO_PIPE(pipe, _PIPEDMC_EVT_CTL_3_A,\
+ _PIPEDMC_EVT_CTL_3_B)
+
+#define _PIPEDMC_DCB_FLIP_COUNT_A 0x906a4
+#define _PIPEDMC_DCB_FLIP_COUNT_B 0x986a4
+#define PIPEDMC_DCB_FLIP_COUNT(pipe) _MMIO_PIPE(pipe, _PIPEDMC_DCB_FLIP_COUNT_A,\
+ _PIPEDMC_DCB_FLIP_COUNT_B)
+
+#define _PIPEDMC_DCB_BALANCE_RESET_A 0x906a8
+#define _PIPEDMC_DCB_BALANCE_RESET_B 0x986a8
+#define PIPEDMC_DCB_BALANCE_RESET(pipe) _MMIO_PIPE(pipe, _PIPEDMC_DCB_BALANCE_RESET_A,\
+ _PIPEDMC_DCB_BALANCE_RESET_B)
#endif /* __INTEL_DMC_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2dadbf7e8922..7e022c47e8ac 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -868,50 +868,32 @@ small_joiner_ram_size_bits(struct intel_display *display)
return 6144 * 8;
}
-static u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp)
+static int align_min_vesa_compressed_bpp_x16(int min_link_bpp_x16)
{
- u32 bits_per_pixel = bpp;
int i;
- /* Error out if the max bpp is less than smallest allowed valid bpp */
- if (bits_per_pixel < valid_dsc_bpp[0]) {
- drm_dbg_kms(display->drm, "Unsupported BPP %u, min %u\n",
- bits_per_pixel, valid_dsc_bpp[0]);
- return 0;
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
+ int vesa_bpp_x16 = fxp_q4_from_int(valid_dsc_bpp[i]);
+
+ if (vesa_bpp_x16 >= min_link_bpp_x16)
+ return vesa_bpp_x16;
}
- /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
- if (DISPLAY_VER(display) >= 13) {
- bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
+ return 0;
+}
- /*
- * According to BSpec, 27 is the max DSC output bpp,
- * 8 is the min DSC output bpp.
- * While we can still clamp higher bpp values to 27, saving bandwidth,
- * if it is required to oompress up to bpp < 8, means we can't do
- * that and probably means we can't fit the required mode, even with
- * DSC enabled.
- */
- if (bits_per_pixel < 8) {
- drm_dbg_kms(display->drm,
- "Unsupported BPP %u, min 8\n",
- bits_per_pixel);
- return 0;
- }
- bits_per_pixel = min_t(u32, bits_per_pixel, 27);
- } else {
- /* Find the nearest match in the array of known BPPs from VESA */
- for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
- if (bits_per_pixel < valid_dsc_bpp[i + 1])
- break;
- }
- drm_dbg_kms(display->drm, "Set dsc bpp from %d to VESA %d\n",
- bits_per_pixel, valid_dsc_bpp[i]);
+static int align_max_vesa_compressed_bpp_x16(int max_link_bpp_x16)
+{
+ int i;
+
+ for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) {
+ int vesa_bpp_x16 = fxp_q4_from_int(valid_dsc_bpp[i]);
- bits_per_pixel = valid_dsc_bpp[i];
+ if (vesa_bpp_x16 <= max_link_bpp_x16)
+ return vesa_bpp_x16;
}
- return bits_per_pixel;
+ return 0;
}
static int bigjoiner_interface_bits(struct intel_display *display)
@@ -977,64 +959,6 @@ u32 get_max_compressed_bpp_with_joiner(struct intel_display *display,
return max_bpp;
}
-/* TODO: return a bpp_x16 value */
-u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display,
- u32 link_clock, u32 lane_count,
- u32 mode_clock, u32 mode_hdisplay,
- int num_joined_pipes,
- enum intel_output_format output_format,
- u32 pipe_bpp,
- u32 timeslots)
-{
- u32 bits_per_pixel, joiner_max_bpp;
-
- /*
- * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
- * (LinkSymbolClock)* 8 * (TimeSlots / 64)
- * for SST -> TimeSlots is 64(i.e all TimeSlots that are available)
- * for MST -> TimeSlots has to be calculated, based on mode requirements
- *
- * Due to FEC overhead, the available bw is reduced to 97.2261%.
- * To support the given mode:
- * Bandwidth required should be <= Available link Bandwidth * FEC Overhead
- * =>ModeClock * bits_per_pixel <= Available Link Bandwidth * FEC Overhead
- * =>bits_per_pixel <= Available link Bandwidth * FEC Overhead / ModeClock
- * =>bits_per_pixel <= (NumberOfLanes * LinkSymbolClock) * 8 (TimeSlots / 64) /
- * (ModeClock / FEC Overhead)
- * =>bits_per_pixel <= (NumberOfLanes * LinkSymbolClock * TimeSlots) /
- * (ModeClock / FEC Overhead * 8)
- */
- bits_per_pixel = ((link_clock * lane_count) * timeslots) /
- (intel_dp_mode_to_fec_clock(mode_clock) * 8);
-
- /* Bandwidth required for 420 is half, that of 444 format */
- if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
- bits_per_pixel *= 2;
-
- /*
- * According to DSC 1.2a Section 4.1.1 Table 4.1 the maximum
- * supported PPS value can be 63.9375 and with the further
- * mention that for 420, 422 formats, bpp should be programmed double
- * the target bpp restricting our target bpp to be 31.9375 at max.
- */
- if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
- bits_per_pixel = min_t(u32, bits_per_pixel, 31);
-
- drm_dbg_kms(display->drm, "Max link bpp is %u for %u timeslots "
- "total bw %u pixel clock %u\n",
- bits_per_pixel, timeslots,
- (link_clock * lane_count * 8),
- intel_dp_mode_to_fec_clock(mode_clock));
-
- joiner_max_bpp = get_max_compressed_bpp_with_joiner(display, mode_clock,
- mode_hdisplay, num_joined_pipes);
- bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
-
- bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(display, bits_per_pixel, pipe_bpp);
-
- return bits_per_pixel;
-}
-
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
int num_joined_pipes)
@@ -1555,24 +1479,20 @@ intel_dp_mode_valid(struct drm_connector *_connector,
dsc_slice_count =
drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd,
true);
+ dsc = dsc_max_compressed_bpp && dsc_slice_count;
} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
- dsc_max_compressed_bpp =
- intel_dp_dsc_get_max_compressed_bpp(display,
- max_link_clock,
- max_lanes,
- target_clock,
- mode->hdisplay,
- num_joined_pipes,
- output_format,
- pipe_bpp, 64);
- dsc_slice_count =
- intel_dp_dsc_get_slice_count(connector,
- target_clock,
- mode->hdisplay,
- num_joined_pipes);
- }
+ unsigned long bw_overhead_flags = 0;
+
+ if (!drm_dp_is_uhbr_rate(max_link_clock))
+ bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
- dsc = dsc_max_compressed_bpp && dsc_slice_count;
+ dsc = intel_dp_mode_valid_with_dsc(connector,
+ max_link_clock, max_lanes,
+ target_clock, mode->hdisplay,
+ num_joined_pipes,
+ output_format, pipe_bpp,
+ bw_overhead_flags);
+ }
}
if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
@@ -1894,12 +1814,44 @@ int intel_dp_dsc_max_src_input_bpc(struct intel_display *display)
return intel_dp_dsc_min_src_input_bpc();
}
+static int align_min_sink_dsc_input_bpp(const struct intel_connector *connector,
+ int min_pipe_bpp)
+{
+ u8 dsc_bpc[3];
+ int num_bpc;
+ int i;
+
+ num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
+ dsc_bpc);
+ for (i = num_bpc - 1; i >= 0; i--) {
+ if (dsc_bpc[i] * 3 >= min_pipe_bpp)
+ return dsc_bpc[i] * 3;
+ }
+
+ return 0;
+}
+
+static int align_max_sink_dsc_input_bpp(const struct intel_connector *connector,
+ int max_pipe_bpp)
+{
+ u8 dsc_bpc[3];
+ int num_bpc;
+ int i;
+
+ num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
+ dsc_bpc);
+ for (i = 0; i < num_bpc; i++) {
+ if (dsc_bpc[i] * 3 <= max_pipe_bpp)
+ return dsc_bpc[i] * 3;
+ }
+
+ return 0;
+}
+
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u8 max_req_bpc)
{
struct intel_display *display = to_intel_display(connector);
- int i, num_bpc;
- u8 dsc_bpc[3] = {};
int dsc_max_bpc;
dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(display);
@@ -1909,14 +1861,7 @@ int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
dsc_max_bpc = min(dsc_max_bpc, max_req_bpc);
- num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
- dsc_bpc);
- for (i = 0; i < num_bpc; i++) {
- if (dsc_max_bpc >= dsc_bpc[i])
- return dsc_bpc[i] * 3;
- }
-
- return 0;
+ return align_max_sink_dsc_input_bpp(connector, dsc_max_bpc * 3);
}
static int intel_dp_source_dsc_version_minor(struct intel_display *display)
@@ -2047,8 +1992,7 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
const struct link_config_limits *limits,
- int dsc_bpp_x16,
- int timeslots)
+ int dsc_bpp_x16)
{
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
int link_rate, lane_count;
@@ -2108,7 +2052,7 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp,
static
u16 intel_dp_dsc_max_sink_compressed_bppx16(const struct intel_connector *connector,
- const struct intel_crtc_state *pipe_config,
+ enum intel_output_format output_format,
int bpc)
{
u16 max_bppx16 = drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd);
@@ -2119,43 +2063,43 @@ u16 intel_dp_dsc_max_sink_compressed_bppx16(const struct intel_connector *connec
* If support not given in DPCD 67h, 68h use the Maximum Allowed bit rate
* values as given in spec Table 2-157 DP v2.0
*/
- switch (pipe_config->output_format) {
+ switch (output_format) {
case INTEL_OUTPUT_FORMAT_RGB:
case INTEL_OUTPUT_FORMAT_YCBCR444:
return (3 * bpc) << 4;
case INTEL_OUTPUT_FORMAT_YCBCR420:
return (3 * (bpc / 2)) << 4;
default:
- MISSING_CASE(pipe_config->output_format);
+ MISSING_CASE(output_format);
break;
}
return 0;
}
-int intel_dp_dsc_sink_min_compressed_bpp(const struct intel_crtc_state *pipe_config)
+static int intel_dp_dsc_sink_min_compressed_bpp(enum intel_output_format output_format)
{
/* From Mandatory bit rate range Support Table 2-157 (DP v2.0) */
- switch (pipe_config->output_format) {
+ switch (output_format) {
case INTEL_OUTPUT_FORMAT_RGB:
case INTEL_OUTPUT_FORMAT_YCBCR444:
return 8;
case INTEL_OUTPUT_FORMAT_YCBCR420:
return 6;
default:
- MISSING_CASE(pipe_config->output_format);
+ MISSING_CASE(output_format);
break;
}
return 0;
}
-int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector,
- const struct intel_crtc_state *pipe_config,
- int bpc)
+static int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector,
+ enum intel_output_format output_format,
+ int bpc)
{
return intel_dp_dsc_max_sink_compressed_bppx16(connector,
- pipe_config, bpc) >> 4;
+ output_format, bpc) >> 4;
}
int intel_dp_dsc_min_src_compressed_bpp(void)
@@ -2213,7 +2157,6 @@ int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16)
{
struct intel_display *display = to_intel_display(intel_dp);
- int i;
if (DISPLAY_VER(display) >= 13) {
if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16))
@@ -2225,12 +2168,41 @@ bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16)
if (fxp_q4_to_frac(bpp_x16))
return false;
- for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
- if (fxp_q4_to_int(bpp_x16) == valid_dsc_bpp[i])
- return true;
+ return align_max_vesa_compressed_bpp_x16(bpp_x16) == bpp_x16;
+}
+
+static int align_min_compressed_bpp_x16(const struct intel_connector *connector, int min_bpp_x16)
+{
+ struct intel_display *display = to_intel_display(connector);
+
+ if (DISPLAY_VER(display) >= 13) {
+ int bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
+
+ drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
+
+ return round_up(min_bpp_x16, bpp_step_x16);
+ } else {
+ return align_min_vesa_compressed_bpp_x16(min_bpp_x16);
}
+}
- return false;
+static int align_max_compressed_bpp_x16(const struct intel_connector *connector,
+ enum intel_output_format output_format,
+ int pipe_bpp, int max_bpp_x16)
+{
+ struct intel_display *display = to_intel_display(connector);
+ int link_bpp_x16 = intel_dp_output_format_link_bpp_x16(output_format, pipe_bpp);
+ int bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
+
+ max_bpp_x16 = min(max_bpp_x16, link_bpp_x16 - bpp_step_x16);
+
+ if (DISPLAY_VER(display) >= 13) {
+ drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
+
+ return round_down(max_bpp_x16, bpp_step_x16);
+ } else {
+ return align_max_vesa_compressed_bpp_x16(max_bpp_x16);
+ }
}
/*
@@ -2241,26 +2213,28 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
const struct link_config_limits *limits,
- int pipe_bpp,
- int timeslots)
+ int pipe_bpp)
{
struct intel_display *display = to_intel_display(intel_dp);
const struct intel_connector *connector = to_intel_connector(conn_state->connector);
int min_bpp_x16, max_bpp_x16, bpp_step_x16;
- int link_bpp_x16;
int bpp_x16;
int ret;
+ min_bpp_x16 = limits->link.min_bpp_x16;
max_bpp_x16 = limits->link.max_bpp_x16;
bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
- /* Compressed BPP should be less than the Input DSC bpp */
- link_bpp_x16 = intel_dp_output_format_link_bpp_x16(pipe_config->output_format, pipe_bpp);
- max_bpp_x16 = min(max_bpp_x16, link_bpp_x16 - bpp_step_x16);
+ max_bpp_x16 = align_max_compressed_bpp_x16(connector, pipe_config->output_format,
+ pipe_bpp, max_bpp_x16);
+ if (intel_dp_is_edp(intel_dp)) {
+ pipe_config->port_clock = limits->max_rate;
+ pipe_config->lane_count = limits->max_lane_count;
- drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
- min_bpp_x16 = round_up(limits->link.min_bpp_x16, bpp_step_x16);
- max_bpp_x16 = round_down(max_bpp_x16, bpp_step_x16);
+ pipe_config->dsc.compressed_bpp_x16 = max_bpp_x16;
+
+ return 0;
+ }
for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16))
@@ -2270,8 +2244,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
pipe_config,
conn_state,
limits,
- bpp_x16,
- timeslots);
+ bpp_x16);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 = bpp_x16;
if (intel_dp->force_dsc_fractional_bpp_en &&
@@ -2328,86 +2301,21 @@ int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
- const struct link_config_limits *limits,
- int timeslots)
+ const struct link_config_limits *limits)
{
- const struct intel_connector *connector =
- to_intel_connector(conn_state->connector);
- u8 dsc_bpc[3] = {};
int forced_bpp, pipe_bpp;
- int num_bpc, i, ret;
-
- forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, limits);
-
- if (forced_bpp) {
- ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
- limits, forced_bpp, timeslots);
- if (ret == 0) {
- pipe_config->pipe_bpp = forced_bpp;
- return 0;
- }
- }
-
- /*
- * Get the maximum DSC bpc that will be supported by any valid
- * link configuration and compressed bpp.
- */
- num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd, dsc_bpc);
- for (i = 0; i < num_bpc; i++) {
- pipe_bpp = dsc_bpc[i] * 3;
- if (pipe_bpp < limits->pipe.min_bpp || pipe_bpp > limits->pipe.max_bpp)
- continue;
-
- ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
- limits, pipe_bpp, timeslots);
- if (ret == 0) {
- pipe_config->pipe_bpp = pipe_bpp;
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
- struct intel_crtc_state *pipe_config,
- struct drm_connector_state *conn_state,
- const struct link_config_limits *limits)
-{
- struct intel_display *display = to_intel_display(intel_dp);
- struct intel_connector *connector =
- to_intel_connector(conn_state->connector);
- int pipe_bpp, forced_bpp;
- int dsc_min_bpp;
- int dsc_max_bpp;
+ int ret;
forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, limits);
-
- if (forced_bpp) {
+ if (forced_bpp)
pipe_bpp = forced_bpp;
- } else {
- int max_bpc = limits->pipe.max_bpp / 3;
-
- /* For eDP use max bpp that can be supported with DSC. */
- pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, max_bpc);
- if (!is_dsc_pipe_bpp_sufficient(limits, pipe_bpp)) {
- drm_dbg_kms(display->drm,
- "Computed BPC is not in DSC BPC limits\n");
- return -EINVAL;
- }
- }
- pipe_config->port_clock = limits->max_rate;
- pipe_config->lane_count = limits->max_lane_count;
-
- dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16);
-
- dsc_max_bpp = fxp_q4_to_int(limits->link.max_bpp_x16);
-
- /* Compressed BPP should be less than the Input DSC bpp */
- dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+ else
+ pipe_bpp = limits->pipe.max_bpp;
- pipe_config->dsc.compressed_bpp_x16 =
- fxp_q4_from_int(max(dsc_min_bpp, dsc_max_bpp));
+ ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
+ limits, pipe_bpp);
+ if (ret)
+ return -EINVAL;
pipe_config->pipe_bpp = pipe_bpp;
@@ -2465,12 +2373,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
* figured out for DP MST DSC.
*/
if (!is_mst) {
- if (intel_dp_is_edp(intel_dp))
- ret = intel_edp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
- conn_state, limits);
- else
- ret = intel_dp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
- conn_state, limits, timeslots);
+ ret = intel_dp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
+ conn_state, limits);
if (ret) {
drm_dbg_kms(display->drm,
"No Valid pipe bpp for given mode ret = %d\n", ret);
@@ -2543,11 +2447,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
static int
dsc_throughput_quirk_max_bpp_x16(const struct intel_connector *connector,
- const struct intel_crtc_state *crtc_state)
+ int mode_clock)
{
- const struct drm_display_mode *adjusted_mode =
- &crtc_state->hw.adjusted_mode;
-
if (!connector->dp.dsc_throughput_quirk)
return INT_MAX;
@@ -2567,7 +2468,7 @@ dsc_throughput_quirk_max_bpp_x16(const struct intel_connector *connector,
* smaller than the YUV422/420 value, but let's not depend on this
* assumption.
*/
- if (adjusted_mode->crtc_clock <
+ if (mode_clock <
min(connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444,
connector->dp.dsc_branch_caps.overall_throughput.yuv422_420) / 2)
return INT_MAX;
@@ -2575,18 +2476,106 @@ dsc_throughput_quirk_max_bpp_x16(const struct intel_connector *connector,
return fxp_q4_from_int(12);
}
+static int compute_min_compressed_bpp_x16(struct intel_connector *connector,
+ enum intel_output_format output_format)
+{
+ int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
+ int min_bpp_x16;
+
+ dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp();
+ dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(output_format);
+ dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
+
+ min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
+
+ min_bpp_x16 = align_min_compressed_bpp_x16(connector, min_bpp_x16);
+
+ return min_bpp_x16;
+}
+
+static int compute_max_compressed_bpp_x16(struct intel_connector *connector,
+ int mode_clock, int mode_hdisplay,
+ int num_joined_pipes,
+ enum intel_output_format output_format,
+ int pipe_max_bpp, int max_link_bpp_x16)
+{
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
+ int throughput_max_bpp_x16;
+ int joiner_max_bpp;
+
+ dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
+ joiner_max_bpp = get_max_compressed_bpp_with_joiner(display,
+ mode_clock,
+ mode_hdisplay,
+ num_joined_pipes);
+ dsc_sink_max_bpp = intel_dp_dsc_sink_max_compressed_bpp(connector,
+ output_format,
+ pipe_max_bpp / 3);
+ dsc_max_bpp = min(dsc_sink_max_bpp, dsc_src_max_bpp);
+ dsc_max_bpp = min(dsc_max_bpp, joiner_max_bpp);
+
+ max_link_bpp_x16 = min(max_link_bpp_x16, fxp_q4_from_int(dsc_max_bpp));
+
+ throughput_max_bpp_x16 = dsc_throughput_quirk_max_bpp_x16(connector,
+ mode_clock);
+ if (throughput_max_bpp_x16 < max_link_bpp_x16) {
+ max_link_bpp_x16 = throughput_max_bpp_x16;
+
+ drm_dbg_kms(display->drm,
+ "[CONNECTOR:%d:%s] Decreasing link max bpp to " FXP_Q4_FMT " due to DSC throughput quirk\n",
+ connector->base.base.id, connector->base.name,
+ FXP_Q4_ARGS(max_link_bpp_x16));
+ }
+
+ max_link_bpp_x16 = align_max_compressed_bpp_x16(connector, output_format,
+ pipe_max_bpp, max_link_bpp_x16);
+
+ return max_link_bpp_x16;
+}
+
+bool intel_dp_mode_valid_with_dsc(struct intel_connector *connector,
+ int link_clock, int lane_count,
+ int mode_clock, int mode_hdisplay,
+ int num_joined_pipes,
+ enum intel_output_format output_format,
+ int pipe_bpp, unsigned long bw_overhead_flags)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ int min_bpp_x16 = compute_min_compressed_bpp_x16(connector, output_format);
+ int max_bpp_x16 = compute_max_compressed_bpp_x16(connector,
+ mode_clock, mode_hdisplay,
+ num_joined_pipes,
+ output_format,
+ pipe_bpp, INT_MAX);
+ int dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
+ mode_clock,
+ mode_hdisplay,
+ num_joined_pipes);
+
+ if (min_bpp_x16 <= 0 || min_bpp_x16 > max_bpp_x16)
+ return false;
+
+ return is_bw_sufficient_for_dsc_config(intel_dp,
+ link_clock, lane_count,
+ mode_clock, mode_hdisplay,
+ dsc_slice_count, min_bpp_x16,
+ bw_overhead_flags);
+}
+
/*
* Calculate the output link min, max bpp values in limits based on the pipe bpp
* range, crtc_state and dsc mode. Return true on success.
*/
static bool
-intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
- const struct intel_connector *connector,
+intel_dp_compute_config_link_bpp_limits(struct intel_connector *connector,
const struct intel_crtc_state *crtc_state,
bool dsc,
struct link_config_limits *limits)
{
- struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -2604,40 +2593,17 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
limits->link.min_bpp_x16 = fxp_q4_from_int(limits->pipe.min_bpp);
} else {
- int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
- int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
- int throughput_max_bpp_x16;
- int joiner_max_bpp;
-
- dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp();
- dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state);
- dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
- limits->link.min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
-
- dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
- joiner_max_bpp =
- get_max_compressed_bpp_with_joiner(display,
- adjusted_mode->crtc_clock,
- adjusted_mode->hdisplay,
- intel_crtc_num_joined_pipes(crtc_state));
- dsc_sink_max_bpp = intel_dp_dsc_sink_max_compressed_bpp(connector,
- crtc_state,
- limits->pipe.max_bpp / 3);
- dsc_max_bpp = min(dsc_sink_max_bpp, dsc_src_max_bpp);
- dsc_max_bpp = min(dsc_max_bpp, joiner_max_bpp);
-
- max_link_bpp_x16 = min(max_link_bpp_x16, fxp_q4_from_int(dsc_max_bpp));
-
- throughput_max_bpp_x16 = dsc_throughput_quirk_max_bpp_x16(connector, crtc_state);
- if (throughput_max_bpp_x16 < max_link_bpp_x16) {
- max_link_bpp_x16 = throughput_max_bpp_x16;
+ limits->link.min_bpp_x16 =
+ compute_min_compressed_bpp_x16(connector, crtc_state->output_format);
- drm_dbg_kms(display->drm,
- "[CRTC:%d:%s][CONNECTOR:%d:%s] Decreasing link max bpp to " FXP_Q4_FMT " due to DSC throughput quirk\n",
- crtc->base.base.id, crtc->base.name,
- connector->base.base.id, connector->base.name,
- FXP_Q4_ARGS(max_link_bpp_x16));
- }
+ max_link_bpp_x16 =
+ compute_max_compressed_bpp_x16(connector,
+ adjusted_mode->crtc_clock,
+ adjusted_mode->hdisplay,
+ intel_crtc_num_joined_pipes(crtc_state),
+ crtc_state->output_format,
+ limits->pipe.max_bpp,
+ max_link_bpp_x16);
}
limits->link.max_bpp_x16 = max_link_bpp_x16;
@@ -2671,15 +2637,19 @@ intel_dp_dsc_compute_pipe_bpp_limits(struct intel_connector *connector,
int dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(display);
limits->pipe.min_bpp = max(limits->pipe.min_bpp, dsc_min_bpc * 3);
+ limits->pipe.min_bpp = align_min_sink_dsc_input_bpp(connector, limits->pipe.min_bpp);
+
limits->pipe.max_bpp = min(limits->pipe.max_bpp, dsc_max_bpc * 3);
+ limits->pipe.max_bpp = align_max_sink_dsc_input_bpp(connector, limits->pipe.max_bpp);
if (limits->pipe.min_bpp <= 0 ||
limits->pipe.min_bpp > limits->pipe.max_bpp) {
drm_dbg_kms(display->drm,
- "[CONNECTOR:%d:%s] Invalid DSC src/sink input BPP (src:%d-%d pipe:%d-%d)\n",
+ "[CONNECTOR:%d:%s] Invalid DSC src/sink input BPP (src:%d-%d pipe:%d-%d sink-align:%d-%d)\n",
connector->base.base.id, connector->base.name,
dsc_min_bpc * 3, dsc_max_bpc * 3,
- orig_limits.pipe.min_bpp, orig_limits.pipe.max_bpp);
+ orig_limits.pipe.min_bpp, orig_limits.pipe.max_bpp,
+ limits->pipe.min_bpp, limits->pipe.max_bpp);
return false;
}
@@ -2745,8 +2715,7 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
intel_dp_test_compute_config(intel_dp, crtc_state, limits);
- return intel_dp_compute_config_link_bpp_limits(intel_dp,
- connector,
+ return intel_dp_compute_config_link_bpp_limits(connector,
crtc_state,
dsc,
limits);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 30eebb8cad6d..25bfbfd291b0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -143,17 +143,12 @@ bool intel_digital_port_connected(struct intel_encoder *encoder);
bool intel_digital_port_connected_locked(struct intel_encoder *encoder);
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u8 dsc_max_bpc);
-u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display,
- u32 link_clock, u32 lane_count,
- u32 mode_clock, u32 mode_hdisplay,
- int num_joined_pipes,
- enum intel_output_format output_format,
- u32 pipe_bpp,
- u32 timeslots);
-int intel_dp_dsc_sink_min_compressed_bpp(const struct intel_crtc_state *pipe_config);
-int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector,
- const struct intel_crtc_state *pipe_config,
- int bpc);
+bool intel_dp_mode_valid_with_dsc(struct intel_connector *connector,
+ int link_clock, int lane_count,
+ int mode_clock, int mode_hdisplay,
+ int num_joined_pipes,
+ enum intel_output_format output_format,
+ int pipe_bpp, unsigned long bw_overhead_flags);
bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16);
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 0db6ed2d9664..24f8e60df9ac 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -463,57 +463,21 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector = to_intel_connector(conn_state->connector);
- int num_bpc;
- u8 dsc_bpc[3] = {};
- int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
- int min_compressed_bpp_x16, max_compressed_bpp_x16;
- int bpp_step_x16;
- max_bpp = limits->pipe.max_bpp;
- min_bpp = limits->pipe.min_bpp;
-
- num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
- dsc_bpc);
-
- drm_dbg_kms(display->drm, "DSC Source supported min bpp %d max bpp %d\n",
- min_bpp, max_bpp);
-
- sink_min_bpp = min_array(dsc_bpc, num_bpc) * 3;
- sink_max_bpp = max_array(dsc_bpc, num_bpc) * 3;
-
- drm_dbg_kms(display->drm, "DSC Sink supported min bpp %d max bpp %d\n",
- sink_min_bpp, sink_max_bpp);
-
- if (min_bpp < sink_min_bpp)
- min_bpp = sink_min_bpp;
-
- if (max_bpp > sink_max_bpp)
- max_bpp = sink_max_bpp;
-
- crtc_state->pipe_bpp = max_bpp;
-
- min_compressed_bpp_x16 = limits->link.min_bpp_x16;
- max_compressed_bpp_x16 = limits->link.max_bpp_x16;
+ crtc_state->pipe_bpp = limits->pipe.max_bpp;
drm_dbg_kms(display->drm,
"DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n",
- FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16));
-
- bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
-
- max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16);
-
- drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
- min_compressed_bpp_x16 = round_up(min_compressed_bpp_x16, bpp_step_x16);
- max_compressed_bpp_x16 = round_down(max_compressed_bpp_x16, bpp_step_x16);
+ FXP_Q4_ARGS(limits->link.min_bpp_x16), FXP_Q4_ARGS(limits->link.max_bpp_x16));
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state,
- min_compressed_bpp_x16,
- max_compressed_bpp_x16,
- bpp_step_x16, true);
+ limits->link.min_bpp_x16,
+ limits->link.max_bpp_x16,
+ intel_dp_dsc_bpp_step_x16(connector),
+ true);
}
static int mode_hblank_period_ns(const struct drm_display_mode *mode)
@@ -1462,8 +1426,6 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
DRM_DP_BW_OVERHEAD_MST | DRM_DP_BW_OVERHEAD_SSC_REF_CLK;
int ret;
bool dsc = false;
- u16 dsc_max_compressed_bpp = 0;
- u8 dsc_slice_count = 0;
int target_clock = mode->clock;
int num_joined_pipes;
@@ -1522,31 +1484,22 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
return 0;
}
- if (intel_dp_has_dsc(connector)) {
+ if (intel_dp_has_dsc(connector) && drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
- if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
- dsc_max_compressed_bpp =
- intel_dp_dsc_get_max_compressed_bpp(display,
- max_link_clock,
- max_lanes,
- target_clock,
- mode->hdisplay,
- num_joined_pipes,
- INTEL_OUTPUT_FORMAT_RGB,
- pipe_bpp, 64);
- dsc_slice_count =
- intel_dp_dsc_get_slice_count(connector,
- target_clock,
- mode->hdisplay,
- num_joined_pipes);
- }
+ if (!drm_dp_is_uhbr_rate(max_link_clock))
+ bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
- dsc = dsc_max_compressed_bpp && dsc_slice_count;
+ dsc = intel_dp_mode_valid_with_dsc(connector,
+ max_link_clock, max_lanes,
+ target_clock, mode->hdisplay,
+ num_joined_pipes,
+ INTEL_OUTPUT_FORMAT_RGB, pipe_bpp,
+ bw_overhead_flags);
}
if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) {
diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c
index 019a722a38bf..170de304fe96 100644
--- a/drivers/gpu/drm/i915/display/intel_dram.c
+++ b/drivers/gpu/drm/i915/display/intel_dram.c
@@ -8,7 +8,6 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_utils.h"
@@ -58,18 +57,18 @@ const char *intel_dram_type_str(enum intel_dram_type type)
static enum intel_dram_type pnv_dram_type(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
- return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
+ return intel_uncore_read(uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2;
}
static unsigned int pnv_mem_freq(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 tmp;
- tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG);
+ tmp = intel_uncore_read(uncore, CLKCFG);
switch (tmp & CLKCFG_MEM_MASK) {
case CLKCFG_MEM_533:
@@ -85,10 +84,10 @@ static unsigned int pnv_mem_freq(struct intel_display *display)
static unsigned int ilk_mem_freq(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u16 ddrpll;
- ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1);
+ ddrpll = intel_uncore_read16(uncore, DDRMPLL1);
switch (ddrpll & 0xff) {
case 0xc:
return 800000;
@@ -158,7 +157,7 @@ unsigned int intel_mem_freq(struct intel_display *display)
static unsigned int i9xx_fsb_freq(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 fsb;
/*
@@ -169,7 +168,7 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display)
* don't know which registers have that information,
* and all the relevant docs have gone to bit heaven :(
*/
- fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK;
+ fsb = intel_uncore_read(uncore, CLKCFG) & CLKCFG_FSB_MASK;
if (display->platform.pineview || display->platform.mobile) {
switch (fsb) {
@@ -214,10 +213,10 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display)
static unsigned int ilk_fsb_freq(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u16 fsb;
- fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff;
+ fsb = intel_uncore_read16(uncore, CSIPLL0) & 0x3ff;
switch (fsb) {
case 0x00c:
@@ -484,7 +483,7 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0,
static int
skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
struct dram_channel_info ch0 = {}, ch1 = {};
u32 val;
int ret;
@@ -492,14 +491,12 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram
/* Assume 16Gb+ DIMMs are present until proven otherwise */
dram_info->has_16gb_dimms = true;
- val = intel_uncore_read(&i915->uncore,
- SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
+ val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
ret = skl_dram_get_channel_info(display, &ch0, 0, val);
if (ret == 0)
dram_info->num_channels++;
- val = intel_uncore_read(&i915->uncore,
- SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
+ val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
ret = skl_dram_get_channel_info(display, &ch1, 1, val);
if (ret == 0)
dram_info->num_channels++;
@@ -530,11 +527,10 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram
static enum intel_dram_type
skl_get_dram_type(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val;
- val = intel_uncore_read(&i915->uncore,
- SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
+ val = intel_uncore_read(uncore, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
switch (val & SKL_DRAM_DDR_TYPE_MASK) {
case SKL_DRAM_DDR_TYPE_DDR3:
@@ -645,7 +641,7 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val)
static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val;
u8 valid_ranks = 0;
int i;
@@ -657,7 +653,7 @@ static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dr
struct dram_dimm_info dimm;
enum intel_dram_type type;
- val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i));
+ val = intel_uncore_read(uncore, BXT_D_CR_DRP0_DUNIT(i));
if (val == 0xFFFFFFFF)
continue;
@@ -770,8 +766,8 @@ static int gen12_get_dram_info(struct intel_display *display, struct dram_info *
static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
- u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
+ u32 val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_GLOBAL);
switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) {
case 0:
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index ec2a3fb171ab..91060e2a5762 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -704,7 +704,36 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state,
if (crtc_state->has_psr)
intel_dsb_emit_wait_dsl(dsb, DSB_OPCODE_WAIT_DSL_OUT, 0, 0);
- if (pre_commit_is_vrr_active(state, crtc)) {
+ if (pre_commit_is_vrr_active(state, crtc) && crtc_state->vrr.dc_balance.enable) {
+ int vblank_delay = crtc_state->set_context_latency;
+ int vmin_vblank_start, vmax_vblank_start;
+
+ vmin_vblank_start = intel_vrr_dcb_vmin_vblank_start_next(crtc_state);
+
+ if (vmin_vblank_start >= 0) {
+ end = vmin_vblank_start;
+ start = end - vblank_delay - latency;
+ intel_dsb_wait_scanline_out(state, dsb, start, end);
+ }
+
+ vmax_vblank_start = intel_vrr_dcb_vmax_vblank_start_next(crtc_state);
+
+ if (vmax_vblank_start >= 0) {
+ end = vmax_vblank_start;
+ start = end - vblank_delay - latency;
+ intel_dsb_wait_scanline_out(state, dsb, start, end);
+ }
+
+ vmin_vblank_start = intel_vrr_dcb_vmin_vblank_start_final(crtc_state);
+ end = vmin_vblank_start;
+ start = end - vblank_delay - latency;
+ intel_dsb_wait_scanline_out(state, dsb, start, end);
+
+ vmax_vblank_start = intel_vrr_dcb_vmax_vblank_start_final(crtc_state);
+ end = vmax_vblank_start;
+ start = end - vblank_delay - latency;
+ intel_dsb_wait_scanline_out(state, dsb, start, end);
+ } else if (pre_commit_is_vrr_active(state, crtc)) {
int vblank_delay = crtc_state->set_context_latency;
end = intel_vrr_vmin_vblank_start(crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h
index 2f31f2c1d0c5..386a5a942572 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2019 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_dsb_buffer.h b/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
index d746c872e0c7..f4577d1f25cd 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2023 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_gvt_api.c b/drivers/gpu/drm/i915/display/intel_gvt_api.c
new file mode 100644
index 000000000000..a69e249395ae
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_gvt_api.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#include <linux/types.h>
+
+#include "intel_display_core.h"
+#include "intel_display_regs.h"
+#include "intel_gvt_api.h"
+
+u32 intel_display_device_pipe_offset(struct intel_display *display, enum pipe pipe)
+{
+ return INTEL_DISPLAY_DEVICE_PIPE_OFFSET(display, pipe);
+}
+EXPORT_SYMBOL_NS_GPL(intel_display_device_pipe_offset, "I915_GVT");
+
+u32 intel_display_device_trans_offset(struct intel_display *display, enum transcoder trans)
+{
+ return INTEL_DISPLAY_DEVICE_TRANS_OFFSET(display, trans);
+}
+EXPORT_SYMBOL_NS_GPL(intel_display_device_trans_offset, "I915_GVT");
+
+u32 intel_display_device_cursor_offset(struct intel_display *display, enum pipe pipe)
+{
+ return INTEL_DISPLAY_DEVICE_CURSOR_OFFSET(display, pipe);
+}
+EXPORT_SYMBOL_NS_GPL(intel_display_device_cursor_offset, "I915_GVT");
+
+u32 intel_display_device_mmio_base(struct intel_display *display)
+{
+ return DISPLAY_MMIO_BASE(display);
+}
+EXPORT_SYMBOL_NS_GPL(intel_display_device_mmio_base, "I915_GVT");
+
+bool intel_display_device_pipe_valid(struct intel_display *display, enum pipe pipe)
+{
+ if (pipe < PIPE_A || pipe >= I915_MAX_PIPES)
+ return false;
+
+ return DISPLAY_RUNTIME_INFO(display)->pipe_mask & BIT(pipe);
+}
+EXPORT_SYMBOL_NS_GPL(intel_display_device_pipe_valid, "I915_GVT");
diff --git a/drivers/gpu/drm/i915/display/intel_gvt_api.h b/drivers/gpu/drm/i915/display/intel_gvt_api.h
new file mode 100644
index 000000000000..ce3b744142a5
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_gvt_api.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#ifndef __INTEL_GVT_API_H__
+#define __INTEL_GVT_API_H__
+
+#include <linux/types.h>
+
+enum pipe;
+enum transcoder;
+struct intel_display;
+
+u32 intel_display_device_pipe_offset(struct intel_display *display, enum pipe pipe);
+u32 intel_display_device_trans_offset(struct intel_display *display, enum transcoder trans);
+u32 intel_display_device_cursor_offset(struct intel_display *display, enum pipe pipe);
+u32 intel_display_device_mmio_base(struct intel_display *display);
+bool intel_display_device_pipe_valid(struct intel_display *display, enum pipe pipe);
+
+#endif /* __INTEL_GVT_API_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c
new file mode 100644
index 000000000000..ee545c033da6
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
+
+#include "intel_display_core.h"
+#include "intel_display_types.h"
+#include "intel_fb.h"
+#include "intel_frontbuffer.h"
+#include "intel_initial_plane.h"
+#include "intel_plane.h"
+
+void intel_initial_plane_vblank_wait(struct intel_crtc *crtc)
+{
+ struct intel_display *display = to_intel_display(crtc);
+
+ display->parent->initial_plane->vblank_wait(&crtc->base);
+}
+
+static const struct intel_plane_state *
+intel_reuse_initial_plane_obj(struct intel_crtc *this,
+ const struct intel_initial_plane_config plane_configs[])
+{
+ struct intel_display *display = to_intel_display(this);
+ struct intel_crtc *crtc;
+
+ for_each_intel_crtc(display->drm, crtc) {
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
+ const struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
+ const struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+
+ if (!crtc_state->hw.active)
+ continue;
+
+ if (!plane_state->ggtt_vma)
+ continue;
+
+ if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base)
+ return plane_state;
+ }
+
+ return NULL;
+}
+
+static struct drm_gem_object *
+intel_alloc_initial_plane_obj(struct intel_display *display,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct intel_framebuffer *fb = plane_config->fb;
+
+ switch (fb->base.modifier) {
+ 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_kms(display->drm, "Unsupported modifier for initial FB: 0x%llx\n",
+ fb->base.modifier);
+ return NULL;
+ }
+
+ return display->parent->initial_plane->alloc_obj(display->drm, plane_config);
+}
+
+static void
+intel_find_initial_plane_obj(struct intel_crtc *crtc,
+ struct intel_initial_plane_config plane_configs[])
+{
+ struct intel_display *display = to_intel_display(crtc);
+ struct intel_initial_plane_config *plane_config = &plane_configs[crtc->pipe];
+ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+ struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state);
+ struct drm_framebuffer *fb;
+ struct i915_vma *vma;
+ int ret;
+
+ /*
+ * TODO:
+ * Disable planes if get_initial_plane_config() failed.
+ * Make sure things work if the surface base is not page aligned.
+ */
+ if (!plane_config->fb)
+ return;
+
+ if (intel_alloc_initial_plane_obj(display, plane_config)) {
+ fb = &plane_config->fb->base;
+ vma = plane_config->vma;
+ } else {
+ const struct intel_plane_state *other_plane_state;
+
+ other_plane_state = intel_reuse_initial_plane_obj(crtc, plane_configs);
+ if (!other_plane_state)
+ goto nofb;
+
+ fb = other_plane_state->hw.fb;
+ vma = other_plane_state->ggtt_vma;
+ }
+
+ plane_state->uapi.rotation = plane_config->rotation;
+ intel_fb_fill_view(to_intel_framebuffer(fb),
+ plane_state->uapi.rotation, &plane_state->view);
+
+ ret = display->parent->initial_plane->setup(plane->base.state, plane_config, fb, vma);
+ if (ret)
+ goto nofb;
+
+ plane_state->uapi.src_x = 0;
+ plane_state->uapi.src_y = 0;
+ plane_state->uapi.src_w = fb->width << 16;
+ plane_state->uapi.src_h = fb->height << 16;
+
+ plane_state->uapi.crtc_x = 0;
+ plane_state->uapi.crtc_y = 0;
+ plane_state->uapi.crtc_w = fb->width;
+ plane_state->uapi.crtc_h = fb->height;
+
+ plane_state->uapi.fb = fb;
+ drm_framebuffer_get(fb);
+
+ plane_state->uapi.crtc = &crtc->base;
+ intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc);
+
+ atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits);
+
+ return;
+
+nofb:
+ /*
+ * We've failed to reconstruct the BIOS FB. Current display state
+ * indicates that the primary plane is visible, but has a NULL FB,
+ * which will lead to problems later if we don't fix it up. The
+ * simplest solution is to just disable the primary plane now and
+ * pretend the BIOS never had it enabled.
+ */
+ intel_plane_disable_noatomic(crtc, plane);
+}
+
+static void plane_config_fini(struct intel_display *display,
+ struct intel_initial_plane_config *plane_config)
+{
+ if (plane_config->fb) {
+ struct drm_framebuffer *fb = &plane_config->fb->base;
+
+ /* We may only have the stub and not a full framebuffer */
+ if (drm_framebuffer_read_refcount(fb))
+ drm_framebuffer_put(fb);
+ else
+ kfree(fb);
+ }
+
+ display->parent->initial_plane->config_fini(plane_config);
+}
+
+void intel_initial_plane_config(struct intel_display *display)
+{
+ struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
+ struct intel_crtc *crtc;
+
+ for_each_intel_crtc(display->drm, crtc) {
+ const struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_initial_plane_config *plane_config =
+ &plane_configs[crtc->pipe];
+
+ if (!crtc_state->hw.active)
+ continue;
+
+ /*
+ * Note that reserving the BIOS fb up front prevents us
+ * from stuffing other stolen allocations like the ring
+ * on top. This prevents some ugliness at boot time, and
+ * can even allow for smooth boot transitions if the BIOS
+ * fb is large enough for the active pipe configuration.
+ */
+ display->funcs.display->get_initial_plane_config(crtc, plane_config);
+
+ /*
+ * If the fb is shared between multiple heads, we'll
+ * just get the first one.
+ */
+ intel_find_initial_plane_obj(crtc, plane_configs);
+
+ if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
+ intel_initial_plane_vblank_wait(crtc);
+
+ plane_config_fini(display, plane_config);
+ }
+}
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.h b/drivers/gpu/drm/i915/display/intel_initial_plane.h
index 5c315acda210..5f9a347be8f0 100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.h
+++ b/drivers/gpu/drm/i915/display/intel_initial_plane.h
@@ -3,13 +3,13 @@
* Copyright © 2021 Intel Corporation
*/
-#ifndef __INTEL_PLANE_INITIAL_H__
-#define __INTEL_PLANE_INITIAL_H__
+#ifndef __INTEL_INITIAL_PLANE_H__
+#define __INTEL_INITIAL_PLANE_H__
struct intel_crtc;
struct intel_display;
void intel_initial_plane_config(struct intel_display *display);
-void intel_plane_initial_vblank_wait(struct intel_crtc *crtc);
+void intel_initial_plane_vblank_wait(struct intel_crtc *crtc);
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c
index 939c8975fd4c..6cdae03ee172 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c
@@ -31,6 +31,7 @@
#define INTEL_LT_PHY_BOTH_LANES (INTEL_LT_PHY_LANE1 |\
INTEL_LT_PHY_LANE0)
#define MODE_DP 3
+#define MODE_HDMI_20 4
#define Q32_TO_INT(x) ((x) >> 32)
#define Q32_TO_FRAC(x) ((x) & 0xFFFFFFFF)
#define DCO_MIN_FREQ_MHZ 11850
@@ -1751,6 +1752,7 @@ int
intel_lt_phy_calc_port_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(encoder);
int clk;
const struct intel_lt_phy_pll_state *lt_state =
&crtc_state->dpll_hw_state.ltpll;
@@ -1768,8 +1770,11 @@ intel_lt_phy_calc_port_clock(struct intel_encoder *encoder,
rate = REG_FIELD_GET8(LT_PHY_VDR_RATE_ENCODING_MASK,
lt_state->config[0]);
clk = intel_lt_phy_get_dp_clock(rate);
- } else {
+ } else if (mode == MODE_HDMI_20) {
clk = intel_lt_phy_calc_hdmi_port_clock(crtc_state);
+ } else {
+ drm_WARN_ON(display->drm, "Unsupported LT PHY Mode!\n");
+ clk = xe3plpd_lt_hdmi_252.clock;
}
return clk;
@@ -2207,13 +2212,18 @@ bool
intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a,
const struct intel_lt_phy_pll_state *b)
{
- if (memcmp(&a->config, &b->config, sizeof(a->config)) != 0)
- return false;
-
- if (memcmp(&a->data, &b->data, sizeof(a->data)) != 0)
- return false;
+ /*
+ * With LT PHY values other than VDR0_CONFIG and VDR2_CONFIG are
+ * unreliable. They cannot always be read back since internally
+ * after power gating values are not restored back to the
+ * shadow VDR registers. Thus we do not compare the whole state
+ * just the two VDR registers.
+ */
+ if (a->config[0] == b->config[0] &&
+ a->config[2] == b->config[2])
+ return true;
- return true;
+ return false;
}
void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
@@ -2259,8 +2269,6 @@ void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state,
struct intel_encoder *encoder;
struct intel_lt_phy_pll_state pll_hw_state = {};
const struct intel_lt_phy_pll_state *pll_sw_state = &new_crtc_state->dpll_hw_state.ltpll;
- int clock;
- int i, j;
if (DISPLAY_VER(display) < 35)
return;
@@ -2275,33 +2283,19 @@ void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state,
encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
intel_lt_phy_pll_readout_hw_state(encoder, new_crtc_state, &pll_hw_state);
- clock = intel_lt_phy_calc_port_clock(encoder, new_crtc_state);
dig_port = enc_to_dig_port(encoder);
if (intel_tc_port_in_tbt_alt_mode(dig_port))
return;
- INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.clock != clock,
- "[CRTC:%d:%s] mismatch in LT PHY: Register CLOCK (expected %d, found %d)",
+ INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[0] != pll_sw_state->config[0],
+ "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG 0: (expected 0x%04x, found 0x%04x)",
crtc->base.base.id, crtc->base.name,
- pll_sw_state->clock, pll_hw_state.clock);
-
- for (i = 0; i < 3; i++) {
- INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[i] != pll_sw_state->config[i],
- "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG%d: (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- pll_sw_state->config[i], pll_hw_state.config[i]);
- }
-
- for (i = 0; i <= 12; i++) {
- for (j = 3; j >= 0; j--)
- INTEL_DISPLAY_STATE_WARN(display,
- pll_hw_state.data[i][j] !=
- pll_sw_state->data[i][j],
- "[CRTC:%d:%s] mismatch in LT PHY PLL DATA[%d][%d]: (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i, j,
- pll_sw_state->data[i][j], pll_hw_state.data[i][j]);
- }
+ pll_sw_state->config[0], pll_hw_state.config[0]);
+ INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[2] != pll_sw_state->config[2],
+ "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG 2: (expected 0x%04x, found 0x%04x)",
+ crtc->base.base.id, crtc->base.name,
+ pll_sw_state->config[2], pll_hw_state.config[2]);
}
void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h
index 7659c92b6c3c..bf41858f1bc3 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2025 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h b/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
index 98ccc069a69b..37e46fb9abde 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: MIT
- *
+/* SPDX-License-Identifier: MIT */
+/*
* Copyright © 2025 Intel Corporation
*/
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c
deleted file mode 100644
index ff1afd3a8f20..000000000000
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ /dev/null
@@ -1,442 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2021 Intel Corporation
- */
-
-#include <drm/drm_print.h>
-
-#include "gem/i915_gem_lmem.h"
-#include "gem/i915_gem_region.h"
-#include "i915_drv.h"
-#include "intel_crtc.h"
-#include "intel_display.h"
-#include "intel_display_core.h"
-#include "intel_display_types.h"
-#include "intel_fb.h"
-#include "intel_frontbuffer.h"
-#include "intel_plane.h"
-#include "intel_plane_initial.h"
-
-void intel_plane_initial_vblank_wait(struct intel_crtc *crtc)
-{
- intel_crtc_wait_for_next_vblank(crtc);
-}
-
-static bool
-intel_reuse_initial_plane_obj(struct intel_crtc *this,
- const struct intel_initial_plane_config plane_configs[],
- struct drm_framebuffer **fb,
- struct i915_vma **vma)
-{
- struct intel_display *display = to_intel_display(this);
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(display->drm, crtc) {
- struct intel_plane *plane =
- to_intel_plane(crtc->base.primary);
- const struct intel_plane_state *plane_state =
- to_intel_plane_state(plane->base.state);
- const struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
-
- if (!crtc_state->hw.active)
- continue;
-
- if (!plane_state->ggtt_vma)
- continue;
-
- if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base) {
- *fb = plane_state->hw.fb;
- *vma = plane_state->ggtt_vma;
- return true;
- }
- }
-
- return false;
-}
-
-static enum intel_memory_type
-initial_plane_memory_type(struct intel_display *display)
-{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
- if (display->platform.dgfx)
- return INTEL_MEMORY_LOCAL;
- else if (HAS_LMEMBAR_SMEM_STOLEN(i915))
- return INTEL_MEMORY_STOLEN_LOCAL;
- else
- return INTEL_MEMORY_STOLEN_SYSTEM;
-}
-
-static bool
-initial_plane_phys(struct intel_display *display,
- struct intel_initial_plane_config *plane_config)
-{
- struct drm_i915_private *i915 = to_i915(display->drm);
- struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
- struct intel_memory_region *mem;
- enum intel_memory_type mem_type;
- bool is_present, is_local;
- dma_addr_t dma_addr;
- u32 base;
-
- mem_type = initial_plane_memory_type(display);
- mem = intel_memory_region_by_type(i915, mem_type);
- if (!mem) {
- drm_dbg_kms(display->drm,
- "Initial plane memory region (type %s) not initialized\n",
- intel_memory_type_str(mem_type));
- return false;
- }
-
- base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT);
-
- dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local);
-
- if (!is_present) {
- drm_err(display->drm,
- "Initial plane FB PTE not present\n");
- return false;
- }
-
- if (intel_memory_type_is_local(mem->type) != is_local) {
- drm_err(display->drm,
- "Initial plane FB PTE unsuitable for %s\n",
- mem->region.name);
- return false;
- }
-
- if (dma_addr < mem->region.start || dma_addr > mem->region.end) {
- drm_err(display->drm,
- "Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n",
- &dma_addr, mem->region.name, &mem->region.start, &mem->region.end);
- return false;
- }
-
- drm_dbg(display->drm,
- "Using dma_addr=%pa, based on initial plane programming\n",
- &dma_addr);
-
- plane_config->phys_base = dma_addr - mem->region.start;
- plane_config->mem = mem;
-
- return true;
-}
-
-static struct i915_vma *
-initial_plane_vma(struct intel_display *display,
- struct intel_initial_plane_config *plane_config)
-{
- struct drm_i915_private *i915 = to_i915(display->drm);
- struct intel_memory_region *mem;
- struct drm_i915_gem_object *obj;
- struct drm_mm_node orig_mm = {};
- struct i915_vma *vma;
- resource_size_t phys_base;
- unsigned int tiling;
- u32 base, size;
- u64 pinctl;
-
- if (plane_config->size == 0)
- return NULL;
-
- if (!initial_plane_phys(display, plane_config))
- return NULL;
-
- phys_base = plane_config->phys_base;
- mem = plane_config->mem;
-
- base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT);
- size = round_up(plane_config->base + plane_config->size,
- mem->min_page_size);
- size -= base;
-
- /*
- * If the FB is too big, just don't use it since fbdev is not very
- * important and we should probably use that space with FBC or other
- * features.
- */
- if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
- mem == i915->mm.stolen_region &&
- size * 2 > i915->dsm.usable_size) {
- drm_dbg_kms(display->drm, "Initial FB size exceeds half of stolen, discarding\n");
- return NULL;
- }
-
- obj = i915_gem_object_create_region_at(mem, phys_base, size,
- I915_BO_ALLOC_USER |
- I915_BO_PREALLOC);
- if (IS_ERR(obj)) {
- drm_dbg_kms(display->drm, "Failed to preallocate initial FB in %s\n",
- mem->region.name);
- return NULL;
- }
-
- /*
- * Mark it WT ahead of time to avoid changing the
- * cache_level during fbdev initialization. The
- * unbind there would get stuck waiting for rcu.
- */
- i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ?
- I915_CACHE_WT : I915_CACHE_NONE);
-
- tiling = intel_fb_modifier_to_tiling(plane_config->fb->base.modifier);
-
- switch (tiling) {
- case I915_TILING_NONE:
- break;
- case I915_TILING_X:
- case I915_TILING_Y:
- obj->tiling_and_stride =
- plane_config->fb->base.pitches[0] |
- tiling;
- break;
- default:
- MISSING_CASE(tiling);
- goto err_obj;
- }
-
- /*
- * MTL GOP likes to place the framebuffer high up in ggtt,
- * which can cause problems for ggtt_reserve_guc_top().
- * Try to pin it to a low ggtt address instead to avoid that.
- */
- base = 0;
-
- if (base != plane_config->base) {
- struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
- int ret;
-
- /*
- * Make sure the original and new locations
- * can't overlap. That would corrupt the original
- * PTEs which are still being used for scanout.
- */
- ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &orig_mm,
- size, plane_config->base,
- I915_COLOR_UNEVICTABLE, PIN_NOEVICT);
- if (ret)
- goto err_obj;
- }
-
- vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL);
- if (IS_ERR(vma))
- goto err_obj;
-
-retry:
- pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base;
- if (!i915_gem_object_is_lmem(obj))
- pinctl |= PIN_MAPPABLE;
- if (i915_vma_pin(vma, 0, 0, pinctl)) {
- if (drm_mm_node_allocated(&orig_mm)) {
- drm_mm_remove_node(&orig_mm);
- /*
- * Try again, but this time pin
- * it to its original location.
- */
- base = plane_config->base;
- goto retry;
- }
- goto err_obj;
- }
-
- if (i915_gem_object_is_tiled(obj) &&
- !i915_vma_is_map_and_fenceable(vma))
- goto err_obj;
-
- if (drm_mm_node_allocated(&orig_mm))
- drm_mm_remove_node(&orig_mm);
-
- drm_dbg_kms(display->drm,
- "Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
- i915_ggtt_offset(vma), plane_config->base);
-
- return vma;
-
-err_obj:
- if (drm_mm_node_allocated(&orig_mm))
- drm_mm_remove_node(&orig_mm);
- i915_gem_object_put(obj);
- return NULL;
-}
-
-static bool
-intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
- struct intel_initial_plane_config *plane_config)
-{
- struct intel_display *display = to_intel_display(crtc);
- struct drm_mode_fb_cmd2 mode_cmd = {};
- struct drm_framebuffer *fb = &plane_config->fb->base;
- struct i915_vma *vma;
-
- switch (fb->modifier) {
- 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(display->drm,
- "Unsupported modifier for initial FB: 0x%llx\n",
- fb->modifier);
- return false;
- }
-
- vma = initial_plane_vma(display, plane_config);
- if (!vma)
- return false;
-
- mode_cmd.pixel_format = fb->format->format;
- mode_cmd.width = fb->width;
- mode_cmd.height = fb->height;
- mode_cmd.pitches[0] = fb->pitches[0];
- mode_cmd.modifier[0] = fb->modifier;
- mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
-
- if (intel_framebuffer_init(to_intel_framebuffer(fb),
- intel_bo_to_drm_bo(vma->obj),
- fb->format, &mode_cmd)) {
- drm_dbg_kms(display->drm, "intel fb init failed\n");
- goto err_vma;
- }
-
- plane_config->vma = vma;
- return true;
-
-err_vma:
- i915_vma_put(vma);
- return false;
-}
-
-static void
-intel_find_initial_plane_obj(struct intel_crtc *crtc,
- struct intel_initial_plane_config plane_configs[])
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_initial_plane_config *plane_config =
- &plane_configs[crtc->pipe];
- struct intel_plane *plane =
- to_intel_plane(crtc->base.primary);
- struct intel_plane_state *plane_state =
- to_intel_plane_state(plane->base.state);
- struct drm_framebuffer *fb;
- struct i915_vma *vma;
-
- /*
- * TODO:
- * Disable planes if get_initial_plane_config() failed.
- * Make sure things work if the surface base is not page aligned.
- */
- if (!plane_config->fb)
- return;
-
- if (intel_alloc_initial_plane_obj(crtc, plane_config)) {
- fb = &plane_config->fb->base;
- vma = plane_config->vma;
- goto valid_fb;
- }
-
- /*
- * Failed to alloc the obj, check to see if we should share
- * an fb with another CRTC instead
- */
- if (intel_reuse_initial_plane_obj(crtc, plane_configs, &fb, &vma))
- goto valid_fb;
-
- /*
- * We've failed to reconstruct the BIOS FB. Current display state
- * indicates that the primary plane is visible, but has a NULL FB,
- * which will lead to problems later if we don't fix it up. The
- * simplest solution is to just disable the primary plane now and
- * pretend the BIOS never had it enabled.
- */
- intel_plane_disable_noatomic(crtc, plane);
-
- return;
-
-valid_fb:
- plane_state->uapi.rotation = plane_config->rotation;
- intel_fb_fill_view(to_intel_framebuffer(fb),
- plane_state->uapi.rotation, &plane_state->view);
-
- __i915_vma_pin(vma);
- plane_state->ggtt_vma = i915_vma_get(vma);
- if (intel_plane_uses_fence(plane_state) &&
- i915_vma_pin_fence(vma) == 0 && vma->fence)
- plane_state->flags |= PLANE_HAS_FENCE;
-
- plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma);
-
- plane_state->uapi.src_x = 0;
- plane_state->uapi.src_y = 0;
- plane_state->uapi.src_w = fb->width << 16;
- plane_state->uapi.src_h = fb->height << 16;
-
- plane_state->uapi.crtc_x = 0;
- plane_state->uapi.crtc_y = 0;
- plane_state->uapi.crtc_w = fb->width;
- plane_state->uapi.crtc_h = fb->height;
-
- if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
- dev_priv->preserve_bios_swizzle = true;
-
- plane_state->uapi.fb = fb;
- drm_framebuffer_get(fb);
-
- plane_state->uapi.crtc = &crtc->base;
- intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc);
-
- atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits);
-}
-
-static void plane_config_fini(struct intel_initial_plane_config *plane_config)
-{
- if (plane_config->fb) {
- struct drm_framebuffer *fb = &plane_config->fb->base;
-
- /* We may only have the stub and not a full framebuffer */
- if (drm_framebuffer_read_refcount(fb))
- drm_framebuffer_put(fb);
- else
- kfree(fb);
- }
-
- if (plane_config->vma)
- i915_vma_put(plane_config->vma);
-}
-
-void intel_initial_plane_config(struct intel_display *display)
-{
- struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(display->drm, crtc) {
- const struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
- struct intel_initial_plane_config *plane_config =
- &plane_configs[crtc->pipe];
-
- if (!crtc_state->hw.active)
- continue;
-
- /*
- * Note that reserving the BIOS fb up front prevents us
- * from stuffing other stolen allocations like the ring
- * on top. This prevents some ugliness at boot time, and
- * can even allow for smooth boot transitions if the BIOS
- * fb is large enough for the active pipe configuration.
- */
- display->funcs.display->get_initial_plane_config(crtc, plane_config);
-
- /*
- * If the fb is shared between multiple heads, we'll
- * just get the first one.
- */
- intel_find_initial_plane_obj(crtc, plane_configs);
-
- if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
- intel_plane_initial_vblank_wait(crtc);
-
- plane_config_fini(plane_config);
- }
-}
diff --git a/drivers/gpu/drm/i915/display/intel_rom.c b/drivers/gpu/drm/i915/display/intel_rom.c
index 2f17dc856e7f..c8f615315310 100644
--- a/drivers/gpu/drm/i915/display/intel_rom.c
+++ b/drivers/gpu/drm/i915/display/intel_rom.c
@@ -3,7 +3,10 @@
* Copyright © 2024 Intel Corporation
*/
-#include "i915_drv.h"
+#include <linux/pci.h>
+
+#include <drm/drm_device.h>
+
#include "i915_reg.h"
#include "intel_rom.h"
@@ -41,7 +44,6 @@ static u16 spi_read16(struct intel_rom *rom, loff_t offset)
struct intel_rom *intel_rom_spi(struct drm_device *drm)
{
- struct drm_i915_private *i915 = to_i915(drm);
struct intel_rom *rom;
u32 static_region;
@@ -49,7 +51,7 @@ struct intel_rom *intel_rom_spi(struct drm_device *drm)
if (!rom)
return NULL;
- rom->uncore = &i915->uncore;
+ rom->uncore = to_intel_uncore(drm);
static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
static_region &= OPTIONROM_SPI_REGIONID_MASK;
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
index 671f357c6563..1b7cfe226ff8 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -8,7 +8,6 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
-#include "i915_drv.h"
#include "intel_color.h"
#include "intel_crtc.h"
#include "intel_de.h"
@@ -305,17 +304,17 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
*/
#ifdef I915
static void intel_vblank_section_enter(struct intel_display *display)
- __acquires(i915->uncore.lock)
+ __acquires(uncore->lock)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
- spin_lock(&i915->uncore.lock);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
+ spin_lock(&uncore->lock);
}
static void intel_vblank_section_exit(struct intel_display *display)
- __releases(i915->uncore.lock)
+ __releases(uncore->lock)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
- spin_unlock(&i915->uncore.lock);
+ struct intel_uncore *uncore = to_intel_uncore(display->drm);
+ spin_unlock(&uncore->lock);
}
#else
static void intel_vblank_section_enter(struct intel_display *display)
@@ -652,6 +651,34 @@ intel_pre_commit_crtc_state(struct intel_atomic_state *state,
return pre_commit_crtc_state(old_crtc_state, new_crtc_state);
}
+static int vrr_vblank_start(const struct intel_crtc_state *crtc_state)
+{
+ bool is_push_sent = intel_vrr_is_push_sent(crtc_state);
+ int vblank_start;
+
+ if (!crtc_state->vrr.dc_balance.enable) {
+ if (is_push_sent)
+ return intel_vrr_vmin_vblank_start(crtc_state);
+ else
+ return intel_vrr_vmax_vblank_start(crtc_state);
+ }
+
+ if (is_push_sent)
+ vblank_start = intel_vrr_dcb_vmin_vblank_start_next(crtc_state);
+ else
+ vblank_start = intel_vrr_dcb_vmax_vblank_start_next(crtc_state);
+
+ if (vblank_start >= 0)
+ return vblank_start;
+
+ if (is_push_sent)
+ vblank_start = intel_vrr_dcb_vmin_vblank_start_final(crtc_state);
+ else
+ vblank_start = intel_vrr_dcb_vmax_vblank_start_final(crtc_state);
+
+ return vblank_start;
+}
+
void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state,
struct intel_vblank_evade_ctx *evade)
@@ -678,10 +705,7 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
drm_WARN_ON(crtc->base.dev, intel_crtc_needs_modeset(new_crtc_state) ||
new_crtc_state->update_m_n || new_crtc_state->update_lrr);
- if (intel_vrr_is_push_sent(crtc_state))
- evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
- else
- evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
+ evade->vblank_start = vrr_vblank_start(crtc_state);
vblank_delay = crtc_state->set_context_latency;
} else {
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index ad5fe841e4b3..5493082f30a7 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -1050,15 +1050,40 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
}
+static
+int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
+ int pixel_rate, int htotal,
+ int dsc_horizontal_slices)
+{
+ int dsc_slice_bubbles;
+ u64 num;
+
+ if (drm_WARN_ON(display->drm, !htotal))
+ return pixel_rate;
+
+ dsc_slice_bubbles = 14 * dsc_horizontal_slices;
+ num = mul_u32_u32(pixel_rate, (htotal + dsc_slice_bubbles));
+
+ return DIV_ROUND_UP_ULL(num, htotal);
+}
+
int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+ int htotal = crtc_state->hw.adjusted_mode.crtc_htotal;
+ int dsc_slices = crtc_state->dsc.slice_count;
+ int pixel_rate;
int min_cdclk;
if (!crtc_state->dsc.compression_enable)
return 0;
+ pixel_rate = intel_dsc_get_pixel_rate_with_dsc_bubbles(display,
+ crtc_state->pixel_rate,
+ htotal,
+ dsc_slices);
+
/*
* When we decide to use only one VDSC engine, since
* each VDSC operates with 1 ppc throughput, pixel clock
@@ -1066,7 +1091,7 @@ int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
* If there 2 VDSC engines, then pixel clock can't be higher than
* VDSC clock(cdclk) * 2 and so on.
*/
- min_cdclk = DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances);
+ min_cdclk = DIV_ROUND_UP(pixel_rate, num_vdsc_instances);
if (crtc_state->joiner_pipes) {
int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
@@ -1084,9 +1109,11 @@ int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
* => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
*/
int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
- int min_cdclk_bj =
- (fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
- pixel_clock) / (2 * bigjoiner_interface_bits);
+ int adjusted_pixel_rate =
+ intel_dsc_get_pixel_rate_with_dsc_bubbles(display, pixel_clock,
+ htotal, dsc_slices);
+ int min_cdclk_bj = (fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
+ adjusted_pixel_rate) / (2 * bigjoiner_interface_bits);
min_cdclk = max(min_cdclk, min_cdclk_bj);
}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index b92c42fde937..db74744ddb31 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -6,9 +6,12 @@
#include <drm/drm_print.h>
+#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
+#include "intel_dmc.h"
+#include "intel_dmc_regs.h"
#include "intel_dp.h"
#include "intel_psr.h"
#include "intel_vrr.h"
@@ -19,6 +22,14 @@
#define FIXED_POINT_PRECISION 100
#define CMRR_PRECISION_TOLERANCE 10
+/*
+ * Tunable parameters for DC Balance correction.
+ * These are captured based on experimentations.
+ */
+#define DCB_CORRECTION_SENSITIVITY 30
+#define DCB_CORRECTION_AGGRESSIVENESS 1000 /* ms × 100; 10 ms */
+#define DCB_BLANK_TARGET 50
+
bool intel_vrr_is_capable(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
@@ -261,6 +272,12 @@ static int intel_vrr_hw_value(const struct intel_crtc_state *crtc_state,
return value - crtc_state->set_context_latency;
}
+static int intel_vrr_vblank_start(const struct intel_crtc_state *crtc_state,
+ int vmin_vmax)
+{
+ return intel_vrr_hw_value(crtc_state, vmin_vmax) - crtc_state->vrr.guardband;
+}
+
/*
* For fixed refresh rate mode Vmin, Vmax and Flipline all are set to
* Vtotal value.
@@ -335,6 +352,56 @@ int intel_vrr_compute_vmax(struct intel_connector *connector,
return vmax;
}
+static bool intel_vrr_dc_balance_possible(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
+
+ /*
+ * FIXME: Currently Firmware supports DC Balancing on PIPE A
+ * and PIPE B. Account those limitation while computing DC
+ * Balance parameters.
+ */
+ return (HAS_VRR_DC_BALANCE(display) &&
+ ((pipe == PIPE_A) || (pipe == PIPE_B)));
+}
+
+static void
+intel_vrr_dc_balance_compute_config(struct intel_crtc_state *crtc_state)
+{
+ int guardband_usec, adjustment_usec;
+ struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+
+ if (!intel_vrr_dc_balance_possible(crtc_state) || !crtc_state->vrr.enable)
+ return;
+
+ crtc_state->vrr.dc_balance.vmax = crtc_state->vrr.vmax;
+ crtc_state->vrr.dc_balance.vmin = crtc_state->vrr.vmin;
+ crtc_state->vrr.dc_balance.max_increase =
+ crtc_state->vrr.vmax - crtc_state->vrr.vmin;
+ crtc_state->vrr.dc_balance.max_decrease =
+ crtc_state->vrr.vmax - crtc_state->vrr.vmin;
+ crtc_state->vrr.dc_balance.guardband =
+ DIV_ROUND_UP(crtc_state->vrr.dc_balance.vmax *
+ DCB_CORRECTION_SENSITIVITY, 100);
+ guardband_usec =
+ intel_scanlines_to_usecs(adjusted_mode,
+ crtc_state->vrr.dc_balance.guardband);
+ /*
+ * The correction_aggressiveness/100 is the number of milliseconds to
+ * adjust by when the balance is at twice the guardband.
+ * guardband_slope = correction_aggressiveness / (guardband * 100)
+ */
+ adjustment_usec = DCB_CORRECTION_AGGRESSIVENESS * 10;
+ crtc_state->vrr.dc_balance.slope =
+ DIV_ROUND_UP(adjustment_usec, guardband_usec);
+ crtc_state->vrr.dc_balance.vblank_target =
+ DIV_ROUND_UP((crtc_state->vrr.vmax - crtc_state->vrr.vmin) *
+ DCB_BLANK_TARGET, 100);
+ crtc_state->vrr.dc_balance.enable = true;
+}
+
void
intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@@ -392,6 +459,8 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
(crtc_state->hw.adjusted_mode.crtc_vtotal -
crtc_state->hw.adjusted_mode.crtc_vsync_end);
}
+
+ intel_vrr_dc_balance_compute_config(crtc_state);
}
static int
@@ -579,6 +648,34 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start));
}
+void
+intel_vrr_dcb_increment_flip_count(struct intel_crtc_state *crtc_state,
+ struct intel_crtc *crtc)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum pipe pipe = crtc->pipe;
+
+ if (!crtc_state->vrr.dc_balance.enable)
+ return;
+
+ intel_de_write(display, PIPEDMC_DCB_FLIP_COUNT(pipe),
+ ++crtc->dc_balance.flip_count);
+}
+
+void
+intel_vrr_dcb_reset(const struct intel_crtc_state *old_crtc_state,
+ struct intel_crtc *crtc)
+{
+ struct intel_display *display = to_intel_display(old_crtc_state);
+ enum pipe pipe = crtc->pipe;
+
+ if (!old_crtc_state->vrr.dc_balance.enable)
+ return;
+
+ intel_de_write(display, PIPEDMC_DCB_FLIP_COUNT(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_BALANCE_RESET(pipe), 0);
+}
+
void intel_vrr_send_push(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
@@ -686,6 +783,92 @@ static void intel_vrr_set_vrr_timings(const struct intel_crtc_state *crtc_state)
intel_vrr_hw_flipline(crtc_state) - 1);
}
+static void
+intel_vrr_enable_dc_balancing(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
+ u32 vrr_ctl = intel_de_read(display, TRANS_VRR_CTL(display, cpu_transcoder));
+
+ if (!crtc_state->vrr.dc_balance.enable)
+ return;
+
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_VMAX_CFG(cpu_transcoder),
+ VRR_DCB_ADJ_VMAX(crtc_state->vrr.vmax - 1));
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE(cpu_transcoder),
+ VRR_DCB_ADJ_VMAX(crtc_state->vrr.vmax - 1));
+ intel_de_write(display, TRANS_VRR_DCB_VMAX(cpu_transcoder),
+ VRR_DCB_VMAX(crtc_state->vrr.vmax - 1));
+ intel_de_write(display, TRANS_VRR_DCB_VMAX_LIVE(cpu_transcoder),
+ VRR_DCB_VMAX(crtc_state->vrr.vmax - 1));
+ intel_de_write(display, TRANS_VRR_DCB_FLIPLINE(cpu_transcoder),
+ VRR_DCB_FLIPLINE(crtc_state->vrr.flipline - 1));
+ intel_de_write(display, TRANS_VRR_DCB_FLIPLINE_LIVE(cpu_transcoder),
+ VRR_DCB_FLIPLINE(crtc_state->vrr.flipline - 1));
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE(cpu_transcoder),
+ VRR_DCB_ADJ_FLIPLINE(crtc_state->vrr.flipline - 1));
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_FLIPLINE_CFG(cpu_transcoder),
+ VRR_DCB_ADJ_FLIPLINE(crtc_state->vrr.flipline - 1));
+ intel_de_write(display, PIPEDMC_DCB_VMIN(pipe),
+ crtc_state->vrr.dc_balance.vmin - 1);
+ intel_de_write(display, PIPEDMC_DCB_VMAX(pipe),
+ crtc_state->vrr.dc_balance.vmax - 1);
+ intel_de_write(display, PIPEDMC_DCB_MAX_INCREASE(pipe),
+ crtc_state->vrr.dc_balance.max_increase);
+ intel_de_write(display, PIPEDMC_DCB_MAX_DECREASE(pipe),
+ crtc_state->vrr.dc_balance.max_decrease);
+ intel_de_write(display, PIPEDMC_DCB_GUARDBAND(pipe),
+ crtc_state->vrr.dc_balance.guardband);
+ intel_de_write(display, PIPEDMC_DCB_SLOPE(pipe),
+ crtc_state->vrr.dc_balance.slope);
+ intel_de_write(display, PIPEDMC_DCB_VBLANK(pipe),
+ crtc_state->vrr.dc_balance.vblank_target);
+ intel_dmc_configure_dc_balance_event(display, pipe, true);
+ intel_de_write(display, TRANS_ADAPTIVE_SYNC_DCB_CTL(cpu_transcoder),
+ ADAPTIVE_SYNC_COUNTER_EN);
+ intel_pipedmc_dcb_enable(NULL, crtc);
+
+ vrr_ctl |= VRR_CTL_DCB_ADJ_ENABLE;
+ intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), vrr_ctl);
+}
+
+static void
+intel_vrr_disable_dc_balancing(const struct intel_crtc_state *old_crtc_state)
+{
+ struct intel_display *display = to_intel_display(old_crtc_state);
+ enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
+ struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
+ u32 vrr_ctl = intel_de_read(display, TRANS_VRR_CTL(display, cpu_transcoder));
+
+ if (!old_crtc_state->vrr.dc_balance.enable)
+ return;
+
+ intel_pipedmc_dcb_disable(NULL, crtc);
+ intel_dmc_configure_dc_balance_event(display, pipe, false);
+ intel_de_write(display, TRANS_ADAPTIVE_SYNC_DCB_CTL(cpu_transcoder), 0);
+ intel_de_write(display, PIPEDMC_DCB_VMIN(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_VMAX(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_MAX_INCREASE(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_MAX_DECREASE(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_GUARDBAND(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_SLOPE(pipe), 0);
+ intel_de_write(display, PIPEDMC_DCB_VBLANK(pipe), 0);
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_VMAX_LIVE(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_FLIPLINE_LIVE(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_VMAX_CFG(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_ADJ_FLIPLINE_CFG(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_VMAX(cpu_transcoder), 0);
+ intel_de_write(display, TRANS_VRR_DCB_FLIPLINE(cpu_transcoder), 0);
+
+ vrr_ctl &= ~VRR_CTL_DCB_ADJ_ENABLE;
+ intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), vrr_ctl);
+}
+
static void intel_vrr_tg_enable(const struct intel_crtc_state *crtc_state,
bool cmrr_enable)
{
@@ -732,6 +915,7 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state)
return;
intel_vrr_set_vrr_timings(crtc_state);
+ intel_vrr_enable_dc_balancing(crtc_state);
if (!intel_vrr_always_use_vrr_tg(display))
intel_vrr_tg_enable(crtc_state, crtc_state->cmrr.enable);
@@ -747,6 +931,7 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state)
if (!intel_vrr_always_use_vrr_tg(display))
intel_vrr_tg_disable(old_crtc_state);
+ intel_vrr_disable_dc_balancing(old_crtc_state);
intel_vrr_set_fixed_rr_timings(old_crtc_state);
}
@@ -779,6 +964,35 @@ bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state)
crtc_state->vrr.flipline == crtc_state->vrr.vmin;
}
+static
+void intel_vrr_get_dc_balance_config(struct intel_crtc_state *crtc_state)
+{
+ u32 reg_val;
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
+
+ if (!intel_vrr_dc_balance_possible(crtc_state))
+ return;
+
+ reg_val = intel_de_read(display, PIPEDMC_DCB_VMIN(pipe));
+ crtc_state->vrr.dc_balance.vmin = reg_val ? reg_val + 1 : 0;
+
+ reg_val = intel_de_read(display, PIPEDMC_DCB_VMAX(pipe));
+ crtc_state->vrr.dc_balance.vmax = reg_val ? reg_val + 1 : 0;
+
+ crtc_state->vrr.dc_balance.guardband =
+ intel_de_read(display, PIPEDMC_DCB_GUARDBAND(pipe));
+ crtc_state->vrr.dc_balance.max_increase =
+ intel_de_read(display, PIPEDMC_DCB_MAX_INCREASE(pipe));
+ crtc_state->vrr.dc_balance.max_decrease =
+ intel_de_read(display, PIPEDMC_DCB_MAX_DECREASE(pipe));
+ crtc_state->vrr.dc_balance.slope =
+ intel_de_read(display, PIPEDMC_DCB_SLOPE(pipe));
+ crtc_state->vrr.dc_balance.vblank_target =
+ intel_de_read(display, PIPEDMC_DCB_VBLANK(pipe));
+}
+
void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
@@ -860,6 +1074,8 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
else
crtc_state->vrr.enable = vrr_enable;
+ intel_vrr_get_dc_balance_config(crtc_state);
+
/*
* #TODO: For Both VRR and CMRR the flag I915_MODE_FLAG_VRR is set for mode_flags.
* Since CMRR is currently disabled, set this flag for VRR for now.
@@ -893,8 +1109,69 @@ int intel_vrr_safe_window_start(const struct intel_crtc_state *crtc_state)
return crtc_state->hw.adjusted_mode.crtc_vdisplay;
}
+static int
+intel_vrr_dcb_vmin_vblank_start(const struct intel_crtc_state *crtc_state)
+{
+ return (intel_vrr_dcb_vmin_vblank_start_next(crtc_state) < 0) ?
+ intel_vrr_dcb_vmin_vblank_start_final(crtc_state) :
+ intel_vrr_dcb_vmin_vblank_start_next(crtc_state);
+}
+
int intel_vrr_vmin_safe_window_end(const struct intel_crtc_state *crtc_state)
{
- return intel_vrr_vmin_vblank_start(crtc_state) -
- crtc_state->set_context_latency;
+ int vmin_vblank_start = crtc_state->vrr.dc_balance.enable ?
+ intel_vrr_dcb_vmin_vblank_start(crtc_state) :
+ intel_vrr_vmin_vblank_start(crtc_state);
+
+ return vmin_vblank_start - crtc_state->set_context_latency;
+}
+
+int intel_vrr_dcb_vmin_vblank_start_next(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ u32 tmp = 0;
+
+ tmp = intel_de_read(display, TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE(cpu_transcoder));
+
+ if (REG_FIELD_GET(VRR_DCB_ADJ_FLIPLINE_CNT_MASK, tmp) == 0)
+ return -EINVAL;
+
+ return intel_vrr_vblank_start(crtc_state, VRR_DCB_ADJ_FLIPLINE(tmp) + 1);
+}
+
+int intel_vrr_dcb_vmax_vblank_start_next(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ u32 tmp = 0;
+
+ tmp = intel_de_read(display, TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE(cpu_transcoder));
+
+ if (REG_FIELD_GET(VRR_DCB_ADJ_VMAX_CNT_MASK, tmp) == 0)
+ return -EINVAL;
+
+ return intel_vrr_vblank_start(crtc_state, VRR_DCB_ADJ_VMAX(tmp) + 1);
+}
+
+int intel_vrr_dcb_vmin_vblank_start_final(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ u32 tmp = 0;
+
+ tmp = intel_de_read(display, TRANS_VRR_DCB_FLIPLINE_LIVE(cpu_transcoder));
+
+ return intel_vrr_vblank_start(crtc_state, VRR_DCB_FLIPLINE(tmp) + 1);
+}
+
+int intel_vrr_dcb_vmax_vblank_start_final(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ u32 tmp = 0;
+
+ tmp = intel_de_read(display, TRANS_VRR_DCB_VMAX_LIVE(cpu_transcoder));
+
+ return intel_vrr_vblank_start(crtc_state, VRR_DCB_VMAX(tmp) + 1);
}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index bc9044621635..bedcc8c4bff2 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -11,6 +11,7 @@
struct drm_connector_state;
struct intel_atomic_state;
struct intel_connector;
+struct intel_crtc;
struct intel_crtc_state;
struct intel_dsb;
struct intel_display;
@@ -28,6 +29,8 @@ void intel_vrr_send_push(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
void intel_vrr_check_push_sent(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
+void intel_vrr_dcb_increment_flip_count(struct intel_crtc_state *crtc_state,
+ struct intel_crtc *crtc);
bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state);
void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state);
void intel_vrr_get_config(struct intel_crtc_state *crtc_state);
@@ -39,8 +42,15 @@ bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state);
void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state);
void intel_vrr_transcoder_disable(const struct intel_crtc_state *crtc_state);
void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state);
+void intel_vrr_dcb_reset(const struct intel_crtc_state *old_crtc_state,
+ struct intel_crtc *crtc);
bool intel_vrr_always_use_vrr_tg(struct intel_display *display);
int intel_vrr_safe_window_start(const struct intel_crtc_state *crtc_state);
int intel_vrr_vmin_safe_window_end(const struct intel_crtc_state *crtc_state);
+int intel_vrr_dcb_vmin_vblank_start_next(const struct intel_crtc_state *crtc_state);
+int intel_vrr_dcb_vmax_vblank_start_next(const struct intel_crtc_state *crtc_state);
+int intel_vrr_dcb_vmin_vblank_start_final(const struct intel_crtc_state *crtc_state);
+int intel_vrr_dcb_vmax_vblank_start_final(const struct intel_crtc_state *crtc_state);
+
#endif /* __INTEL_VRR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
index ba9b9215dc11..427ada0d3973 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
@@ -8,6 +8,73 @@
#include "intel_display_reg_defs.h"
+#define _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_A 0x604d4
+#define _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_B 0x614d4
+#define TRANS_VRR_DCB_ADJ_FLIPLINE_CFG(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_A, \
+ _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_B)
+#define VRR_DCB_ADJ_FLIPLINE_CNT_MASK REG_GENMASK(31, 24)
+#define VRR_DCB_ADJ_FLIPLINE_MASK REG_GENMASK(19, 0)
+#define VRR_DCB_ADJ_FLIPLINE(flipline) REG_FIELD_PREP(VRR_DCB_ADJ_FLIPLINE_MASK, \
+ (flipline))
+
+#define _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE_A 0x90700
+#define _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE_B 0x98700
+#define TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE_A, \
+ _TRANS_VRR_DCB_ADJ_FLIPLINE_CFG_LIVE_B)
+
+#define _TRANS_VRR_DCB_ADJ_VMAX_CFG_A 0x604d8
+#define _TRANS_VRR_DCB_ADJ_VMAX_CFG_B 0x614d8
+#define TRANS_VRR_DCB_ADJ_VMAX_CFG(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_ADJ_VMAX_CFG_A, \
+ _TRANS_VRR_DCB_ADJ_VMAX_CFG_B)
+#define VRR_DCB_ADJ_VMAX_CNT_MASK REG_GENMASK(31, 24)
+#define VRR_DCB_ADJ_VMAX_MASK REG_GENMASK(19, 0)
+#define VRR_DCB_ADJ_VMAX(vmax) REG_FIELD_PREP(VRR_DCB_ADJ_VMAX_MASK, (vmax))
+
+#define _TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE_A 0x906f8
+#define _TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE_B 0x986f8
+#define TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE_A, \
+ _TRANS_VRR_DCB_ADJ_VMAX_CFG_LIVE_B)
+
+#define _TRANS_VRR_DCB_FLIPLINE_A 0x60418
+#define _TRANS_VRR_DCB_FLIPLINE_B 0x61418
+#define TRANS_VRR_DCB_FLIPLINE(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_FLIPLINE_A, \
+ _TRANS_VRR_DCB_FLIPLINE_B)
+#define VRR_DCB_FLIPLINE_MASK REG_GENMASK(19, 0)
+#define VRR_DCB_FLIPLINE(flipline) REG_FIELD_PREP(VRR_DCB_FLIPLINE_MASK, \
+ (flipline))
+
+#define _TRANS_VRR_DCB_FLIPLINE_LIVE_A 0x906fc
+#define _TRANS_VRR_DCB_FLIPLINE_LIVE_B 0x986fc
+#define TRANS_VRR_DCB_FLIPLINE_LIVE(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_FLIPLINE_LIVE_A, \
+ _TRANS_VRR_DCB_FLIPLINE_LIVE_B)
+
+#define _TRANS_VRR_DCB_VMAX_A 0x60414
+#define _TRANS_VRR_DCB_VMAX_B 0x61414
+#define TRANS_VRR_DCB_VMAX(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_VMAX_A, \
+ _TRANS_VRR_DCB_VMAX_B)
+#define VRR_DCB_VMAX_MASK REG_GENMASK(19, 0)
+#define VRR_DCB_VMAX(vmax) REG_FIELD_PREP(VRR_DCB_VMAX_MASK, (vmax))
+
+#define _TRANS_VRR_DCB_VMAX_LIVE_A 0x906f4
+#define _TRANS_VRR_DCB_VMAX_LIVE_B 0x986f4
+#define TRANS_VRR_DCB_VMAX_LIVE(trans) _MMIO_TRANS(trans, \
+ _TRANS_VRR_DCB_VMAX_LIVE_A, \
+ _TRANS_VRR_DCB_VMAX_LIVE_B)
+
+#define _TRANS_ADAPTIVE_SYNC_DCB_CTL_A 0x604c0
+#define _TRANS_ADAPTIVE_SYNC_DCB_CTL_B 0x614c0
+#define TRANS_ADAPTIVE_SYNC_DCB_CTL(trans) _MMIO_TRANS(trans, \
+ _TRANS_ADAPTIVE_SYNC_DCB_CTL_A, \
+ _TRANS_ADAPTIVE_SYNC_DCB_CTL_B)
+#define ADAPTIVE_SYNC_COUNTER_EN REG_BIT(31)
+
#define _TRANS_VRR_CTL_A 0x60420
#define _TRANS_VRR_CTL_B 0x61420
#define _TRANS_VRR_CTL_C 0x62420
@@ -19,6 +86,7 @@
#define VRR_CTL_CMRR_ENABLE REG_BIT(27)
#define VRR_CTL_PIPELINE_FULL_MASK REG_GENMASK(10, 3)
#define VRR_CTL_PIPELINE_FULL(x) REG_FIELD_PREP(VRR_CTL_PIPELINE_FULL_MASK, (x))
+#define VRR_CTL_DCB_ADJ_ENABLE REG_BIT(28)
#define VRR_CTL_PIPELINE_FULL_OVERRIDE REG_BIT(0)
#define XELPD_VRR_CTL_VRR_GUARDBAND_MASK REG_GENMASK(15, 0)
#define XELPD_VRR_CTL_VRR_GUARDBAND(x) REG_FIELD_PREP(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, (x))
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
index c4854c5b4e0f..c1deea20c28a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -113,7 +113,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj,
if (clflush) {
i915_sw_fence_await_reservation(&clflush->base.chain,
obj->base.resv, true,
- i915_fence_timeout(i915),
+ i915_fence_timeout(),
I915_FENCE_GFP);
dma_resv_add_fence(obj->base.resv, &clflush->base.dma,
DMA_RESV_USAGE_KERNEL);
diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index 8cc6e712b0f7..253b41789be9 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -36,10 +36,11 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
#include "gt/intel_ggtt_fencing.h"
+
#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
{
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
index 295a7b5e1d7c..1937e04d3791 100644
--- a/drivers/gpu/drm/i915/gvt/cfg_space.c
+++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
@@ -33,8 +33,8 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "gvt.h"
+#include "i915_drv.h"
#include "intel_pci_config.h"
enum {
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index df04e4ead8ea..bf7c3d3f5f8a 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -38,27 +38,29 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
+#include "display/i9xx_plane_regs.h"
#include "display/intel_display_regs.h"
+#include "display/intel_sprite_regs.h"
+
+#include "gem/i915_gem_context.h"
+#include "gem/i915_gem_pm.h"
+
+#include "gt/intel_context.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_gt_regs.h"
+#include "gt/intel_gt_requests.h"
#include "gt/intel_lrc.h"
#include "gt/intel_ring.h"
-#include "gt/intel_gt_requests.h"
#include "gt/shmem_utils.h"
+
+#include "display_helpers.h"
#include "gvt.h"
+#include "i915_drv.h"
#include "i915_pvinfo.h"
+#include "i915_reg.h"
#include "trace.h"
-#include "display/i9xx_plane_regs.h"
-#include "display/intel_display_core.h"
-#include "display/intel_sprite_regs.h"
-#include "gem/i915_gem_context.h"
-#include "gem/i915_gem_pm.h"
-#include "gt/intel_context.h"
-
#define INVALID_OP (~0U)
#define OP_LEN_MI 9
diff --git a/drivers/gpu/drm/i915/gvt/debugfs.c b/drivers/gpu/drm/i915/gvt/debugfs.c
index 415422b5943c..ae3fd2c3cd23 100644
--- a/drivers/gpu/drm/i915/gvt/debugfs.c
+++ b/drivers/gpu/drm/i915/gvt/debugfs.c
@@ -20,10 +20,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include <linux/debugfs.h>
#include <linux/list_sort.h>
-#include "i915_drv.h"
+
#include "gvt.h"
+#include "i915_drv.h"
struct mmio_diff_param {
struct intel_vgpu *vgpu;
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index 06517d1f07a2..21341842c0a9 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -35,20 +35,21 @@
#include <drm/display/drm_dp.h>
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
-#include "display/intel_display_regs.h"
-#include "gvt.h"
-
#include "display/bxt_dpio_phy_regs.h"
#include "display/i9xx_plane_regs.h"
#include "display/intel_crt_regs.h"
#include "display/intel_cursor_regs.h"
#include "display/intel_display.h"
-#include "display/intel_display_core.h"
+#include "display/intel_display_regs.h"
#include "display/intel_dpio_phy.h"
+#include "display/intel_dpll_mgr.h"
#include "display/intel_sprite_regs.h"
+#include "display_helpers.h"
+#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
+
static int get_edp_pipe(struct intel_vgpu *vgpu)
{
u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP);
@@ -187,7 +188,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
{
struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915;
struct intel_display *display = dev_priv->display;
- int pipe;
+ enum pipe pipe;
if (IS_BROXTON(dev_priv)) {
enum transcoder trans;
@@ -199,7 +200,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) |
GEN8_DE_PORT_HOTPLUG(HPD_PORT_C));
- for_each_pipe(display, pipe) {
+ gvt_for_each_pipe(display, pipe) {
vgpu_vreg_t(vgpu, TRANSCONF(display, pipe)) &=
~(TRANSCONF_ENABLE | TRANSCONF_STATE_ENABLE);
vgpu_vreg_t(vgpu, DSPCNTR(display, pipe)) &= ~DISP_ENABLE;
@@ -515,7 +516,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
vgpu_vreg_t(vgpu, PCH_ADPA) &= ~ADPA_CRT_HOTPLUG_MONITOR_MASK;
/* Disable Primary/Sprite/Cursor plane */
- for_each_pipe(display, pipe) {
+ gvt_for_each_pipe(display, pipe) {
vgpu_vreg_t(vgpu, DSPCNTR(display, pipe)) &= ~DISP_ENABLE;
vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
vgpu_vreg_t(vgpu, CURCNTR(display, pipe)) &= ~MCURSOR_MODE_MASK;
@@ -668,10 +669,10 @@ void intel_vgpu_emulate_vblank(struct intel_vgpu *vgpu)
{
struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
struct intel_display *display = i915->display;
- int pipe;
+ enum pipe pipe;
mutex_lock(&vgpu->vgpu_lock);
- for_each_pipe(display, pipe)
+ gvt_for_each_pipe(display, pipe)
emulate_vblank_on_pipe(vgpu, pipe);
mutex_unlock(&vgpu->vgpu_lock);
}
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index bc7f05f9a271..41a3b053663a 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -35,8 +35,8 @@
#ifndef _GVT_DISPLAY_H_
#define _GVT_DISPLAY_H_
-#include <linux/types.h>
#include <linux/hrtimer.h>
+#include <linux/types.h>
struct intel_gvt;
struct intel_vgpu;
diff --git a/drivers/gpu/drm/i915/gvt/display_helpers.h b/drivers/gpu/drm/i915/gvt/display_helpers.h
new file mode 100644
index 000000000000..0418397c09c4
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/display_helpers.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2025 Intel Corporation
+ */
+
+#ifndef __DISPLAY_HELPERS_H__
+#define __DISPLAY_HELPERS_H__
+
+#include "display/intel_gvt_api.h"
+
+#define DISPLAY_MMIO_BASE(display) \
+ intel_display_device_mmio_base((display))
+
+/*
+ * #FIXME:
+ * TRANSCONF() uses pipe-based addressing via _MMIO_PIPE2().
+ * Some GVT call sites pass enum transcoder instead of enum pipe.
+ * Cast the argument to enum pipe for now since TRANSCODER_A..D map
+ * 1:1 to PIPE_A..D.
+ * TRANSCODER_EDP is an exception, the cast preserves the existing
+ * behaviour but this needs to be handled later either by using the
+ * correct pipe or by switching TRANSCONF() to use _MMIO_TRANS2().
+ */
+#define INTEL_DISPLAY_DEVICE_PIPE_OFFSET(display, idx) \
+ intel_display_device_pipe_offset((display), (enum pipe)(idx))
+
+#define INTEL_DISPLAY_DEVICE_TRANS_OFFSET(display, trans) \
+ intel_display_device_trans_offset((display), (trans))
+
+#define INTEL_DISPLAY_DEVICE_CURSOR_OFFSET(display, pipe) \
+ intel_display_device_cursor_offset((display), (pipe))
+
+#define gvt_for_each_pipe(display, __p) \
+ for ((__p) = PIPE_A; (__p) < I915_MAX_PIPES; (__p)++) \
+ for_each_if(intel_display_device_pipe_valid((display), (__p)))
+
+#endif /* __DISPLAY_HELPERS_H__ */
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 92506c80322d..8e76869b352c 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -35,12 +35,12 @@
#include <drm/drm_plane.h>
#include <drm/drm_print.h>
+#include "display/skl_universal_plane_regs.h"
+
#include "gem/i915_gem_dmabuf.h"
-#include "i915_drv.h"
#include "gvt.h"
-
-#include "display/skl_universal_plane_regs.h"
+#include "i915_drv.h"
#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
index 3dcdb6570eda..aa7523386d94 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -30,7 +30,12 @@
#ifndef _GVT_DMABUF_H_
#define _GVT_DMABUF_H_
-#include <linux/vfio.h>
+
+#include <linux/kref.h>
+#include <linux/types.h>
+
+struct intel_vgpu;
+struct intel_vgpu_dmabuf_obj;
struct intel_vgpu_fb_info {
__u64 start;
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
index 30e414381af3..021afff1cd5d 100644
--- a/drivers/gpu/drm/i915/gvt/edid.c
+++ b/drivers/gpu/drm/i915/gvt/edid.c
@@ -38,6 +38,7 @@
#include "display/intel_dp_aux_regs.h"
#include "display/intel_gmbus.h"
#include "display/intel_gmbus_regs.h"
+
#include "gvt.h"
#include "i915_drv.h"
#include "i915_reg.h"
diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c
index 274c6ef42400..29147a9f162e 100644
--- a/drivers/gpu/drm/i915/gvt/execlist.c
+++ b/drivers/gpu/drm/i915/gvt/execlist.c
@@ -32,8 +32,8 @@
*
*/
-#include "i915_drv.h"
#include "gvt.h"
+#include "i915_drv.h"
#define _EL_OFFSET_STATUS 0x234
#define _EL_OFFSET_STATUS_BUF 0x370
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c
index a8079cfa8e1d..d7abf38df532 100644
--- a/drivers/gpu/drm/i915/gvt/fb_decoder.c
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c
@@ -35,18 +35,18 @@
#include <uapi/drm/drm_fourcc.h>
-#include "gvt.h"
-#include "i915_drv.h"
-#include "i915_pvinfo.h"
-#include "i915_reg.h"
-#include "display/intel_display_regs.h"
-
#include "display/i9xx_plane_regs.h"
#include "display/intel_cursor_regs.h"
-#include "display/intel_display_core.h"
+#include "display/intel_display_regs.h"
#include "display/intel_sprite_regs.h"
#include "display/skl_universal_plane_regs.h"
+#include "display_helpers.h"
+#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_pvinfo.h"
+#include "i915_reg.h"
+
#define PRIMARY_FORMAT_NUM 16
struct pixel_format {
int drm_format; /* Pixel format in DRM definition */
diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h
index 436d43c0087b..bc1e9d149e25 100644
--- a/drivers/gpu/drm/i915/gvt/fb_decoder.h
+++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h
@@ -38,8 +38,6 @@
#include <linux/types.h>
-#include "display/intel_display_limits.h"
-
struct intel_vgpu;
#define _PLANE_CTL_FORMAT_SHIFT 24
diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c
index 221a3ae81baf..e452298991be 100644
--- a/drivers/gpu/drm/i915/gvt/firmware.c
+++ b/drivers/gpu/drm/i915/gvt/firmware.c
@@ -28,12 +28,12 @@
*
*/
-#include <linux/firmware.h>
#include <linux/crc32.h>
+#include <linux/firmware.h>
#include <linux/vmalloc.h>
-#include "i915_drv.h"
#include "gvt.h"
+#include "i915_drv.h"
#include "i915_pvinfo.h"
#define FIRMWARE_VERSION (0x0)
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 076d9139edc6..49028e7ef1e0 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -33,16 +33,17 @@
*
*/
+#include <linux/vmalloc.h>
+
#include <drm/drm_print.h>
-#include "i915_drv.h"
+#include "gt/intel_gt_regs.h"
+
#include "gvt.h"
+#include "i915_drv.h"
#include "i915_pvinfo.h"
#include "trace.h"
-#include "gt/intel_gt_regs.h"
-#include <linux/vmalloc.h>
-
#if defined(VERBOSE_DEBUG)
#define gvt_vdbg_mm(fmt, args...) gvt_dbg_mm(fmt, ##args)
#else
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 1d10c16e6465..7fd2356f463c 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -34,29 +34,29 @@
#define _GVT_H_
#include <uapi/linux/pci_regs.h>
-#include <linux/vfio.h>
#include <linux/mdev.h>
-
+#include <linux/vfio.h>
#include <asm/kvm_page_track.h>
+#include "display/intel_display_limits.h"
+
#include "gt/intel_gt.h"
-#include "intel_gvt.h"
+#include "cmd_parser.h"
#include "debug.h"
-#include "mmio.h"
-#include "reg.h"
-#include "interrupt.h"
-#include "gtt.h"
#include "display.h"
+#include "dmabuf.h"
#include "edid.h"
#include "execlist.h"
-#include "scheduler.h"
-#include "sched_policy.h"
-#include "mmio_context.h"
-#include "cmd_parser.h"
#include "fb_decoder.h"
-#include "dmabuf.h"
+#include "gtt.h"
+#include "intel_gvt.h"
+#include "interrupt.h"
+#include "mmio.h"
+#include "mmio_context.h"
#include "page_track.h"
+#include "reg.h"
+#include "scheduler.h"
#define GVT_MAX_VGPU 8
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 36ea12ade849..bd20f287720f 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -36,20 +36,16 @@
*/
+#include <linux/vmalloc.h>
+
#include <drm/display/drm_dp.h>
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
-#include "display/intel_display_regs.h"
-#include "gvt.h"
-#include "i915_pvinfo.h"
-#include "intel_mchbar_regs.h"
#include "display/bxt_dpio_phy_regs.h"
#include "display/i9xx_plane_regs.h"
#include "display/intel_crt_regs.h"
#include "display/intel_cursor_regs.h"
-#include "display/intel_display_core.h"
+#include "display/intel_display_regs.h"
#include "display/intel_display_types.h"
#include "display/intel_dmc_regs.h"
#include "display/intel_dp_aux_regs.h"
@@ -64,8 +60,17 @@
#include "display/skl_universal_plane_regs.h"
#include "display/skl_watermark_regs.h"
#include "display/vlv_dsi_pll_regs.h"
+
+#include "gt/intel_engine_regs.h"
#include "gt/intel_gt_regs.h"
-#include <linux/vmalloc.h>
+
+#include "display_helpers.h"
+#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_pvinfo.h"
+#include "i915_reg.h"
+#include "intel_mchbar_regs.h"
+#include "sched_policy.h"
/* XXX FIXME i915 has changed PP_XXX definition */
#define PCH_PP_STATUS _MMIO(0xc7200)
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
index 3e66269bc4ee..91d22b1c62e2 100644
--- a/drivers/gpu/drm/i915/gvt/interrupt.c
+++ b/drivers/gpu/drm/i915/gvt/interrupt.c
@@ -33,10 +33,11 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
#include "display/intel_display_regs.h"
+
#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
#include "trace.h"
struct intel_gvt_irq_info {
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 3abc9206f1a8..009aa2df7958 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -33,26 +33,26 @@
* Zhi Wang <zhi.a.wang@intel.com>
*/
+#include <linux/debugfs.h>
+#include <linux/eventfd.h>
#include <linux/init.h>
-#include <linux/mm.h>
#include <linux/kthread.h>
-#include <linux/sched/mm.h>
-#include <linux/types.h>
#include <linux/list.h>
-#include <linux/rbtree.h>
-#include <linux/spinlock.h>
-#include <linux/eventfd.h>
#include <linux/mdev.h>
-#include <linux/debugfs.h>
-
+#include <linux/mm.h>
#include <linux/nospec.h>
+#include <linux/rbtree.h>
+#include <linux/sched/mm.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
#include <drm/drm_edid.h>
#include <drm/drm_print.h>
+#include "gvt.h"
#include "i915_drv.h"
#include "intel_gvt.h"
-#include "gvt.h"
+#include "sched_policy.h"
MODULE_IMPORT_NS("DMA_BUF");
MODULE_IMPORT_NS("I915_GVT");
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
index 214eb7effa31..9e98db2d4f67 100644
--- a/drivers/gpu/drm/i915/gvt/mmio.c
+++ b/drivers/gpu/drm/i915/gvt/mmio.c
@@ -37,15 +37,16 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_reg.h"
-#include "display/intel_display_regs.h"
-#include "gvt.h"
-
#include "display/bxt_dpio_phy_regs.h"
+#include "display/intel_display_regs.h"
#include "display/intel_dpio_phy.h"
+
#include "gt/intel_gt_regs.h"
+#include "gvt.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
+
/**
* intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset
* @vgpu: a vGPU
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.h b/drivers/gpu/drm/i915/gvt/mmio_context.h
index a821edf574dd..c0e3695e3bbe 100644
--- a/drivers/gpu/drm/i915/gvt/mmio_context.h
+++ b/drivers/gpu/drm/i915/gvt/mmio_context.h
@@ -38,8 +38,6 @@
#include <linux/types.h>
-#include "gt/intel_engine_regs.h"
-
struct i915_request;
struct intel_context;
struct intel_engine_cs;
@@ -57,7 +55,4 @@ bool is_inhibit_context(struct intel_context *ce);
int intel_vgpu_restore_inhibit_context(struct intel_vgpu *vgpu,
struct i915_request *req);
-#define IS_RESTORE_INHIBIT(a) \
- IS_MASKED_BITS_ENABLED(a, CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT)
-
#endif
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index dbad4d853d3a..d6e76ba31d60 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -22,8 +22,9 @@
*/
#include <linux/acpi.h>
-#include "i915_drv.h"
+
#include "gvt.h"
+#include "i915_drv.h"
/*
* Note: Only for GVT-g virtual VBT generation, other usage must
diff --git a/drivers/gpu/drm/i915/gvt/page_track.c b/drivers/gpu/drm/i915/gvt/page_track.c
index 20c3cd807488..b22ef801963e 100644
--- a/drivers/gpu/drm/i915/gvt/page_track.c
+++ b/drivers/gpu/drm/i915/gvt/page_track.c
@@ -20,8 +20,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include "i915_drv.h"
+
#include "gvt.h"
+#include "i915_drv.h"
/**
* intel_vgpu_find_page_track - find page track rcord of guest page
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c
index 6c2d68e88266..9736a15a896f 100644
--- a/drivers/gpu/drm/i915/gvt/sched_policy.c
+++ b/drivers/gpu/drm/i915/gvt/sched_policy.c
@@ -31,8 +31,9 @@
*
*/
-#include "i915_drv.h"
#include "gvt.h"
+#include "i915_drv.h"
+#include "sched_policy.h"
static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu)
{
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 63ad1fed525a..15fdd514ca83 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -38,20 +38,26 @@
#include <drm/drm_print.h>
#include "gem/i915_gem_pm.h"
+
#include "gt/intel_context.h"
+#include "gt/intel_engine_regs.h"
#include "gt/intel_execlists_submission.h"
#include "gt/intel_gt_regs.h"
#include "gt/intel_lrc.h"
#include "gt/intel_ring.h"
+#include "gvt.h"
#include "i915_drv.h"
#include "i915_gem_gtt.h"
#include "i915_perf_oa_regs.h"
-#include "gvt.h"
+#include "sched_policy.h"
#define RING_CTX_OFF(x) \
offsetof(struct execlist_ring_context, x)
+#define IS_RESTORE_INHIBIT(a) \
+ IS_MASKED_BITS_ENABLED(a, CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT)
+
static void set_context_pdp_root_pointer(
struct execlist_ring_context *ring_context,
u32 pdp[8])
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h
index 63874d385c6f..8cd0601e478f 100644
--- a/drivers/gpu/drm/i915/gvt/trace.h
+++ b/drivers/gpu/drm/i915/gvt/trace.h
@@ -31,9 +31,9 @@
#if !defined(_GVT_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
#define _GVT_TRACE_H_
-#include <linux/types.h>
#include <linux/stringify.h>
#include <linux/tracepoint.h>
+#include <linux/types.h>
#include <asm/tsc.h>
#undef TRACE_SYSTEM
diff --git a/drivers/gpu/drm/i915/gvt/trace_points.c b/drivers/gpu/drm/i915/gvt/trace_points.c
index fe552e877e09..79b75356d622 100644
--- a/drivers/gpu/drm/i915/gvt/trace_points.c
+++ b/drivers/gpu/drm/i915/gvt/trace_points.c
@@ -30,5 +30,7 @@
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
+
#include "trace.h"
+
#endif
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index c49e4bf95a30..96d0bd1fa337 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -31,12 +31,14 @@
*
*/
+#include <linux/vmalloc.h>
+
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "gvt.h"
+#include "i915_drv.h"
#include "i915_pvinfo.h"
-#include <linux/vmalloc.h>
+#include "sched_policy.h"
void populate_pvinfo_page(struct intel_vgpu *vgpu)
{
diff --git a/drivers/gpu/drm/i915/i915_config.c b/drivers/gpu/drm/i915/i915_config.c
index 3cb615ffa96d..9e13b1be407c 100644
--- a/drivers/gpu/drm/i915/i915_config.c
+++ b/drivers/gpu/drm/i915/i915_config.c
@@ -8,8 +8,7 @@
#include "i915_config.h"
#include "i915_jiffies.h"
-unsigned long
-i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context)
+unsigned long i915_fence_context_timeout(u64 context)
{
if (CONFIG_DRM_I915_FENCE_TIMEOUT && context)
return msecs_to_jiffies_timeout(CONFIG_DRM_I915_FENCE_TIMEOUT);
diff --git a/drivers/gpu/drm/i915/i915_config.h b/drivers/gpu/drm/i915/i915_config.h
index 10e18b036489..f386328d9e95 100644
--- a/drivers/gpu/drm/i915/i915_config.h
+++ b/drivers/gpu/drm/i915/i915_config.h
@@ -9,15 +9,11 @@
#include <linux/types.h>
#include <linux/limits.h>
-struct drm_i915_private;
+unsigned long i915_fence_context_timeout(u64 context);
-unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915,
- u64 context);
-
-static inline unsigned long
-i915_fence_timeout(const struct drm_i915_private *i915)
+static inline unsigned long i915_fence_timeout(void)
{
- return i915_fence_context_timeout(i915, U64_MAX);
+ return i915_fence_context_timeout(U64_MAX);
}
#endif /* __I915_CONFIG_H__ */
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index e025273e9ab1..f0105c5b49a7 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -99,6 +99,7 @@
#include "i915_gmch.h"
#include "i915_hdcp_gsc.h"
#include "i915_hwmon.h"
+#include "i915_initial_plane.h"
#include "i915_ioc32.h"
#include "i915_ioctl.h"
#include "i915_irq.h"
@@ -764,6 +765,7 @@ static bool vgpu_active(struct drm_device *drm)
static const struct intel_display_parent_interface parent = {
.hdcp = &i915_display_hdcp_interface,
+ .initial_plane = &i915_display_initial_plane_interface,
.irq = &i915_display_irq_interface,
.panic = &i915_display_panic_interface,
.pc8 = &i915_display_pc8_interface,
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 7582ef34bf3f..303d8d9b7775 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -686,7 +686,7 @@ static void err_print_guc_ctb(struct drm_i915_error_state_buf *m,
}
/* This list includes registers that are useful in debugging GuC hangs. */
-const struct {
+static const struct {
u32 start;
u32 count;
} guc_hw_reg_state[] = {
diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c
new file mode 100644
index 000000000000..7fb52d81f7b6
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_initial_plane.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
+
+#include "display/intel_crtc.h"
+#include "display/intel_display_types.h"
+#include "display/intel_fb.h"
+#include "gem/i915_gem_lmem.h"
+#include "gem/i915_gem_region.h"
+
+#include "i915_drv.h"
+#include "i915_initial_plane.h"
+
+static void i915_initial_plane_vblank_wait(struct drm_crtc *crtc)
+{
+ intel_crtc_wait_for_next_vblank(to_intel_crtc(crtc));
+}
+
+static enum intel_memory_type
+initial_plane_memory_type(struct drm_i915_private *i915)
+{
+ if (IS_DGFX(i915))
+ return INTEL_MEMORY_LOCAL;
+ else if (HAS_LMEMBAR_SMEM_STOLEN(i915))
+ return INTEL_MEMORY_STOLEN_LOCAL;
+ else
+ return INTEL_MEMORY_STOLEN_SYSTEM;
+}
+
+static bool
+initial_plane_phys(struct drm_i915_private *i915,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+ struct intel_memory_region *mem;
+ enum intel_memory_type mem_type;
+ bool is_present, is_local;
+ dma_addr_t dma_addr;
+ u32 base;
+
+ mem_type = initial_plane_memory_type(i915);
+ mem = intel_memory_region_by_type(i915, mem_type);
+ if (!mem) {
+ drm_dbg_kms(&i915->drm,
+ "Initial plane memory region (type %s) not initialized\n",
+ intel_memory_type_str(mem_type));
+ return false;
+ }
+
+ base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT);
+
+ dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local);
+
+ if (!is_present) {
+ drm_err(&i915->drm, "Initial plane FB PTE not present\n");
+ return false;
+ }
+
+ if (intel_memory_type_is_local(mem->type) != is_local) {
+ drm_err(&i915->drm, "Initial plane FB PTE unsuitable for %s\n",
+ mem->region.name);
+ return false;
+ }
+
+ if (dma_addr < mem->region.start || dma_addr > mem->region.end) {
+ drm_err(&i915->drm,
+ "Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n",
+ &dma_addr, mem->region.name, &mem->region.start, &mem->region.end);
+ return false;
+ }
+
+ drm_dbg(&i915->drm, "Using dma_addr=%pa, based on initial plane programming\n",
+ &dma_addr);
+
+ plane_config->phys_base = dma_addr - mem->region.start;
+ plane_config->mem = mem;
+
+ return true;
+}
+
+static struct i915_vma *
+initial_plane_vma(struct drm_i915_private *i915,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct intel_memory_region *mem;
+ struct drm_i915_gem_object *obj;
+ struct drm_mm_node orig_mm = {};
+ struct i915_vma *vma;
+ resource_size_t phys_base;
+ unsigned int tiling;
+ u32 base, size;
+ u64 pinctl;
+
+ if (plane_config->size == 0)
+ return NULL;
+
+ if (!initial_plane_phys(i915, plane_config))
+ return NULL;
+
+ phys_base = plane_config->phys_base;
+ mem = plane_config->mem;
+
+ base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT);
+ size = round_up(plane_config->base + plane_config->size,
+ mem->min_page_size);
+ size -= base;
+
+ /*
+ * If the FB is too big, just don't use it since fbdev is not very
+ * important and we should probably use that space with FBC or other
+ * features.
+ */
+ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
+ mem == i915->mm.stolen_region &&
+ size * 2 > i915->dsm.usable_size) {
+ drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n");
+ return NULL;
+ }
+
+ obj = i915_gem_object_create_region_at(mem, phys_base, size,
+ I915_BO_ALLOC_USER |
+ I915_BO_PREALLOC);
+ if (IS_ERR(obj)) {
+ drm_dbg_kms(&i915->drm, "Failed to preallocate initial FB in %s\n",
+ mem->region.name);
+ return NULL;
+ }
+
+ /*
+ * Mark it WT ahead of time to avoid changing the
+ * cache_level during fbdev initialization. The
+ * unbind there would get stuck waiting for rcu.
+ */
+ i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ?
+ I915_CACHE_WT : I915_CACHE_NONE);
+
+ tiling = intel_fb_modifier_to_tiling(plane_config->fb->base.modifier);
+
+ switch (tiling) {
+ case I915_TILING_NONE:
+ break;
+ case I915_TILING_X:
+ case I915_TILING_Y:
+ obj->tiling_and_stride =
+ plane_config->fb->base.pitches[0] |
+ tiling;
+ break;
+ default:
+ MISSING_CASE(tiling);
+ goto err_obj;
+ }
+
+ /*
+ * MTL GOP likes to place the framebuffer high up in ggtt,
+ * which can cause problems for ggtt_reserve_guc_top().
+ * Try to pin it to a low ggtt address instead to avoid that.
+ */
+ base = 0;
+
+ if (base != plane_config->base) {
+ struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+ int ret;
+
+ /*
+ * Make sure the original and new locations
+ * can't overlap. That would corrupt the original
+ * PTEs which are still being used for scanout.
+ */
+ ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &orig_mm,
+ size, plane_config->base,
+ I915_COLOR_UNEVICTABLE, PIN_NOEVICT);
+ if (ret)
+ goto err_obj;
+ }
+
+ vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL);
+ if (IS_ERR(vma))
+ goto err_obj;
+
+retry:
+ pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base;
+ if (!i915_gem_object_is_lmem(obj))
+ pinctl |= PIN_MAPPABLE;
+ if (i915_vma_pin(vma, 0, 0, pinctl)) {
+ if (drm_mm_node_allocated(&orig_mm)) {
+ drm_mm_remove_node(&orig_mm);
+ /*
+ * Try again, but this time pin
+ * it to its original location.
+ */
+ base = plane_config->base;
+ goto retry;
+ }
+ goto err_obj;
+ }
+
+ if (i915_gem_object_is_tiled(obj) &&
+ !i915_vma_is_map_and_fenceable(vma))
+ goto err_obj;
+
+ if (drm_mm_node_allocated(&orig_mm))
+ drm_mm_remove_node(&orig_mm);
+
+ drm_dbg_kms(&i915->drm,
+ "Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
+ i915_ggtt_offset(vma), plane_config->base);
+
+ return vma;
+
+err_obj:
+ if (drm_mm_node_allocated(&orig_mm))
+ drm_mm_remove_node(&orig_mm);
+ i915_gem_object_put(obj);
+ return NULL;
+}
+
+static struct drm_gem_object *
+i915_alloc_initial_plane_obj(struct drm_device *drm,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct drm_i915_private *i915 = to_i915(drm);
+ struct drm_mode_fb_cmd2 mode_cmd = {};
+ struct drm_framebuffer *fb = &plane_config->fb->base;
+ struct i915_vma *vma;
+
+ vma = initial_plane_vma(i915, plane_config);
+ if (!vma)
+ return NULL;
+
+ mode_cmd.pixel_format = fb->format->format;
+ mode_cmd.width = fb->width;
+ mode_cmd.height = fb->height;
+ mode_cmd.pitches[0] = fb->pitches[0];
+ mode_cmd.modifier[0] = fb->modifier;
+ mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
+
+ if (intel_framebuffer_init(to_intel_framebuffer(fb),
+ intel_bo_to_drm_bo(vma->obj),
+ fb->format, &mode_cmd)) {
+ drm_dbg_kms(&i915->drm, "intel fb init failed\n");
+ goto err_vma;
+ }
+
+ plane_config->vma = vma;
+ return intel_bo_to_drm_bo(vma->obj);
+
+err_vma:
+ i915_vma_put(vma);
+ return NULL;
+}
+
+static int
+i915_initial_plane_setup(struct drm_plane_state *_plane_state,
+ struct intel_initial_plane_config *plane_config,
+ struct drm_framebuffer *fb,
+ struct i915_vma *vma)
+{
+ struct intel_plane_state *plane_state = to_intel_plane_state(_plane_state);
+ struct drm_i915_private *dev_priv = to_i915(_plane_state->plane->dev);
+
+ __i915_vma_pin(vma);
+ plane_state->ggtt_vma = i915_vma_get(vma);
+ if (intel_plane_uses_fence(plane_state) &&
+ i915_vma_pin_fence(vma) == 0 && vma->fence)
+ plane_state->flags |= PLANE_HAS_FENCE;
+
+ plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma);
+
+ if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+ dev_priv->preserve_bios_swizzle = true;
+
+ return 0;
+}
+
+static void i915_plane_config_fini(struct intel_initial_plane_config *plane_config)
+{
+ if (plane_config->vma)
+ i915_vma_put(plane_config->vma);
+}
+
+const struct intel_display_initial_plane_interface i915_display_initial_plane_interface = {
+ .vblank_wait = i915_initial_plane_vblank_wait,
+ .alloc_obj = i915_alloc_initial_plane_obj,
+ .setup = i915_initial_plane_setup,
+ .config_fini = i915_plane_config_fini,
+};
diff --git a/drivers/gpu/drm/i915/i915_initial_plane.h b/drivers/gpu/drm/i915/i915_initial_plane.h
new file mode 100644
index 000000000000..99ba462659a6
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_initial_plane.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_INITIAL_PLANE_H__
+#define __I915_INITIAL_PLANE_H__
+
+extern const struct intel_display_initial_plane_interface i915_display_initial_plane_interface;
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 4399941236cb..d2c7b1090df0 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -1351,8 +1351,7 @@ __i915_request_await_external(struct i915_request *rq, struct dma_fence *fence)
{
mark_external(rq);
return i915_sw_fence_await_dma_fence(&rq->submit, fence,
- i915_fence_context_timeout(rq->i915,
- fence->context),
+ i915_fence_context_timeout(fence->context),
I915_FENCE_GFP);
}
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 9e5b7fcadbe2..ecc20e0528f4 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -38,22 +38,18 @@
struct drm_i915_private;
-#ifndef MISSING_CASE
#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
__stringify(x), (long)(x))
-#endif
#define i915_probe_error(i915, fmt, ...) ({ \
drm_err(&(i915)->drm, fmt, ##__VA_ARGS__); \
})
-#ifndef fetch_and_zero
#define fetch_and_zero(ptr) ({ \
typeof(*ptr) __T = *(ptr); \
*(ptr) = (typeof(*ptr))0; \
__T; \
})
-#endif
/*
* check_user_mbz: Check that a user value exists and is zero
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c
index 5f615ec0e580..6b43713899b8 100644
--- a/drivers/gpu/drm/i915/intel_gvt.c
+++ b/drivers/gpu/drm/i915/intel_gvt.c
@@ -21,16 +21,19 @@
* SOFTWARE.
*/
+#include <linux/vmalloc.h>
+
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_vgpu.h"
-#include "intel_gvt.h"
#include "gem/i915_gem_dmabuf.h"
+
#include "gt/intel_context.h"
#include "gt/intel_ring.h"
#include "gt/shmem_utils.h"
-#include <linux/vmalloc.h>
+
+#include "i915_drv.h"
+#include "i915_vgpu.h"
+#include "intel_gvt.h"
/**
* DOC: Intel GVT-g host support
diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
index ca57a3dd3148..478d00f89a4b 100644
--- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
+++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
@@ -12,6 +12,7 @@
#include "display/intel_crt_regs.h"
#include "display/intel_cursor_regs.h"
#include "display/intel_display_core.h"
+#include "display/intel_display_regs.h"
#include "display/intel_display_types.h"
#include "display/intel_dmc_regs.h"
#include "display/intel_dp_aux_regs.h"
@@ -27,14 +28,15 @@
#include "display/skl_universal_plane_regs.h"
#include "display/skl_watermark_regs.h"
#include "display/vlv_dsi_pll_regs.h"
+
#include "gt/intel_engine_regs.h"
#include "gt/intel_gt_regs.h"
+
#include "gvt/reg.h"
#include "i915_drv.h"
#include "i915_pvinfo.h"
#include "i915_reg.h"
-#include "display/intel_display_regs.h"
#include "intel_gvt.h"
#include "intel_mchbar_regs.h"
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 8dcc85cb8d42..2b20c79d7ec9 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -200,8 +200,7 @@ endif
# i915 Display compat #defines and #includes
subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
-I$(src)/compat-i915-headers \
- -I$(srctree)/drivers/gpu/drm/i915/display/ \
- -Ddrm_i915_private=xe_device
+ -I$(srctree)/drivers/gpu/drm/i915/display/
# Rule to build display code shared with i915
$(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE
@@ -219,8 +218,8 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
display/xe_dsb_buffer.o \
display/xe_fb_pin.o \
display/xe_hdcp_gsc.o \
+ display/xe_initial_plane.o \
display/xe_panic.o \
- display/xe_plane_initial.o \
display/xe_stolen.o \
display/xe_tdf.o
@@ -296,6 +295,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_hotplug.o \
i915-display/intel_hotplug_irq.o \
i915-display/intel_hti.o \
+ i915-display/intel_initial_plane.o \
i915-display/intel_link_bw.o \
i915-display/intel_lspcon.o \
i915-display/intel_lt_phy.o \
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h
index e835bea08d1b..d4522203e2dd 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h
@@ -8,10 +8,7 @@
#include <linux/sched.h>
-struct drm_i915_private;
-
-static inline unsigned long
-i915_fence_timeout(const struct drm_i915_private *i915)
+static inline unsigned long i915_fence_timeout(void)
{
return MAX_SCHEDULE_TIMEOUT;
}
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
deleted file mode 100644
index 04d1925f9a19..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-#ifndef _XE_I915_DRV_H_
-#define _XE_I915_DRV_H_
-
-/*
- * "Adaptation header" to allow i915 display to also build for xe driver.
- * TODO: refactor i915 and xe so this can cease to exist
- */
-
-#include <drm/drm_drv.h>
-
-#include "xe_device_types.h"
-
-static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
-{
- return container_of(dev, struct drm_i915_private, drm);
-}
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
deleted file mode 100644
index 3639721f0bf8..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-/* for a couple of users under i915/display */
-#define i915_inject_probe_failure(unused) ((unused) && 0)
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
index d93ddacdf743..c05d4c4292d3 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h
@@ -10,8 +10,6 @@
#include "xe_device_types.h"
#include "xe_mmio.h"
-#define FORCEWAKE_ALL XE_FORCEWAKE_ALL
-
static inline struct intel_uncore *to_intel_uncore(struct drm_device *drm)
{
return &to_xe_device(drm)->uncore;
@@ -154,9 +152,10 @@ static inline void intel_uncore_write_notrace(struct intel_uncore *uncore,
xe_mmio_write32(__compat_uncore_to_mmio(uncore), reg, val);
}
-#define intel_uncore_forcewake_get(x, y) do { } while (0)
-#define intel_uncore_forcewake_put(x, y) do { } while (0)
-
-#define intel_uncore_arm_unclaimed_mmio_detection(x) do { } while (0)
+static inline bool
+intel_uncore_arm_unclaimed_mmio_detection(struct intel_uncore *uncore)
+{
+ return false;
+}
#endif /* __INTEL_UNCORE_H__ */
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index eda65a05f601..f8a831b5dc7d 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -37,6 +37,7 @@
#include "skl_watermark.h"
#include "xe_display_rpm.h"
#include "xe_hdcp_gsc.h"
+#include "xe_initial_plane.h"
#include "xe_module.h"
#include "xe_panic.h"
#include "xe_stolen.h"
@@ -538,6 +539,7 @@ static const struct intel_display_irq_interface xe_display_irq_interface = {
static const struct intel_display_parent_interface parent = {
.hdcp = &xe_display_hdcp_interface,
+ .initial_plane = &xe_display_initial_plane_interface,
.irq = &xe_display_irq_interface,
.panic = &xe_display_panic_interface,
.rpm = &xe_display_rpm_interface,
diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c
index 6a935a75f2a4..a22a9182dadb 100644
--- a/drivers/gpu/drm/xe/display/xe_fb_pin.c
+++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c
@@ -373,7 +373,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
{
*out_flags = 0;
- return __xe_pin_fb_vma(to_intel_framebuffer(fb), view, phys_alignment);
+ return __xe_pin_fb_vma(to_intel_framebuffer(fb), view, alignment);
}
void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags)
diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c
new file mode 100644
index 000000000000..4cfeafcc158d
--- /dev/null
+++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+/* for ioread64 */
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+#include <drm/intel/display_parent_interface.h>
+
+#include "regs/xe_gtt_defs.h"
+#include "xe_ggtt.h"
+#include "xe_mmio.h"
+
+#include "i915_vma.h"
+#include "intel_crtc.h"
+#include "intel_display_regs.h"
+#include "intel_display_types.h"
+#include "intel_fb.h"
+#include "intel_fb_pin.h"
+#include "xe_bo.h"
+#include "xe_vram_types.h"
+#include "xe_wa.h"
+
+#include <generated/xe_device_wa_oob.h>
+
+/* Early xe has no irq */
+static void xe_initial_plane_vblank_wait(struct drm_crtc *_crtc)
+{
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct xe_device *xe = to_xe_device(crtc->base.dev);
+ struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe)));
+ u32 timestamp;
+ int ret;
+
+ timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp);
+
+ ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, &timestamp, false);
+ if (ret < 0)
+ drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret);
+}
+
+static struct xe_bo *
+initial_plane_bo(struct xe_device *xe,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct xe_tile *tile0 = xe_device_get_root_tile(xe);
+ struct xe_bo *bo;
+ resource_size_t phys_base;
+ u32 base, size, flags;
+ u64 page_size = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K;
+
+ if (plane_config->size == 0)
+ return NULL;
+
+ flags = XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT;
+
+ base = round_down(plane_config->base, page_size);
+ if (IS_DGFX(xe)) {
+ u64 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base);
+
+ if (!(pte & XE_GGTT_PTE_DM)) {
+ drm_err(&xe->drm,
+ "Initial plane programming missing DM bit\n");
+ return NULL;
+ }
+
+ phys_base = pte & ~(page_size - 1);
+ flags |= XE_BO_FLAG_VRAM0;
+
+ /*
+ * We don't currently expect this to ever be placed in the
+ * stolen portion.
+ */
+ if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram)) {
+ drm_err(&xe->drm,
+ "Initial plane programming using invalid range, phys_base=%pa\n",
+ &phys_base);
+ return NULL;
+ }
+
+ drm_dbg(&xe->drm,
+ "Using phys_base=%pa, based on initial plane programming\n",
+ &phys_base);
+ } else {
+ struct ttm_resource_manager *stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
+
+ if (!stolen)
+ return NULL;
+ phys_base = base;
+ flags |= XE_BO_FLAG_STOLEN;
+
+ if (XE_DEVICE_WA(xe, 22019338487_display))
+ return NULL;
+
+ /*
+ * If the FB is too big, just don't use it since fbdev is not very
+ * important and we should probably use that space with FBC or other
+ * features.
+ */
+ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
+ plane_config->size * 2 >> PAGE_SHIFT >= stolen->size)
+ return NULL;
+ }
+
+ size = round_up(plane_config->base + plane_config->size,
+ page_size);
+ size -= base;
+
+ bo = xe_bo_create_pin_map_at_novm(xe, tile0, size, phys_base,
+ ttm_bo_type_kernel, flags, 0, false);
+ if (IS_ERR(bo)) {
+ drm_dbg(&xe->drm,
+ "Failed to create bo phys_base=%pa size %u with flags %x: %li\n",
+ &phys_base, size, flags, PTR_ERR(bo));
+ return NULL;
+ }
+
+ return bo;
+}
+
+static struct drm_gem_object *
+xe_alloc_initial_plane_obj(struct drm_device *drm,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct xe_device *xe = to_xe_device(drm);
+ struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+ struct drm_framebuffer *fb = &plane_config->fb->base;
+ struct xe_bo *bo;
+
+ mode_cmd.pixel_format = fb->format->format;
+ mode_cmd.width = fb->width;
+ mode_cmd.height = fb->height;
+ mode_cmd.pitches[0] = fb->pitches[0];
+ mode_cmd.modifier[0] = fb->modifier;
+ mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
+
+ bo = initial_plane_bo(xe, plane_config);
+ if (!bo)
+ return NULL;
+
+ if (intel_framebuffer_init(to_intel_framebuffer(fb),
+ &bo->ttm.base, fb->format, &mode_cmd)) {
+ drm_dbg_kms(&xe->drm, "intel fb init failed\n");
+ goto err_bo;
+ }
+ /* Reference handed over to fb */
+ xe_bo_put(bo);
+
+ return &bo->ttm.base;
+
+err_bo:
+ xe_bo_unpin_map_no_vm(bo);
+ return NULL;
+}
+
+static int
+xe_initial_plane_setup(struct drm_plane_state *_plane_state,
+ struct intel_initial_plane_config *plane_config,
+ struct drm_framebuffer *fb,
+ struct i915_vma *_unused)
+{
+ struct intel_plane_state *plane_state = to_intel_plane_state(_plane_state);
+ struct i915_vma *vma;
+
+ vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt,
+ 0, 0, 0, false, &plane_state->flags);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+
+ plane_state->ggtt_vma = vma;
+
+ plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma);
+
+ plane_config->vma = vma;
+
+ return 0;
+}
+
+static void xe_plane_config_fini(struct intel_initial_plane_config *plane_config)
+{
+}
+
+const struct intel_display_initial_plane_interface xe_display_initial_plane_interface = {
+ .vblank_wait = xe_initial_plane_vblank_wait,
+ .alloc_obj = xe_alloc_initial_plane_obj,
+ .setup = xe_initial_plane_setup,
+ .config_fini = xe_plane_config_fini,
+};
diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.h b/drivers/gpu/drm/xe/display/xe_initial_plane.h
new file mode 100644
index 000000000000..399d15f14441
--- /dev/null
+++ b/drivers/gpu/drm/xe/display/xe_initial_plane.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __XE_INITIAL_PLANE_H__
+#define __XE_INITIAL_PLANE_H__
+
+extern const struct intel_display_initial_plane_interface xe_display_initial_plane_interface;
+
+#endif
diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c
deleted file mode 100644
index 01c105a93bb9..000000000000
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ /dev/null
@@ -1,321 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2021 Intel Corporation
- */
-
-/* for ioread64 */
-#include <linux/io-64-nonatomic-lo-hi.h>
-
-#include "regs/xe_gtt_defs.h"
-#include "xe_ggtt.h"
-#include "xe_mmio.h"
-
-#include "i915_vma.h"
-#include "intel_crtc.h"
-#include "intel_display.h"
-#include "intel_display_core.h"
-#include "intel_display_regs.h"
-#include "intel_display_types.h"
-#include "intel_fb.h"
-#include "intel_fb_pin.h"
-#include "intel_frontbuffer.h"
-#include "intel_plane.h"
-#include "intel_plane_initial.h"
-#include "xe_bo.h"
-#include "xe_vram_types.h"
-#include "xe_wa.h"
-
-#include <generated/xe_device_wa_oob.h>
-
-void intel_plane_initial_vblank_wait(struct intel_crtc *crtc)
-{
- /* Early xe has no irq */
- struct xe_device *xe = to_xe_device(crtc->base.dev);
- struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe)));
- u32 timestamp;
- int ret;
-
- timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp);
-
- ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, &timestamp, false);
- if (ret < 0)
- drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret);
-}
-
-static bool
-intel_reuse_initial_plane_obj(struct intel_crtc *this,
- const struct intel_initial_plane_config plane_configs[],
- struct drm_framebuffer **fb)
-{
- struct xe_device *xe = to_xe_device(this->base.dev);
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(&xe->drm, crtc) {
- struct intel_plane *plane =
- to_intel_plane(crtc->base.primary);
- const struct intel_plane_state *plane_state =
- to_intel_plane_state(plane->base.state);
- const struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
-
- if (!crtc_state->hw.active)
- continue;
-
- if (!plane_state->ggtt_vma)
- continue;
-
- if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base) {
- *fb = plane_state->hw.fb;
- return true;
- }
- }
-
- return false;
-}
-
-static struct xe_bo *
-initial_plane_bo(struct xe_device *xe,
- struct intel_initial_plane_config *plane_config)
-{
- struct xe_tile *tile0 = xe_device_get_root_tile(xe);
- struct xe_bo *bo;
- resource_size_t phys_base;
- u32 base, size, flags;
- u64 page_size = xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K;
-
- if (plane_config->size == 0)
- return NULL;
-
- flags = XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT;
-
- base = round_down(plane_config->base, page_size);
- if (IS_DGFX(xe)) {
- u64 pte = xe_ggtt_read_pte(tile0->mem.ggtt, base);
-
- if (!(pte & XE_GGTT_PTE_DM)) {
- drm_err(&xe->drm,
- "Initial plane programming missing DM bit\n");
- return NULL;
- }
-
- phys_base = pte & ~(page_size - 1);
- flags |= XE_BO_FLAG_VRAM0;
-
- /*
- * We don't currently expect this to ever be placed in the
- * stolen portion.
- */
- if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram)) {
- drm_err(&xe->drm,
- "Initial plane programming using invalid range, phys_base=%pa\n",
- &phys_base);
- return NULL;
- }
-
- drm_dbg(&xe->drm,
- "Using phys_base=%pa, based on initial plane programming\n",
- &phys_base);
- } else {
- struct ttm_resource_manager *stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
-
- if (!stolen)
- return NULL;
- phys_base = base;
- flags |= XE_BO_FLAG_STOLEN;
-
- if (XE_DEVICE_WA(xe, 22019338487_display))
- return NULL;
-
- /*
- * If the FB is too big, just don't use it since fbdev is not very
- * important and we should probably use that space with FBC or other
- * features.
- */
- if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
- plane_config->size * 2 >> PAGE_SHIFT >= stolen->size)
- return NULL;
- }
-
- size = round_up(plane_config->base + plane_config->size,
- page_size);
- size -= base;
-
- bo = xe_bo_create_pin_map_at_novm(xe, tile0, size, phys_base,
- ttm_bo_type_kernel, flags, 0, false);
- if (IS_ERR(bo)) {
- drm_dbg(&xe->drm,
- "Failed to create bo phys_base=%pa size %u with flags %x: %li\n",
- &phys_base, size, flags, PTR_ERR(bo));
- return NULL;
- }
-
- return bo;
-}
-
-static bool
-intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
- struct intel_initial_plane_config *plane_config)
-{
- struct xe_device *xe = to_xe_device(crtc->base.dev);
- struct drm_mode_fb_cmd2 mode_cmd = { 0 };
- struct drm_framebuffer *fb = &plane_config->fb->base;
- struct xe_bo *bo;
-
- switch (fb->modifier) {
- 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_kms(&xe->drm,
- "Unsupported modifier for initial FB: 0x%llx\n",
- fb->modifier);
- return false;
- }
-
- mode_cmd.pixel_format = fb->format->format;
- mode_cmd.width = fb->width;
- mode_cmd.height = fb->height;
- mode_cmd.pitches[0] = fb->pitches[0];
- mode_cmd.modifier[0] = fb->modifier;
- mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
-
- bo = initial_plane_bo(xe, plane_config);
- if (!bo)
- return false;
-
- if (intel_framebuffer_init(to_intel_framebuffer(fb),
- &bo->ttm.base, fb->format, &mode_cmd)) {
- drm_dbg_kms(&xe->drm, "intel fb init failed\n");
- goto err_bo;
- }
- /* Reference handed over to fb */
- xe_bo_put(bo);
-
- return true;
-
-err_bo:
- xe_bo_unpin_map_no_vm(bo);
- return false;
-}
-
-static void
-intel_find_initial_plane_obj(struct intel_crtc *crtc,
- struct intel_initial_plane_config plane_configs[])
-{
- struct intel_initial_plane_config *plane_config =
- &plane_configs[crtc->pipe];
- struct intel_plane *plane =
- to_intel_plane(crtc->base.primary);
- struct intel_plane_state *plane_state =
- to_intel_plane_state(plane->base.state);
- struct drm_framebuffer *fb;
- struct i915_vma *vma;
-
- /*
- * TODO:
- * Disable planes if get_initial_plane_config() failed.
- * Make sure things work if the surface base is not page aligned.
- */
- if (!plane_config->fb)
- return;
-
- if (intel_alloc_initial_plane_obj(crtc, plane_config))
- fb = &plane_config->fb->base;
- else if (!intel_reuse_initial_plane_obj(crtc, plane_configs, &fb))
- goto nofb;
-
- plane_state->uapi.rotation = plane_config->rotation;
- intel_fb_fill_view(to_intel_framebuffer(fb),
- plane_state->uapi.rotation, &plane_state->view);
-
- vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt,
- 0, 0, 0, false, &plane_state->flags);
- if (IS_ERR(vma))
- goto nofb;
-
- plane_state->ggtt_vma = vma;
-
- plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma);
-
- plane_state->uapi.src_x = 0;
- plane_state->uapi.src_y = 0;
- plane_state->uapi.src_w = fb->width << 16;
- plane_state->uapi.src_h = fb->height << 16;
-
- plane_state->uapi.crtc_x = 0;
- plane_state->uapi.crtc_y = 0;
- plane_state->uapi.crtc_w = fb->width;
- plane_state->uapi.crtc_h = fb->height;
-
- plane_state->uapi.fb = fb;
- drm_framebuffer_get(fb);
-
- plane_state->uapi.crtc = &crtc->base;
- intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc);
-
- atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits);
-
- plane_config->vma = vma;
- return;
-
-nofb:
- /*
- * We've failed to reconstruct the BIOS FB. Current display state
- * indicates that the primary plane is visible, but has a NULL FB,
- * which will lead to problems later if we don't fix it up. The
- * simplest solution is to just disable the primary plane now and
- * pretend the BIOS never had it enabled.
- */
- intel_plane_disable_noatomic(crtc, plane);
-}
-
-static void plane_config_fini(struct intel_initial_plane_config *plane_config)
-{
- if (plane_config->fb) {
- struct drm_framebuffer *fb = &plane_config->fb->base;
-
- /* We may only have the stub and not a full framebuffer */
- if (drm_framebuffer_read_refcount(fb))
- drm_framebuffer_put(fb);
- else
- kfree(fb);
- }
-}
-
-void intel_initial_plane_config(struct intel_display *display)
-{
- struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(display->drm, crtc) {
- const struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
- struct intel_initial_plane_config *plane_config =
- &plane_configs[crtc->pipe];
-
- if (!crtc_state->hw.active)
- continue;
-
- /*
- * Note that reserving the BIOS fb up front prevents us
- * from stuffing other stolen allocations like the ring
- * on top. This prevents some ugliness at boot time, and
- * can even allow for smooth boot transitions if the BIOS
- * fb is large enough for the active pipe configuration.
- */
- display->funcs.display->get_initial_plane_config(crtc, plane_config);
-
- /*
- * If the fb is shared between multiple heads, we'll
- * just get the first one.
- */
- intel_find_initial_plane_obj(crtc, plane_configs);
-
- if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
- intel_plane_initial_vblank_wait(crtc);
-
- plane_config_fini(plane_config);
- }
-}
diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h
index 10c50b42844e..ce946859a3a9 100644
--- a/include/drm/intel/display_parent_interface.h
+++ b/include/drm/intel/display_parent_interface.h
@@ -7,9 +7,15 @@
#include <linux/types.h>
struct dma_fence;
+struct drm_crtc;
struct drm_device;
+struct drm_framebuffer;
+struct drm_gem_object;
+struct drm_plane_state;
struct drm_scanout_buffer;
+struct i915_vma;
struct intel_hdcp_gsc_context;
+struct intel_initial_plane_config;
struct intel_panic;
struct intel_stolen_node;
struct ref_tracker;
@@ -25,6 +31,14 @@ struct intel_display_hdcp_interface {
void (*gsc_context_free)(struct intel_hdcp_gsc_context *gsc_context);
};
+struct intel_display_initial_plane_interface {
+ void (*vblank_wait)(struct drm_crtc *crtc);
+ struct drm_gem_object *(*alloc_obj)(struct drm_device *drm, struct intel_initial_plane_config *plane_config);
+ int (*setup)(struct drm_plane_state *plane_state, struct intel_initial_plane_config *plane_config,
+ struct drm_framebuffer *fb, struct i915_vma *vma);
+ void (*config_fini)(struct intel_initial_plane_config *plane_configs);
+};
+
struct intel_display_irq_interface {
bool (*enabled)(struct drm_device *drm);
void (*synchronize)(struct drm_device *drm);
@@ -95,6 +109,9 @@ struct intel_display_parent_interface {
/** @hdcp: HDCP GSC interface */
const struct intel_display_hdcp_interface *hdcp;
+ /** @initial_plane: Initial plane interface */
+ const struct intel_display_initial_plane_interface *initial_plane;
+
/** @irq: IRQ interface */
const struct intel_display_irq_interface *irq;
diff --git a/include/drm/intel/intel_lb_mei_interface.h b/include/drm/intel/intel_lb_mei_interface.h
index d65be2cba2ab..0850738a30fc 100644
--- a/include/drm/intel/intel_lb_mei_interface.h
+++ b/include/drm/intel/intel_lb_mei_interface.h
@@ -53,7 +53,8 @@ enum intel_lb_status {
*/
struct intel_lb_component_ops {
/**
- * push_payload - Sends a payload to the authentication firmware
+ * @push_payload: Sends a payload to the authentication firmware
+ *
* @dev: Device struct corresponding to the mei device
* @type: Payload type (see &enum intel_lb_type)
* @flags: Payload flags bitmap (e.g. %INTEL_LB_FLAGS_IS_PERSISTENT)