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
This commit is contained in:
Dave Airlie
2026-01-16 12:57:20 +10:00
95 changed files with 2017 additions and 1443 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2024 Intel Corporation
*/

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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));

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/

View File

@@ -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

View File

@@ -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;

View File

@@ -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"

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/

View File

@@ -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;

View File

@@ -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__ */

View File

@@ -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 {

View File

@@ -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))

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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__ */

View File

@@ -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;
bits_per_pixel = valid_dsc_bpp[i];
for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) {
int vesa_bpp_x16 = fxp_q4_from_int(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;
dsc = dsc_max_compressed_bpp && dsc_slice_count;
if (!drm_dp_is_uhbr_rate(max_link_clock))
bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
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;
}
return false;
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);
}
}
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;
int 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;
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;
else
pipe_bpp = limits->pipe.max_bpp;
/* 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);
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;
limits->link.min_bpp_x16 =
compute_min_compressed_bpp_x16(connector, crtc_state->output_format);
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;
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);

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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:

View File

@@ -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);

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/

View File

@@ -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");

View File

@@ -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__ */

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
/*
* 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;
if (memcmp(&a->data, &b->data, sizeof(a->data)) != 0)
return false;
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,

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2025 Intel Corporation
*/

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: MIT
*
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2025 Intel Corporation
*/

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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__ */

View File

@@ -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))

View File

@@ -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);

View File

@@ -36,10 +36,11 @@
#include <drm/drm_print.h>
#include "gt/intel_ggtt_fencing.h"
#include "gvt.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "gt/intel_ggtt_fencing.h"
#include "gvt.h"
static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
{

View File

@@ -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 {

View File

@@ -38,26 +38,28 @@
#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 "gvt.h"
#include "i915_pvinfo.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"
#include "display_helpers.h"
#include "gvt.h"
#include "i915_drv.h"
#include "i915_pvinfo.h"
#include "i915_reg.h"
#include "trace.h"
#define INVALID_OP (~0U)

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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__ */

View File

@@ -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))

View File

@@ -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;

View File

@@ -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"

View File

@@ -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

View File

@@ -35,17 +35,17 @@
#include <uapi/drm/drm_fourcc.h>
#include "display/i9xx_plane_regs.h"
#include "display/intel_cursor_regs.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"
#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_sprite_regs.h"
#include "display/skl_universal_plane_regs.h"
#define PRIMARY_FORMAT_NUM 16
struct pixel_format {

View File

@@ -38,8 +38,6 @@
#include <linux/types.h>
#include "display/intel_display_limits.h"
struct intel_vgpu;
#define _PLANE_CTL_FORMAT_SHIFT 24

View File

@@ -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)

View File

@@ -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

View File

@@ -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 "gt/intel_gt.h"
#include "intel_gvt.h"
#include "display/intel_display_limits.h"
#include "gt/intel_gt.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

View File

@@ -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)

View File

@@ -33,10 +33,11 @@
#include <drm/drm_print.h>
#include "display/intel_display_regs.h"
#include "gvt.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "display/intel_display_regs.h"
#include "gvt.h"
#include "trace.h"
struct intel_gvt_irq_info {

View File

@@ -33,26 +33,26 @@
* Zhi Wang <zhi.a.wang@intel.com>
*/
#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/eventfd.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mdev.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");

View File

@@ -37,14 +37,15 @@
#include <drm/drm_print.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"
#include "display/intel_display_regs.h"
#include "gvt.h"
#include "display/bxt_dpio_phy_regs.h"
#include "display/intel_dpio_phy.h"
#include "gt/intel_gt_regs.h"
/**
* intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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])

View File

@@ -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

View File

@@ -30,5 +30,7 @@
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "trace.h"
#endif

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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__ */

View File

@@ -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,

View File

@@ -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[] = {

View File

@@ -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,
};

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -21,16 +21,19 @@
* SOFTWARE.
*/
#include <linux/vmalloc.h>
#include <drm/drm_print.h>
#include "gem/i915_gem_dmabuf.h"
#include "gt/intel_context.h"
#include "gt/intel_ring.h"
#include "gt/shmem_utils.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>
/**
* DOC: Intel GVT-g host support

View File

@@ -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"