summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2025-12-27 16:25:56 +1000
committerDave Airlie <airlied@redhat.com>2025-12-27 16:27:04 +1000
commitc5fb82d113c6266e65fee2a7e0dc8f48c3bd12cc (patch)
tree75a2c2a5ee400b24950071148336275c614f6a3d /drivers
parent7bc0f871f992f1469229ffcd2b40a45ec5f695b0 (diff)
parent35ec71285c9311395b14bedc60fa94f6b7e24d2d (diff)
Merge tag 'drm-intel-next-2025-12-19' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
Beyond Display related: - Switch to use kernel standard fault injection in i915 (Juha-Pekka) Display uAPI related: - Display uapi vs. hw state fixes (Ville) - Expose sharpness only if num_scalers is >= 2 (Nemesa) Display related: - More display driver refactor and clean-ups, specially towards separation (Jani) - Add initial support Xe3p_LPD for NVL (Gustavo, Sai, ) - BMG FBC W/a (Vinod) - RPM fix (Dibin) - Add MTL+ platforms to support dpll framework (Mika, Imre) - Other PLL related fixes (Imre) - Fix DIMM_S DRAM decoding on ICL (Ville) - Async flip refactor (Ville, Jouni) - Go back to using AUX interrupts (Ville) - Reduce severity of failed DII FEC enabling (Grzelak) - Enable system cache support for FBC (Vinod) - Move PSR/Panel Replay sink data into intel_connector and other PSR changes (Jouni) - Detect AuxCCS support via display parent interface (Tvrtko) - Clean up link BW/DSC slice config computation(Imre) - Toggle powerdown states for C10 on HDMI (Gustavo) - Add parent interface for PC8 forcewake tricks (Ville) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patch.msgid.link/aUW3bVDdE63aSFOJ@intel.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/display/drm_dp_helper.c103
-rw-r--r--drivers/gpu/drm/i915/Makefile20
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c5
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c2
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c9
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.c5
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_alpm.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c76
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_bo.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_bo.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_cmtg.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_colorop.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_colorop.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c31
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_cursor.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c927
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h29
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c116
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c102
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h18
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.c203
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c48
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h48
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c64
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_regs.h23
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reset.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_rps.c31
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_rps.h21
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h52
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c234
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c16
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c33
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c24
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c336
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_dram.c (renamed from drivers/gpu/drm/i915/soc/intel_dram.c)399
-rw-r--r--drivers/gpu/drm/i915/display/intel_dram.h (renamed from drivers/gpu/drm/i915/soc/intel_dram.h)12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c42
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb_buffer.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb_buffer.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi.h7
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c266
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc_regs.h12
-rw-r--r--drivers/gpu/drm/i915/display/intel_fifo_underrun.c109
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.h22
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c78
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_lpe_audio.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_lt_phy.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_setup.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_panic.c27
-rw-r--r--drivers/gpu/drm/i915/display/intel_panic.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_parent.c214
-rw-r--r--drivers/gpu/drm/i915/display/intel_parent.h70
-rw-r--r--drivers/gpu/drm/i915/display/intel_pipe_crc.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane.c96
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane_initial.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.c63
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c317
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_rom.c (renamed from drivers/gpu/drm/i915/soc/intel_rom.c)0
-rw-r--r--drivers/gpu/drm/i915/display/intel_rom.h (renamed from drivers/gpu/drm/i915/soc/intel_rom.h)0
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c40
-rw-r--r--drivers/gpu/drm/i915/display/intel_vbt_defs.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c44
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c19
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c8
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.c52
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.h23
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c9
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_print.h5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.c40
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_wopcm.c3
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c8
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc.c4
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.c17
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c60
-rw-r--r--drivers/gpu/drm/i915/i915_display_pc8.c31
-rw-r--r--drivers/gpu/drm/i915/i915_display_pc8.h9
-rw-r--r--drivers/gpu/drm/i915/i915_driver.c75
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_edram.c44
-rw-r--r--drivers/gpu/drm/i915/i915_edram.h11
-rw-r--r--drivers/gpu/drm/i915/i915_freq.c111
-rw-r--r--drivers/gpu/drm/i915/i915_freq.h13
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gmch.c (renamed from drivers/gpu/drm/i915/soc/intel_gmch.c)61
-rw-r--r--drivers/gpu/drm/i915/i915_gmch.h13
-rw-r--r--drivers/gpu/drm/i915/i915_hdcp_gsc.c (renamed from drivers/gpu/drm/i915/display/intel_hdcp_gsc.c)22
-rw-r--r--drivers/gpu/drm/i915/i915_hdcp_gsc.h9
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c16
-rw-r--r--drivers/gpu/drm/i915/i915_irq.h2
-rw-r--r--drivers/gpu/drm/i915/i915_panic.c35
-rw-r--r--drivers/gpu/drm/i915/i915_panic.h9
-rw-r--r--drivers/gpu/drm/i915/i915_params.c5
-rw-r--r--drivers/gpu/drm/i915/i915_params.h1
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c6
-rw-r--r--drivers/gpu/drm/i915/i915_utils.c30
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h22
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.c10
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.h6
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.c3
-rw-r--r--drivers/gpu/drm/i915/intel_mchbar_regs.h68
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c4
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.c2
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.h14
-rw-r--r--drivers/gpu/drm/i915/soc/intel_gmch.h20
-rw-r--r--drivers/gpu/drm/i915/vlv_suspend.c2
-rw-r--r--drivers/gpu/drm/xe/Makefile19
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h13
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h40
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h11
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_active.h22
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_active_types.h13
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h15
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h6
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h6
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h18
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/intel_wakeref.h10
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h29
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h6
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h6
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h6
-rw-r--r--drivers/gpu/drm/xe/display/ext/i915_irq.c85
-rw-r--r--drivers/gpu/drm/xe/display/intel_bo.c8
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.c28
-rw-r--r--drivers/gpu/drm/xe/display/xe_display_misc.c16
-rw-r--r--drivers/gpu/drm/xe/display/xe_display_rpm.c3
-rw-r--r--drivers/gpu/drm/xe/display/xe_dsb_buffer.c49
-rw-r--r--drivers/gpu/drm/xe/display/xe_hdcp_gsc.c25
-rw-r--r--drivers/gpu/drm/xe/display/xe_hdcp_gsc.h9
-rw-r--r--drivers/gpu/drm/xe/display/xe_panic.c16
-rw-r--r--drivers/gpu/drm/xe/display/xe_panic.h9
-rw-r--r--drivers/gpu/drm/xe/display/xe_plane_initial.c6
-rw-r--r--drivers/gpu/drm/xe/display/xe_stolen.c62
-rw-r--r--drivers/gpu/drm/xe/display/xe_stolen.h9
-rw-r--r--drivers/gpu/drm/xe/xe_device_types.h8
174 files changed, 3706 insertions, 2506 deletions
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index f9fdf19de74a..a697cc227e28 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2705,6 +2705,71 @@ u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
EXPORT_SYMBOL(drm_dp_dsc_sink_bpp_incr);
/**
+ * drm_dp_dsc_slice_count_to_mask() - Convert a slice count to a slice count mask
+ * @slice_count: slice count
+ *
+ * Convert @slice_count to a slice count mask.
+ *
+ * Returns the slice count mask.
+ */
+u32 drm_dp_dsc_slice_count_to_mask(int slice_count)
+{
+ return BIT(slice_count - 1);
+}
+EXPORT_SYMBOL(drm_dp_dsc_slice_count_to_mask);
+
+/**
+ * drm_dp_dsc_sink_slice_count_mask() - Get the mask of valid DSC sink slice counts
+ * @dsc_dpcd: the sink's DSC DPCD capabilities
+ * @is_edp: %true for an eDP sink
+ *
+ * Get the mask of supported slice counts from the sink's DSC DPCD register.
+ *
+ * Returns:
+ * Mask of slice counts supported by the DSC sink:
+ * - > 0: bit#0,1,3,5..,23 set if the sink supports 1,2,4,6..,24 slices
+ * - 0: if the sink doesn't support any slices
+ */
+u32 drm_dp_dsc_sink_slice_count_mask(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
+ bool is_edp)
+{
+ u8 slice_cap1 = dsc_dpcd[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
+ u32 mask = 0;
+
+ if (!is_edp) {
+ /* For DP, use values from DSC_SLICE_CAP_1 and DSC_SLICE_CAP2 */
+ u8 slice_cap2 = dsc_dpcd[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
+
+ if (slice_cap2 & DP_DSC_24_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(24);
+ if (slice_cap2 & DP_DSC_20_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(20);
+ if (slice_cap2 & DP_DSC_16_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(16);
+ }
+
+ /* DP, eDP v1.5+ */
+ if (slice_cap1 & DP_DSC_12_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(12);
+ if (slice_cap1 & DP_DSC_10_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(10);
+ if (slice_cap1 & DP_DSC_8_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(8);
+ if (slice_cap1 & DP_DSC_6_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(6);
+ /* DP, eDP v1.4+ */
+ if (slice_cap1 & DP_DSC_4_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(4);
+ if (slice_cap1 & DP_DSC_2_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(2);
+ if (slice_cap1 & DP_DSC_1_PER_DP_DSC_SINK)
+ mask |= drm_dp_dsc_slice_count_to_mask(1);
+
+ return mask;
+}
+EXPORT_SYMBOL(drm_dp_dsc_sink_slice_count_mask);
+
+/**
* drm_dp_dsc_sink_max_slice_count() - Get the max slice count
* supported by the DSC sink.
* @dsc_dpcd: DSC capabilities from DPCD
@@ -2723,43 +2788,7 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_bpp_incr);
u8 drm_dp_dsc_sink_max_slice_count(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
bool is_edp)
{
- u8 slice_cap1 = dsc_dpcd[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
-
- if (is_edp) {
- /* For eDP, register DSC_SLICE_CAPABILITIES_1 gives slice count */
- if (slice_cap1 & DP_DSC_4_PER_DP_DSC_SINK)
- return 4;
- if (slice_cap1 & DP_DSC_2_PER_DP_DSC_SINK)
- return 2;
- if (slice_cap1 & DP_DSC_1_PER_DP_DSC_SINK)
- return 1;
- } else {
- /* For DP, use values from DSC_SLICE_CAP_1 and DSC_SLICE_CAP2 */
- u8 slice_cap2 = dsc_dpcd[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
-
- if (slice_cap2 & DP_DSC_24_PER_DP_DSC_SINK)
- return 24;
- if (slice_cap2 & DP_DSC_20_PER_DP_DSC_SINK)
- return 20;
- if (slice_cap2 & DP_DSC_16_PER_DP_DSC_SINK)
- return 16;
- if (slice_cap1 & DP_DSC_12_PER_DP_DSC_SINK)
- return 12;
- if (slice_cap1 & DP_DSC_10_PER_DP_DSC_SINK)
- return 10;
- if (slice_cap1 & DP_DSC_8_PER_DP_DSC_SINK)
- return 8;
- if (slice_cap1 & DP_DSC_6_PER_DP_DSC_SINK)
- return 6;
- if (slice_cap1 & DP_DSC_4_PER_DP_DSC_SINK)
- return 4;
- if (slice_cap1 & DP_DSC_2_PER_DP_DSC_SINK)
- return 2;
- if (slice_cap1 & DP_DSC_1_PER_DP_DSC_SINK)
- return 1;
- }
-
- return 0;
+ return fls(drm_dp_dsc_sink_slice_count_mask(dsc_dpcd, is_edp));
}
EXPORT_SYMBOL(drm_dp_dsc_sink_max_slice_count);
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1d5536476549..5f7b2bbe448c 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -27,7 +27,10 @@ i915-y += \
i915_config.o \
i915_driver.o \
i915_drm_client.o \
+ i915_edram.o \
+ i915_freq.o \
i915_getparam.o \
+ i915_gmch.o \
i915_ioctl.o \
i915_irq.o \
i915_mitigations.o \
@@ -54,12 +57,6 @@ i915-y += \
vlv_iosf_sb.o \
vlv_suspend.o
-# core peripheral code
-i915-y += \
- soc/intel_dram.o \
- soc/intel_gmch.o \
- soc/intel_rom.o
-
# core library code
i915-y += \
i915_memcpy.o \
@@ -77,6 +74,12 @@ i915-$(CONFIG_DEBUG_FS) += \
i915-$(CONFIG_PERF_EVENTS) += \
i915_pmu.o
+# core display adaptation
+i915-y += \
+ i915_display_pc8.o \
+ i915_hdcp_gsc.o \
+ i915_panic.o
+
# "Graphics Technology" (aka we talk to the gpu)
gt-y += \
gt/gen2_engine_cs.o \
@@ -267,6 +270,7 @@ i915-y += \
display/intel_dpll_mgr.o \
display/intel_dpt.o \
display/intel_dpt_common.o \
+ display/intel_dram.o \
display/intel_drrs.o \
display/intel_dsb.o \
display/intel_dsb_buffer.o \
@@ -280,7 +284,6 @@ i915-y += \
display/intel_frontbuffer.o \
display/intel_global_state.o \
display/intel_hdcp.o \
- display/intel_hdcp_gsc.o \
display/intel_hdcp_gsc_message.o \
display/intel_hotplug.o \
display/intel_hotplug_irq.o \
@@ -292,7 +295,7 @@ i915-y += \
display/intel_modeset_setup.o \
display/intel_modeset_verify.o \
display/intel_overlay.o \
- display/intel_panic.o \
+ display/intel_parent.o \
display/intel_pch.o \
display/intel_pch_display.o \
display/intel_pch_refclk.o \
@@ -301,6 +304,7 @@ i915-y += \
display/intel_pmdemand.o \
display/intel_psr.o \
display/intel_quirks.o \
+ display/intel_rom.o \
display/intel_sbi.o \
display/intel_sprite.o \
display/intel_sprite_uapi.o \
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index a3ff21b2f69f..4cb753177fd8 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -302,7 +302,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(display,
@@ -684,12 +684,11 @@ static void intel_enable_dp(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
u32 dp_reg = intel_de_read(display, intel_dp->output_reg);
- intel_wakeref_t wakeref;
if (drm_WARN_ON(display->drm, dp_reg & DP_PORT_EN))
return;
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
if (display->platform.valleyview || display->platform.cherryview)
vlv_pps_port_enable_unlocked(encoder, pipe_config);
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index f6e2d1ed5639..8b22447e8e23 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -68,7 +68,7 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(display,
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index 51ccc6bd5f21..b1fecf178906 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -22,7 +22,6 @@
#include "intel_fb.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
-#include "intel_panic.h"
#include "intel_plane.h"
#include "intel_sprite.h"
@@ -134,7 +133,7 @@ static struct intel_fbc *i9xx_plane_fbc(struct intel_display *display,
enum i9xx_plane_id i9xx_plane)
{
if (i9xx_plane_has_fbc(display, i9xx_plane))
- return display->fbc[INTEL_FBC_A];
+ return display->fbc.instances[INTEL_FBC_A];
else
return NULL;
}
@@ -724,7 +723,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
u32 val;
@@ -819,7 +818,7 @@ unsigned int vlv_plane_min_alignment(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
- if (intel_plane_can_async_flip(plane, fb->format->format, fb->modifier))
+ if (intel_plane_can_async_flip(plane, fb->format, fb->modifier))
return 256 * 1024;
/* FIXME undocumented so not sure what's actually needed */
@@ -843,7 +842,7 @@ static unsigned int g4x_primary_min_alignment(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
- if (intel_plane_can_async_flip(plane, fb->format->format, fb->modifier))
+ if (intel_plane_can_async_flip(plane, fb->format, fb->modifier))
return 256 * 1024;
if (intel_scanout_needs_vtd_wa(display))
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c
index 01f3803fa09f..167277cd8877 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -7,8 +7,6 @@
#include <drm/drm_print.h>
-#include "soc/intel_dram.h"
-
#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_wm.h"
@@ -19,6 +17,7 @@
#include "intel_display.h"
#include "intel_display_regs.h"
#include "intel_display_trace.h"
+#include "intel_dram.h"
#include "intel_fb.h"
#include "intel_mchbar_regs.h"
#include "intel_wm.h"
@@ -91,7 +90,7 @@ static const struct cxsr_latency cxsr_latency_table[] = {
static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *display)
{
- const struct dram_info *dram_info = intel_dram_info(display->drm);
+ const struct dram_info *dram_info = intel_dram_info(display);
bool is_ddr3 = dram_info->type == INTEL_DRAM_DDR3;
int i;
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 9230792960f2..dac781f54661 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -1411,7 +1411,7 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
intel_display_power_put(display,
@@ -1722,7 +1722,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum transcoder dsi_trans;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum port port;
bool ret = false;
u32 tmp;
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index 6372f533f65b..7ce8c674bb03 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -326,11 +326,9 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
if (intel_dp->as_sdp_supported) {
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
- if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
- DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP)
+ if (crtc_state->link_off_after_as_sdp_when_pr_active)
pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU;
- if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
- DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR))
+ if (crtc_state->disable_as_sdp_when_pr_active)
pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE;
intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder),
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 5bdaef38f13d..5f3c175afdd2 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -1042,10 +1042,10 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state)
static unsigned long intel_audio_component_get_power(struct device *kdev)
{
struct intel_display *display = to_intel_display(kdev);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
/* Catch potential impedance mismatches before they occur! */
- BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long));
+ BUILD_BUG_ON(sizeof(wakeref) > sizeof(unsigned long));
wakeref = intel_display_power_get(display, POWER_DOMAIN_AUDIO_PLAYBACK);
@@ -1074,7 +1074,7 @@ static void intel_audio_component_put_power(struct device *kdev,
unsigned long cookie)
{
struct intel_display *display = to_intel_display(kdev);
- intel_wakeref_t wakeref = (intel_wakeref_t)cookie;
+ struct ref_tracker *wakeref = (struct ref_tracker *)cookie;
/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
if (--display->audio.power_refcount == 0)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 4b41068e9e35..ae0b922d5bc3 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -34,14 +34,13 @@
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
-#include "soc/intel_rom.h"
-
#include "intel_display.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_gmbus.h"
+#include "intel_rom.h"
#define _INTEL_BIOS_PRIVATE
#include "intel_vbt_defs.h"
@@ -2529,6 +2528,54 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
}
+static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
+ enum port port)
+{
+ struct intel_display *display = devdata->display;
+
+ if (!intel_bios_encoder_is_dedicated_external(devdata))
+ return;
+
+ /*
+ * Since dedicated_external is for ports connected to PHYs outside of
+ * the Type-C subsystem, clear bits that would only make sense for ports
+ * with PHYs in the Type-C subsystem.
+ */
+
+ /*
+ * Bit dp_usb_type_c is marked as "don't care" in Bspec when
+ * dedicated_external is set.
+ */
+ if (devdata->child.dp_usb_type_c) {
+ drm_dbg_kms(display->drm,
+ "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
+ port_name(port));
+ devdata->child.dp_usb_type_c = 0;
+ }
+
+ /*
+ * Bit tbt is marked as "don't care" in Bspec when dedicated_external is
+ * set.
+ */
+ if (devdata->child.tbt) {
+ drm_dbg_kms(display->drm,
+ "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
+ port_name(port));
+ devdata->child.tbt = 0;
+ }
+
+ /*
+ * DDI allocation for TC capable ports only make sense for PHYs in the
+ * Type-C subsystem.
+ */
+ if (devdata->child.dyn_port_over_tc) {
+ drm_dbg_kms(display->drm,
+ "VBT claims Port %c supports dynamic DDI allocation in TCSS, but the port is dedicated external, ignoring\n",
+ port_name(port));
+ devdata->child.dyn_port_over_tc = 0;
+ }
+}
+
static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
enum port port)
{
@@ -2693,6 +2740,16 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
supports_typec_usb, supports_tbt,
devdata->dsc != NULL);
+ if (intel_bios_encoder_is_dedicated_external(devdata))
+ drm_dbg_kms(display->drm,
+ "Port %c is dedicated external\n",
+ port_name(port));
+
+ if (intel_bios_encoder_supports_dyn_port_over_tc(devdata))
+ drm_dbg_kms(display->drm,
+ "Port %c supports dynamic DDI allocation in TCSS\n",
+ port_name(port));
+
hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
if (hdmi_level_shift >= 0) {
drm_dbg_kms(display->drm,
@@ -2750,6 +2807,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
return;
}
+ sanitize_dedicated_external(devdata, port);
sanitize_device_type(devdata, port);
sanitize_hdmi_level_shift(devdata, port);
}
@@ -2777,7 +2835,7 @@ static int child_device_expected_size(u16 version)
{
BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
- if (version > 263)
+ if (version > 264)
return -ENOENT;
else if (version >= 263)
return 44;
@@ -3721,6 +3779,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
return devdata->display->vbt.version >= 209 && devdata->child.tbt;
}
+bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
+{
+ return devdata->display->vbt.version >= 264 &&
+ devdata->child.dedicated_external;
+}
+
+bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
+{
+ return devdata->display->vbt.version >= 264 &&
+ devdata->child.dyn_port_over_tc;
+}
+
bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
{
return devdata && devdata->child.lane_reversal;
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index f9e438b2787b..75dff27b4228 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
diff --git a/drivers/gpu/drm/i915/display/intel_bo.c b/drivers/gpu/drm/i915/display/intel_bo.c
index f3687eb63467..8f372b33d48b 100644
--- a/drivers/gpu/drm/i915/display/intel_bo.c
+++ b/drivers/gpu/drm/i915/display/intel_bo.c
@@ -6,6 +6,7 @@
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "gem/i915_gem_object_frontbuffer.h"
+#include "pxp/intel_pxp.h"
#include "i915_debugfs.h"
#include "intel_bo.h"
@@ -29,6 +30,11 @@ bool intel_bo_is_protected(struct drm_gem_object *obj)
return i915_gem_object_is_protected(to_intel_bo(obj));
}
+int intel_bo_key_check(struct drm_gem_object *obj)
+{
+ return intel_pxp_key_check(obj, false);
+}
+
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
return i915_gem_fb_mmap(to_intel_bo(obj), vma);
diff --git a/drivers/gpu/drm/i915/display/intel_bo.h b/drivers/gpu/drm/i915/display/intel_bo.h
index fc05f680dc76..516a3836a6bc 100644
--- a/drivers/gpu/drm/i915/display/intel_bo.h
+++ b/drivers/gpu/drm/i915/display/intel_bo.h
@@ -16,6 +16,7 @@ bool intel_bo_is_tiled(struct drm_gem_object *obj);
bool intel_bo_is_userptr(struct drm_gem_object *obj);
bool intel_bo_is_shmem(struct drm_gem_object *obj);
bool intel_bo_is_protected(struct drm_gem_object *obj);
+int intel_bo_key_check(struct drm_gem_object *obj);
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
int intel_bo_read_from_page(struct drm_gem_object *obj, u64 offset, void *dst, int size);
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index 1f6461be50ef..d27835ed49c2 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -6,8 +6,6 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_print.h>
-#include "soc/intel_dram.h"
-
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_bw.h"
@@ -16,6 +14,7 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
+#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_uncore.h"
@@ -800,7 +799,7 @@ static unsigned int icl_qgv_bw(struct intel_display *display,
void intel_bw_init_hw(struct intel_display *display)
{
- const struct dram_info *dram_info = intel_dram_info(display->drm);
+ const struct dram_info *dram_info = intel_dram_info(display);
if (!HAS_DISPLAY(display))
return;
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 37801c744b05..0aa59d624095 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -28,10 +28,7 @@
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
-#include "soc/intel_dram.h"
-
#include "hsw_ips.h"
-#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
@@ -42,11 +39,13 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
+#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
#include "intel_pcode.h"
#include "intel_plane.h"
#include "intel_psr.h"
+#include "intel_step.h"
#include "intel_vdsc.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
@@ -668,7 +667,7 @@ static void vlv_set_cdclk(struct intel_display *display,
{
int cdclk = cdclk_config->cdclk;
u32 val, cmd = cdclk_config->voltage_level;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int ret;
switch (cdclk) {
@@ -758,7 +757,7 @@ static void chv_set_cdclk(struct intel_display *display,
{
int cdclk = cdclk_config->cdclk;
u32 val, cmd = cdclk_config->voltage_level;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int ret;
switch (cdclk) {
@@ -3738,10 +3737,8 @@ static int pch_rawclk(struct intel_display *display)
static int i9xx_hrawclk(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
/* hrawclock is 1/4 the FSB frequency */
- return DIV_ROUND_CLOSEST(intel_fsb_freq(i915), 4);
+ return DIV_ROUND_CLOSEST(intel_fsb_freq(display), 4);
}
/**
diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c b/drivers/gpu/drm/i915/display/intel_cmtg.c
index 165138b95cb2..e1fdc6fe9762 100644
--- a/drivers/gpu/drm/i915/display/intel_cmtg.c
+++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
@@ -85,7 +85,6 @@ static bool intel_cmtg_transcoder_is_secondary(struct intel_display *display,
enum transcoder trans)
{
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
u32 val = 0;
if (!HAS_TRANSCODER(display, trans))
@@ -93,7 +92,7 @@ static bool intel_cmtg_transcoder_is_secondary(struct intel_display *display,
power_domain = POWER_DOMAIN_TRANSCODER(trans);
- with_intel_display_power_if_enabled(display, power_domain, wakeref)
+ with_intel_display_power_if_enabled(display, power_domain)
val = intel_de_read(display, TRANS_DDI_FUNC_CTL2(display, trans));
return val & CMTG_SECONDARY_MODE;
diff --git a/drivers/gpu/drm/i915/display/intel_colorop.c b/drivers/gpu/drm/i915/display/intel_colorop.c
index f2fc0d8780ce..1d84933f05aa 100644
--- a/drivers/gpu/drm/i915/display/intel_colorop.c
+++ b/drivers/gpu/drm/i915/display/intel_colorop.c
@@ -2,7 +2,9 @@
/*
* Copyright © 2025 Intel Corporation
*/
+
#include "intel_colorop.h"
+#include "intel_display_types.h"
struct intel_colorop *to_intel_colorop(struct drm_colorop *colorop)
{
diff --git a/drivers/gpu/drm/i915/display/intel_colorop.h b/drivers/gpu/drm/i915/display/intel_colorop.h
index 21d58eb9f3d0..9276eee6e75a 100644
--- a/drivers/gpu/drm/i915/display/intel_colorop.h
+++ b/drivers/gpu/drm/i915/display/intel_colorop.h
@@ -6,7 +6,9 @@
#ifndef __INTEL_COLOROP_H__
#define __INTEL_COLOROP_H__
-#include "intel_display_types.h"
+enum intel_color_block;
+struct drm_colorop;
+struct intel_colorop;
struct intel_colorop *to_intel_colorop(struct drm_colorop *colorop);
struct intel_colorop *intel_colorop_alloc(void);
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 913d90a7a508..c128bc4215c4 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -156,27 +156,17 @@ void intel_connector_destroy(struct drm_connector *connector)
int intel_connector_register(struct drm_connector *_connector)
{
struct intel_connector *connector = to_intel_connector(_connector);
- struct drm_i915_private *i915 = to_i915(_connector->dev);
int ret;
ret = intel_panel_register(connector);
if (ret)
- goto err;
-
- if (i915_inject_probe_failure(i915)) {
- ret = -EFAULT;
- goto err_panel;
- }
+ return ret;
intel_connector_debugfs_add(connector);
return 0;
-
-err_panel:
- intel_panel_unregister(connector);
-err:
- return ret;
}
+ALLOW_ERROR_INJECTION(intel_connector_register, ERRNO);
void intel_connector_unregister(struct drm_connector *_connector)
{
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 82e89cdbe5a5..5f9a03877ea9 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -109,7 +109,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(display,
@@ -847,7 +847,7 @@ intel_crt_detect(struct drm_connector *connector,
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *encoder = &crt->base;
struct drm_atomic_state *state;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int status;
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] force=%d\n",
@@ -936,7 +936,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
struct intel_display *display = to_intel_display(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *encoder = &crt->base;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
struct i2c_adapter *ddc;
int ret;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 9d2a23c96c61..778ebc5095c3 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -13,8 +13,6 @@
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_work.h>
-#include "i915_drv.h"
-#include "i915_vgpu.h"
#include "i9xx_plane.h"
#include "icl_dsi.h"
#include "intel_atomic.h"
@@ -28,6 +26,7 @@
#include "intel_drrs.h"
#include "intel_dsi.h"
#include "intel_fifo_underrun.h"
+#include "intel_parent.h"
#include "intel_pipe_crc.h"
#include "intel_plane.h"
#include "intel_psr.h"
@@ -309,7 +308,7 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
};
-int intel_crtc_init(struct intel_display *display, enum pipe pipe)
+static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
{
struct intel_plane *primary, *cursor;
const struct drm_crtc_funcs *funcs;
@@ -396,7 +395,7 @@ int intel_crtc_init(struct intel_display *display, enum pipe pipe)
drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
- if (HAS_CASF(display))
+ if (HAS_CASF(display) && crtc->num_scalers >= 2)
drm_crtc_create_sharpness_strength_property(&crtc->base);
return 0;
@@ -407,6 +406,23 @@ fail:
return ret;
}
+int intel_crtc_init(struct intel_display *display)
+{
+ enum pipe pipe;
+ int ret;
+
+ drm_dbg_kms(display->drm, "%d display pipe%s available.\n",
+ INTEL_NUM_PIPES(display), str_plural(INTEL_NUM_PIPES(display)));
+
+ for_each_pipe(display, pipe) {
+ ret = __intel_crtc_init(display, pipe);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
@@ -553,7 +569,7 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
- if (old_plane_state->uapi.crtc == &crtc->base)
+ if (old_plane_state->hw.crtc == &crtc->base)
intel_plane_init_cursor_vblank_work(old_plane_state,
new_plane_state);
}
@@ -671,7 +687,6 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
int scanline_end = intel_get_crtc_scanline(crtc);
u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
ktime_t end_vbl_time = ktime_get();
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
@@ -706,7 +721,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
int i;
for_each_old_intel_plane_in_state(state, plane, old_plane_state, i) {
- if (old_plane_state->uapi.crtc == &crtc->base &&
+ if (old_plane_state->hw.crtc == &crtc->base &&
old_plane_state->unpin_work.vblank) {
drm_vblank_work_schedule(&old_plane_state->unpin_work,
drm_crtc_accurate_vblank_count(&crtc->base) + 1,
@@ -737,7 +752,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
local_irq_enable();
- if (intel_vgpu_active(dev_priv))
+ if (intel_parent_vgpu_active(display))
goto out;
if (crtc->debug.start_vbl_count &&
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h
index 07917e8a9ae3..12507b51ee77 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -37,7 +37,7 @@ void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state);
void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
struct drm_pending_vblank_event **event);
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
-int intel_crtc_init(struct intel_display *display, enum pipe pipe);
+int intel_crtc_init(struct intel_display *display);
int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index a10b2425b94d..2c5d917fbd7e 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -324,7 +324,7 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(PIPE_A);
@@ -727,7 +727,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
u32 val;
@@ -974,6 +974,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = intel_cursor_format_mod_supported,
+ .format_mod_supported_async = intel_plane_format_mod_supported_async,
};
static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index d98b4cf6b60e..2c87c58812da 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -11,6 +11,7 @@
#include "intel_alpm.h"
#include "intel_cx0_phy.h"
#include "intel_cx0_phy_regs.h"
+#include "intel_display_regs.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
@@ -104,11 +105,11 @@ static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
* We also do the msgbus timer programming here to ensure that the timer
* is already programmed before any access to the msgbus.
*/
-static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
+static struct ref_tracker *intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
intel_psr_pause(intel_dp);
wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF);
@@ -117,7 +118,7 @@ static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *enc
return wakeref;
}
-static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
+static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, struct ref_tracker *wakeref)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -444,13 +445,38 @@ static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state)
}
}
+static void intel_c10_msgbus_access_begin(struct intel_encoder *encoder,
+ u8 lane_mask)
+{
+ if (!intel_encoder_is_c10phy(encoder))
+ return;
+
+ intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
+}
+
+static void intel_c10_msgbus_access_commit(struct intel_encoder *encoder,
+ u8 lane_mask, bool master_lane)
+{
+ u8 val = C10_VDR_CTRL_UPDATE_CFG;
+
+ if (!intel_encoder_is_c10phy(encoder))
+ return;
+
+ if (master_lane)
+ val |= C10_VDR_CTRL_MASTER_LANE;
+
+ intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1),
+ 0, val, MB_WRITE_COMMITTED);
+}
+
void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_ddi_buf_trans *trans;
u8 owned_lane_mask;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int n_entries, ln;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
@@ -467,9 +493,9 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
return;
}
+ intel_c10_msgbus_access_begin(encoder, owned_lane_mask);
+
if (intel_encoder_is_c10phy(encoder)) {
- intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CMN(3),
C10_CMN3_TXVBOOST_MASK,
C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)),
@@ -508,9 +534,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
MB_WRITE_COMMITTED);
- if (intel_encoder_is_c10phy(encoder))
- intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false);
intel_cx0_phy_transaction_end(encoder, wakeref);
}
@@ -2005,7 +2029,7 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = {
};
static const struct intel_c10pll_state * const *
-intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
+intel_c10pll_tables_get(const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
if (intel_crtc_has_dp_encoder(crtc_state)) {
@@ -2035,6 +2059,15 @@ static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
}
}
+#define C10_PLL_SSC_REG_START_IDX 4
+#define C10_PLL_SSC_REG_COUNT 5
+
+static bool intel_c10pll_ssc_enabled(const struct intel_c10pll_state *pll_state)
+{
+ return memchr_inv(&pll_state->pll[C10_PLL_SSC_REG_START_IDX],
+ 0, sizeof(pll_state->pll[0]) * C10_PLL_SSC_REG_COUNT);
+}
+
static void intel_c10pll_update_pll(struct intel_encoder *encoder,
struct intel_cx0pll_state *pll_state)
{
@@ -2044,16 +2077,42 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder,
if (pll_state->ssc_enabled)
return;
- drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < 9);
- for (i = 4; i < 9; i++)
+ drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) <
+ C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT);
+ for (i = C10_PLL_SSC_REG_START_IDX;
+ i < C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT;
+ i++)
pll_state->c10.pll[i] = 0;
}
+static bool c10pll_state_is_dp(const struct intel_c10pll_state *pll_state)
+{
+ return !REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
+}
+
+static bool c20pll_state_is_dp(const struct intel_c20pll_state *pll_state)
+{
+ return pll_state->vdr.serdes_rate & PHY_C20_IS_DP;
+}
+
+static bool cx0pll_state_is_dp(const struct intel_cx0pll_state *pll_state)
+{
+ if (pll_state->use_c10)
+ return c10pll_state_is_dp(&pll_state->c10);
+
+ return c20pll_state_is_dp(&pll_state->c20);
+}
+
+/*
+ * TODO: Convert the following to align with intel_c20pll_find_table() and
+ * intel_c20pll_calc_state_from_table().
+ */
static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
const struct intel_c10pll_state * const *tables,
- bool is_dp, int port_clock,
+ bool is_dp, int port_clock, int lane_count,
struct intel_cx0pll_state *pll_state)
{
+ struct intel_display *display = to_intel_display(encoder);
int i;
for (i = 0; tables[i]; i++) {
@@ -2061,7 +2120,11 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
pll_state->c10 = *tables[i];
intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
intel_c10pll_update_pll(encoder, pll_state);
+
pll_state->use_c10 = true;
+ pll_state->lane_count = lane_count;
+
+ drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&pll_state->c10));
return 0;
}
@@ -2070,9 +2133,12 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
return -EINVAL;
}
-static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+static int intel_c10pll_calc_state(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state)
{
+ struct intel_display *display = to_intel_display(encoder);
+ bool is_dp = intel_crtc_has_dp_encoder(crtc_state);
const struct intel_c10pll_state * const *tables;
int err;
@@ -2080,43 +2146,126 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
if (!tables)
return -EINVAL;
- err = intel_c10pll_calc_state_from_table(encoder, tables,
- intel_crtc_has_dp_encoder(crtc_state),
- crtc_state->port_clock,
- &crtc_state->dpll_hw_state.cx0pll);
+ err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp,
+ crtc_state->port_clock, crtc_state->lane_count,
+ &hw_state->cx0pll);
if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
return err;
/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
- intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
+ intel_snps_hdmi_pll_compute_c10pll(&hw_state->cx0pll.c10,
crtc_state->port_clock);
- intel_c10pll_update_pll(encoder,
- &crtc_state->dpll_hw_state.cx0pll);
- crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
+ intel_c10pll_update_pll(encoder, &hw_state->cx0pll);
+
+ hw_state->cx0pll.use_c10 = true;
+ hw_state->cx0pll.lane_count = crtc_state->lane_count;
+
+ drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&hw_state->cx0pll.c10));
return 0;
}
static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
- const struct intel_c10pll_state *pll_state);
+ const struct intel_c10pll_state *pll_state)
+{
+ unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+ unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400;
+ int tmpclk = 0;
+
+ if (pll_state->pll[0] & C10_PLL0_FRACEN) {
+ frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11];
+ frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13];
+ frac_den = pll_state->pll[10] << 8 | pll_state->pll[9];
+ }
+
+ multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 |
+ pll_state->pll[2]) / 2 + 16;
+
+ tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]);
+ hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
+
+ tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
+ DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
+ 10 << (tx_clk_div + 16));
+ tmpclk *= (hdmi_div ? 2 : 1);
+
+ return tmpclk;
+}
+
+static int readout_enabled_lane_count(struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ u8 enabled_tx_lane_count = 0;
+ int max_tx_lane_count = 4;
+ bool lane_reversal;
+ int tx_lane;
+
+ lane_reversal = intel_de_read(display, XELPDP_PORT_BUF_CTL1(display, encoder->port)) &
+ XELPDP_PORT_REVERSAL;
+
+ /*
+ * TODO: also check inactive TX lanes in all PHY lanes owned by the
+ * display. For now checking only those PHY lane(s) which are owned
+ * based on the active TX lane count (i.e.
+ * 1,2 active TX lanes -> PHY lane#0
+ * 3,4 active TX lanes -> PHY lane#0 and PHY lane#1).
+ *
+ * In case of lane reversal for 1, 2 active TX lanes, only PHY
+ * lane#1 is used. This is only possible in TypeC legacy mode or if
+ * the port is connected to a non-TC PHY. In both of these cases both
+ * PHY lane#0 and #1 are owned by display, so check all 4 TX lanes in
+ * both PHY lanes in those cases.
+ */
+ if (!lane_reversal)
+ max_tx_lane_count = DDI_PORT_WIDTH_GET(intel_de_read(display,
+ DDI_BUF_CTL(encoder->port)));
+
+ if (!drm_WARN_ON(display->drm, max_tx_lane_count == 0))
+ max_tx_lane_count = round_up(max_tx_lane_count, 2);
+
+ for (tx_lane = 0; tx_lane < max_tx_lane_count; tx_lane++) {
+ u8 phy_lane_mask = tx_lane < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
+ int tx = tx_lane % 2 + 1;
+ u8 val;
+
+ val = intel_cx0_read(encoder, phy_lane_mask, PHY_CX0_TX_CONTROL(tx, 2));
+ if (!(val & CONTROL2_DISABLE_SINGLE_TX))
+ enabled_tx_lane_count++;
+ }
+
+ return enabled_tx_lane_count;
+}
+
+static bool readout_ssc_state(struct intel_encoder *encoder, bool is_mpll_b)
+{
+ struct intel_display *display = to_intel_display(encoder);
+
+ return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) &
+ (is_mpll_b ? XELPDP_SSC_ENABLE_PLLB : XELPDP_SSC_ENABLE_PLLA);
+}
static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
- struct intel_c10pll_state *pll_state)
+ struct intel_cx0pll_state *cx0pll_state)
{
+ struct intel_c10pll_state *pll_state = &cx0pll_state->c10;
+ struct intel_display *display = to_intel_display(encoder);
+ enum phy phy = intel_encoder_to_phy(encoder);
u8 lane = INTEL_CX0_LANE0;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int i;
+ cx0pll_state->use_c10 = true;
+
wakeref = intel_cx0_phy_transaction_begin(encoder);
/*
* According to C10 VDR Register programming Sequence we need
* to do this to read PHY internal registers from MsgBus.
*/
- intel_cx0_rmw(encoder, lane, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_MSGBUS_ACCESS,
- MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_begin(encoder, lane);
+
+ cx0pll_state->lane_count = readout_enabled_lane_count(encoder);
for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i));
@@ -2127,6 +2276,15 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
pll_state->clock = intel_c10pll_calc_port_clock(encoder, pll_state);
+
+ cx0pll_state->ssc_enabled = readout_ssc_state(encoder, true);
+
+ if (cx0pll_state->ssc_enabled != intel_c10pll_ssc_enabled(pll_state))
+ drm_dbg_kms(display->drm,
+ "PHY %c: SSC state mismatch: port SSC is %s, PLL SSC is %s\n",
+ phy_name(phy),
+ str_enabled_disabled(cx0pll_state->ssc_enabled),
+ str_enabled_disabled(intel_c10pll_ssc_enabled(pll_state)));
}
static void intel_c10_pll_program(struct intel_display *display,
@@ -2135,9 +2293,7 @@ static void intel_c10_pll_program(struct intel_display *display,
{
int i;
- intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_MSGBUS_ACCESS,
- MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_begin(encoder, INTEL_CX0_BOTH_LANES);
/* Program the pll values only for the master lane */
for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
@@ -2152,12 +2308,11 @@ static void intel_c10_pll_program(struct intel_display *display,
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
MB_WRITE_COMMITTED);
- intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG,
- MB_WRITE_COMMITTED);
+
+ intel_c10_msgbus_access_commit(encoder, INTEL_CX0_LANE0, true);
}
-static void intel_c10pll_dump_hw_state(struct intel_display *display,
+static void intel_c10pll_dump_hw_state(struct drm_printer *p,
const struct intel_c10pll_state *hw_state)
{
bool fracen;
@@ -2166,33 +2321,32 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display,
unsigned int multiplier, tx_clk_div;
fracen = hw_state->pll[0] & C10_PLL0_FRACEN;
- drm_dbg_kms(display->drm, "c10pll_hw_state: fracen: %s, ",
- str_yes_no(fracen));
+ drm_printf(p, "c10pll_hw_state: clock: %d, fracen: %s, ",
+ hw_state->clock, str_yes_no(fracen));
if (fracen) {
frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11];
frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13];
frac_den = hw_state->pll[10] << 8 | hw_state->pll[9];
- drm_dbg_kms(display->drm, "quot: %u, rem: %u, den: %u,\n",
- frac_quot, frac_rem, frac_den);
+ drm_printf(p, "quot: %u, rem: %u, den: %u,\n",
+ frac_quot, frac_rem, frac_den);
}
multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 |
hw_state->pll[2]) / 2 + 16;
tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]);
- drm_dbg_kms(display->drm,
- "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div);
+ drm_printf(p,
+ "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div);
- drm_dbg_kms(display->drm, "c10pll_rawhw_state:");
- drm_dbg_kms(display->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx,
- hw_state->cmn);
+ drm_printf(p, "c10pll_rawhw_state:");
+ drm_printf(p, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn);
BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4);
for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4)
- drm_dbg_kms(display->drm,
- "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
- i, hw_state->pll[i], i + 1, hw_state->pll[i + 1],
- i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
+ drm_printf(p,
+ "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
+ i, hw_state->pll[i], i + 1, hw_state->pll[i + 1],
+ i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
}
/*
@@ -2210,7 +2364,7 @@ static bool is_arrowlake_s_by_host_bridge(void)
return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id);
}
-static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state)
+static u16 intel_c20_hdmi_tmds_tx_cgf_1(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
u16 tx_misc;
@@ -2234,9 +2388,9 @@ static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state)
C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl));
}
-static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
+static int intel_c20_compute_hdmi_tmds_pll(const struct intel_crtc_state *crtc_state,
+ struct intel_c20pll_state *pll_state)
{
- struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
u64 datarate;
u64 mpll_tx_clk_div;
u64 vco_freq_shift;
@@ -2304,7 +2458,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
}
static const struct intel_c20pll_state * const *
-intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
+intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(crtc_state);
@@ -2332,42 +2486,220 @@ intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
return NULL;
}
-static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+static u8 intel_c20_get_dp_rate(u32 clock)
{
- const struct intel_c20pll_state * const *tables;
- int i;
+ switch (clock) {
+ case 162000: /* 1.62 Gbps DP1.4 */
+ return 0;
+ case 270000: /* 2.7 Gbps DP1.4 */
+ return 1;
+ case 540000: /* 5.4 Gbps DP 1.4 */
+ return 2;
+ case 810000: /* 8.1 Gbps DP1.4 */
+ return 3;
+ case 216000: /* 2.16 Gbps eDP */
+ return 4;
+ case 243000: /* 2.43 Gbps eDP */
+ return 5;
+ case 324000: /* 3.24 Gbps eDP */
+ return 6;
+ case 432000: /* 4.32 Gbps eDP */
+ return 7;
+ case 1000000: /* 10 Gbps DP2.0 */
+ return 8;
+ case 1350000: /* 13.5 Gbps DP2.0 */
+ return 9;
+ case 2000000: /* 20 Gbps DP2.0 */
+ return 10;
+ case 648000: /* 6.48 Gbps eDP*/
+ return 11;
+ case 675000: /* 6.75 Gbps eDP*/
+ return 12;
+ default:
+ MISSING_CASE(clock);
+ return 0;
+ }
+}
- /* try computed C20 HDMI tables before using consolidated tables */
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
- if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0)
- return 0;
+static u8 intel_c20_get_hdmi_rate(u32 clock)
+{
+ if (clock >= 25175 && clock <= 600000)
+ return 0;
+
+ switch (clock) {
+ case 300000: /* 3 Gbps */
+ case 600000: /* 6 Gbps */
+ case 1200000: /* 12 Gbps */
+ return 1;
+ case 800000: /* 8 Gbps */
+ return 2;
+ case 1000000: /* 10 Gbps */
+ return 3;
+ default:
+ MISSING_CASE(clock);
+ return 0;
}
+}
+
+static bool is_dp2(u32 clock)
+{
+ /* DP2.0 clock rates */
+ if (clock == 1000000 || clock == 1350000 || clock == 2000000)
+ return true;
+
+ return false;
+}
+
+static int intel_get_c20_custom_width(u32 clock, bool dp)
+{
+ if (dp && is_dp2(clock))
+ return 2;
+ else if (intel_hdmi_is_frl(clock))
+ return 1;
+ else
+ return 0;
+}
+
+static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, bool is_dp,
+ int port_clock)
+{
+ vdr->custom_width = intel_get_c20_custom_width(port_clock, is_dp);
+
+ vdr->serdes_rate = 0;
+ vdr->hdmi_rate = 0;
+
+ if (is_dp) {
+ vdr->serdes_rate = PHY_C20_IS_DP |
+ PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock));
+ } else {
+ if (intel_hdmi_is_frl(port_clock))
+ vdr->serdes_rate = PHY_C20_IS_HDMI_FRL;
+
+ vdr->hdmi_rate = intel_c20_get_hdmi_rate(port_clock);
+ }
+}
+
+#define PHY_C20_SERDES_RATE_MASK (PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL)
+
+static void intel_c20_readout_vdr_params(struct intel_encoder *encoder,
+ struct intel_c20pll_vdr_state *vdr, bool *cntx)
+{
+ u8 serdes;
+
+ serdes = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE);
+ *cntx = serdes & PHY_C20_CONTEXT_TOGGLE;
+
+ vdr->custom_width = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_WIDTH) &
+ PHY_C20_CUSTOM_WIDTH_MASK;
+
+ vdr->serdes_rate = serdes & PHY_C20_SERDES_RATE_MASK;
+ if (!(vdr->serdes_rate & PHY_C20_IS_DP))
+ vdr->hdmi_rate = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_HDMI_RATE) &
+ PHY_C20_HDMI_RATE_MASK;
+ else
+ vdr->hdmi_rate = 0;
+}
+
+static void intel_c20_program_vdr_params(struct intel_encoder *encoder,
+ const struct intel_c20pll_vdr_state *vdr,
+ u8 owned_lane_mask)
+{
+ struct intel_display *display = to_intel_display(encoder);
+
+ drm_WARN_ON(display->drm, vdr->custom_width & ~PHY_C20_CUSTOM_WIDTH_MASK);
+ intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH,
+ PHY_C20_CUSTOM_WIDTH_MASK, vdr->custom_width,
+ MB_WRITE_COMMITTED);
+
+ drm_WARN_ON(display->drm, vdr->serdes_rate & ~PHY_C20_SERDES_RATE_MASK);
+ intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
+ PHY_C20_SERDES_RATE_MASK, vdr->serdes_rate,
+ MB_WRITE_COMMITTED);
+
+ if (vdr->serdes_rate & PHY_C20_IS_DP)
+ return;
+
+ drm_WARN_ON(display->drm, vdr->hdmi_rate & ~PHY_C20_HDMI_RATE_MASK);
+ intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE,
+ PHY_C20_HDMI_RATE_MASK, vdr->hdmi_rate,
+ MB_WRITE_COMMITTED);
+}
+
+static const struct intel_c20pll_state *
+intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_c20pll_state * const *tables;
+ int i;
tables = intel_c20_pll_tables_get(crtc_state, encoder);
if (!tables)
+ return NULL;
+
+ for (i = 0; tables[i]; i++)
+ if (crtc_state->port_clock == tables[i]->clock)
+ return tables[i];
+
+ return NULL;
+}
+
+static int intel_c20pll_calc_state_from_table(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder,
+ struct intel_cx0pll_state *pll_state)
+{
+ const struct intel_c20pll_state *table;
+
+ table = intel_c20_pll_find_table(crtc_state, encoder);
+ if (!table)
return -EINVAL;
- for (i = 0; tables[i]; i++) {
- if (crtc_state->port_clock == tables[i]->clock) {
- crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
- intel_cx0pll_update_ssc(encoder,
- &crtc_state->dpll_hw_state.cx0pll,
- intel_crtc_has_dp_encoder(crtc_state));
- crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
- return 0;
- }
- }
+ pll_state->c20 = *table;
- return -EINVAL;
+ intel_cx0pll_update_ssc(encoder, pll_state, intel_crtc_has_dp_encoder(crtc_state));
+
+ return 0;
+}
+
+static int intel_c20pll_calc_state(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ bool is_dp = intel_crtc_has_dp_encoder(crtc_state);
+ int err = -ENOENT;
+
+ 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);
+
+ if (err)
+ err = intel_c20pll_calc_state_from_table(crtc_state, encoder,
+ &hw_state->cx0pll);
+
+ if (err)
+ return err;
+
+ intel_c20_calc_vdr_params(&hw_state->cx0pll.c20.vdr,
+ is_dp, crtc_state->port_clock);
+
+ drm_WARN_ON(display->drm, is_dp != c20pll_state_is_dp(&hw_state->cx0pll.c20));
+
+ return 0;
}
-int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state)
{
+ memset(hw_state, 0, sizeof(*hw_state));
+
if (intel_encoder_is_c10phy(encoder))
- return intel_c10pll_calc_state(crtc_state, encoder);
- return intel_c20pll_calc_state(crtc_state, encoder);
+ return intel_c10pll_calc_state(crtc_state, encoder, hw_state);
+ return intel_c20pll_calc_state(crtc_state, encoder, hw_state);
}
static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state)
@@ -2421,17 +2753,22 @@ static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
}
static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
- struct intel_c20pll_state *pll_state)
+ struct intel_cx0pll_state *cx0pll_state)
{
+ struct intel_c20pll_state *pll_state = &cx0pll_state->c20;
struct intel_display *display = to_intel_display(encoder);
bool cntx;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int i;
+ cx0pll_state->use_c10 = false;
+
wakeref = intel_cx0_phy_transaction_begin(encoder);
- /* 1. Read current context selection */
- cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE;
+ cx0pll_state->lane_count = readout_enabled_lane_count(encoder);
+
+ /* 1. Read VDR params and current context selection */
+ intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx);
/* Read Tx configuration */
for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
@@ -2486,103 +2823,52 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state);
intel_cx0_phy_transaction_end(encoder, wakeref);
+
+ cx0pll_state->ssc_enabled = readout_ssc_state(encoder, intel_c20phy_use_mpllb(pll_state));
}
-static void intel_c20pll_dump_hw_state(struct intel_display *display,
+static void intel_c20pll_dump_hw_state(struct drm_printer *p,
const struct intel_c20pll_state *hw_state)
{
int i;
- drm_dbg_kms(display->drm, "c20pll_hw_state:\n");
- drm_dbg_kms(display->drm,
- "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n",
- hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
- drm_dbg_kms(display->drm,
- "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
- hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]);
+ drm_printf(p, "c20pll_hw_state: clock: %d\n", hw_state->clock);
+ drm_printf(p,
+ "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n",
+ hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
+ drm_printf(p,
+ "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
+ hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]);
if (intel_c20phy_use_mpllb(hw_state)) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
- drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i,
- hw_state->mpllb[i]);
+ drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]);
} else {
for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
- drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i,
- hw_state->mplla[i]);
- }
-}
+ drm_printf(p, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]);
-void intel_cx0pll_dump_hw_state(struct intel_display *display,
- const struct intel_cx0pll_state *hw_state)
-{
- if (hw_state->use_c10)
- intel_c10pll_dump_hw_state(display, &hw_state->c10);
- else
- intel_c20pll_dump_hw_state(display, &hw_state->c20);
-}
-
-static u8 intel_c20_get_dp_rate(u32 clock)
-{
- switch (clock) {
- case 162000: /* 1.62 Gbps DP1.4 */
- return 0;
- case 270000: /* 2.7 Gbps DP1.4 */
- return 1;
- case 540000: /* 5.4 Gbps DP 1.4 */
- return 2;
- case 810000: /* 8.1 Gbps DP1.4 */
- return 3;
- case 216000: /* 2.16 Gbps eDP */
- return 4;
- case 243000: /* 2.43 Gbps eDP */
- return 5;
- case 324000: /* 3.24 Gbps eDP */
- return 6;
- case 432000: /* 4.32 Gbps eDP */
- return 7;
- case 1000000: /* 10 Gbps DP2.0 */
- return 8;
- case 1350000: /* 13.5 Gbps DP2.0 */
- return 9;
- case 2000000: /* 20 Gbps DP2.0 */
- return 10;
- case 648000: /* 6.48 Gbps eDP*/
- return 11;
- case 675000: /* 6.75 Gbps eDP*/
- return 12;
- default:
- MISSING_CASE(clock);
- return 0;
+ /* For full coverage, also print the additional PLL B entry. */
+ BUILD_BUG_ON(ARRAY_SIZE(hw_state->mplla) + 1 != ARRAY_SIZE(hw_state->mpllb));
+ drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]);
}
-}
-static u8 intel_c20_get_hdmi_rate(u32 clock)
-{
- if (clock >= 25175 && clock <= 600000)
- return 0;
-
- switch (clock) {
- case 300000: /* 3 Gbps */
- case 600000: /* 6 Gbps */
- case 1200000: /* 12 Gbps */
- return 1;
- case 800000: /* 8 Gbps */
- return 2;
- case 1000000: /* 10 Gbps */
- return 3;
- default:
- MISSING_CASE(clock);
- return 0;
- }
+ drm_printf(p,
+ "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n",
+ hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate);
}
-static bool is_dp2(u32 clock)
+void intel_cx0pll_dump_hw_state(struct drm_printer *p,
+ const struct intel_cx0pll_state *hw_state)
{
- /* DP2.0 clock rates */
- if (clock == 1000000 || clock == 1350000 || clock == 2000000)
- return true;
+ drm_printf(p,
+ "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n",
+ hw_state->lane_count, str_yes_no(hw_state->ssc_enabled),
+ str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode));
- return false;
+ if (hw_state->use_c10)
+ intel_c10pll_dump_hw_state(p, &hw_state->c10);
+ else
+ intel_c20pll_dump_hw_state(p, &hw_state->c20);
}
static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder)
@@ -2594,23 +2880,11 @@ static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder)
return intel_tc_port_in_legacy_mode(intel_dig_port);
}
-static int intel_get_c20_custom_width(u32 clock, bool dp)
-{
- if (dp && is_dp2(clock))
- return 2;
- else if (intel_hdmi_is_frl(clock))
- return 1;
- else
- return 0;
-}
-
static void intel_c20_pll_program(struct intel_display *display,
struct intel_encoder *encoder,
- const struct intel_c20pll_state *pll_state,
- bool is_dp, int port_clock)
+ const struct intel_c20pll_state *pll_state)
{
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
- u8 serdes;
bool cntx;
int i;
@@ -2679,30 +2953,11 @@ static void intel_c20_pll_program(struct intel_display *display,
}
}
- /* 4. Program custom width to match the link protocol */
- intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH,
- PHY_C20_CUSTOM_WIDTH_MASK,
- PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)),
- MB_WRITE_COMMITTED);
-
- /* 5. For DP or 6. For HDMI */
- serdes = 0;
- if (is_dp)
- serdes = PHY_C20_IS_DP |
- PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock));
- else if (intel_hdmi_is_frl(port_clock))
- serdes = PHY_C20_IS_HDMI_FRL;
-
- intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
- PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL,
- serdes,
- MB_WRITE_COMMITTED);
-
- if (!is_dp)
- intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE,
- PHY_C20_HDMI_RATE_MASK,
- intel_c20_get_hdmi_rate(port_clock),
- MB_WRITE_COMMITTED);
+ /*
+ * 4. Program custom width to match the link protocol.
+ * 5. For DP or 6. For HDMI
+ */
+ intel_c20_program_vdr_params(encoder, &pll_state->vdr, owned_lane_mask);
/*
* 7. Write Vendor specific registers to toggle context setting to load
@@ -2713,39 +2968,13 @@ static void intel_c20_pll_program(struct intel_display *display,
MB_WRITE_COMMITTED);
}
-static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
- const struct intel_c10pll_state *pll_state)
-{
- unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
- unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400;
- int tmpclk = 0;
-
- if (pll_state->pll[0] & C10_PLL0_FRACEN) {
- frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11];
- frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13];
- frac_den = pll_state->pll[10] << 8 | pll_state->pll[9];
- }
-
- multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 |
- pll_state->pll[2]) / 2 + 16;
-
- tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]);
- hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
-
- tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
- DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
- 10 << (tx_clk_div + 16));
- tmpclk *= (hdmi_div ? 2 : 1);
-
- return tmpclk;
-}
-
static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
const struct intel_cx0pll_state *pll_state,
- bool is_dp, int port_clock,
+ int port_clock,
bool lane_reversal)
{
struct intel_display *display = to_intel_display(encoder);
+ bool is_dp = cx0pll_state_is_dp(pll_state);
u32 val = 0;
intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port),
@@ -2830,7 +3059,7 @@ void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder,
intel_cx0_get_powerdown_update(lane_mask),
XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_MS))
drm_warn(display->drm,
- "PHY %c failed to bring out of lane reset\n",
+ "PHY %c failed to change powerdown state\n",
phy_name(phy));
}
@@ -2938,11 +3167,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c
bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder));
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
- if (intel_encoder_is_c10phy(encoder))
- intel_cx0_rmw(encoder, owned_lane_mask,
- PHY_C10_VDR_CONTROL(1), 0,
- C10_VDR_CTRL_MSGBUS_ACCESS,
- MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_begin(encoder, owned_lane_mask);
if (lane_reversal)
disables = REG_GENMASK8(3, 0) >> lane_count;
@@ -2967,11 +3192,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c
MB_WRITE_COMMITTED);
}
- if (intel_encoder_is_c10phy(encoder))
- intel_cx0_rmw(encoder, owned_lane_mask,
- PHY_C10_VDR_CONTROL(1), 0,
- C10_VDR_CTRL_UPDATE_CFG,
- MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false);
}
static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask)
@@ -2996,23 +3217,30 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
return val;
}
-static void __intel_cx0pll_enable(struct intel_encoder *encoder,
- const struct intel_cx0pll_state *pll_state,
- bool is_dp, int port_clock, int lane_count)
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+ const struct intel_cx0pll_state *pll_state)
{
+ int port_clock = pll_state->use_c10 ? pll_state->c10.clock : pll_state->c20.clock;
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->lane_reversal;
u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 :
INTEL_CX0_LANE0;
- intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);
+ struct ref_tracker *wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ /*
+ * Lane reversal is never used in DP-alt mode, in that case the
+ * corresponding lane swapping (based on the TypeC cable flip state
+ * for instance) is handled automatically by the HW via a TCSS mux.
+ */
+ drm_WARN_ON(display->drm, lane_reversal && intel_tc_port_in_dp_alt_mode(dig_port));
/*
* 1. Program PORT_CLOCK_CTL REGISTER to configure
* clock muxes, gating and SSC
*/
- intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
+ intel_program_port_clock_ctl(encoder, pll_state, port_clock, lane_reversal);
/* 2. Bring PHY out of reset. */
intel_cx0_phy_lane_reset(encoder, lane_reversal);
@@ -3034,13 +3262,13 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder,
if (intel_encoder_is_c10phy(encoder))
intel_c10_pll_program(display, encoder, &pll_state->c10);
else
- intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock);
+ intel_c20_pll_program(display, encoder, &pll_state->c20);
/*
* 6. Program the enabled and disabled owned PHY lane
* transmitters over message bus
*/
- intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
+ intel_cx0_program_phy_lane(encoder, pll_state->lane_count, lane_reversal);
/*
* 7. Follow the Display Voltage Frequency Switching - Sequence
@@ -3074,16 +3302,40 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder,
* Frequency Change. We handle this step in bxt_set_cdclk().
*/
- /* TODO: enable TBT-ALT mode */
+ /*
+ * 12. Toggle powerdown if HDMI is enabled on C10 PHY.
+ *
+ * Wa_13013502646:
+ * Fixes: HDMI lane to lane skew violations on C10 display PHYs.
+ * Workaround: Toggle powerdown value by setting first to P0 and then to P2, for both
+ * PHY lanes.
+ */
+ if (!cx0pll_state_is_dp(pll_state) && pll_state->use_c10) {
+ intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES,
+ XELPDP_P0_STATE_ACTIVE);
+ intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES,
+ XELPDP_P2_STATE_READY);
+ }
+
intel_cx0_phy_transaction_end(encoder, wakeref);
}
-static void intel_cx0pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state)
{
- __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
- intel_crtc_has_dp_encoder(crtc_state),
- crtc_state->port_clock, crtc_state->lane_count);
+ memset(hw_state, 0, sizeof(*hw_state));
+
+ hw_state->cx0pll.tbt_mode = true;
+}
+
+bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
+{
+ memset(hw_state, 0, sizeof(*hw_state));
+
+ hw_state->cx0pll.tbt_mode = true;
+
+ return true;
}
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
@@ -3148,8 +3400,7 @@ static int intel_mtl_tbt_clock_select(struct intel_display *display,
}
}
-void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, int port_clock)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@@ -3163,7 +3414,7 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
mask = XELPDP_DDI_CLOCK_SELECT_MASK(display);
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display,
- intel_mtl_tbt_clock_select(display, crtc_state->port_clock));
+ intel_mtl_tbt_clock_select(display, port_clock));
mask |= XELPDP_FORWARD_CLOCK_UNGATE;
val |= XELPDP_FORWARD_CLOCK_UNGATE;
@@ -3201,18 +3452,23 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
* clock frequency.
*/
intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
- crtc_state->port_clock);
+ port_clock);
}
void intel_mtl_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ intel_cx0pll_enable(encoder, &dpll_hw_state->cx0pll);
+}
+
+void intel_mtl_pll_enable_clock(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
if (intel_tc_port_in_tbt_alt_mode(dig_port))
- intel_mtl_tbt_pll_enable(encoder, crtc_state);
- else
- intel_cx0pll_enable(encoder, crtc_state);
+ intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock);
}
/*
@@ -3224,7 +3480,7 @@ void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int i;
u8 owned_lane_mask;
@@ -3236,9 +3492,7 @@ void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
wakeref = intel_cx0_phy_transaction_begin(encoder);
- if (intel_encoder_is_c10phy(encoder))
- intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0,
- C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
+ intel_c10_msgbus_access_begin(encoder, owned_lane_mask);
for (i = 0; i < 4; i++) {
int tx = i % 2 + 1;
@@ -3273,7 +3527,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
- intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);
+ struct ref_tracker *wakeref = intel_cx0_phy_transaction_begin(encoder);
/* 1. Change owned PHY lane power to Disable state. */
intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES,
@@ -3329,7 +3583,7 @@ static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder)
intel_cx0_get_pclk_pll_request(lane);
}
-void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
+void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@@ -3369,12 +3623,15 @@ void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
void intel_mtl_pll_disable(struct intel_encoder *encoder)
{
+ intel_cx0pll_disable(encoder);
+}
+
+void intel_mtl_pll_disable_clock(struct intel_encoder *encoder)
+{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
if (intel_tc_port_in_tbt_alt_mode(dig_port))
- intel_mtl_tbt_pll_disable(encoder);
- else
- intel_cx0pll_disable(encoder);
+ intel_mtl_tbt_pll_disable_clock(encoder);
}
enum icl_port_dpll_id
@@ -3398,50 +3655,20 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
return ICL_PORT_DPLL_DEFAULT;
}
-static void intel_c10pll_state_verify(const struct intel_crtc_state *state,
- struct intel_crtc *crtc,
- struct intel_encoder *encoder,
- struct intel_c10pll_state *mpllb_hw_state)
-{
- struct intel_display *display = to_intel_display(state);
- const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
- u8 expected = mpllb_sw_state->pll[i];
-
- INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->pll[i] != expected,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name, i,
- expected, mpllb_hw_state->pll[i]);
- }
-
- INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->tx != mpllb_sw_state->tx,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name,
- mpllb_sw_state->tx, mpllb_hw_state->tx);
-
- INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->cmn != mpllb_sw_state->cmn,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name,
- mpllb_sw_state->cmn, mpllb_hw_state->cmn);
-}
-
-void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
+bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_cx0pll_state *pll_state)
{
- pll_state->use_c10 = false;
+ memset(pll_state, 0, sizeof(*pll_state));
- pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder));
- if (pll_state->tbt_mode)
- return;
+ if (!intel_cx0_pll_is_enabled(encoder))
+ return false;
- if (intel_encoder_is_c10phy(encoder)) {
- intel_c10pll_readout_hw_state(encoder, &pll_state->c10);
- pll_state->use_c10 = true;
- } else {
- intel_c20pll_readout_hw_state(encoder, &pll_state->c20);
- }
+ if (intel_encoder_is_c10phy(encoder))
+ intel_c10pll_readout_hw_state(encoder, pll_state);
+ else
+ intel_c20pll_readout_hw_state(encoder, pll_state);
+
+ return true;
}
static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a,
@@ -3505,91 +3732,6 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder,
return intel_c20pll_calc_port_clock(encoder, &pll_state->c20);
}
-static void intel_c20pll_state_verify(const struct intel_crtc_state *state,
- struct intel_crtc *crtc,
- struct intel_encoder *encoder,
- struct intel_c20pll_state *mpll_hw_state)
-{
- struct intel_display *display = to_intel_display(state);
- const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20;
- bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state);
- bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state);
- int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state);
- int i;
-
- INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->clock != clock,
- "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)",
- crtc->base.base.id, crtc->base.name,
- mpll_sw_state->clock, mpll_hw_state->clock);
-
- INTEL_DISPLAY_STATE_WARN(display, sw_use_mpllb != hw_use_mpllb,
- "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)",
- crtc->base.base.id, crtc->base.name,
- sw_use_mpllb, hw_use_mpllb);
-
- if (hw_use_mpllb) {
- for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
- INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i],
- "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]);
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
- INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i],
- "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]);
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
- INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->tx[i] != mpll_sw_state->tx[i],
- "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->tx[i], mpll_hw_state->tx[i]);
- }
-
- for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) {
- INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i],
- "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]);
- }
-}
-
-void intel_cx0pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
-{
- struct intel_display *display = to_intel_display(state);
- const struct intel_crtc_state *new_crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
- struct intel_encoder *encoder;
- struct intel_cx0pll_state mpll_hw_state = {};
-
- if (!IS_DISPLAY_VER(display, 14, 30))
- return;
-
- if (!new_crtc_state->hw.active)
- return;
-
- /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */
- if (!intel_crtc_needs_modeset(new_crtc_state) &&
- !intel_crtc_needs_fastset(new_crtc_state))
- return;
-
- encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
- intel_cx0pll_readout_hw_state(encoder, &mpll_hw_state);
-
- if (mpll_hw_state.tbt_mode)
- return;
-
- if (intel_encoder_is_c10phy(encoder))
- intel_c10pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c10);
- else
- intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20);
-}
-
/*
* WA 14022081154
* The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle
@@ -3613,6 +3755,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display)
for_each_intel_encoder(display->drm, encoder) {
struct intel_cx0pll_state pll_state = {};
int port_clock = 162000;
+ int lane_count = 4;
if (!intel_encoder_is_dig_port(encoder))
continue;
@@ -3625,7 +3768,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display)
if (intel_c10pll_calc_state_from_table(encoder,
mtl_c10_edp_tables,
- true, port_clock,
+ true, port_clock, lane_count,
&pll_state) < 0) {
drm_WARN_ON(display->drm,
"Unable to calc C10 state from the tables\n");
@@ -3636,7 +3779,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display)
"[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n",
encoder->base.base.id, encoder->base.name);
- __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4);
+ intel_cx0pll_enable(encoder, &pll_state);
intel_cx0pll_disable(encoder);
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 84d334b865f7..9f10113e2d18 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -11,6 +11,7 @@
#define MB_WRITE_COMMITTED true
#define MB_WRITE_UNCOMMITTED false
+struct drm_printer;
enum icl_port_dpll_id;
struct intel_atomic_state;
struct intel_c10pll_state;
@@ -19,6 +20,8 @@ struct intel_crtc;
struct intel_crtc_state;
struct intel_cx0pll_state;
struct intel_display;
+struct intel_dpll;
+struct intel_dpll_hw_state;
struct intel_encoder;
struct intel_hdmi;
@@ -26,22 +29,30 @@ void intel_clear_response_ready_flag(struct intel_encoder *encoder,
int lane);
bool intel_encoder_is_c10phy(struct intel_encoder *encoder);
void intel_mtl_pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state);
void intel_mtl_pll_disable(struct intel_encoder *encoder);
enum icl_port_dpll_id
intel_mtl_port_pll_type(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
+void intel_mtl_pll_enable_clock(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
+void intel_mtl_pll_disable_clock(struct intel_encoder *encoder);
+void intel_mtl_pll_disable_clock(struct intel_encoder *encoder);
+void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder,
+ int port_clock);
+void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder);
-int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder);
-void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
+int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder,
+ struct intel_dpll_hw_state *hw_state);
+bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_cx0pll_state *pll_state);
int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_cx0pll_state *pll_state);
-void intel_cx0pll_dump_hw_state(struct intel_display *display,
+void intel_cx0pll_dump_hw_state(struct drm_printer *p,
const struct intel_cx0pll_state *hw_state);
-void intel_cx0pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc *crtc);
bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a,
const struct intel_cx0pll_state *b);
void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
@@ -59,7 +70,13 @@ void intel_cx0_write(struct intel_encoder *encoder,
int intel_cx0_wait_for_ack(struct intel_encoder *encoder,
int command, int lane, u32 *val);
void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane);
+
+void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state);
+bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *hw_state);
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
+
void intel_cx0_pll_power_save_wa(struct intel_display *display);
void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 002ccd47856d..cb91d07cdaa6 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -89,6 +89,8 @@
#include "skl_scaler.h"
#include "skl_universal_plane.h"
+struct intel_dpll;
+
static const u8 index_to_dp_signal_levels[] = {
[0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
@@ -726,7 +728,7 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
bool enable, u32 hdcp_mask)
{
struct intel_display *display = to_intel_display(intel_encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int ret = 0;
wakeref = intel_display_power_get_if_enabled(display,
@@ -747,7 +749,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
int type = intel_connector->base.connector_type;
enum port port = encoder->port;
enum transcoder cpu_transcoder;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum pipe pipe = 0;
u32 ddi_mode;
bool ret;
@@ -803,7 +805,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum pipe p;
u32 tmp;
u8 mst_pipe_mask = 0, dp128b132b_pipe_mask = 0;
@@ -846,7 +848,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
for_each_pipe(display, p) {
enum transcoder cpu_transcoder = (enum transcoder)p;
u32 port_mask, ddi_select, ddi_mode;
- intel_wakeref_t trans_wakeref;
+ struct ref_tracker *trans_wakeref;
trans_wakeref = intel_display_power_get_if_enabled(display,
POWER_DOMAIN_TRANSCODER(cpu_transcoder));
@@ -1000,7 +1002,7 @@ main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
struct intel_display *display = to_intel_display(dig_port);
enum intel_display_power_domain domain =
intel_ddi_main_link_aux_domain(dig_port, crtc_state);
- intel_wakeref_t wf;
+ struct ref_tracker *wf;
wf = fetch_and_zero(&dig_port->aux_wakeref);
if (!wf)
@@ -2446,7 +2448,7 @@ static void intel_ddi_enable_fec(struct intel_encoder *encoder,
return;
}
- drm_err(display->drm, "Failed to enable FEC after retries\n");
+ drm_dbg_kms(display->drm, "Failed to enable FEC after retries\n");
}
static void intel_ddi_disable_fec(struct intel_encoder *encoder,
@@ -3128,7 +3130,7 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &dig_port->dp;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool is_mst = intel_crtc_has_type(old_crtc_state,
INTEL_OUTPUT_DP_MST);
@@ -3196,7 +3198,7 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
dig_port->set_infoframes(encoder, false,
old_crtc_state, old_conn_state);
@@ -3667,8 +3669,8 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc *pipe_crtc;
- /* FIXME: Add MTL pll_mgr */
- if (DISPLAY_VER(display) >= 14 || !intel_encoder_is_tc(encoder))
+ /* FIXME: Add NVL+ and DG2 pll_mgr */
+ if (!intel_encoder_is_tc(encoder) || !display->dpll.mgr)
return;
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
@@ -3963,7 +3965,7 @@ static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
for_each_cpu_transcoder_masked(display, cpu_transcoder, transcoders) {
enum intel_display_power_domain power_domain;
- intel_wakeref_t trans_wakeref;
+ struct ref_tracker *trans_wakeref;
power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
trans_wakeref = intel_display_power_get_if_enabled(display,
@@ -4255,19 +4257,70 @@ static void xe3plpd_ddi_get_config(struct intel_encoder *encoder,
intel_ddi_get_config(encoder, crtc_state);
}
-static void mtl_ddi_get_config(struct intel_encoder *encoder,
- struct intel_crtc_state *crtc_state)
+static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll)
{
- intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll);
+ return pll->info->id == DPLL_ID_ICL_TBTPLL;
+}
- if (crtc_state->dpll_hw_state.cx0pll.tbt_mode)
+static void mtl_ddi_cx0_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
+ enum icl_port_dpll_id port_dpll_id,
+ enum intel_dpll_id pll_id)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ struct icl_port_dpll *port_dpll;
+ struct intel_dpll *pll;
+ bool pll_active;
+
+ port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
+ pll = intel_get_dpll_by_id(display, pll_id);
+
+ if (drm_WARN_ON(display->drm, !pll))
+ return;
+
+ port_dpll->pll = pll;
+ pll_active = intel_dpll_get_hw_state(display, pll, &port_dpll->hw_state);
+ drm_WARN_ON(display->drm, !pll_active);
+
+ icl_set_active_port_dpll(crtc_state, port_dpll_id);
+
+ if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll))
crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
else
- crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll);
+ crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll,
+ &crtc_state->dpll_hw_state);
intel_ddi_get_config(encoder, crtc_state);
}
+/*
+ * Get the configuration for either a port using a C10 PHY PLL, or a port using a
+ * C20 PHY PLL in the cases of:
+ * - BMG port A/B
+ * - PTL port B eDP over TypeC PHY
+ */
+static void mtl_ddi_non_tc_phy_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(encoder);
+
+ mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT,
+ mtl_port_to_pll_id(display, encoder->port));
+}
+
+static void mtl_ddi_tc_phy_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(encoder);
+
+ if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
+ mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT,
+ DPLL_ID_ICL_TBTPLL);
+ else
+ mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_MG_PHY,
+ mtl_port_to_pll_id(display, encoder->port));
+}
+
static void dg2_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
@@ -4305,11 +4358,6 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
intel_ddi_get_config(encoder, crtc_state);
}
-static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll)
-{
- return pll->info->id == DPLL_ID_ICL_TBTPLL;
-}
-
static enum icl_port_dpll_id
icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
@@ -5100,7 +5148,7 @@ static const char *intel_ddi_encoder_name(struct intel_display *display,
port_name(port - PORT_D_XELPD + PORT_D),
phy_name(phy));
} else if (DISPLAY_VER(display) >= 12) {
- enum tc_port tc_port = intel_port_to_tc(display, port);
+ enum tc_port tc_port = intel_tc_phy_port_to_tc(display, port);
seq_buf_printf(s, "DDI %s%c/PHY %s%c",
port >= PORT_TC1 ? "TC" : "",
@@ -5108,7 +5156,7 @@ static const char *intel_ddi_encoder_name(struct intel_display *display,
tc_port != TC_PORT_NONE ? "TC" : "",
tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
} else if (DISPLAY_VER(display) >= 11) {
- enum tc_port tc_port = intel_port_to_tc(display, port);
+ enum tc_port tc_port = intel_tc_phy_port_to_tc(display, port);
seq_buf_printf(s, "DDI %c%s/PHY %s%c",
port_name(port),
@@ -5252,10 +5300,13 @@ void intel_ddi_init(struct intel_display *display,
encoder->port_pll_type = intel_mtl_port_pll_type;
encoder->get_config = xe3plpd_ddi_get_config;
} else if (DISPLAY_VER(display) >= 14) {
- encoder->enable_clock = intel_mtl_pll_enable;
- encoder->disable_clock = intel_mtl_pll_disable;
- encoder->port_pll_type = intel_mtl_port_pll_type;
- encoder->get_config = mtl_ddi_get_config;
+ encoder->enable_clock = intel_mtl_pll_enable_clock;
+ encoder->disable_clock = intel_mtl_pll_disable_clock;
+ encoder->port_pll_type = icl_ddi_tc_port_pll_type;
+ if (intel_encoder_is_tc(encoder))
+ encoder->get_config = mtl_ddi_tc_phy_get_config;
+ else
+ encoder->get_config = mtl_ddi_non_tc_phy_get_config;
} else if (display->platform.dg2) {
encoder->enable_clock = intel_mpllb_enable;
encoder->disable_clock = intel_mpllb_disable;
@@ -5372,6 +5423,17 @@ void intel_ddi_init(struct intel_display *display,
goto err;
}
+ /*
+ * FIXME: We currently need to store dedicated_external because devdata
+ * does not live long enough for when intel_encoder_is_tc() is called on
+ * the unbind path. This needs to be fixed by making sure that the VBT
+ * data is kept long enough, so that
+ * intel_bios_encoder_is_dedicated_external() can be called directly
+ * from intel_encoder_is_tc().
+ */
+ if (intel_bios_encoder_is_dedicated_external(devdata))
+ dig_port->dedicated_external = true;
+
if (intel_encoder_is_tc(encoder)) {
bool is_legacy =
!intel_bios_encoder_supports_typec_usb(devdata) &&
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 095a319f8bc9..d5947cc9b94c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -372,7 +372,7 @@ void assert_transcoder(struct intel_display *display,
{
bool cur_state;
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
/* we keep both pipes enabled on 830 */
if (display->platform.i830)
@@ -1810,7 +1810,17 @@ bool intel_phy_is_combo(struct intel_display *display, enum phy phy)
return false;
}
-/* Prefer intel_encoder_is_tc() */
+/*
+ * This function returns true if the DDI port respective to the PHY enumeration
+ * is a Type-C capable port.
+ *
+ * Depending on the VBT, the port might be configured
+ * as a "dedicated external" port, meaning that actual physical PHY is outside
+ * of the Type-C subsystem and, as such, not really a "Type-C PHY".
+ *
+ * Prefer intel_encoder_is_tc(), especially if you really need to know if we
+ * are dealing with Type-C connections.
+ */
bool intel_phy_is_tc(struct intel_display *display, enum phy phy)
{
/*
@@ -1859,17 +1869,32 @@ enum phy intel_port_to_phy(struct intel_display *display, enum port port)
}
/* Prefer intel_encoder_to_tc() */
+/*
+ * Return TC_PORT_1..I915_MAX_TC_PORTS for any TypeC DDI port. The function
+ * can be also called for TypeC DDI ports not connected to a TypeC PHY such as
+ * the PORT_TC1..4 ports on RKL/ADLS/BMG.
+ */
enum tc_port intel_port_to_tc(struct intel_display *display, enum port port)
{
- if (!intel_phy_is_tc(display, intel_port_to_phy(display, port)))
- return TC_PORT_NONE;
-
if (DISPLAY_VER(display) >= 12)
return TC_PORT_1 + port - PORT_TC1;
else
return TC_PORT_1 + port - PORT_C;
}
+/*
+ * Return TC_PORT_1..I915_MAX_TC_PORTS for TypeC DDI ports connected to a TypeC PHY.
+ * Note that on RKL, ADLS, BMG the PORT_TC1..4 ports are connected to a non-TypeC
+ * PHY, so on those platforms the function returns TC_PORT_NONE.
+ */
+enum tc_port intel_tc_phy_port_to_tc(struct intel_display *display, enum port port)
+{
+ if (!intel_phy_is_tc(display, intel_port_to_phy(display, port)))
+ return TC_PORT_NONE;
+
+ return intel_port_to_tc(display, port);
+}
+
enum phy intel_encoder_to_phy(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
@@ -1894,6 +1919,10 @@ bool intel_encoder_is_snps(struct intel_encoder *encoder)
bool intel_encoder_is_tc(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (dig_port && dig_port->dedicated_external)
+ return false;
return intel_phy_is_tc(display, intel_encoder_to_phy(encoder));
}
@@ -1902,7 +1931,7 @@ enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
- return intel_port_to_tc(display, encoder->port);
+ return intel_tc_phy_port_to_tc(display, encoder->port);
}
enum intel_display_power_domain
@@ -3020,7 +3049,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
struct intel_display *display = to_intel_display(crtc);
enum intel_display_power_domain power_domain;
enum transcoder cpu_transcoder = (enum transcoder)crtc->pipe;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret = false;
u32 tmp;
@@ -3364,7 +3393,7 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
struct intel_display *display = to_intel_display(crtc);
enum intel_display_power_domain power_domain;
enum transcoder cpu_transcoder = (enum transcoder)crtc->pipe;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret = false;
u32 tmp;
@@ -3454,12 +3483,11 @@ static bool transcoder_ddi_func_is_enabled(struct intel_display *display,
enum transcoder cpu_transcoder)
{
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
u32 tmp = 0;
power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
- with_intel_display_power_if_enabled(display, power_domain, wakeref)
+ with_intel_display_power_if_enabled(display, power_domain)
tmp = intel_de_read(display,
TRANS_DDI_FUNC_CTL(display, cpu_transcoder));
@@ -3481,10 +3509,9 @@ static void enabled_uncompressed_joiner_pipes(struct intel_display *display,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
- intel_wakeref_t wakeref;
power_domain = POWER_DOMAIN_PIPE(pipe);
- with_intel_display_power_if_enabled(display, power_domain, wakeref) {
+ with_intel_display_power_if_enabled(display, power_domain) {
u32 tmp = intel_de_read(display, ICL_PIPE_DSS_CTL1(pipe));
if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
@@ -3510,10 +3537,9 @@ static void enabled_bigjoiner_pipes(struct intel_display *display,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
- intel_wakeref_t wakeref;
power_domain = intel_dsc_power_domain(crtc, (enum transcoder)pipe);
- with_intel_display_power_if_enabled(display, power_domain, wakeref) {
+ with_intel_display_power_if_enabled(display, power_domain) {
u32 tmp = intel_de_read(display, ICL_PIPE_DSS_CTL1(pipe));
if (!(tmp & BIG_JOINER_ENABLE))
@@ -3580,10 +3606,9 @@ static void enabled_ultrajoiner_pipes(struct intel_display *display,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
- intel_wakeref_t wakeref;
power_domain = intel_dsc_power_domain(crtc, (enum transcoder)pipe);
- with_intel_display_power_if_enabled(display, power_domain, wakeref) {
+ with_intel_display_power_if_enabled(display, power_domain) {
u32 tmp = intel_de_read(display, ICL_PIPE_DSS_CTL1(pipe));
if (!(tmp & ULTRA_JOINER_ENABLE))
@@ -3741,12 +3766,11 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
for_each_cpu_transcoder_masked(display, cpu_transcoder,
panel_transcoder_mask) {
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
enum pipe trans_pipe;
u32 tmp = 0;
power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
- with_intel_display_power_if_enabled(display, power_domain, wakeref)
+ with_intel_display_power_if_enabled(display, power_domain)
tmp = intel_de_read(display,
TRANS_DDI_FUNC_CTL(display, cpu_transcoder));
@@ -4977,24 +5001,6 @@ pipe_config_pll_mismatch(struct drm_printer *p, bool fastset,
intel_dpll_dump_hw_state(display, p, b);
}
-static void
-pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset,
- const struct intel_crtc *crtc,
- const char *name,
- const struct intel_cx0pll_state *a,
- const struct intel_cx0pll_state *b)
-{
- struct intel_display *display = to_intel_display(crtc);
- char *chipname = a->use_c10 ? "C10" : "C20";
-
- pipe_config_mismatch(p, fastset, crtc, name, chipname);
-
- drm_printf(p, "expected:\n");
- intel_cx0pll_dump_hw_state(display, a);
- drm_printf(p, "found:\n");
- intel_cx0pll_dump_hw_state(display, b);
-}
-
static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state)
{
struct intel_display *display = to_intel_display(old_crtc_state);
@@ -5146,16 +5152,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} \
} while (0)
-#define PIPE_CONF_CHECK_PLL_CX0(name) do { \
- if (!intel_cx0pll_compare_hw_state(&current_config->name, \
- &pipe_config->name)) { \
- pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \
- &current_config->name, \
- &pipe_config->name); \
- ret = false; \
- } \
-} while (0)
-
#define PIPE_CONF_CHECK_PLL_LT(name) do { \
if (!intel_lt_phy_pll_compare_hw_state(&current_config->name, \
&pipe_config->name)) { \
@@ -5395,8 +5391,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
/* FIXME convert MTL+ platforms over to dpll_mgr */
if (HAS_LT_PHY(display))
PIPE_CONF_CHECK_PLL_LT(dpll_hw_state.ltpll);
- else if (DISPLAY_VER(display) >= 14)
- PIPE_CONF_CHECK_PLL_CX0(dpll_hw_state.cx0pll);
PIPE_CONF_CHECK_X(dsi_pll.ctrl);
PIPE_CONF_CHECK_X(dsi_pll.div);
@@ -6032,14 +6026,6 @@ static int intel_async_flip_check_uapi(struct intel_atomic_state *state,
return -EINVAL;
}
- /* FIXME: selective fetch should be disabled for async flips */
- if (new_crtc_state->enable_psr2_sel_fetch) {
- drm_dbg_kms(display->drm,
- "[CRTC:%d:%s] async flip disallowed with PSR2 selective fetch\n",
- crtc->base.base.id, crtc->base.name);
- return -EINVAL;
- }
-
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
if (plane->pipe != crtc->pipe)
@@ -6130,7 +6116,7 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
if (!plane->async_flip)
continue;
- if (!intel_plane_can_async_flip(plane, new_plane_state->hw.fb->format->format,
+ if (!intel_plane_can_async_flip(plane, new_plane_state->hw.fb->format,
new_plane_state->hw.fb->modifier)) {
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] pixel format %p4cc / modifier 0x%llx does not support async flip\n",
@@ -7399,7 +7385,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
- intel_wakeref_t wakeref = NULL;
+ struct ref_tracker *wakeref = NULL;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index bcc6ccb69d2b..f8e6e4e82722 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -451,6 +451,7 @@ bool intel_phy_is_combo(struct intel_display *display, enum phy phy);
bool intel_phy_is_tc(struct intel_display *display, enum phy phy);
bool intel_phy_is_snps(struct intel_display *display, enum phy phy);
enum tc_port intel_port_to_tc(struct intel_display *display, enum port port);
+enum tc_port intel_tc_phy_port_to_tc(struct intel_display *display, enum port port);
enum phy intel_encoder_to_phy(struct intel_encoder *encoder);
bool intel_encoder_is_combo(struct intel_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 9b8414b77c15..d708d322aa85 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -386,7 +386,7 @@ struct intel_display {
struct {
struct intel_dmc *dmc;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
} dmc;
struct {
@@ -395,6 +395,21 @@ struct intel_display {
} dsi;
struct {
+ const struct dram_info *info;
+ } dram;
+
+ struct {
+ struct intel_fbc *instances[I915_MAX_FBCS];
+
+ /* xe3p_lpd+: FBC instance utilizing the system cache */
+ struct sys_cache_cfg {
+ /* Protect concurrecnt access to system cache configuration */
+ struct mutex lock;
+ enum intel_fbc_id id;
+ } sys_cache;
+ } fbc;
+
+ struct {
/* list of fbdev register on this device */
struct intel_fbdev *fbdev;
} fbdev;
@@ -611,7 +626,6 @@ struct intel_display {
struct drm_dp_tunnel_mgr *dp_tunnel_mgr;
struct intel_audio audio;
struct intel_dpll_global dpll;
- struct intel_fbc *fbc[I915_MAX_FBCS];
struct intel_frontbuffer_tracking fb_tracking;
struct intel_hotplug hotplug;
struct intel_opregion *opregion;
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 9bbfdae8d024..aba13e8a9051 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -86,7 +86,7 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
static int i915_sr_status(struct seq_file *m, void *unused)
{
struct intel_display *display = node_to_intel_display(m->private);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool sr_enabled = false;
wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT);
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index 1170afaa8680..471f236c9ddf 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -1420,6 +1420,10 @@ static const struct platform_desc ptl_desc = {
}
};
+static const struct platform_desc nvl_desc = {
+ PLATFORM(novalake),
+};
+
__diag_pop();
/*
@@ -1495,6 +1499,7 @@ static const struct {
INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc),
INTEL_PTL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc),
INTEL_WCL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc),
+ INTEL_NVLS_IDS(INTEL_DISPLAY_DEVICE, &nvl_desc),
};
static const struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index b559ef43d547..50b2e9ae2c18 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -103,7 +103,9 @@ struct pci_dev;
func(battlemage) \
/* Display ver 30 (based on GMD ID) */ \
func(pantherlake) \
- func(pantherlake_wildcatlake)
+ func(pantherlake_wildcatlake) \
+ /* Display ver 35 (based on GMD ID) */ \
+ func(novalake)
#define __MEMBER(name) unsigned long name:1;
@@ -147,7 +149,7 @@ struct intel_display_platforms {
#define HAS_4TILE(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_ASYNC_FLIPS(__display) (DISPLAY_VER(__display) >= 5)
#define HAS_AS_SDP(__display) (DISPLAY_VER(__display) >= 13)
-#define HAS_AUX_CCS(__display) (IS_DISPLAY_VER(__display, 9, 12) || (__display)->platform.alderlake_p || (__display)->platform.meteorlake)
+#define HAS_AUX_DIST(__display) (IS_DISPLAY_VER(__display, 9, 12) || (__display)->platform.alderlake_p || (__display)->platform.meteorlake)
#define HAS_BIGJOINER(__display) (DISPLAY_VER(__display) >= 11 && HAS_DSC(__display))
#define HAS_CASF(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_CDCLK_CRAWL(__display) (DISPLAY_INFO(__display)->has_cdclk_crawl)
@@ -173,6 +175,7 @@ struct intel_display_platforms {
#define HAS_DSC_MST(__display) (DISPLAY_VER(__display) >= 12 && HAS_DSC(__display))
#define HAS_FBC(__display) (DISPLAY_RUNTIME_INFO(__display)->fbc_mask != 0)
#define HAS_FBC_DIRTY_RECT(__display) (DISPLAY_VER(__display) >= 30)
+#define HAS_FBC_SYS_CACHE(__display) (DISPLAY_VER(__display) >= 35 && !(__display)->platform.dgfx)
#define HAS_FPGA_DBG_UNCLAIMED(__display) (DISPLAY_INFO(__display)->has_fpga_dbg)
#define HAS_FW_BLC(__display) (DISPLAY_VER(__display) >= 3)
#define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake)
@@ -185,6 +188,7 @@ struct intel_display_platforms {
#define HAS_IPS(__display) ((__display)->platform.haswell_ult || (__display)->platform.broadwell)
#define HAS_LRR(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_LSPCON(__display) (IS_DISPLAY_VER(__display, 9, 10))
+#define HAS_LT_PHY(__display) ((__display)->platform.novalake)
#define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14)
#define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay)
@@ -197,6 +201,7 @@ struct intel_display_platforms {
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(__display) (DISPLAY_VER(__display) >= 13)
+#define HAS_UNDERRUN_DBG_INFO(__display) (DISPLAY_VER(__display) >= 35)
#define HAS_ULTRAJOINER(__display) (((__display)->platform.dgfx && \
DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
#define HAS_VRR(__display) (DISPLAY_VER(__display) >= 11)
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 7e000ba3e08b..e1d29aea0ddc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -199,12 +199,8 @@ void intel_display_driver_early_probe(struct intel_display *display)
/* part #1: call before irq install */
int intel_display_driver_probe_noirq(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
int ret;
- if (i915_inject_probe_failure(i915))
- return -ENODEV;
-
if (HAS_DISPLAY(display)) {
ret = drm_vblank_init(display->drm,
INTEL_NUM_PIPES(display));
@@ -317,6 +313,7 @@ cleanup_bios:
return ret;
}
+ALLOW_ERROR_INJECTION(intel_display_driver_probe_noirq, ERRNO);
static void set_display_access(struct intel_display *display,
bool any_task_allowed,
@@ -452,7 +449,6 @@ bool intel_display_driver_check_access(struct intel_display *display)
/* part #2: call after irq install, but before gem init */
int intel_display_driver_probe_nogem(struct intel_display *display)
{
- enum pipe pipe;
int ret;
if (!HAS_DISPLAY(display))
@@ -466,15 +462,9 @@ int intel_display_driver_probe_nogem(struct intel_display *display)
intel_gmbus_setup(display);
- drm_dbg_kms(display->drm, "%d display pipe%s available.\n",
- INTEL_NUM_PIPES(display),
- INTEL_NUM_PIPES(display) > 1 ? "s" : "");
-
- for_each_pipe(display, pipe) {
- ret = intel_crtc_init(display, pipe);
- if (ret)
- goto err_mode_config;
- }
+ ret = intel_crtc_init(display);
+ if (ret)
+ goto err_mode_config;
intel_plane_possible_crtcs_init(display);
intel_dpll_init(display);
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 43b27deb4a26..9adeebb376b1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -6,8 +6,6 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
-#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "icl_dsi_regs.h"
#include "intel_crtc.h"
@@ -19,57 +17,83 @@
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
-#include "intel_dmc_wl.h"
#include "intel_dp_aux.h"
#include "intel_dsb.h"
#include "intel_fdi_regs.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hotplug_irq.h"
+#include "intel_parent.h"
#include "intel_pipe_crc_regs.h"
#include "intel_plane.h"
#include "intel_pmdemand.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
-#include "intel_uncore.h"
-static void
-intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs,
- u32 imr_val, u32 ier_val)
+static void irq_reset(struct intel_display *display, struct i915_irq_regs regs)
{
- intel_dmc_wl_get(display, regs.imr);
- intel_dmc_wl_get(display, regs.ier);
- intel_dmc_wl_get(display, regs.iir);
+ intel_de_write(display, regs.imr, 0xffffffff);
+ intel_de_posting_read(display, regs.imr);
- gen2_irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val);
+ intel_de_write(display, regs.ier, 0);
- intel_dmc_wl_put(display, regs.iir);
- intel_dmc_wl_put(display, regs.ier);
- intel_dmc_wl_put(display, regs.imr);
+ /* IIR can theoretically queue up two events. Be paranoid. */
+ intel_de_write(display, regs.iir, 0xffffffff);
+ intel_de_posting_read(display, regs.iir);
+ intel_de_write(display, regs.iir, 0xffffffff);
+ intel_de_posting_read(display, regs.iir);
}
-static void
-intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs regs)
+/*
+ * We should clear IMR at preinstall/uninstall, and just check at postinstall.
+ */
+static void assert_iir_is_zero(struct intel_display *display, i915_reg_t reg)
{
- intel_dmc_wl_get(display, regs.imr);
- intel_dmc_wl_get(display, regs.ier);
- intel_dmc_wl_get(display, regs.iir);
+ u32 val = intel_de_read(display, reg);
- gen2_irq_reset(to_intel_uncore(display->drm), regs);
+ if (val == 0)
+ return;
- intel_dmc_wl_put(display, regs.iir);
- intel_dmc_wl_put(display, regs.ier);
- intel_dmc_wl_put(display, regs.imr);
+ drm_WARN(display->drm, 1,
+ "Interrupt register 0x%x is not zero: 0x%08x\n",
+ i915_mmio_reg_offset(reg), val);
+ intel_de_write(display, reg, 0xffffffff);
+ intel_de_posting_read(display, reg);
+ intel_de_write(display, reg, 0xffffffff);
+ intel_de_posting_read(display, reg);
}
-static void
-intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_reg_t reg)
+static void irq_init(struct intel_display *display, struct i915_irq_regs regs,
+ u32 imr_val, u32 ier_val)
{
- intel_dmc_wl_get(display, reg);
+ assert_iir_is_zero(display, regs.iir);
+
+ intel_de_write(display, regs.ier, ier_val);
+ intel_de_write(display, regs.imr, imr_val);
+ intel_de_posting_read(display, regs.imr);
+}
- gen2_assert_iir_is_zero(to_intel_uncore(display->drm), reg);
+static void error_reset(struct intel_display *display, struct i915_error_regs regs)
+{
+ intel_de_write(display, regs.emr, 0xffffffff);
+ intel_de_posting_read(display, regs.emr);
- intel_dmc_wl_put(display, reg);
+ intel_de_write(display, regs.eir, 0xffffffff);
+ intel_de_posting_read(display, regs.eir);
+ intel_de_write(display, regs.eir, 0xffffffff);
+ intel_de_posting_read(display, regs.eir);
+}
+
+static void error_init(struct intel_display *display, struct i915_error_regs regs,
+ u32 emr_val)
+{
+ intel_de_write(display, regs.eir, 0xffffffff);
+ intel_de_posting_read(display, regs.eir);
+ intel_de_write(display, regs.eir, 0xffffffff);
+ intel_de_posting_read(display, regs.eir);
+
+ intel_de_write(display, regs.emr, emr_val);
+ intel_de_posting_read(display, regs.emr);
}
struct pipe_fault_handler {
@@ -135,7 +159,6 @@ intel_handle_vblank(struct intel_display *display, enum pipe pipe)
void ilk_update_display_irq(struct intel_display *display,
u32 interrupt_mask, u32 enabled_irq_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 new_val;
lockdep_assert_held(&display->irq.lock);
@@ -146,7 +169,7 @@ void ilk_update_display_irq(struct intel_display *display,
new_val |= (~enabled_irq_mask & interrupt_mask);
if (new_val != display->irq.ilk_de_imr_mask &&
- !drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) {
+ !drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) {
display->irq.ilk_de_imr_mask = new_val;
intel_de_write(display, DEIMR, display->irq.ilk_de_imr_mask);
intel_de_posting_read(display, DEIMR);
@@ -172,7 +195,6 @@ void ilk_disable_display_irq(struct intel_display *display, u32 bits)
void bdw_update_port_irq(struct intel_display *display,
u32 interrupt_mask, u32 enabled_irq_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 new_val;
u32 old_val;
@@ -180,7 +202,7 @@ void bdw_update_port_irq(struct intel_display *display,
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
- if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)))
+ if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)))
return;
old_val = intel_de_read(display, GEN8_DE_PORT_IMR);
@@ -206,14 +228,13 @@ static void bdw_update_pipe_irq(struct intel_display *display,
enum pipe pipe, u32 interrupt_mask,
u32 enabled_irq_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 new_val;
lockdep_assert_held(&display->irq.lock);
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
- if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)))
+ if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)))
return;
new_val = display->irq.de_pipe_imr_mask[pipe];
@@ -249,7 +270,6 @@ void ibx_display_interrupt_update(struct intel_display *display,
u32 interrupt_mask,
u32 enabled_irq_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 sdeimr = intel_de_read(display, SDEIMR);
sdeimr &= ~interrupt_mask;
@@ -259,7 +279,7 @@ void ibx_display_interrupt_update(struct intel_display *display,
lockdep_assert_held(&display->irq.lock);
- if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)))
+ if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)))
return;
intel_de_write(display, SDEIMR, sdeimr);
@@ -323,7 +343,6 @@ out:
void i915_enable_pipestat(struct intel_display *display,
enum pipe pipe, u32 status_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
i915_reg_t reg = PIPESTAT(display, pipe);
u32 enable_mask;
@@ -332,7 +351,7 @@ void i915_enable_pipestat(struct intel_display *display,
pipe_name(pipe), status_mask);
lockdep_assert_held(&display->irq.lock);
- drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv));
+ drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display));
if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == status_mask)
return;
@@ -347,7 +366,6 @@ void i915_enable_pipestat(struct intel_display *display,
void i915_disable_pipestat(struct intel_display *display,
enum pipe pipe, u32 status_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
i915_reg_t reg = PIPESTAT(display, pipe);
u32 enable_mask;
@@ -356,7 +374,7 @@ void i915_disable_pipestat(struct intel_display *display,
pipe_name(pipe), status_mask);
lockdep_assert_held(&display->irq.lock);
- drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv));
+ drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display));
if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == 0)
return;
@@ -1918,15 +1936,14 @@ static void _vlv_display_irq_reset(struct intel_display *display)
else
intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
- gen2_error_reset(to_intel_uncore(display->drm),
- VLV_ERROR_REGS);
+ error_reset(display, VLV_ERROR_REGS);
i915_hotplug_interrupt_update_locked(display, 0xffffffff, 0);
intel_de_rmw(display, PORT_HOTPLUG_STAT(display), 0, 0);
i9xx_pipestat_irq_reset(display);
- intel_display_irq_regs_reset(display, VLV_IRQ_REGS);
+ irq_reset(display, VLV_IRQ_REGS);
display->irq.vlv_imr_mask = ~0u;
}
@@ -2014,8 +2031,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display)
DPINVGTT_STATUS_MASK_VLV |
DPINVGTT_EN_MASK_VLV);
- gen2_error_init(to_intel_uncore(display->drm),
- VLV_ERROR_REGS, ~vlv_error_mask());
+ error_init(display, VLV_ERROR_REGS, ~vlv_error_mask());
pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
@@ -2038,7 +2054,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display)
display->irq.vlv_imr_mask = ~enable_mask;
- intel_display_irq_regs_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask);
+ irq_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask);
}
void vlv_display_irq_postinstall(struct intel_display *display)
@@ -2054,7 +2070,7 @@ static void ibx_display_irq_reset(struct intel_display *display)
if (HAS_PCH_NOP(display))
return;
- gen2_irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS);
+ irq_reset(display, SDE_IRQ_REGS);
if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display))
intel_de_write(display, SERR_INT, 0xffffffff);
@@ -2062,9 +2078,7 @@ static void ibx_display_irq_reset(struct intel_display *display)
void ilk_display_irq_reset(struct intel_display *display)
{
- struct intel_uncore *uncore = to_intel_uncore(display->drm);
-
- gen2_irq_reset(uncore, DE_IRQ_REGS);
+ irq_reset(display, DE_IRQ_REGS);
display->irq.ilk_de_imr_mask = ~0u;
if (DISPLAY_VER(display) == 7)
@@ -2091,10 +2105,10 @@ void gen8_display_irq_reset(struct intel_display *display)
for_each_pipe(display, pipe)
if (intel_display_power_is_enabled(display,
POWER_DOMAIN_PIPE(pipe)))
- intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
- intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS);
- intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS);
+ irq_reset(display, GEN8_DE_PORT_IRQ_REGS);
+ irq_reset(display, GEN8_DE_MISC_IRQ_REGS);
if (HAS_PCH_SPLIT(display))
ibx_display_irq_reset(display);
@@ -2136,39 +2150,38 @@ void gen11_display_irq_reset(struct intel_display *display)
for_each_pipe(display, pipe)
if (intel_display_power_is_enabled(display,
POWER_DOMAIN_PIPE(pipe)))
- intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
- intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS);
- intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS);
+ irq_reset(display, GEN8_DE_PORT_IRQ_REGS);
+ irq_reset(display, GEN8_DE_MISC_IRQ_REGS);
if (DISPLAY_VER(display) >= 14)
- intel_display_irq_regs_reset(display, PICAINTERRUPT_IRQ_REGS);
+ irq_reset(display, PICAINTERRUPT_IRQ_REGS);
else
- intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS);
+ irq_reset(display, GEN11_DE_HPD_IRQ_REGS);
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
- intel_display_irq_regs_reset(display, SDE_IRQ_REGS);
+ irq_reset(display, SDE_IRQ_REGS);
}
void gen8_irq_power_well_post_enable(struct intel_display *display,
u8 pipe_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
gen8_de_pipe_flip_done_mask(display);
enum pipe pipe;
spin_lock_irq(&display->irq.lock);
- if (!intel_irqs_enabled(dev_priv)) {
+ if (!intel_parent_irq_enabled(display)) {
spin_unlock_irq(&display->irq.lock);
return;
}
for_each_pipe_masked(display, pipe, pipe_mask)
- intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe),
- display->irq.de_pipe_imr_mask[pipe],
- ~display->irq.de_pipe_imr_mask[pipe] | extra_ier);
+ irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe),
+ display->irq.de_pipe_imr_mask[pipe],
+ ~display->irq.de_pipe_imr_mask[pipe] | extra_ier);
spin_unlock_irq(&display->irq.lock);
}
@@ -2176,23 +2189,22 @@ void gen8_irq_power_well_post_enable(struct intel_display *display,
void gen8_irq_power_well_pre_disable(struct intel_display *display,
u8 pipe_mask)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
enum pipe pipe;
spin_lock_irq(&display->irq.lock);
- if (!intel_irqs_enabled(dev_priv)) {
+ if (!intel_parent_irq_enabled(display)) {
spin_unlock_irq(&display->irq.lock);
return;
}
for_each_pipe_masked(display, pipe, pipe_mask)
- intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
spin_unlock_irq(&display->irq.lock);
/* make sure we're done processing display irqs */
- intel_synchronize_irq(dev_priv);
+ intel_parent_irq_synchronize(display);
}
/*
@@ -2220,13 +2232,11 @@ static void ibx_irq_postinstall(struct intel_display *display)
else
mask = SDE_GMBUS_CPT;
- intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff);
+ irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void valleyview_enable_display_irqs(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
-
spin_lock_irq(&display->irq.lock);
if (display->irq.vlv_display_irqs_enabled)
@@ -2234,7 +2244,7 @@ void valleyview_enable_display_irqs(struct intel_display *display)
display->irq.vlv_display_irqs_enabled = true;
- if (intel_irqs_enabled(dev_priv)) {
+ if (intel_parent_irq_enabled(display)) {
_vlv_display_irq_reset(display);
_vlv_display_irq_postinstall(display);
}
@@ -2245,8 +2255,6 @@ out:
void valleyview_disable_display_irqs(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
-
spin_lock_irq(&display->irq.lock);
if (!display->irq.vlv_display_irqs_enabled)
@@ -2254,7 +2262,7 @@ void valleyview_disable_display_irqs(struct intel_display *display)
display->irq.vlv_display_irqs_enabled = false;
- if (intel_irqs_enabled(dev_priv))
+ if (intel_parent_irq_enabled(display))
_vlv_display_irq_reset(display);
out:
spin_unlock_irq(&display->irq.lock);
@@ -2286,7 +2294,7 @@ void ilk_de_irq_postinstall(struct intel_display *display)
}
if (display->platform.haswell) {
- intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR);
+ assert_iir_is_zero(display, EDP_PSR_IIR);
display_mask |= DE_EDP_PSR_INT_HSW;
}
@@ -2297,8 +2305,8 @@ void ilk_de_irq_postinstall(struct intel_display *display)
ibx_irq_postinstall(display);
- intel_display_irq_regs_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask,
- display_mask | extra_mask);
+ irq_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask,
+ display_mask | extra_mask);
}
static void mtp_irq_postinstall(struct intel_display *display);
@@ -2374,11 +2382,10 @@ void gen8_de_irq_postinstall(struct intel_display *display)
if (!intel_display_power_is_enabled(display, domain))
continue;
- intel_display_irq_regs_assert_irr_is_zero(display,
- TRANS_PSR_IIR(display, trans));
+ assert_iir_is_zero(display, TRANS_PSR_IIR(display, trans));
}
} else {
- intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR);
+ assert_iir_is_zero(display, EDP_PSR_IIR);
}
for_each_pipe(display, pipe) {
@@ -2386,44 +2393,50 @@ void gen8_de_irq_postinstall(struct intel_display *display)
if (intel_display_power_is_enabled(display,
POWER_DOMAIN_PIPE(pipe)))
- intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe),
- display->irq.de_pipe_imr_mask[pipe],
- de_pipe_enables);
+ irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe),
+ display->irq.de_pipe_imr_mask[pipe],
+ de_pipe_enables);
}
- intel_display_irq_regs_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked,
- de_port_enables);
- intel_display_irq_regs_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked,
- de_misc_masked);
+ irq_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables);
+ irq_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked);
if (IS_DISPLAY_VER(display, 11, 13)) {
u32 de_hpd_masked = 0;
u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
GEN11_DE_TBT_HOTPLUG_MASK;
- intel_display_irq_regs_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked,
- de_hpd_enables);
+ irq_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, de_hpd_enables);
}
}
+u32 xelpdp_pica_aux_mask(struct intel_display *display)
+{
+ u32 mask = XELPDP_AUX_TC_MASK;
+
+ if (DISPLAY_VER(display) >= 20)
+ mask |= XE2LPD_AUX_DDI_MASK;
+
+ return mask;
+}
+
static void mtp_irq_postinstall(struct intel_display *display)
{
u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
- u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
+ u32 de_hpd_mask = xelpdp_pica_aux_mask(display);
u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
XELPDP_TBT_HOTPLUG_MASK;
- intel_display_irq_regs_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask,
- de_hpd_enables);
+ irq_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, de_hpd_enables);
- intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff);
+ irq_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff);
}
static void icp_irq_postinstall(struct intel_display *display)
{
u32 mask = SDE_GMBUS_ICP;
- intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff);
+ irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void gen11_de_irq_postinstall(struct intel_display *display)
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h b/drivers/gpu/drm/i915/display/intel_display_irq.h
index 84acd31948cf..b25d180254d7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.h
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.h
@@ -16,6 +16,8 @@ struct drm_printer;
struct intel_display;
struct intel_display_irq_snapshot;
+u32 xelpdp_pica_aux_mask(struct intel_display *display);
+
void valleyview_enable_display_irqs(struct intel_display *display);
void valleyview_disable_display_irqs(struct intel_display *display);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 2a4cc1dcc293..47042a4c3a30 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -8,10 +8,7 @@
#include <drm/drm_print.h>
-#include "soc/intel_dram.h"
-
#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_cdclk.h"
@@ -26,7 +23,9 @@
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dmc.h"
+#include "intel_dram.h"
#include "intel_mchbar_regs.h"
+#include "intel_parent.h"
#include "intel_pch_refclk.h"
#include "intel_pcode.h"
#include "intel_pmdemand.h"
@@ -545,8 +544,8 @@ __intel_display_power_get_domain(struct intel_display *display,
* Any power domain reference obtained by this function must have a symmetric
* call to intel_display_power_put() to release the reference again.
*/
-intel_wakeref_t intel_display_power_get(struct intel_display *display,
- enum intel_display_power_domain domain)
+struct ref_tracker *intel_display_power_get(struct intel_display *display,
+ enum intel_display_power_domain domain)
{
struct i915_power_domains *power_domains = &display->power.domains;
struct ref_tracker *wakeref;
@@ -572,7 +571,7 @@ intel_wakeref_t intel_display_power_get(struct intel_display *display,
* Any power domain reference obtained by this function must have a symmetric
* call to intel_display_power_put() to release the reference again.
*/
-intel_wakeref_t
+struct ref_tracker *
intel_display_power_get_if_enabled(struct intel_display *display,
enum intel_display_power_domain domain)
{
@@ -639,7 +638,7 @@ static void __intel_display_power_put(struct intel_display *display,
static void
queue_async_put_domains_work(struct i915_power_domains *power_domains,
- intel_wakeref_t wakeref,
+ struct ref_tracker *wakeref,
int delay_ms)
{
struct intel_display *display = container_of(power_domains,
@@ -741,7 +740,7 @@ out_verify:
*/
void __intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref,
+ struct ref_tracker *wakeref,
int delay_ms)
{
struct i915_power_domains *power_domains = &display->power.domains;
@@ -800,7 +799,7 @@ void intel_display_power_flush_work(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_power_domain_mask async_put_mask;
- intel_wakeref_t work_wakeref;
+ struct ref_tracker *work_wakeref;
mutex_lock(&power_domains->lock);
@@ -854,7 +853,7 @@ intel_display_power_flush_work_sync(struct intel_display *display)
*/
void intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref)
+ struct ref_tracker *wakeref)
{
__intel_display_power_put(display, domain);
intel_display_rpm_put(display, wakeref);
@@ -886,7 +885,7 @@ intel_display_power_get_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
- intel_wakeref_t __maybe_unused wf;
+ struct ref_tracker *__maybe_unused wf;
drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits));
@@ -902,7 +901,7 @@ intel_display_power_get_in_set_if_enabled(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
- intel_wakeref_t wf;
+ struct ref_tracker *wf;
drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits));
@@ -929,7 +928,7 @@ intel_display_power_put_mask_in_set(struct intel_display *display,
!bitmap_subset(mask->bits, power_domain_set->mask.bits, POWER_DOMAIN_NUM));
for_each_power_domain(domain, mask) {
- intel_wakeref_t __maybe_unused wf = INTEL_WAKEREF_DEF;
+ struct ref_tracker *__maybe_unused wf = INTEL_WAKEREF_DEF;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);
@@ -1202,7 +1201,6 @@ static void hsw_assert_cdclk(struct intel_display *display)
static void assert_can_disable_lcpll(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc)
@@ -1247,7 +1245,7 @@ static void assert_can_disable_lcpll(struct intel_display *display)
* gen-specific and since we only disable LCPLL after we fully disable
* the interrupts, the check below should be enough.
*/
- INTEL_DISPLAY_STATE_WARN(display, intel_irqs_enabled(dev_priv),
+ INTEL_DISPLAY_STATE_WARN(display, intel_parent_irq_enabled(display),
"IRQs enabled\n");
}
@@ -1341,10 +1339,10 @@ static void hsw_restore_lcpll(struct intel_display *display)
return;
/*
- * Make sure we're not on PC8 state before disabling PC8, otherwise
- * we'll hang the machine. To prevent PC8 state, just enable force_wake.
+ * Make sure we're not on PC8 state before disabling
+ * PC8, otherwise we'll hang the machine.
*/
- intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
+ intel_parent_pc8_block(display);
if (val & LCPLL_POWER_DOWN_ALLOW) {
val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -1374,7 +1372,7 @@ static void hsw_restore_lcpll(struct intel_display *display)
"Switching back to LCPLL failed\n");
}
- intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
+ intel_parent_pc8_unblock(display);
intel_update_cdclk(display);
intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
@@ -1417,8 +1415,6 @@ static void hsw_enable_pc8(struct intel_display *display)
static void hsw_disable_pc8(struct intel_display *display)
{
- struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm);
-
drm_dbg_kms(display->drm, "Disabling package C8+\n");
hsw_restore_lcpll(display);
@@ -1426,7 +1422,7 @@ static void hsw_disable_pc8(struct intel_display *display)
/* Many display registers don't survive PC8+ */
#ifdef I915 /* FIXME */
- intel_clock_gating_init(dev_priv);
+ intel_clock_gating_init(display->drm);
#endif
}
@@ -1618,7 +1614,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = {
static void tgl_bw_buddy_init(struct intel_display *display)
{
- const struct dram_info *dram_info = intel_dram_info(display->drm);
+ const struct dram_info *dram_info = intel_dram_info(display);
const struct buddy_page_mask *table;
unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask;
int config, i;
@@ -2006,7 +2002,7 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume)
*/
void intel_power_domains_driver_remove(struct intel_display *display)
{
- intel_wakeref_t wakeref __maybe_unused =
+ struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&display->power.domains.init_wakeref);
/* Remove the refcount we took to keep power well support disabled. */
@@ -2067,7 +2063,7 @@ void intel_power_domains_sanitize_state(struct intel_display *display)
*/
void intel_power_domains_enable(struct intel_display *display)
{
- intel_wakeref_t wakeref __maybe_unused =
+ struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&display->power.domains.init_wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
@@ -2106,7 +2102,7 @@ void intel_power_domains_disable(struct intel_display *display)
void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
{
struct i915_power_domains *power_domains = &display->power.domains;
- intel_wakeref_t wakeref __maybe_unused =
+ struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&power_domains->init_wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index f8813b0e16df..d616d5d09cbe 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -9,15 +9,17 @@
#include <linux/mutex.h>
#include <linux/workqueue.h>
-#include "intel_wakeref.h"
-
enum aux_ch;
enum port;
struct i915_power_well;
struct intel_display;
struct intel_encoder;
+struct ref_tracker;
struct seq_file;
+/* -ENOENT means we got the ref, but there's no tracking */
+#define INTEL_WAKEREF_DEF ERR_PTR(-ENOENT)
+
/*
* Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances
* consecutive, so that the pipe,transcoder,port -> power domain macros
@@ -142,14 +144,14 @@ struct i915_power_domains {
u32 target_dc_state;
u32 allowed_dc_mask;
- intel_wakeref_t init_wakeref;
- intel_wakeref_t disable_wakeref;
+ struct ref_tracker *init_wakeref;
+ struct ref_tracker *disable_wakeref;
struct mutex lock;
int domain_use_count[POWER_DOMAIN_NUM];
struct delayed_work async_put_work;
- intel_wakeref_t async_put_wakeref;
+ struct ref_tracker *async_put_wakeref;
struct intel_power_domain_mask async_put_domains[2];
int async_put_next_delay;
@@ -159,7 +161,7 @@ struct i915_power_domains {
struct intel_display_power_domain_set {
struct intel_power_domain_mask mask;
#ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM
- intel_wakeref_t wakerefs[POWER_DOMAIN_NUM];
+ struct ref_tracker *wakerefs[POWER_DOMAIN_NUM];
#endif
};
@@ -187,24 +189,24 @@ u32 intel_display_power_get_current_dc_state(struct intel_display *display);
bool intel_display_power_is_enabled(struct intel_display *display,
enum intel_display_power_domain domain);
-intel_wakeref_t intel_display_power_get(struct intel_display *display,
- enum intel_display_power_domain domain);
-intel_wakeref_t
+struct ref_tracker *intel_display_power_get(struct intel_display *display,
+ enum intel_display_power_domain domain);
+struct ref_tracker *
intel_display_power_get_if_enabled(struct intel_display *display,
enum intel_display_power_domain domain);
void __intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref,
+ struct ref_tracker *wakeref,
int delay_ms);
void intel_display_power_flush_work(struct intel_display *display);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
void intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref);
+ struct ref_tracker *wakeref);
static inline void
intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref)
+ struct ref_tracker *wakeref)
{
__intel_display_power_put_async(display, domain, wakeref, -1);
}
@@ -212,7 +214,7 @@ intel_display_power_put_async(struct intel_display *display,
static inline void
intel_display_power_put_async_delay(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref,
+ struct ref_tracker *wakeref,
int delay_ms)
{
__intel_display_power_put_async(display, domain, wakeref, delay_ms);
@@ -224,7 +226,7 @@ void intel_display_power_put_unchecked(struct intel_display *display,
static inline void
intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref)
+ struct ref_tracker *wakeref)
{
intel_display_power_put_unchecked(display, domain);
}
@@ -232,7 +234,7 @@ intel_display_power_put(struct intel_display *display,
static inline void
intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref)
+ struct ref_tracker *wakeref)
{
__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, -1);
}
@@ -240,7 +242,7 @@ intel_display_power_put_async(struct intel_display *display,
static inline void
intel_display_power_put_async_delay(struct intel_display *display,
enum intel_display_power_domain domain,
- intel_wakeref_t wakeref,
+ struct ref_tracker *wakeref,
int delay_ms)
{
__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, delay_ms);
@@ -297,12 +299,18 @@ enum dbuf_slice {
void gen9_dbuf_slices_update(struct intel_display *display,
u8 req_slices);
-#define with_intel_display_power(display, domain, wf) \
- for ((wf) = intel_display_power_get((display), (domain)); (wf); \
+#define __with_intel_display_power(display, domain, wf) \
+ for (struct ref_tracker *(wf) = intel_display_power_get((display), (domain)); (wf); \
intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
-#define with_intel_display_power_if_enabled(display, domain, wf) \
- for ((wf) = intel_display_power_get_if_enabled((display), (domain)); (wf); \
+#define with_intel_display_power(display, domain) \
+ __with_intel_display_power(display, domain, __UNIQUE_ID(wakeref))
+
+#define __with_intel_display_power_if_enabled(display, domain, wf) \
+ for (struct ref_tracker *(wf) = intel_display_power_get_if_enabled((display), (domain)); (wf); \
intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
+#define with_intel_display_power_if_enabled(display, domain) \
+ __with_intel_display_power_if_enabled(display, domain, __UNIQUE_ID(wakeref))
+
#endif /* __INTEL_DISPLAY_POWER_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index f4f7e73acc87..db185a859133 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -7,8 +7,6 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_combo_phy.h"
@@ -28,6 +26,7 @@
#include "intel_dpio_phy.h"
#include "intel_dpll.h"
#include "intel_hotplug.h"
+#include "intel_parent.h"
#include "intel_pcode.h"
#include "intel_pps.h"
#include "intel_psr.h"
@@ -258,8 +257,9 @@ aux_ch_to_digital_port(struct intel_display *display,
return NULL;
}
-static enum phy icl_aux_pw_to_phy(struct intel_display *display,
- const struct i915_power_well *power_well)
+static struct intel_encoder *
+icl_aux_pw_to_encoder(struct intel_display *display,
+ const struct i915_power_well *power_well)
{
enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
struct intel_digital_port *dig_port = aux_ch_to_digital_port(display, aux_ch);
@@ -271,7 +271,23 @@ static enum phy icl_aux_pw_to_phy(struct intel_display *display,
* as HDMI-only and routed to a combo PHY, the encoder either won't be
* present at all or it will not have an aux_ch assigned.
*/
- return dig_port ? intel_encoder_to_phy(&dig_port->base) : PHY_NONE;
+ return dig_port ? &dig_port->base : NULL;
+}
+
+static enum phy icl_aux_pw_to_phy(struct intel_display *display,
+ const struct i915_power_well *power_well)
+{
+ struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
+
+ return encoder ? intel_encoder_to_phy(encoder) : PHY_NONE;
+}
+
+static bool icl_aux_pw_is_tc_phy(struct intel_display *display,
+ const struct i915_power_well *power_well)
+{
+ struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
+
+ return encoder && intel_encoder_is_tc(encoder);
}
static void hsw_wait_for_power_well_enable(struct intel_display *display,
@@ -570,9 +586,7 @@ static void
icl_aux_power_well_enable(struct intel_display *display,
struct i915_power_well *power_well)
{
- enum phy phy = icl_aux_pw_to_phy(display, power_well);
-
- if (intel_phy_is_tc(display, phy))
+ if (icl_aux_pw_is_tc_phy(display, power_well))
return icl_tc_phy_aux_power_well_enable(display, power_well);
else if (display->platform.icelake)
return icl_combo_phy_aux_power_well_enable(display,
@@ -585,9 +599,7 @@ static void
icl_aux_power_well_disable(struct intel_display *display,
struct i915_power_well *power_well)
{
- enum phy phy = icl_aux_pw_to_phy(display, power_well);
-
- if (intel_phy_is_tc(display, phy))
+ if (icl_aux_pw_is_tc_phy(display, power_well))
return hsw_power_well_disable(display, power_well);
else if (display->platform.icelake)
return icl_combo_phy_aux_power_well_disable(display,
@@ -628,8 +640,6 @@ static bool hsw_power_well_enabled(struct intel_display *display,
static void assert_can_enable_dc9(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
-
drm_WARN_ONCE(display->drm,
(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC9),
"DC9 already programmed to be enabled.\n");
@@ -641,7 +651,7 @@ static void assert_can_enable_dc9(struct intel_display *display)
intel_de_read(display, HSW_PWR_WELL_CTL2) &
HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2),
"Power well 2 on.\n");
- drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv),
+ drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display),
"Interrupts not disabled yet.\n");
/*
@@ -655,9 +665,7 @@ static void assert_can_enable_dc9(struct intel_display *display)
static void assert_can_disable_dc9(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
-
- drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv),
+ drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display),
"Interrupts not disabled yet.\n");
drm_WARN_ONCE(display->drm,
intel_de_read(display, DC_STATE_EN) &
@@ -1281,12 +1289,10 @@ static void vlv_display_power_well_init(struct intel_display *display)
static void vlv_display_power_well_deinit(struct intel_display *display)
{
- struct drm_i915_private *dev_priv = to_i915(display->drm);
-
valleyview_disable_display_irqs(display);
/* make sure we're done processing display irqs */
- intel_synchronize_irq(dev_priv);
+ intel_parent_irq_synchronize(display);
vlv_pps_reset_all(display);
@@ -1852,7 +1858,7 @@ static void xelpdp_aux_power_well_enable(struct intel_display *display,
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
enum phy phy = icl_aux_pw_to_phy(display, power_well);
- if (intel_phy_is_tc(display, phy))
+ if (icl_aux_pw_is_tc_phy(display, power_well))
icl_tc_port_assert_ref_held(display, power_well,
aux_ch_to_digital_port(display, aux_ch));
@@ -1860,19 +1866,19 @@ static void xelpdp_aux_power_well_enable(struct intel_display *display,
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST);
- /*
- * The power status flag cannot be used to determine whether aux
- * power wells have finished powering up. Instead we're
- * expected to just wait a fixed 600us after raising the request
- * bit.
- */
- if (DISPLAY_VER(display) >= 35) {
+ if (HAS_LT_PHY(display)) {
if (intel_de_wait_for_set_ms(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch),
XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 2))
drm_warn(display->drm,
"Timeout waiting for PHY %c AUX channel power to be up\n",
phy_name(phy));
} else {
+ /*
+ * The power status flag cannot be used to determine whether aux
+ * power wells have finished powering up. Instead we're
+ * expected to just wait a fixed 600us after raising the request
+ * bit.
+ */
usleep_range(600, 1200);
}
}
@@ -1887,7 +1893,7 @@ static void xelpdp_aux_power_well_disable(struct intel_display *display,
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
0);
- if (DISPLAY_VER(display) >= 35) {
+ if (HAS_LT_PHY(display)) {
if (intel_de_wait_for_clear_ms(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch),
XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 1))
drm_warn(display->drm,
diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
index 9d71e26a4fa2..9e0d853f4b61 100644
--- a/drivers/gpu/drm/i915/display/intel_display_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
@@ -882,6 +882,21 @@
#define PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK REG_GENMASK(2, 0) /* tgl+ */
#define PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id) REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
+#define _UNDERRUN_DBG1_A 0x70064
+#define _UNDERRUN_DBG1_B 0x71064
+#define UNDERRUN_DBG1(pipe) _MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
+#define UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK REG_GENMASK(29, 24)
+#define UNDERRUN_DDB_EMPTY_MASK REG_GENMASK(21, 16)
+#define UNDERRUN_DBUF_NOT_FILLED_MASK REG_GENMASK(13, 8)
+#define UNDERRUN_BELOW_WM0_MASK REG_GENMASK(5, 0)
+
+#define _UNDERRUN_DBG2_A 0x70068
+#define _UNDERRUN_DBG2_B 0x71068
+#define UNDERRUN_DBG2(pipe) _MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
+#define UNDERRUN_FRAME_LINE_COUNTERS_FROZEN REG_BIT(31)
+#define UNDERRUN_PIPE_FRAME_COUNT_MASK REG_GENMASK(30, 20)
+#define UNDERRUN_LINE_COUNT_MASK REG_GENMASK(19, 0)
+
#define DPINVGTT _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
#define DPINVGTT_EN_MASK_CHV REG_GENMASK(27, 16)
#define DPINVGTT_EN_MASK_VLV REG_GENMASK(23, 16)
@@ -1416,6 +1431,7 @@
#define GEN12_DCPR_STATUS_1 _MMIO(0x46440)
#define XELPDP_PMDEMAND_INFLIGHT_STATUS REG_BIT(26)
+#define XE3P_UNDERRUN_PKGC REG_BIT(21)
#define FUSE_STRAP _MMIO(0x42014)
#define ILK_INTERNAL_GRAPHICS_DISABLE REG_BIT(31)
@@ -2349,8 +2365,13 @@ enum skl_power_gate {
#define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6)
#define DDI_A_4_LANES REG_BIT(4)
#define DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1)
+#define DDI_PORT_WIDTH_ENCODE(width) ((width) == 3 ? 4 : (width) - 1)
+#define DDI_PORT_WIDTH_DECODE(regval) ((regval) == 4 ? 3 : (regval) + 1)
#define DDI_PORT_WIDTH(width) REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, \
- ((width) == 3 ? 4 : (width) - 1))
+ DDI_PORT_WIDTH_ENCODE(width))
+#define DDI_PORT_WIDTH_GET(regval) DDI_PORT_WIDTH_DECODE(REG_FIELD_GET(DDI_PORT_WIDTH_MASK, \
+ (regval)))
+
#define DDI_PORT_WIDTH_SHIFT 1
#define DDI_INIT_DISPLAY_DETECTED REG_BIT(0)
diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c
index 03e8c68d2913..d00ef5bdcbda 100644
--- a/drivers/gpu/drm/i915/display/intel_display_reset.c
+++ b/drivers/gpu/drm/i915/display/intel_display_reset.c
@@ -6,13 +6,13 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_print.h>
-#include "i915_drv.h"
#include "intel_clock_gating.h"
#include "intel_cx0_phy.h"
#include "intel_display_core.h"
#include "intel_display_driver.h"
#include "intel_display_reset.h"
#include "intel_display_types.h"
+#include "intel_display_utils.h"
#include "intel_hotplug.h"
#include "intel_pps.h"
@@ -79,7 +79,6 @@ bool intel_display_reset_prepare(struct intel_display *display,
void intel_display_reset_finish(struct intel_display *display, bool test_only)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_modeset_acquire_ctx *ctx = &display->restore.reset_ctx;
struct drm_atomic_state *state;
int ret;
@@ -107,7 +106,7 @@ void intel_display_reset_finish(struct intel_display *display, bool test_only)
*/
intel_pps_unlock_regs_wa(display);
intel_display_driver_init_hw(display);
- intel_clock_gating_init(i915);
+ intel_clock_gating_init(display->drm);
intel_cx0_pll_power_save_wa(display);
intel_hpd_init(display);
diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c
index 82ea1ec482e4..e77811396474 100644
--- a/drivers/gpu/drm/i915/display/intel_display_rps.c
+++ b/drivers/gpu/drm/i915/display/intel_display_rps.c
@@ -3,38 +3,39 @@
* Copyright © 2023 Intel Corporation
*/
+#include <linux/dma-fence.h>
+
#include <drm/drm_crtc.h>
#include <drm/drm_vblank.h>
-#include "gt/intel_rps.h"
-#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_irq.h"
#include "intel_display_rps.h"
#include "intel_display_types.h"
+#include "intel_parent.h"
struct wait_rps_boost {
struct wait_queue_entry wait;
struct drm_crtc *crtc;
- struct i915_request *request;
+ struct dma_fence *fence;
};
static int do_rps_boost(struct wait_queue_entry *_wait,
unsigned mode, int sync, void *key)
{
struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait);
- struct i915_request *rq = wait->request;
+ struct intel_display *display = to_intel_display(wait->crtc->dev);
/*
* If we missed the vblank, but the request is already running it
* is reasonable to assume that it will complete before the next
- * vblank without our intervention, so leave RPS alone.
+ * vblank without our intervention, so leave RPS alone if not started.
*/
- if (!i915_request_started(rq))
- intel_rps_boost(rq);
- i915_request_put(rq);
+ intel_parent_rps_boost_if_not_started(display, wait->fence);
+
+ dma_fence_put(wait->fence);
drm_crtc_vblank_put(wait->crtc);
@@ -49,7 +50,7 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
struct intel_display *display = to_intel_display(crtc->dev);
struct wait_rps_boost *wait;
- if (!dma_fence_is_i915(fence))
+ if (!intel_parent_rps_available(display))
return;
if (DISPLAY_VER(display) < 6)
@@ -64,7 +65,7 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
return;
}
- wait->request = to_request(dma_fence_get(fence));
+ wait->fence = dma_fence_get(fence);
wait->crtc = crtc;
wait->wait.func = do_rps_boost;
@@ -77,12 +78,14 @@ void intel_display_rps_mark_interactive(struct intel_display *display,
struct intel_atomic_state *state,
bool interactive)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
+ if (!intel_parent_rps_available(display))
+ return;
if (state->rps_interactive == interactive)
return;
- intel_rps_mark_interactive(&to_gt(i915)->rps, interactive);
+ intel_parent_rps_mark_interactive(display, interactive);
+
state->rps_interactive = interactive;
}
@@ -102,7 +105,5 @@ void ilk_display_rps_disable(struct intel_display *display)
void ilk_display_rps_irq_handler(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
- gen5_rps_irq_handler(&to_gt(i915)->rps);
+ intel_parent_rps_ilk_irq_handler(display);
}
diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.h b/drivers/gpu/drm/i915/display/intel_display_rps.h
index 183d154f2c7c..96b1fd00ead4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_rps.h
+++ b/drivers/gpu/drm/i915/display/intel_display_rps.h
@@ -13,7 +13,6 @@ struct drm_crtc;
struct intel_atomic_state;
struct intel_display;
-#ifdef I915
void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
struct dma_fence *fence);
void intel_display_rps_mark_interactive(struct intel_display *display,
@@ -22,25 +21,5 @@ void intel_display_rps_mark_interactive(struct intel_display *display,
void ilk_display_rps_enable(struct intel_display *display);
void ilk_display_rps_disable(struct intel_display *display);
void ilk_display_rps_irq_handler(struct intel_display *display);
-#else
-static inline void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
- struct dma_fence *fence)
-{
-}
-static inline void intel_display_rps_mark_interactive(struct intel_display *display,
- struct intel_atomic_state *state,
- bool interactive)
-{
-}
-static inline void ilk_display_rps_enable(struct intel_display *display)
-{
-}
-static inline void ilk_display_rps_disable(struct intel_display *display)
-{
-}
-static inline void ilk_display_rps_irq_handler(struct intel_display *display)
-{
-}
-#endif
#endif /* __INTEL_DISPLAY_RPS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 06bf8f7c0989..6ff53cd58052 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -509,6 +509,12 @@ struct intel_hdcp {
bool force_hdcp14;
};
+enum intel_panel_replay_dsc_support {
+ INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED,
+ INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY,
+ INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE,
+};
+
struct intel_connector {
struct drm_connector base;
/*
@@ -561,6 +567,30 @@ struct intel_connector {
} overall_throughput;
int max_line_width;
} dsc_branch_caps;
+
+ struct {
+ u8 dpcd[DP_PANEL_REPLAY_CAP_SIZE];
+#define INTEL_PR_DPCD_INDEX(pr_dpcd_register) ((pr_dpcd_register) - DP_PANEL_REPLAY_CAP_SUPPORT)
+
+ bool support;
+ bool su_support;
+ enum intel_panel_replay_dsc_support dsc_support;
+
+ u16 su_w_granularity;
+ u16 su_y_granularity;
+ } panel_replay_caps;
+
+ struct {
+ u8 dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
+
+ bool support;
+ bool su_support;
+
+ u16 su_w_granularity;
+ u16 su_y_granularity;
+
+ u8 sync_latency;
+ } psr_caps;
} dp;
struct {
@@ -955,12 +985,6 @@ struct intel_csc_matrix {
u16 postoff[3];
};
-enum intel_panel_replay_dsc_support {
- INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED,
- INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY,
- INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE,
-};
-
struct scaler_filter_coeff {
u16 sign;
u16 exp;
@@ -1152,6 +1176,8 @@ struct intel_crtc_state {
bool enable_psr2_su_region_et;
bool req_psr2_sdp_prior_scanline;
bool has_panel_replay;
+ bool link_off_after_as_sdp_when_pr_active;
+ bool disable_as_sdp_when_pr_active;
bool wm_level_disabled;
bool pkg_c_latency_used;
/* Only used for state verification. */
@@ -1662,7 +1688,7 @@ struct intel_pps {
unsigned long last_power_on;
unsigned long last_backlight_off;
ktime_t panel_power_off_time;
- intel_wakeref_t vdd_wakeref;
+ struct ref_tracker *vdd_wakeref;
union {
/*
@@ -1716,14 +1742,12 @@ struct intel_psr {
bool active;
struct work_struct work;
unsigned int busy_frontbuffer_bits;
- bool sink_psr2_support;
bool link_standby;
bool sel_update_enabled;
bool psr2_sel_fetch_enabled;
bool psr2_sel_fetch_cff_enabled;
bool su_region_et_enabled;
bool req_psr2_sdp_prior_scanline;
- u8 sink_sync_latency;
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1732,8 +1756,6 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
- bool sink_panel_replay_su_support;
- enum intel_panel_replay_dsc_support sink_panel_replay_dsc_support;
bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
@@ -1760,9 +1782,6 @@ struct intel_dp {
bool needs_modeset_retry;
bool use_max_params;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
- u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
- u8 pr_dpcd[DP_PANEL_REPLAY_CAP_SIZE];
-#define INTEL_PR_DPCD_INDEX(pr_dpcd_register) ((pr_dpcd_register) - DP_PANEL_REPLAY_CAP_SUPPORT)
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
@@ -1940,12 +1959,13 @@ struct intel_digital_port {
bool lane_reversal;
bool ddi_a_4_lanes;
bool release_cl2_override;
+ bool dedicated_external;
u8 max_lanes;
/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
enum aux_ch aux_ch;
enum intel_display_power_domain ddi_io_power_domain;
- intel_wakeref_t ddi_io_wakeref;
- intel_wakeref_t aux_wakeref;
+ struct ref_tracker *ddi_io_wakeref;
+ struct ref_tracker *aux_wakeref;
struct intel_tc_port *tc;
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c
index e38e5e87877c..a00af39f7538 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.c
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.c
@@ -70,6 +70,10 @@ bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa,
return DISPLAY_VER(display) == 13;
case INTEL_DISPLAY_WA_22014263786:
return IS_DISPLAY_VERx100(display, 1100, 1400);
+ case INTEL_DISPLAY_WA_15018326506:
+ return display->platform.battlemage;
+ case INTEL_DISPLAY_WA_14025769978:
+ return DISPLAY_VER(display) == 35;
default:
drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name);
break;
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h
index 3644e8e2b724..a68c0bb7e516 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.h
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.h
@@ -26,6 +26,8 @@ enum intel_display_wa {
INTEL_DISPLAY_WA_16025573575,
INTEL_DISPLAY_WA_14011503117,
INTEL_DISPLAY_WA_22014263786,
+ INTEL_DISPLAY_WA_15018326506,
+ INTEL_DISPLAY_WA_14025769978,
};
bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name);
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 6ebbd97e6351..2fb6fec6dc99 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -1322,7 +1322,7 @@ static void intel_dmc_runtime_pm_get(struct intel_display *display)
static void intel_dmc_runtime_pm_put(struct intel_display *display)
{
- intel_wakeref_t wakeref __maybe_unused =
+ struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&display->dmc.wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 0ec82fcbcf48..2dadbf7e8922 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -424,18 +424,44 @@ static int intel_dp_min_lane_count(struct intel_dp *intel_dp)
return 1;
}
+int intel_dp_link_bw_overhead(int link_clock, int lane_count, int hdisplay,
+ int dsc_slice_count, int bpp_x16, unsigned long flags)
+{
+ int overhead;
+
+ WARN_ON(flags & ~(DRM_DP_BW_OVERHEAD_MST | DRM_DP_BW_OVERHEAD_SSC_REF_CLK |
+ DRM_DP_BW_OVERHEAD_FEC));
+
+ if (drm_dp_is_uhbr_rate(link_clock))
+ flags |= DRM_DP_BW_OVERHEAD_UHBR;
+
+ if (dsc_slice_count)
+ flags |= DRM_DP_BW_OVERHEAD_DSC;
+
+ overhead = drm_dp_bw_overhead(lane_count, hdisplay,
+ dsc_slice_count,
+ bpp_x16,
+ flags);
+
+ /*
+ * TODO: clarify whether a minimum required by the fixed FEC overhead
+ * in the bspec audio programming sequence is required here.
+ */
+ return max(overhead, intel_dp_bw_fec_overhead(flags & DRM_DP_BW_OVERHEAD_FEC));
+}
+
/*
* The required data bandwidth for a mode with given pixel clock and bpp. This
* is the required net bandwidth independent of the data bandwidth efficiency.
- *
- * TODO: check if callers of this functions should use
- * intel_dp_effective_data_rate() instead.
*/
-int
-intel_dp_link_required(int pixel_clock, int bpp)
+int intel_dp_link_required(int link_clock, int lane_count,
+ int mode_clock, int mode_hdisplay,
+ int link_bpp_x16, unsigned long bw_overhead_flags)
{
- /* pixel_clock is in kHz, divide bpp by 8 for bit to Byte conversion */
- return DIV_ROUND_UP(pixel_clock * bpp, 8);
+ int bw_overhead = intel_dp_link_bw_overhead(link_clock, lane_count, mode_hdisplay,
+ 0, link_bpp_x16, bw_overhead_flags);
+
+ return intel_dp_effective_data_rate(mode_clock, link_bpp_x16, bw_overhead);
}
/**
@@ -520,7 +546,8 @@ static int mtl_max_source_rate(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- if (intel_encoder_is_c10phy(encoder))
+ if (intel_encoder_is_c10phy(encoder) ||
+ display->platform.pantherlake_wildcatlake)
return 810000;
if (DISPLAY_VERx100(display) == 1401)
@@ -1013,6 +1040,8 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int num_joined_pipes)
{
struct intel_display *display = to_intel_display(connector);
+ u32 sink_slice_count_mask =
+ drm_dp_dsc_sink_slice_count_mask(connector->dp.dsc_dpcd, false);
u8 min_slice_count, i;
int max_slice_width;
int tp_rgb_yuv444;
@@ -1084,9 +1113,9 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
(!HAS_DSC_3ENGINES(display) || num_joined_pipes != 4))
continue;
- if (test_slice_count >
- drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
- break;
+ if (!(drm_dp_dsc_slice_count_to_mask(test_slice_count) &
+ sink_slice_count_mask))
+ continue;
/*
* Bigjoiner needs small joiner to be enabled.
@@ -1103,8 +1132,14 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
return test_slice_count;
}
- drm_dbg_kms(display->drm, "Unsupported Slice Count %d\n",
- min_slice_count);
+ /* Print slice count 1,2,4,..24 if bit#0,1,3,..23 is set in the mask. */
+ sink_slice_count_mask <<= 1;
+ drm_dbg_kms(display->drm,
+ "[CONNECTOR:%d:%s] Unsupported slice count (min: %d, sink supported: %*pbl)\n",
+ connector->base.base.id, connector->base.name,
+ min_slice_count,
+ (int)BITS_PER_TYPE(sink_slice_count_mask), &sink_slice_count_mask);
+
return 0;
}
@@ -1226,7 +1261,7 @@ int intel_dp_min_bpp(enum intel_output_format output_format)
return 8 * 3;
}
-int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
+int intel_dp_output_format_link_bpp_x16(enum intel_output_format output_format, int pipe_bpp)
{
/*
* bpp value was assumed to RGB format. And YCbCr 4:2:0 output
@@ -1234,9 +1269,9 @@ int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
* of bytes of RGB pixel.
*/
if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
- bpp /= 2;
+ pipe_bpp /= 2;
- return bpp;
+ return fxp_q4_from_int(pipe_bpp);
}
static enum intel_output_format
@@ -1252,8 +1287,8 @@ intel_dp_sink_format(struct intel_connector *connector,
}
static int
-intel_dp_mode_min_output_bpp(struct intel_connector *connector,
- const struct drm_display_mode *mode)
+intel_dp_mode_min_link_bpp_x16(struct intel_connector *connector,
+ const struct drm_display_mode *mode)
{
enum intel_output_format output_format, sink_format;
@@ -1261,7 +1296,8 @@ intel_dp_mode_min_output_bpp(struct intel_connector *connector,
output_format = intel_dp_output_format(connector, sink_format);
- return intel_dp_output_bpp(output_format, intel_dp_min_bpp(output_format));
+ return intel_dp_output_format_link_bpp_x16(output_format,
+ intel_dp_min_bpp(output_format));
}
static bool intel_dp_hdisplay_bad(struct intel_display *display,
@@ -1333,11 +1369,11 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
/* If PCON supports FRL MODE, check FRL bandwidth constraints */
if (intel_dp->dfp.pcon_max_frl_bw) {
+ int link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode);
int target_bw;
int max_frl_bw;
- int bpp = intel_dp_mode_min_output_bpp(connector, mode);
- target_bw = bpp * target_clock;
+ target_bw = fxp_q4_to_int_roundup(link_bpp_x16) * target_clock;
max_frl_bw = intel_dp->dfp.pcon_max_frl_bw;
@@ -1452,6 +1488,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
enum drm_mode_status status;
bool dsc = false;
int num_joined_pipes;
+ int link_bpp_x16;
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
@@ -1494,8 +1531,10 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_rate = intel_dp_max_link_data_rate(intel_dp, max_link_clock, max_lanes);
- mode_rate = intel_dp_link_required(target_clock,
- intel_dp_mode_min_output_bpp(connector, mode));
+ link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode);
+ mode_rate = intel_dp_link_required(max_link_clock, max_lanes,
+ target_clock, mode->hdisplay,
+ link_bpp_x16, 0);
if (intel_dp_has_dsc(connector)) {
int pipe_bpp;
@@ -1802,14 +1841,13 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
const struct link_config_limits *limits)
{
int bpp, i, lane_count, clock = intel_dp_mode_clock(pipe_config, conn_state);
- int mode_rate, link_rate, link_avail;
+ int link_rate, link_avail;
for (bpp = fxp_q4_to_int(limits->link.max_bpp_x16);
bpp >= fxp_q4_to_int(limits->link.min_bpp_x16);
bpp -= 2 * 3) {
- int link_bpp = intel_dp_output_bpp(pipe_config->output_format, bpp);
-
- mode_rate = intel_dp_link_required(clock, link_bpp);
+ int link_bpp_x16 =
+ intel_dp_output_format_link_bpp_x16(pipe_config->output_format, bpp);
for (i = 0; i < intel_dp->num_common_rates; i++) {
link_rate = intel_dp_common_rate(intel_dp, i);
@@ -1820,11 +1858,17 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
for (lane_count = limits->min_lane_count;
lane_count <= limits->max_lane_count;
lane_count <<= 1) {
+ const struct drm_display_mode *adjusted_mode =
+ &pipe_config->hw.adjusted_mode;
+ int mode_rate =
+ intel_dp_link_required(link_rate, lane_count,
+ clock, adjusted_mode->hdisplay,
+ link_bpp_x16, 0);
+
link_avail = intel_dp_max_link_data_rate(intel_dp,
link_rate,
lane_count);
-
if (mode_rate <= link_avail) {
pipe_config->lane_count = lane_count;
pipe_config->pipe_bpp = bpp;
@@ -1982,17 +2026,21 @@ static bool intel_dp_dsc_supports_format(const struct intel_connector *connector
return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, sink_dsc_format);
}
-static bool is_bw_sufficient_for_dsc_config(int dsc_bpp_x16, u32 link_clock,
- u32 lane_count, u32 mode_clock,
- enum intel_output_format output_format,
- int timeslots)
+static bool is_bw_sufficient_for_dsc_config(struct intel_dp *intel_dp,
+ int link_clock, int lane_count,
+ int mode_clock, int mode_hdisplay,
+ int dsc_slice_count, int link_bpp_x16,
+ unsigned long bw_overhead_flags)
{
- u32 available_bw, required_bw;
+ int available_bw;
+ int required_bw;
- available_bw = (link_clock * lane_count * timeslots * 16) / 8;
- required_bw = dsc_bpp_x16 * (intel_dp_mode_to_fec_clock(mode_clock));
+ available_bw = intel_dp_max_link_data_rate(intel_dp, link_clock, lane_count);
+ required_bw = intel_dp_link_required(link_clock, lane_count,
+ mode_clock, mode_hdisplay,
+ link_bpp_x16, bw_overhead_flags);
- return available_bw > required_bw;
+ return available_bw >= required_bw;
}
static int dsc_compute_link_config(struct intel_dp *intel_dp,
@@ -2038,10 +2086,16 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp,
if (ret)
continue;
} else {
- if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate,
- lane_count, adjusted_mode->clock,
- pipe_config->output_format,
- timeslots))
+ unsigned long bw_overhead_flags =
+ pipe_config->fec_enable ? DRM_DP_BW_OVERHEAD_FEC : 0;
+
+ if (!is_bw_sufficient_for_dsc_config(intel_dp,
+ link_rate, lane_count,
+ adjusted_mode->crtc_clock,
+ adjusted_mode->hdisplay,
+ pipe_config->dsc.slice_count,
+ dsc_bpp_x16,
+ bw_overhead_flags))
continue;
}
@@ -2192,24 +2246,17 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
const struct intel_connector *connector = to_intel_connector(conn_state->connector);
- const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
- int output_bpp;
int min_bpp_x16, max_bpp_x16, bpp_step_x16;
- int dsc_joiner_max_bpp;
- int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
+ int link_bpp_x16;
int bpp_x16;
int ret;
- dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(display, adjusted_mode->clock,
- adjusted_mode->hdisplay,
- num_joined_pipes);
- max_bpp_x16 = min(fxp_q4_from_int(dsc_joiner_max_bpp), limits->link.max_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 */
- output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp);
- max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16);
+ 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);
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);
@@ -2560,6 +2607,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
int throughput_max_bpp_x16;
+ int joiner_max_bpp;
dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp();
dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state);
@@ -2567,17 +2615,20 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
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 = dsc_sink_max_bpp ?
- min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp;
+ 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);
- throughput_max_bpp_x16 = clamp(throughput_max_bpp_x16,
- limits->link.min_bpp_x16, max_link_bpp_x16);
if (throughput_max_bpp_x16 < max_link_bpp_x16) {
max_link_bpp_x16 = throughput_max_bpp_x16;
@@ -2592,7 +2643,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
limits->link.max_bpp_x16 = max_link_bpp_x16;
drm_dbg_kms(display->drm,
- "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " FXP_Q4_FMT "\n",
+ "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d min link_bpp " FXP_Q4_FMT " max link_bpp " FXP_Q4_FMT "\n",
encoder->base.base.id, encoder->base.name,
crtc->base.base.id, crtc->base.name,
adjusted_mode->crtc_clock,
@@ -2600,21 +2651,40 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
limits->max_lane_count,
limits->max_rate,
limits->pipe.max_bpp,
+ FXP_Q4_ARGS(limits->link.min_bpp_x16),
FXP_Q4_ARGS(limits->link.max_bpp_x16));
+ if (limits->link.min_bpp_x16 <= 0 ||
+ limits->link.min_bpp_x16 > limits->link.max_bpp_x16)
+ return false;
+
return true;
}
-static void
-intel_dp_dsc_compute_pipe_bpp_limits(struct intel_dp *intel_dp,
+static bool
+intel_dp_dsc_compute_pipe_bpp_limits(struct intel_connector *connector,
struct link_config_limits *limits)
{
- struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_display *display = to_intel_display(connector);
+ const struct link_config_limits orig_limits = *limits;
int dsc_min_bpc = intel_dp_dsc_min_src_input_bpc();
int dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(display);
- limits->pipe.max_bpp = clamp(limits->pipe.max_bpp, dsc_min_bpc * 3, dsc_max_bpc * 3);
- limits->pipe.min_bpp = clamp(limits->pipe.min_bpp, dsc_min_bpc * 3, dsc_max_bpc * 3);
+ limits->pipe.min_bpp = max(limits->pipe.min_bpp, dsc_min_bpc * 3);
+ limits->pipe.max_bpp = min(limits->pipe.max_bpp, dsc_max_bpc * 3);
+
+ 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->base.base.id, connector->base.name,
+ dsc_min_bpc * 3, dsc_max_bpc * 3,
+ orig_limits.pipe.min_bpp, orig_limits.pipe.max_bpp);
+
+ return false;
+ }
+
+ return true;
}
bool
@@ -2654,8 +2724,8 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
respect_downstream_limits);
}
- if (dsc)
- intel_dp_dsc_compute_pipe_bpp_limits(intel_dp, limits);
+ if (dsc && !intel_dp_dsc_compute_pipe_bpp_limits(connector, limits))
+ return false;
if (is_mst || intel_dp->use_max_params) {
/*
@@ -2686,11 +2756,13 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
- int bpp = crtc_state->dsc.compression_enable ?
- fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) :
- crtc_state->pipe_bpp;
+ int link_bpp_x16 = crtc_state->dsc.compression_enable ?
+ crtc_state->dsc.compressed_bpp_x16 :
+ fxp_q4_from_int(crtc_state->pipe_bpp);
- return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
+ return intel_dp_link_required(crtc_state->port_clock, crtc_state->lane_count,
+ adjusted_mode->crtc_clock, adjusted_mode->hdisplay,
+ link_bpp_x16, 0);
}
bool intel_dp_joiner_needs_dsc(struct intel_display *display,
@@ -3259,8 +3331,8 @@ int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state,
if (crtc_state->dsc.compression_enable)
link_bpp_x16 = crtc_state->dsc.compressed_bpp_x16;
else
- link_bpp_x16 = fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format,
- crtc_state->pipe_bpp));
+ link_bpp_x16 = intel_dp_output_format_link_bpp_x16(crtc_state->output_format,
+ crtc_state->pipe_bpp);
/* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */
hactive_sym_cycles = drm_dp_link_symbol_cycles(max_lane_count,
@@ -3370,8 +3442,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (pipe_config->dsc.compression_enable)
link_bpp_x16 = pipe_config->dsc.compressed_bpp_x16;
else
- link_bpp_x16 = fxp_q4_from_int(intel_dp_output_bpp(pipe_config->output_format,
- pipe_config->pipe_bpp));
+ link_bpp_x16 = intel_dp_output_format_link_bpp_x16(pipe_config->output_format,
+ pipe_config->pipe_bpp);
if (intel_dp->mso_link_count) {
int n = intel_dp->mso_link_count;
@@ -4562,7 +4634,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
* This has to be called after intel_dp->edp_dpcd is filled, PSR checks
* for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1]
*/
- intel_psr_init_dpcd(intel_dp);
+ intel_psr_init_dpcd(intel_dp, connector);
intel_edp_set_sink_rates(intel_dp);
intel_dp_set_max_sink_lane_count(intel_dp);
@@ -5791,9 +5863,8 @@ bool intel_digital_port_connected_locked(struct intel_encoder *encoder)
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool is_glitch_free = intel_tc_port_handles_hpd_glitches(dig_port);
bool is_connected = false;
- intel_wakeref_t wakeref;
- with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE) {
poll_timeout_us(is_connected = dig_port->connected(encoder),
is_connected || is_glitch_free,
30, 4000, false);
@@ -6049,10 +6120,19 @@ intel_dp_detect(struct drm_connector *_connector,
if (status == connector_status_disconnected) {
intel_dp_test_reset(intel_dp);
+ /*
+ * FIXME: Resetting these caps here cause
+ * state computation fail if the connector need to be
+ * modeset after sink disconnect. Move resetting them
+ * to where new sink is connected.
+ */
memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd));
+ memset(connector->dp.panel_replay_caps.dpcd, 0,
+ sizeof(connector->dp.panel_replay_caps.dpcd));
intel_dp->psr.sink_panel_replay_support = false;
- intel_dp->psr.sink_panel_replay_su_support = false;
- intel_dp->psr.sink_panel_replay_dsc_support =
+ connector->dp.panel_replay_caps.support = false;
+ connector->dp.panel_replay_caps.su_support = false;
+ connector->dp.panel_replay_caps.dsc_support =
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED;
intel_dp_mst_disconnect(intel_dp);
@@ -6075,7 +6155,7 @@ intel_dp_detect(struct drm_connector *_connector,
connector->base.epoch_counter++;
if (!intel_dp_is_edp(intel_dp))
- intel_psr_init_dpcd(intel_dp);
+ intel_psr_init_dpcd(intel_dp, connector);
intel_dp_detect_dsc_caps(intel_dp, connector);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 200a8b267f64..30eebb8cad6d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -117,7 +117,11 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
bool intel_dp_source_supports_tps3(struct intel_display *display);
bool intel_dp_source_supports_tps4(struct intel_display *display);
-int intel_dp_link_required(int pixel_clock, int bpp);
+int intel_dp_link_bw_overhead(int link_clock, int lane_count, int hdisplay,
+ int dsc_slice_count, int bpp_x16, unsigned long flags);
+int intel_dp_link_required(int link_clock, int lane_count,
+ int mode_clock, int mode_hdisplay,
+ int link_bpp_x16, unsigned long bw_overhead_flags);
int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
int bw_overhead);
int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
@@ -193,7 +197,8 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp);
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
-int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
+int intel_dp_output_format_link_bpp_x16(enum intel_output_format output_format,
+ int pipe_bpp);
bool intel_dp_compute_config_limits(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 809799f63e32..b20ec3e589fa 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -6,6 +6,7 @@
#include <drm/drm_print.h>
#include "intel_de.h"
+#include "intel_display_jiffies.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dp.h"
@@ -60,16 +61,17 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
const unsigned int timeout_ms = 10;
u32 status;
- int ret;
+ bool done;
- ret = intel_de_wait_ms(display, ch_ctl,
- DP_AUX_CH_CTL_SEND_BUSY, 0,
- timeout_ms, &status);
+#define C (((status = intel_de_read_notrace(display, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+ done = wait_event_timeout(display->gmbus.wait_queue, C,
+ msecs_to_jiffies_timeout(timeout_ms));
- if (ret == -ETIMEDOUT)
+ if (!done)
drm_err(display->drm,
"%s: did not complete or timeout within %ums (status 0x%08x)\n",
intel_dp->aux.name, timeout_ms, status);
+#undef C
return status;
}
@@ -245,8 +247,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
i915_reg_t ch_ctl, ch_data[5];
u32 aux_clock_divider;
enum intel_display_power_domain aux_domain;
- intel_wakeref_t aux_wakeref;
- intel_wakeref_t pps_wakeref = NULL;
+ struct ref_tracker *aux_wakeref;
+ struct ref_tracker *pps_wakeref = NULL;
int i, ret, recv_bytes;
int try, clock = 0;
u32 status;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index aad5fe14962f..54c585c59b90 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -1195,7 +1195,9 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
intel_panel_preferred_fixed_mode(intel_dp->attached_connector);
int mode_rate, max_rate;
- mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
+ mode_rate = intel_dp_link_required(link_rate, lane_count,
+ fixed_mode->clock, fixed_mode->hdisplay,
+ fxp_q4_from_int(18), 0);
max_rate = intel_dp_max_link_data_rate(intel_dp, link_rate, lane_count);
if (mode_rate > max_rate)
return false;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 4c0b943fe86f..0db6ed2d9664 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -180,26 +180,16 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
unsigned long flags = DRM_DP_BW_OVERHEAD_MST;
- int overhead;
- flags |= intel_dp_is_uhbr(crtc_state) ? DRM_DP_BW_OVERHEAD_UHBR : 0;
flags |= ssc ? DRM_DP_BW_OVERHEAD_SSC_REF_CLK : 0;
flags |= crtc_state->fec_enable ? DRM_DP_BW_OVERHEAD_FEC : 0;
- if (dsc_slice_count)
- flags |= DRM_DP_BW_OVERHEAD_DSC;
-
- overhead = drm_dp_bw_overhead(crtc_state->lane_count,
- adjusted_mode->hdisplay,
- dsc_slice_count,
- bpp_x16,
- flags);
-
- /*
- * TODO: clarify whether a minimum required by the fixed FEC overhead
- * in the bspec audio programming sequence is required here.
- */
- return max(overhead, intel_dp_bw_fec_overhead(crtc_state->fec_enable));
+ return intel_dp_link_bw_overhead(crtc_state->port_clock,
+ crtc_state->lane_count,
+ adjusted_mode->hdisplay,
+ dsc_slice_count,
+ bpp_x16,
+ flags);
}
static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state,
@@ -344,8 +334,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
}
link_bpp_x16 = dsc ? bpp_x16 :
- fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format,
- fxp_q4_to_int(bpp_x16)));
+ intel_dp_output_format_link_bpp_x16(crtc_state->output_format,
+ fxp_q4_to_int(bpp_x16));
local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state,
false, dsc_slice_count, link_bpp_x16);
@@ -1468,6 +1458,8 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
const int min_bpp = 18;
int max_dotclk = display->cdclk.max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
+ unsigned long bw_overhead_flags =
+ DRM_DP_BW_OVERHEAD_MST | DRM_DP_BW_OVERHEAD_SSC_REF_CLK;
int ret;
bool dsc = false;
u16 dsc_max_compressed_bpp = 0;
@@ -1499,7 +1491,10 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
max_rate = intel_dp_max_link_data_rate(intel_dp,
max_link_clock, max_lanes);
- mode_rate = intel_dp_link_required(mode->clock, min_bpp);
+ mode_rate = intel_dp_link_required(max_link_clock, max_lanes,
+ mode->clock, mode->hdisplay,
+ fxp_q4_from_int(min_bpp),
+ bw_overhead_flags);
/*
* TODO:
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 4f1db8493a2e..a4f372c9e6fc 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -1212,27 +1212,6 @@ static int dg2_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
-static int mtl_crtc_compute_clock(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
-{
- struct intel_crtc_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
- struct intel_encoder *encoder =
- intel_get_crtc_new_encoder(state, crtc_state);
- int ret;
-
- ret = intel_cx0pll_calc_state(crtc_state, encoder);
- if (ret)
- return ret;
-
- /* TODO: Do the readback via intel_dpll_compute() */
- crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll);
-
- crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state);
-
- return 0;
-}
-
static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1719,7 +1698,8 @@ static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = {
};
static const struct intel_dpll_global_funcs mtl_dpll_funcs = {
- .crtc_compute_clock = mtl_crtc_compute_clock,
+ .crtc_compute_clock = hsw_crtc_compute_clock,
+ .crtc_get_dpll = hsw_crtc_get_dpll,
};
static const struct intel_dpll_global_funcs dg2_dpll_funcs = {
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 9c7cf03cf022..9aa84a430f09 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -203,6 +203,22 @@ enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port)
return tc_port - TC_PORT_1 + DPLL_ID_ICL_MGPLL1;
}
+enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port)
+{
+ if (port >= PORT_TC1)
+ return icl_tc_port_to_pll_id(intel_port_to_tc(display, port));
+
+ switch (port) {
+ case PORT_A:
+ return DPLL_ID_ICL_DPLL0;
+ case PORT_B:
+ return DPLL_ID_ICL_DPLL1;
+ default:
+ MISSING_CASE(port);
+ return DPLL_ID_ICL_DPLL0;
+ }
+}
+
static i915_reg_t
intel_combo_pll_enable_reg(struct intel_display *display,
struct intel_dpll *pll)
@@ -531,7 +547,7 @@ static bool ibx_pch_dpll_get_hw_state(struct intel_display *display,
{
struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx;
const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 val;
wakeref = intel_display_power_get_if_enabled(display,
@@ -752,7 +768,7 @@ static bool hsw_ddi_wrpll_get_hw_state(struct intel_display *display,
{
struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw;
const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 val;
wakeref = intel_display_power_get_if_enabled(display,
@@ -773,7 +789,7 @@ static bool hsw_ddi_spll_get_hw_state(struct intel_display *display,
struct intel_dpll_hw_state *dpll_hw_state)
{
struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 val;
wakeref = intel_display_power_get_if_enabled(display,
@@ -1431,7 +1447,7 @@ static bool skl_ddi_pll_get_hw_state(struct intel_display *display,
struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl;
const struct skl_dpll_regs *regs = skl_dpll_regs;
const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
u32 val;
@@ -1469,7 +1485,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct intel_display *display,
struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl;
const struct skl_dpll_regs *regs = skl_dpll_regs;
const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 val;
bool ret;
@@ -2172,7 +2188,7 @@ static bool bxt_ddi_pll_get_hw_state(struct intel_display *display,
{
struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt;
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum dpio_phy phy;
enum dpio_channel ch;
u32 val;
@@ -3490,6 +3506,37 @@ err_unreference_tbt_pll:
return ret;
}
+/*
+ * Get the PLL for either a port using a C10 PHY PLL, or for a port using a
+ * C20 PHY PLL in the cases of:
+ * - BMG port A/B
+ * - PTL port B eDP over TypeC PHY
+ */
+static int mtl_get_non_tc_phy_dpll(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(crtc);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll =
+ &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ enum intel_dpll_id pll_id = mtl_port_to_pll_id(display, encoder->port);
+
+ port_dpll->pll = intel_find_dpll(state, crtc,
+ &port_dpll->hw_state,
+ BIT(pll_id));
+ if (!port_dpll->pll)
+ return -EINVAL;
+
+ intel_reference_dpll(state, crtc,
+ port_dpll->pll, &port_dpll->hw_state);
+
+ icl_update_active_dpll(state, crtc, encoder);
+
+ return 0;
+}
+
static int icl_compute_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
@@ -3551,7 +3598,7 @@ static bool mg_pll_get_hw_state(struct intel_display *display,
struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl;
const enum intel_dpll_id id = pll->info->id;
enum tc_port tc_port = icl_pll_id_to_tc_port(id);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret = false;
u32 val;
@@ -3618,7 +3665,7 @@ static bool dkl_pll_get_hw_state(struct intel_display *display,
struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl;
const enum intel_dpll_id id = pll->info->id;
enum tc_port tc_port = icl_pll_id_to_tc_port(id);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret = false;
u32 val;
@@ -3690,7 +3737,7 @@ static bool icl_pll_get_hw_state(struct intel_display *display,
{
struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl;
const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret = false;
u32 val;
@@ -3753,9 +3800,9 @@ static bool combo_pll_get_hw_state(struct intel_display *display,
return icl_pll_get_hw_state(display, pll, dpll_hw_state, enable_reg);
}
-static bool tbt_pll_get_hw_state(struct intel_display *display,
- struct intel_dpll *pll,
- struct intel_dpll_hw_state *dpll_hw_state)
+static bool icl_tbt_pll_get_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *dpll_hw_state)
{
return icl_pll_get_hw_state(display, pll, dpll_hw_state, TBT_PLL_ENABLE);
}
@@ -3984,9 +4031,9 @@ static void combo_pll_enable(struct intel_display *display,
/* DVFS post sequence would be here. See the comment above. */
}
-static void tbt_pll_enable(struct intel_display *display,
- struct intel_dpll *pll,
- const struct intel_dpll_hw_state *dpll_hw_state)
+static void icl_tbt_pll_enable(struct intel_display *display,
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
{
const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl;
@@ -4069,8 +4116,8 @@ static void combo_pll_disable(struct intel_display *display,
icl_pll_disable(display, pll, enable_reg);
}
-static void tbt_pll_disable(struct intel_display *display,
- struct intel_dpll *pll)
+static void icl_tbt_pll_disable(struct intel_display *display,
+ struct intel_dpll *pll)
{
icl_pll_disable(display, pll, TBT_PLL_ENABLE);
}
@@ -4142,10 +4189,10 @@ static const struct intel_dpll_funcs combo_pll_funcs = {
.get_freq = icl_ddi_combo_pll_get_freq,
};
-static const struct intel_dpll_funcs tbt_pll_funcs = {
- .enable = tbt_pll_enable,
- .disable = tbt_pll_disable,
- .get_hw_state = tbt_pll_get_hw_state,
+static const struct intel_dpll_funcs icl_tbt_pll_funcs = {
+ .enable = icl_tbt_pll_enable,
+ .disable = icl_tbt_pll_disable,
+ .get_hw_state = icl_tbt_pll_get_hw_state,
.get_freq = icl_ddi_tbt_pll_get_freq,
};
@@ -4159,7 +4206,7 @@ static const struct intel_dpll_funcs mg_pll_funcs = {
static const struct dpll_info icl_plls[] = {
{ .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
{ .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
+ { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
.is_alt_port_dpll = true, },
{ .name = "MG PLL 1", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
{ .name = "MG PLL 2", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
@@ -4207,7 +4254,7 @@ static const struct intel_dpll_funcs dkl_pll_funcs = {
static const struct dpll_info tgl_plls[] = {
{ .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
{ .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
+ { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
.is_alt_port_dpll = true, },
{ .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
{ .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
@@ -4285,7 +4332,7 @@ static const struct intel_dpll_mgr adls_pll_mgr = {
static const struct dpll_info adlp_plls[] = {
{ .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
{ .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
+ { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
.is_alt_port_dpll = true, },
{ .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
{ .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
@@ -4305,6 +4352,224 @@ static const struct intel_dpll_mgr adlp_pll_mgr = {
.compare_hw_state = icl_compare_hw_state,
};
+static struct intel_encoder *get_intel_encoder(struct intel_display *display,
+ const struct intel_dpll *pll)
+{
+ struct intel_encoder *encoder;
+ enum intel_dpll_id mtl_id;
+
+ for_each_intel_encoder(display->drm, encoder) {
+ mtl_id = mtl_port_to_pll_id(display, encoder->port);
+
+ if (mtl_id == pll->info->id)
+ return encoder;
+ }
+
+ return NULL;
+}
+
+static bool mtl_pll_get_hw_state(struct intel_display *display,
+ struct intel_dpll *pll,
+ struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (!encoder)
+ return false;
+
+ return intel_cx0pll_readout_hw_state(encoder, &dpll_hw_state->cx0pll);
+}
+
+static int mtl_pll_get_freq(struct intel_display *display,
+ const struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return -EINVAL;
+
+ return intel_cx0pll_calc_port_clock(encoder, &dpll_hw_state->cx0pll);
+}
+
+static void mtl_pll_enable(struct intel_display *display,
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return;
+
+ intel_mtl_pll_enable(encoder, pll, dpll_hw_state);
+}
+
+static void mtl_pll_disable(struct intel_display *display,
+ struct intel_dpll *pll)
+{
+ struct intel_encoder *encoder = get_intel_encoder(display, pll);
+
+ if (drm_WARN_ON(display->drm, !encoder))
+ return;
+
+ intel_mtl_pll_disable(encoder);
+}
+
+static const struct intel_dpll_funcs mtl_pll_funcs = {
+ .enable = mtl_pll_enable,
+ .disable = mtl_pll_disable,
+ .get_hw_state = mtl_pll_get_hw_state,
+ .get_freq = mtl_pll_get_freq,
+};
+
+static void mtl_tbt_pll_enable(struct intel_display *display,
+ struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *hw_state)
+{
+}
+
+static void mtl_tbt_pll_disable(struct intel_display *display,
+ struct intel_dpll *pll)
+{
+}
+
+static int mtl_tbt_pll_get_freq(struct intel_display *display,
+ const struct intel_dpll *pll,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ /*
+ * The PLL outputs multiple frequencies at the same time, selection is
+ * made at DDI clock mux level.
+ */
+ drm_WARN_ON(display->drm, 1);
+
+ return 0;
+}
+
+static const struct intel_dpll_funcs mtl_tbt_pll_funcs = {
+ .enable = mtl_tbt_pll_enable,
+ .disable = mtl_tbt_pll_disable,
+ .get_hw_state = intel_mtl_tbt_pll_readout_hw_state,
+ .get_freq = mtl_tbt_pll_get_freq,
+};
+
+static const struct dpll_info mtl_plls[] = {
+ { .name = "DPLL 0", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
+ { .name = "DPLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
+ { .name = "TBT PLL", .funcs = &mtl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
+ .is_alt_port_dpll = true, .always_on = true },
+ { .name = "TC PLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
+ { .name = "TC PLL 2", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
+ { .name = "TC PLL 3", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, },
+ { .name = "TC PLL 4", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL4, },
+ {}
+};
+
+/*
+ * Compute the state for either a C10 PHY PLL, or in the case of the PTL port B,
+ * eDP on TypeC PHY case for a C20 PHY PLL.
+ */
+static int mtl_compute_non_tc_phy_dpll(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll =
+ &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ int ret;
+
+ ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state);
+ if (ret)
+ return ret;
+
+ /* this is mainly for the fastset check */
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
+
+ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder,
+ &port_dpll->hw_state.cx0pll);
+
+ return 0;
+}
+
+static int mtl_compute_tc_phy_dplls(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll;
+ int ret;
+
+ port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ intel_mtl_tbt_pll_calc_state(&port_dpll->hw_state);
+
+ port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY];
+ ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state);
+ if (ret)
+ return ret;
+
+ /* this is mainly for the fastset check */
+ if (old_crtc_state->intel_dpll &&
+ old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL)
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
+ else
+ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY);
+
+ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder,
+ &port_dpll->hw_state.cx0pll);
+
+ return 0;
+}
+
+static int mtl_compute_dplls(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ if (intel_encoder_is_tc(encoder))
+ return mtl_compute_tc_phy_dplls(state, crtc, encoder);
+ else
+ return mtl_compute_non_tc_phy_dpll(state, crtc, encoder);
+}
+
+static int mtl_get_dplls(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+ if (intel_encoder_is_tc(encoder))
+ return icl_get_tc_phy_dplls(state, crtc, encoder);
+ else
+ return mtl_get_non_tc_phy_dpll(state, crtc, encoder);
+}
+
+static void mtl_dump_hw_state(struct drm_printer *p,
+ const struct intel_dpll_hw_state *dpll_hw_state)
+{
+ intel_cx0pll_dump_hw_state(p, &dpll_hw_state->cx0pll);
+}
+
+static bool mtl_compare_hw_state(const struct intel_dpll_hw_state *_a,
+ const struct intel_dpll_hw_state *_b)
+{
+ const struct intel_cx0pll_state *a = &_a->cx0pll;
+ const struct intel_cx0pll_state *b = &_b->cx0pll;
+
+ return intel_cx0pll_compare_hw_state(a, b);
+}
+
+static const struct intel_dpll_mgr mtl_pll_mgr = {
+ .dpll_info = mtl_plls,
+ .compute_dplls = mtl_compute_dplls,
+ .get_dplls = mtl_get_dplls,
+ .put_dplls = icl_put_dplls,
+ .update_active_dpll = icl_update_active_dpll,
+ .update_ref_clks = icl_update_dpll_ref_clks,
+ .dump_hw_state = mtl_dump_hw_state,
+ .compare_hw_state = mtl_compare_hw_state,
+};
+
/**
* intel_dpll_init - Initialize DPLLs
* @display: intel_display device
@@ -4319,9 +4584,11 @@ void intel_dpll_init(struct intel_display *display)
mutex_init(&display->dpll.lock);
- if (DISPLAY_VER(display) >= 14 || display->platform.dg2)
- /* No shared DPLLs on DG2; port PLLs are part of the PHY */
+ if (DISPLAY_VER(display) >= 35 || display->platform.dg2)
+ /* No shared DPLLs on NVL or DG2; port PLLs are part of the PHY */
dpll_mgr = NULL;
+ else if (DISPLAY_VER(display) >= 14)
+ dpll_mgr = &mtl_pll_mgr;
else if (display->platform.alderlake_p)
dpll_mgr = &adlp_pll_mgr;
else if (display->platform.alderlake_s)
@@ -4675,11 +4942,18 @@ verify_single_dpll_state(struct intel_display *display,
"%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
pll->info->name, pipe_mask, pll->state.pipe_mask);
- INTEL_DISPLAY_STATE_WARN(display,
- pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
- sizeof(dpll_hw_state)),
- "%s: pll hw state mismatch\n",
- pll->info->name);
+ if (INTEL_DISPLAY_STATE_WARN(display,
+ pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
+ sizeof(dpll_hw_state)),
+ "%s: pll hw state mismatch\n",
+ pll->info->name)) {
+ struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL);
+
+ drm_printf(&p, "PLL %s HW state:\n", pll->info->name);
+ intel_dpll_dump_hw_state(display, &p, &dpll_hw_state);
+ drm_printf(&p, "PLL %s SW state:\n", pll->info->name);
+ intel_dpll_dump_hw_state(display, &p, &pll->state.hw_state);
+ }
}
static bool has_alt_port_dpll(const struct intel_dpll *old_pll,
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 6183da90b28d..5b71c860515f 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -28,7 +28,6 @@
#include <linux/types.h>
#include "intel_display_power.h"
-#include "intel_wakeref.h"
#define for_each_dpll(__display, __pll, __i) \
for ((__i) = 0; (__i) < (__display)->dpll.num_dpll && \
@@ -42,6 +41,7 @@ struct intel_crtc_state;
struct intel_dpll_funcs;
struct intel_encoder;
struct intel_shared_dpll;
+struct ref_tracker;
/**
* enum intel_dpll_id - possible DPLL ids
@@ -255,6 +255,11 @@ struct intel_c20pll_state {
u16 mplla[10];
u16 mpllb[11];
};
+ struct intel_c20pll_vdr_state {
+ u8 custom_width;
+ u8 serdes_rate;
+ u8 hdmi_rate;
+ } vdr;
};
struct intel_cx0pll_state {
@@ -262,6 +267,7 @@ struct intel_cx0pll_state {
struct intel_c10pll_state c10;
struct intel_c20pll_state c20;
};
+ int lane_count;
bool ssc_enabled;
bool use_c10;
bool tbt_mode;
@@ -390,7 +396,7 @@ struct intel_dpll {
* @wakeref: In some platforms a device-level runtime pm reference may
* need to be grabbed to disable DC states while this DPLL is enabled
*/
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
};
#define SKL_DPLL0 0
@@ -444,6 +450,7 @@ bool intel_dpll_compare_hw_state(struct intel_display *display,
const struct intel_dpll_hw_state *a,
const struct intel_dpll_hw_state *b);
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);
+enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port);
bool intel_dpll_is_combophy(enum intel_dpll_id id);
void intel_dpll_state_verify(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c
index 3e588762709a..019a722a38bf 100644
--- a/drivers/gpu/drm/i915/soc/intel_dram.c
+++ b/drivers/gpu/drm/i915/display/intel_dram.c
@@ -8,11 +8,10 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
-#include "../display/intel_display_core.h" /* FIXME */
-
#include "i915_drv.h"
#include "i915_reg.h"
-#include "i915_utils.h"
+#include "intel_display_core.h"
+#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
@@ -57,14 +56,17 @@ const char *intel_dram_type_str(enum intel_dram_type type)
#undef DRAM_TYPE_STR
-static enum intel_dram_type pnv_dram_type(struct drm_i915_private *i915)
+static enum intel_dram_type pnv_dram_type(struct intel_display *display)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
+
return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2;
}
-static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv)
+static unsigned int pnv_mem_freq(struct intel_display *display)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 tmp;
tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG);
@@ -81,8 +83,9 @@ static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv)
return 0;
}
-static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv)
+static unsigned int ilk_mem_freq(struct intel_display *display)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
u16 ddrpll;
ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1);
@@ -96,19 +99,19 @@ static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv)
case 0x18:
return 1600000;
default:
- drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n",
- ddrpll & 0xff);
+ drm_dbg_kms(display->drm, "unknown memory frequency 0x%02x\n",
+ ddrpll & 0xff);
return 0;
}
}
-static unsigned int chv_mem_freq(struct drm_i915_private *i915)
+static unsigned int chv_mem_freq(struct intel_display *display)
{
u32 val;
- vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK));
- val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG);
- vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK));
+ vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK));
+ val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG);
+ vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK));
switch ((val >> 2) & 0x7) {
case 3:
@@ -118,13 +121,13 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915)
}
}
-static unsigned int vlv_mem_freq(struct drm_i915_private *i915)
+static unsigned int vlv_mem_freq(struct intel_display *display)
{
u32 val;
- vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT));
- val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS);
- vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT));
+ vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT));
+ val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS);
+ vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT));
switch ((val >> 6) & 3) {
case 0:
@@ -139,22 +142,23 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915)
return 0;
}
-unsigned int intel_mem_freq(struct drm_i915_private *i915)
+unsigned int intel_mem_freq(struct intel_display *display)
{
- if (IS_PINEVIEW(i915))
- return pnv_mem_freq(i915);
- else if (GRAPHICS_VER(i915) == 5)
- return ilk_mem_freq(i915);
- else if (IS_CHERRYVIEW(i915))
- return chv_mem_freq(i915);
- else if (IS_VALLEYVIEW(i915))
- return vlv_mem_freq(i915);
+ if (display->platform.pineview)
+ return pnv_mem_freq(display);
+ else if (DISPLAY_VER(display) == 5)
+ return ilk_mem_freq(display);
+ else if (display->platform.cherryview)
+ return chv_mem_freq(display);
+ else if (display->platform.valleyview)
+ return vlv_mem_freq(display);
else
return 0;
}
-static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915)
+static unsigned int i9xx_fsb_freq(struct intel_display *display)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
u32 fsb;
/*
@@ -167,7 +171,7 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915)
*/
fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK;
- if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) {
+ if (display->platform.pineview || display->platform.mobile) {
switch (fsb) {
case CLKCFG_FSB_400:
return 400000;
@@ -208,8 +212,9 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915)
}
}
-static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv)
+static unsigned int ilk_fsb_freq(struct intel_display *display)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
u16 fsb;
fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff;
@@ -230,33 +235,33 @@ static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv)
case 0x018:
return 6400000;
default:
- drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb);
+ drm_dbg_kms(display->drm, "unknown fsb frequency 0x%04x\n", fsb);
return 0;
}
}
-unsigned int intel_fsb_freq(struct drm_i915_private *i915)
+unsigned int intel_fsb_freq(struct intel_display *display)
{
- if (GRAPHICS_VER(i915) == 5)
- return ilk_fsb_freq(i915);
- else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4)
- return i9xx_fsb_freq(i915);
+ if (DISPLAY_VER(display) == 5)
+ return ilk_fsb_freq(display);
+ else if (IS_DISPLAY_VER(display, 3, 4))
+ return i9xx_fsb_freq(display);
else
return 0;
}
-static int i915_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+static int i915_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
- dram_info->fsb_freq = intel_fsb_freq(i915);
+ dram_info->fsb_freq = intel_fsb_freq(display);
if (dram_info->fsb_freq)
- drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq);
+ drm_dbg_kms(display->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq);
- dram_info->mem_freq = intel_mem_freq(i915);
+ dram_info->mem_freq = intel_mem_freq(display);
if (dram_info->mem_freq)
- drm_dbg(&i915->drm, "DDR speed: %d kHz\n", dram_info->mem_freq);
+ drm_dbg_kms(display->drm, "DDR speed: %d kHz\n", dram_info->mem_freq);
- if (IS_PINEVIEW(i915))
- dram_info->type = pnv_dram_type(i915);
+ if (display->platform.pineview)
+ dram_info->type = pnv_dram_type(display);
return 0;
}
@@ -267,69 +272,121 @@ static int intel_dimm_num_devices(const struct dram_dimm_info *dimm)
}
/* Returns total Gb for the whole DIMM */
-static int skl_get_dimm_size(u16 val)
+static int skl_get_dimm_s_size(u32 val)
+{
+ return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8;
+}
+
+static int skl_get_dimm_l_size(u32 val)
{
- return (val & SKL_DRAM_SIZE_MASK) * 8;
+ return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8;
}
-static int skl_get_dimm_width(u16 val)
+static int skl_get_dimm_s_width(u32 val)
{
- if (skl_get_dimm_size(val) == 0)
+ if (skl_get_dimm_s_size(val) == 0)
return 0;
- switch (val & SKL_DRAM_WIDTH_MASK) {
- case SKL_DRAM_WIDTH_X8:
- case SKL_DRAM_WIDTH_X16:
- case SKL_DRAM_WIDTH_X32:
- val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
- return 8 << val;
+ switch (val & SKL_DIMM_S_WIDTH_MASK) {
+ case SKL_DIMM_S_WIDTH_X8:
+ case SKL_DIMM_S_WIDTH_X16:
+ case SKL_DIMM_S_WIDTH_X32:
+ return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val);
default:
MISSING_CASE(val);
return 0;
}
}
-static int skl_get_dimm_ranks(u16 val)
+static int skl_get_dimm_l_width(u32 val)
{
- if (skl_get_dimm_size(val) == 0)
+ if (skl_get_dimm_l_size(val) == 0)
return 0;
- val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT;
+ switch (val & SKL_DIMM_L_WIDTH_MASK) {
+ case SKL_DIMM_L_WIDTH_X8:
+ case SKL_DIMM_L_WIDTH_X16:
+ case SKL_DIMM_L_WIDTH_X32:
+ return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val);
+ default:
+ MISSING_CASE(val);
+ return 0;
+ }
+}
+
+static int skl_get_dimm_s_ranks(u32 val)
+{
+ if (skl_get_dimm_s_size(val) == 0)
+ return 0;
+
+ return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1;
+}
+
+static int skl_get_dimm_l_ranks(u32 val)
+{
+ if (skl_get_dimm_l_size(val) == 0)
+ return 0;
- return val + 1;
+ return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1;
}
/* Returns total Gb for the whole DIMM */
-static int icl_get_dimm_size(u16 val)
+static int icl_get_dimm_s_size(u32 val)
{
- return (val & ICL_DRAM_SIZE_MASK) * 8 / 2;
+ return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2;
}
-static int icl_get_dimm_width(u16 val)
+static int icl_get_dimm_l_size(u32 val)
{
- if (icl_get_dimm_size(val) == 0)
+ return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2;
+}
+
+static int icl_get_dimm_s_width(u32 val)
+{
+ if (icl_get_dimm_s_size(val) == 0)
return 0;
- switch (val & ICL_DRAM_WIDTH_MASK) {
- case ICL_DRAM_WIDTH_X8:
- case ICL_DRAM_WIDTH_X16:
- case ICL_DRAM_WIDTH_X32:
- val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT;
- return 8 << val;
+ switch (val & ICL_DIMM_S_WIDTH_MASK) {
+ case ICL_DIMM_S_WIDTH_X8:
+ case ICL_DIMM_S_WIDTH_X16:
+ case ICL_DIMM_S_WIDTH_X32:
+ return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val);
default:
MISSING_CASE(val);
return 0;
}
}
-static int icl_get_dimm_ranks(u16 val)
+static int icl_get_dimm_l_width(u32 val)
{
- if (icl_get_dimm_size(val) == 0)
+ if (icl_get_dimm_l_size(val) == 0)
return 0;
- val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT;
+ switch (val & ICL_DIMM_L_WIDTH_MASK) {
+ case ICL_DIMM_L_WIDTH_X8:
+ case ICL_DIMM_L_WIDTH_X16:
+ case ICL_DIMM_L_WIDTH_X32:
+ return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val);
+ default:
+ MISSING_CASE(val);
+ return 0;
+ }
+}
+
+static int icl_get_dimm_s_ranks(u32 val)
+{
+ if (icl_get_dimm_s_size(val) == 0)
+ return 0;
+
+ return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1;
+}
+
+static int icl_get_dimm_l_ranks(u32 val)
+{
+ if (icl_get_dimm_l_size(val) == 0)
+ return 0;
- return val + 1;
+ return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1;
}
static bool
@@ -340,38 +397,62 @@ skl_is_16gb_dimm(const struct dram_dimm_info *dimm)
}
static void
-skl_dram_get_dimm_info(struct drm_i915_private *i915,
- struct dram_dimm_info *dimm,
- int channel, char dimm_name, u16 val)
-{
- if (GRAPHICS_VER(i915) >= 11) {
- dimm->size = icl_get_dimm_size(val);
- dimm->width = icl_get_dimm_width(val);
- dimm->ranks = icl_get_dimm_ranks(val);
- } else {
- dimm->size = skl_get_dimm_size(val);
- dimm->width = skl_get_dimm_width(val);
- dimm->ranks = skl_get_dimm_ranks(val);
- }
-
- drm_dbg_kms(&i915->drm,
+skl_dram_print_dimm_info(struct intel_display *display,
+ struct dram_dimm_info *dimm,
+ int channel, char dimm_name)
+{
+ drm_dbg_kms(display->drm,
"CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n",
channel, dimm_name, dimm->size, dimm->width, dimm->ranks,
str_yes_no(skl_is_16gb_dimm(dimm)));
}
+static void
+skl_dram_get_dimm_l_info(struct intel_display *display,
+ struct dram_dimm_info *dimm,
+ int channel, u32 val)
+{
+ if (DISPLAY_VER(display) >= 11) {
+ dimm->size = icl_get_dimm_l_size(val);
+ dimm->width = icl_get_dimm_l_width(val);
+ dimm->ranks = icl_get_dimm_l_ranks(val);
+ } else {
+ dimm->size = skl_get_dimm_l_size(val);
+ dimm->width = skl_get_dimm_l_width(val);
+ dimm->ranks = skl_get_dimm_l_ranks(val);
+ }
+
+ skl_dram_print_dimm_info(display, dimm, channel, 'L');
+}
+
+static void
+skl_dram_get_dimm_s_info(struct intel_display *display,
+ struct dram_dimm_info *dimm,
+ int channel, u32 val)
+{
+ if (DISPLAY_VER(display) >= 11) {
+ dimm->size = icl_get_dimm_s_size(val);
+ dimm->width = icl_get_dimm_s_width(val);
+ dimm->ranks = icl_get_dimm_s_ranks(val);
+ } else {
+ dimm->size = skl_get_dimm_s_size(val);
+ dimm->width = skl_get_dimm_s_width(val);
+ dimm->ranks = skl_get_dimm_s_ranks(val);
+ }
+
+ skl_dram_print_dimm_info(display, dimm, channel, 'S');
+}
+
static int
-skl_dram_get_channel_info(struct drm_i915_private *i915,
+skl_dram_get_channel_info(struct intel_display *display,
struct dram_channel_info *ch,
int channel, u32 val)
{
- skl_dram_get_dimm_info(i915, &ch->dimm_l,
- channel, 'L', val & 0xffff);
- skl_dram_get_dimm_info(i915, &ch->dimm_s,
- channel, 'S', val >> 16);
+ skl_dram_get_dimm_l_info(display, &ch->dimm_l, channel, val);
+ skl_dram_get_dimm_s_info(display, &ch->dimm_s, channel, val);
if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) {
- drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel);
+ drm_dbg_kms(display->drm, "CH%u not populated\n", channel);
return -EINVAL;
}
@@ -385,7 +466,7 @@ skl_dram_get_channel_info(struct drm_i915_private *i915,
ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) ||
skl_is_16gb_dimm(&ch->dimm_s);
- drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n",
+ drm_dbg_kms(display->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n",
channel, ch->ranks, str_yes_no(ch->is_16gb_dimm));
return 0;
@@ -401,8 +482,9 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0,
}
static int
-skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
struct dram_channel_info ch0 = {}, ch1 = {};
u32 val;
int ret;
@@ -412,23 +494,23 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram
val = intel_uncore_read(&i915->uncore,
SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
- ret = skl_dram_get_channel_info(i915, &ch0, 0, val);
+ 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);
- ret = skl_dram_get_channel_info(i915, &ch1, 1, val);
+ ret = skl_dram_get_channel_info(display, &ch1, 1, val);
if (ret == 0)
dram_info->num_channels++;
if (dram_info->num_channels == 0) {
- drm_info(&i915->drm, "Number of memory channels is zero\n");
+ drm_info(display->drm, "Number of memory channels is zero\n");
return -EINVAL;
}
if (ch0.ranks == 0 && ch1.ranks == 0) {
- drm_info(&i915->drm, "couldn't get memory rank information\n");
+ drm_info(display->drm, "couldn't get memory rank information\n");
return -EINVAL;
}
@@ -436,18 +518,19 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram
dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1);
- drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n",
+ drm_dbg_kms(display->drm, "Memory configuration is symmetric? %s\n",
str_yes_no(dram_info->symmetric_memory));
- drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n",
+ drm_dbg_kms(display->drm, "16Gb+ DIMMs: %s\n",
str_yes_no(dram_info->has_16gb_dimms));
return 0;
}
static enum intel_dram_type
-skl_get_dram_type(struct drm_i915_private *i915)
+skl_get_dram_type(struct intel_display *display)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
u32 val;
val = intel_uncore_read(&i915->uncore,
@@ -469,13 +552,13 @@ skl_get_dram_type(struct drm_i915_private *i915)
}
static int
-skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+skl_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
int ret;
- dram_info->type = skl_get_dram_type(i915);
+ dram_info->type = skl_get_dram_type(display);
- ret = skl_dram_get_channels_info(i915, dram_info);
+ ret = skl_dram_get_channels_info(display, dram_info);
if (ret)
return ret;
@@ -560,8 +643,9 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val)
dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm);
}
-static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
u32 val;
u8 valid_ranks = 0;
int i;
@@ -582,11 +666,11 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr
bxt_get_dimm_info(&dimm, val);
type = bxt_get_dimm_type(val);
- drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN &&
+ drm_WARN_ON(display->drm, type != INTEL_DRAM_UNKNOWN &&
dram_info->type != INTEL_DRAM_UNKNOWN &&
dram_info->type != type);
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n",
i - BXT_D_CR_DRP0_DUNIT_START,
dimm.size, dimm.width, dimm.ranks);
@@ -599,25 +683,25 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr
}
if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) {
- drm_info(&i915->drm, "couldn't get memory information\n");
+ drm_info(display->drm, "couldn't get memory information\n");
return -EINVAL;
}
return 0;
}
-static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv,
+static int icl_pcode_read_mem_global_info(struct intel_display *display,
struct dram_info *dram_info)
{
u32 val = 0;
int ret;
- ret = intel_pcode_read(&dev_priv->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
+ ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
if (ret)
return ret;
- if (GRAPHICS_VER(dev_priv) == 12) {
+ if (DISPLAY_VER(display) >= 12) {
switch (val & 0xf) {
case 0:
dram_info->type = INTEL_DRAM_DDR4;
@@ -668,25 +752,25 @@ static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv,
return 0;
}
-static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+static int gen11_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
int ret;
- ret = skl_dram_get_channels_info(i915, dram_info);
+ ret = skl_dram_get_channels_info(display, dram_info);
if (ret)
return ret;
- return icl_pcode_read_mem_global_info(i915, dram_info);
+ return icl_pcode_read_mem_global_info(display, dram_info);
}
-static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+static int gen12_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
- return icl_pcode_read_mem_global_info(i915, dram_info);
+ return icl_pcode_read_mem_global_info(display, dram_info);
}
-static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info)
+static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
- struct intel_display *display = i915->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL);
switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) {
@@ -709,11 +793,11 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info
dram_info->type = INTEL_DRAM_LPDDR3;
break;
case 8:
- drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+ drm_WARN_ON(display->drm, !display->platform.dgfx);
dram_info->type = INTEL_DRAM_GDDR;
break;
case 9:
- drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+ drm_WARN_ON(display->drm, !display->platform.dgfx);
dram_info->type = INTEL_DRAM_GDDR_ECC;
break;
default:
@@ -731,41 +815,40 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info
return 0;
}
-int intel_dram_detect(struct drm_i915_private *i915)
+int intel_dram_detect(struct intel_display *display)
{
- struct intel_display *display = i915->display;
struct dram_info *dram_info;
int ret;
- if (IS_DG2(i915) || !intel_display_device_present(display))
+ if (display->platform.dg2 || !HAS_DISPLAY(display))
return 0;
- dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL);
+ dram_info = drmm_kzalloc(display->drm, sizeof(*dram_info), GFP_KERNEL);
if (!dram_info)
return -ENOMEM;
- i915->dram_info = dram_info;
+ display->dram.info = dram_info;
if (DISPLAY_VER(display) >= 14)
- ret = xelpdp_get_dram_info(i915, dram_info);
- else if (GRAPHICS_VER(i915) >= 12)
- ret = gen12_get_dram_info(i915, dram_info);
- else if (GRAPHICS_VER(i915) >= 11)
- ret = gen11_get_dram_info(i915, dram_info);
- else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915))
- ret = bxt_get_dram_info(i915, dram_info);
- else if (GRAPHICS_VER(i915) >= 9)
- ret = skl_get_dram_info(i915, dram_info);
+ ret = xelpdp_get_dram_info(display, dram_info);
+ else if (DISPLAY_VER(display) >= 12)
+ ret = gen12_get_dram_info(display, dram_info);
+ else if (DISPLAY_VER(display) >= 11)
+ ret = gen11_get_dram_info(display, dram_info);
+ else if (display->platform.broxton || display->platform.geminilake)
+ ret = bxt_get_dram_info(display, dram_info);
+ else if (DISPLAY_VER(display) >= 9)
+ ret = skl_get_dram_info(display, dram_info);
else
- ret = i915_get_dram_info(i915, dram_info);
+ ret = i915_get_dram_info(display, dram_info);
- drm_dbg_kms(&i915->drm, "DRAM type: %s\n",
+ drm_dbg_kms(display->drm, "DRAM type: %s\n",
intel_dram_type_str(dram_info->type));
- drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels);
+ drm_dbg_kms(display->drm, "DRAM channels: %u\n", dram_info->num_channels);
- drm_dbg_kms(&i915->drm, "Num QGV points %u\n", dram_info->num_qgv_points);
- drm_dbg_kms(&i915->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points);
+ drm_dbg_kms(display->drm, "Num QGV points %u\n", dram_info->num_qgv_points);
+ drm_dbg_kms(display->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points);
/* TODO: Do we want to abort probe on dram detection failures? */
if (ret)
@@ -779,45 +862,7 @@ int intel_dram_detect(struct drm_i915_private *i915)
* checks, and prefer not dereferencing on platforms that shouldn't look at dram
* info, to catch accidental and incorrect dram info checks.
*/
-const struct dram_info *intel_dram_info(struct drm_device *drm)
+const struct dram_info *intel_dram_info(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(drm);
-
- return i915->dram_info;
-}
-
-static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap)
-{
- static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 };
- static const u8 sets[4] = { 1, 1, 2, 2 };
-
- return EDRAM_NUM_BANKS(cap) *
- ways[EDRAM_WAYS_IDX(cap)] *
- sets[EDRAM_SETS_IDX(cap)];
-}
-
-void intel_dram_edram_detect(struct drm_i915_private *i915)
-{
- u32 edram_cap = 0;
-
- if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9))
- return;
-
- edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP);
-
- /* NB: We can't write IDICR yet because we don't have gt funcs set up */
-
- if (!(edram_cap & EDRAM_ENABLED))
- return;
-
- /*
- * The needed capability bits for size calculation are not there with
- * pre gen9 so return 128MB always.
- */
- if (GRAPHICS_VER(i915) < 9)
- i915->edram_size_mb = 128;
- else
- i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap);
-
- drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb);
+ return display->dram.info;
}
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/display/intel_dram.h
index 8475ee379daa..5800b7b4e614 100644
--- a/drivers/gpu/drm/i915/soc/intel_dram.h
+++ b/drivers/gpu/drm/i915/display/intel_dram.h
@@ -8,8 +8,7 @@
#include <linux/types.h>
-struct drm_i915_private;
-struct drm_device;
+struct intel_display;
struct dram_info {
enum intel_dram_type {
@@ -35,11 +34,10 @@ struct dram_info {
bool has_16gb_dimms;
};
-void intel_dram_edram_detect(struct drm_i915_private *i915);
-int intel_dram_detect(struct drm_i915_private *i915);
-unsigned int intel_fsb_freq(struct drm_i915_private *i915);
-unsigned int intel_mem_freq(struct drm_i915_private *i915);
-const struct dram_info *intel_dram_info(struct drm_device *drm);
+int intel_dram_detect(struct intel_display *display);
+unsigned int intel_fsb_freq(struct intel_display *display);
+unsigned int intel_mem_freq(struct intel_display *display);
+const struct dram_info *intel_dram_info(struct intel_display *display);
const char *intel_dram_type_str(enum intel_dram_type type);
#endif /* __INTEL_DRAM_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index 4ad4efbf9253..ec2a3fb171ab 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -26,7 +26,7 @@
struct intel_dsb {
enum intel_dsb_id id;
- struct intel_dsb_buffer dsb_buf;
+ struct intel_dsb_buffer *dsb_buf;
struct intel_crtc *crtc;
/*
@@ -211,10 +211,10 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(display->drm,
" 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
- intel_dsb_buffer_read(&dsb->dsb_buf, i),
- intel_dsb_buffer_read(&dsb->dsb_buf, i + 1),
- intel_dsb_buffer_read(&dsb->dsb_buf, i + 2),
- intel_dsb_buffer_read(&dsb->dsb_buf, i + 3));
+ intel_dsb_buffer_read(dsb->dsb_buf, i),
+ intel_dsb_buffer_read(dsb->dsb_buf, i + 1),
+ intel_dsb_buffer_read(dsb->dsb_buf, i + 2),
+ intel_dsb_buffer_read(dsb->dsb_buf, i + 3));
drm_dbg_kms(display->drm, "}\n");
}
@@ -231,12 +231,12 @@ unsigned int intel_dsb_size(struct intel_dsb *dsb)
unsigned int intel_dsb_head(struct intel_dsb *dsb)
{
- return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf);
+ return intel_dsb_buffer_ggtt_offset(dsb->dsb_buf);
}
static unsigned int intel_dsb_tail(struct intel_dsb *dsb)
{
- return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + intel_dsb_size(dsb);
+ return intel_dsb_buffer_ggtt_offset(dsb->dsb_buf) + intel_dsb_size(dsb);
}
static void intel_dsb_ins_align(struct intel_dsb *dsb)
@@ -263,8 +263,8 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
dsb->ins[0] = ldw;
dsb->ins[1] = udw;
- intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, dsb->ins[0]);
- intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, dsb->ins[1]);
+ intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, dsb->ins[0]);
+ intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, dsb->ins[1]);
}
static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
@@ -335,13 +335,13 @@ void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
/* Update the count */
dsb->ins[0]++;
- intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
+ intel_dsb_buffer_write(dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
- intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
+ intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, val);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
- intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0);
+ intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos, 0);
}
void intel_dsb_reg_write(struct intel_dsb *dsb,
@@ -521,7 +521,7 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
aligned_tail = ALIGN(tail, CACHELINE_BYTES);
if (aligned_tail > tail)
- intel_dsb_buffer_memset(&dsb->dsb_buf, dsb->free_pos, 0,
+ intel_dsb_buffer_memset(dsb->dsb_buf, dsb->free_pos, 0,
aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
@@ -541,7 +541,7 @@ static void intel_dsb_gosub_align(struct intel_dsb *dsb)
* "Ensure GOSUB is not placed in cacheline QW slot 6 or 7 (numbered 0-7)"
*/
if (aligned_tail - tail <= 2 * 8)
- intel_dsb_buffer_memset(&dsb->dsb_buf, dsb->free_pos, 0,
+ intel_dsb_buffer_memset(dsb->dsb_buf, dsb->free_pos, 0,
aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
@@ -606,14 +606,14 @@ void intel_dsb_gosub_finish(struct intel_dsb *dsb)
*/
intel_dsb_noop(dsb, 8);
- intel_dsb_buffer_flush_map(&dsb->dsb_buf);
+ intel_dsb_buffer_flush_map(dsb->dsb_buf);
}
void intel_dsb_finish(struct intel_dsb *dsb)
{
intel_dsb_align_tail(dsb);
- intel_dsb_buffer_flush_map(&dsb->dsb_buf);
+ intel_dsb_buffer_flush_map(dsb->dsb_buf);
}
static u32 dsb_error_int_status(struct intel_display *display)
@@ -888,7 +888,7 @@ void intel_dsb_wait(struct intel_dsb *dsb)
!is_busy,
100, 1000, false);
if (ret) {
- u32 offset = intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf);
+ u32 offset = intel_dsb_buffer_ggtt_offset(dsb->dsb_buf);
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id),
DSB_ENABLE | DSB_HALT);
@@ -934,6 +934,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
unsigned int max_cmds)
{
struct intel_display *display = to_intel_display(state);
+ struct intel_dsb_buffer *dsb_buf;
struct ref_tracker *wakeref;
struct intel_dsb *dsb;
unsigned int size;
@@ -953,9 +954,12 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
/* ~1 qword per instruction, full cachelines */
size = ALIGN(max_cmds * 8, CACHELINE_BYTES);
- if (!intel_dsb_buffer_create(crtc, &dsb->dsb_buf, size))
+ dsb_buf = intel_dsb_buffer_create(display->drm, size);
+ if (IS_ERR(dsb_buf))
goto out_put_rpm;
+ dsb->dsb_buf = dsb_buf;
+
intel_display_rpm_put(display, wakeref);
dsb->id = dsb_id;
@@ -988,7 +992,7 @@ out:
*/
void intel_dsb_cleanup(struct intel_dsb *dsb)
{
- intel_dsb_buffer_cleanup(&dsb->dsb_buf);
+ intel_dsb_buffer_cleanup(dsb->dsb_buf);
kfree(dsb);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dsb_buffer.c b/drivers/gpu/drm/i915/display/intel_dsb_buffer.c
index c77d48bda26a..50faf3869b6c 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb_buffer.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb_buffer.c
@@ -7,9 +7,14 @@
#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
#include "i915_vma.h"
-#include "intel_display_types.h"
#include "intel_dsb_buffer.h"
+struct intel_dsb_buffer {
+ u32 *cmd_buf;
+ struct i915_vma *vma;
+ size_t buf_size;
+};
+
u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf)
{
return i915_ggtt_offset(dsb_buf->vma);
@@ -32,48 +37,66 @@ void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val,
memset(&dsb_buf->cmd_buf[idx], val, size);
}
-bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size)
+struct intel_dsb_buffer *intel_dsb_buffer_create(struct drm_device *drm, size_t size)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(drm);
+ struct intel_dsb_buffer *dsb_buf;
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
u32 *buf;
+ int ret;
+
+ dsb_buf = kzalloc(sizeof(*dsb_buf), GFP_KERNEL);
+ if (!dsb_buf)
+ return ERR_PTR(-ENOMEM);
if (HAS_LMEM(i915)) {
obj = i915_gem_object_create_lmem(i915, PAGE_ALIGN(size),
I915_BO_ALLOC_CONTIGUOUS);
- if (IS_ERR(obj))
- return false;
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
+ goto err;
+ }
} else {
obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size));
- if (IS_ERR(obj))
- return false;
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
+ goto err;
+ }
i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
}
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
i915_gem_object_put(obj);
- return false;
+ goto err;
}
buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
- return false;
+ goto err;
}
dsb_buf->vma = vma;
dsb_buf->cmd_buf = buf;
dsb_buf->buf_size = size;
- return true;
+ return dsb_buf;
+
+err:
+ kfree(dsb_buf);
+
+ return ERR_PTR(ret);
}
void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf)
{
i915_vma_unpin_and_release(&dsb_buf->vma, I915_VMA_RELEASE_MAP);
+ kfree(dsb_buf);
}
void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf)
diff --git a/drivers/gpu/drm/i915/display/intel_dsb_buffer.h b/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
index 425acd393905..d746c872e0c7 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb_buffer.h
@@ -8,21 +8,14 @@
#include <linux/types.h>
-struct intel_crtc;
-struct i915_vma;
-
-struct intel_dsb_buffer {
- u32 *cmd_buf;
- struct i915_vma *vma;
- size_t buf_size;
-};
+struct drm_device;
+struct intel_dsb_buffer;
u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf);
void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val);
u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx);
void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size);
-bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf,
- size_t size);
+struct intel_dsb_buffer *intel_dsb_buffer_create(struct drm_device *drm, size_t size);
void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf);
void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf);
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h
index 89c7166a3860..489d26ffd235 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -29,6 +29,9 @@
#include "intel_display_types.h"
+struct intel_dsi_host;
+struct ref_tracker;
+
#define INTEL_DSI_VIDEO_MODE 0
#define INTEL_DSI_COMMAND_MODE 1
@@ -37,13 +40,11 @@
#define DSI_DUAL_LINK_FRONT_BACK 1
#define DSI_DUAL_LINK_PIXEL_ALT 2
-struct intel_dsi_host;
-
struct intel_dsi {
struct intel_encoder base;
struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
- intel_wakeref_t io_wakeref[I915_MAX_PORTS];
+ struct ref_tracker *io_wakeref[I915_MAX_PORTS];
/* GPIO Desc for panel and backlight control */
struct gpio_desc *gpio_panel;
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index b34b4961fe1c..b9bd9b6dfe94 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -20,7 +20,7 @@
#include "intel_fb.h"
#include "intel_fb_bo.h"
#include "intel_frontbuffer.h"
-#include "intel_panic.h"
+#include "intel_parent.h"
#include "intel_plane.h"
#define check_array_bounds(display, a, i) drm_WARN_ON((display)->drm, (i) >= ARRAY_SIZE(a))
@@ -558,7 +558,7 @@ static bool plane_has_modifier(struct intel_display *display,
* where supported.
*/
if (intel_fb_is_ccs_modifier(md->modifier) &&
- HAS_AUX_CCS(display) != !!md->ccs.packed_aux_planes)
+ intel_parent_has_auxccs(display) != !!md->ccs.packed_aux_planes)
return false;
if (md->modifier == I915_FORMAT_MOD_4_TILED_BMG_CCS &&
@@ -2216,7 +2216,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
int ret;
int i;
- intel_fb->panic = intel_panic_alloc();
+ intel_fb->panic = intel_parent_panic_alloc(display);
if (!intel_fb->panic)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 437d2fda20a7..fef2f35ff1e9 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -45,12 +45,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
-#include "gem/i915_gem_stolen.h"
-
-#include "gt/intel_gt_types.h"
-
-#include "i915_drv.h"
-#include "i915_vgpu.h"
#include "i915_vma.h"
#include "i9xx_plane_regs.h"
#include "intel_de.h"
@@ -64,6 +58,8 @@
#include "intel_fbc.h"
#include "intel_fbc_regs.h"
#include "intel_frontbuffer.h"
+#include "intel_parent.h"
+#include "intel_step.h"
#define for_each_fbc_id(__display, __fbc_id) \
for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \
@@ -71,7 +67,9 @@
#define for_each_intel_fbc(__display, __fbc, __fbc_id) \
for_each_fbc_id((__display), (__fbc_id)) \
- for_each_if((__fbc) = (__display)->fbc[(__fbc_id)])
+ for_each_if((__fbc) = (__display)->fbc.instances[(__fbc_id)])
+
+#define FBC_SYS_CACHE_ID_NONE I915_MAX_FBCS
struct intel_fbc_funcs {
void (*activate)(struct intel_fbc *fbc);
@@ -129,6 +127,19 @@ struct intel_fbc {
const char *no_fbc_reason;
};
+static struct intel_fbc *intel_fbc_for_pipe(struct intel_display *display, enum pipe pipe)
+{
+ struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
+ struct intel_plane *primary = NULL;
+
+ primary = to_intel_plane(crtc->base.primary);
+
+ if (drm_WARN_ON(display->drm, !primary))
+ return NULL;
+
+ return primary->fbc;
+}
+
/* plane stride in pixels */
static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
{
@@ -204,7 +215,7 @@ static unsigned int _intel_fbc_cfb_stride(struct intel_display *display,
static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16;
unsigned int cpp = intel_fbc_cfb_cpp(plane_state);
@@ -235,7 +246,7 @@ static unsigned int _intel_fbc_cfb_size(struct intel_display *display,
static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
unsigned int height = drm_rect_height(&plane_state->uapi.src) >> 16;
return _intel_fbc_cfb_size(display, height, intel_fbc_cfb_stride(plane_state));
@@ -243,7 +254,7 @@ static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_sta
static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
unsigned int stride_aligned = intel_fbc_cfb_stride(plane_state);
unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
const struct drm_framebuffer *fb = plane_state->hw.fb;
@@ -267,9 +278,7 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s
static bool intel_fbc_has_fences(struct intel_display *display)
{
- struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm);
-
- return intel_gt_support_legacy_fencing(to_gt(i915));
+ return intel_parent_has_fenced_regions(display);
}
static u32 i8xx_fbc_ctl(struct intel_fbc *fbc)
@@ -382,17 +391,17 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
struct intel_display *display = fbc->display;
drm_WARN_ON(display->drm,
- range_end_overflows_t(u64, i915_gem_stolen_area_address(display->drm),
- i915_gem_stolen_node_offset(fbc->compressed_fb),
+ range_end_overflows_t(u64, intel_parent_stolen_area_address(display),
+ intel_parent_stolen_node_offset(display, fbc->compressed_fb),
U32_MAX));
drm_WARN_ON(display->drm,
- range_end_overflows_t(u64, i915_gem_stolen_area_address(display->drm),
- i915_gem_stolen_node_offset(fbc->compressed_llb),
+ range_end_overflows_t(u64, intel_parent_stolen_area_address(display),
+ intel_parent_stolen_node_offset(display, fbc->compressed_llb),
U32_MAX));
intel_de_write(display, FBC_CFB_BASE,
- i915_gem_stolen_node_address(fbc->compressed_fb));
+ intel_parent_stolen_node_address(display, fbc->compressed_fb));
intel_de_write(display, FBC_LL_BASE,
- i915_gem_stolen_node_address(fbc->compressed_llb));
+ intel_parent_stolen_node_address(display, fbc->compressed_llb));
}
static const struct intel_fbc_funcs i8xx_fbc_funcs = {
@@ -500,7 +509,7 @@ static void g4x_fbc_program_cfb(struct intel_fbc *fbc)
struct intel_display *display = fbc->display;
intel_de_write(display, DPFC_CB_BASE,
- i915_gem_stolen_node_offset(fbc->compressed_fb));
+ intel_parent_stolen_node_offset(display, fbc->compressed_fb));
}
static const struct intel_fbc_funcs g4x_fbc_funcs = {
@@ -569,7 +578,7 @@ static void ilk_fbc_program_cfb(struct intel_fbc *fbc)
struct intel_display *display = fbc->display;
intel_de_write(display, ILK_DPFC_CB_BASE(fbc->id),
- i915_gem_stolen_node_offset(fbc->compressed_fb));
+ intel_parent_stolen_node_offset(display, fbc->compressed_fb));
}
static const struct intel_fbc_funcs ilk_fbc_funcs = {
@@ -808,7 +817,7 @@ static u64 intel_fbc_stolen_end(struct intel_display *display)
* underruns, even if that range is not reserved by the BIOS. */
if (display->platform.broadwell ||
(DISPLAY_VER(display) == 9 && !display->platform.broxton))
- end = i915_gem_stolen_area_size(display->drm) - 8 * 1024 * 1024;
+ end = intel_parent_stolen_area_size(display) - 8 * 1024 * 1024;
else
end = U64_MAX;
@@ -843,14 +852,14 @@ static int find_compression_limit(struct intel_fbc *fbc,
size /= limit;
/* Try to over-allocate to reduce reallocations and fragmentation. */
- ret = i915_gem_stolen_insert_node_in_range(fbc->compressed_fb,
- size <<= 1, 4096, 0, end);
+ ret = intel_parent_stolen_insert_node_in_range(display, fbc->compressed_fb,
+ size <<= 1, 4096, 0, end);
if (ret == 0)
return limit;
for (; limit <= intel_fbc_max_limit(display); limit <<= 1) {
- ret = i915_gem_stolen_insert_node_in_range(fbc->compressed_fb,
- size >>= 1, 4096, 0, end);
+ ret = intel_parent_stolen_insert_node_in_range(display, fbc->compressed_fb,
+ size >>= 1, 4096, 0, end);
if (ret == 0)
return limit;
}
@@ -865,12 +874,12 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
int ret;
drm_WARN_ON(display->drm,
- i915_gem_stolen_node_allocated(fbc->compressed_fb));
+ intel_parent_stolen_node_allocated(display, fbc->compressed_fb));
drm_WARN_ON(display->drm,
- i915_gem_stolen_node_allocated(fbc->compressed_llb));
+ intel_parent_stolen_node_allocated(display, fbc->compressed_llb));
if (DISPLAY_VER(display) < 5 && !display->platform.g4x) {
- ret = i915_gem_stolen_insert_node(fbc->compressed_llb, 4096, 4096);
+ ret = intel_parent_stolen_insert_node(display, fbc->compressed_llb, 4096, 4096);
if (ret)
goto err;
}
@@ -886,14 +895,14 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
drm_dbg_kms(display->drm,
"reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n",
- i915_gem_stolen_node_size(fbc->compressed_fb), fbc->limit);
+ intel_parent_stolen_node_size(display, fbc->compressed_fb), fbc->limit);
return 0;
err_llb:
- if (i915_gem_stolen_node_allocated(fbc->compressed_llb))
- i915_gem_stolen_remove_node(fbc->compressed_llb);
+ if (intel_parent_stolen_node_allocated(display, fbc->compressed_llb))
+ intel_parent_stolen_remove_node(display, fbc->compressed_llb);
err:
- if (i915_gem_stolen_initialized(display->drm))
+ if (intel_parent_stolen_initialized(display))
drm_info_once(display->drm,
"not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
return -ENOSPC;
@@ -945,15 +954,83 @@ static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
fbc_compressor_clkgate_disable_wa(fbc, true);
}
+static void fbc_sys_cache_update_config(struct intel_display *display, u32 reg,
+ enum intel_fbc_id id)
+{
+ if (!HAS_FBC_SYS_CACHE(display))
+ return;
+
+ lockdep_assert_held(&display->fbc.sys_cache.lock);
+
+ /*
+ * Wa_14025769978:
+ * Fixes: SoC hardware issue in read caching
+ * Workaround: disable cache read setting which is enabled by default.
+ */
+ if (!intel_display_wa(display, 14025769978))
+ /* Cache read enable is set by default */
+ reg |= FBC_SYS_CACHE_READ_ENABLE;
+
+ intel_de_write(display, XE3P_LPD_FBC_SYS_CACHE_USAGE_CFG, reg);
+
+ display->fbc.sys_cache.id = id;
+}
+
+static void fbc_sys_cache_disable(const struct intel_fbc *fbc)
+{
+ struct intel_display *display = fbc->display;
+ struct sys_cache_cfg *sys_cache = &display->fbc.sys_cache;
+
+ mutex_lock(&sys_cache->lock);
+ /* clear only if "fbc" reserved the cache */
+ if (sys_cache->id == fbc->id)
+ fbc_sys_cache_update_config(display, 0, FBC_SYS_CACHE_ID_NONE);
+ mutex_unlock(&sys_cache->lock);
+}
+
+static int fbc_sys_cache_limit(struct intel_display *display)
+{
+ if (DISPLAY_VER(display) == 35)
+ return 2 * 1024 * 1024;
+
+ return 0;
+}
+
+static void fbc_sys_cache_enable(const struct intel_fbc *fbc)
+{
+ struct intel_display *display = fbc->display;
+ struct sys_cache_cfg *sys_cache = &display->fbc.sys_cache;
+ int range, offset;
+ u32 cfg;
+
+ if (!HAS_FBC_SYS_CACHE(display))
+ return;
+
+ range = fbc_sys_cache_limit(display) / (64 * 1024);
+
+ offset = intel_parent_stolen_node_offset(display, fbc->compressed_fb) / (4 * 1024);
+
+ cfg = FBC_SYS_CACHE_TAG_USE_RES_SPACE | FBC_SYS_CACHEABLE_RANGE(range) |
+ FBC_SYS_CACHE_START_BASE(offset);
+
+ mutex_lock(&sys_cache->lock);
+ /* update sys cache config only if sys cache is unassigned */
+ if (sys_cache->id == FBC_SYS_CACHE_ID_NONE)
+ fbc_sys_cache_update_config(display, cfg, fbc->id);
+ mutex_unlock(&sys_cache->lock);
+}
+
static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
{
+ struct intel_display *display = fbc->display;
+
if (WARN_ON(intel_fbc_hw_is_active(fbc)))
return;
- if (i915_gem_stolen_node_allocated(fbc->compressed_llb))
- i915_gem_stolen_remove_node(fbc->compressed_llb);
- if (i915_gem_stolen_node_allocated(fbc->compressed_fb))
- i915_gem_stolen_remove_node(fbc->compressed_fb);
+ if (intel_parent_stolen_node_allocated(display, fbc->compressed_llb))
+ intel_parent_stolen_remove_node(display, fbc->compressed_llb);
+ if (intel_parent_stolen_node_allocated(display, fbc->compressed_fb))
+ intel_parent_stolen_remove_node(display, fbc->compressed_fb);
}
void intel_fbc_cleanup(struct intel_display *display)
@@ -966,11 +1043,16 @@ void intel_fbc_cleanup(struct intel_display *display)
__intel_fbc_cleanup_cfb(fbc);
mutex_unlock(&fbc->lock);
- i915_gem_stolen_node_free(fbc->compressed_fb);
- i915_gem_stolen_node_free(fbc->compressed_llb);
+ intel_parent_stolen_node_free(display, fbc->compressed_fb);
+ intel_parent_stolen_node_free(display, fbc->compressed_llb);
kfree(fbc);
}
+
+ mutex_lock(&display->fbc.sys_cache.lock);
+ drm_WARN_ON(display->drm,
+ display->fbc.sys_cache.id != FBC_SYS_CACHE_ID_NONE);
+ mutex_unlock(&display->fbc.sys_cache.lock);
}
static bool i8xx_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
@@ -1016,7 +1098,7 @@ static bool icl_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
static bool stride_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
if (DISPLAY_VER(display) >= 11)
return icl_fbc_stride_is_valid(plane_state);
@@ -1032,7 +1114,7 @@ static bool stride_is_valid(const struct intel_plane_state *plane_state)
static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
const struct drm_framebuffer *fb = plane_state->hw.fb;
switch (fb->format->format) {
@@ -1052,7 +1134,7 @@ static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane
static bool g4x_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
const struct drm_framebuffer *fb = plane_state->hw.fb;
switch (fb->format->format) {
@@ -1131,7 +1213,7 @@ intel_fbc_is_enable_pixel_normalizer(const struct intel_plane_state *plane_state
static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
if (DISPLAY_VER(display) >= 35)
return xe3p_lpd_fbc_pixel_format_is_valid(plane_state);
@@ -1167,7 +1249,7 @@ static bool skl_fbc_rotation_is_valid(const struct intel_plane_state *plane_stat
static bool rotation_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
if (DISPLAY_VER(display) >= 9)
return skl_fbc_rotation_is_valid(plane_state);
@@ -1206,7 +1288,7 @@ static void intel_fbc_max_surface_size(struct intel_display *display,
*/
static bool intel_fbc_surface_size_ok(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
unsigned int effective_w, effective_h, max_w, max_h;
intel_fbc_max_surface_size(display, &max_w, &max_h);
@@ -1239,7 +1321,7 @@ static void intel_fbc_max_plane_size(struct intel_display *display,
static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
unsigned int w, h, max_w, max_h;
intel_fbc_max_plane_size(display, &max_w, &max_h);
@@ -1264,7 +1346,7 @@ static bool skl_fbc_tiling_valid(const struct intel_plane_state *plane_state)
static bool tiling_is_valid(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
if (DISPLAY_VER(display) >= 9)
return skl_fbc_tiling_valid(plane_state);
@@ -1344,7 +1426,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_plane *plane)
{
- struct intel_display *display = to_intel_display(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_plane_state *plane_state =
@@ -1377,7 +1459,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
{
- struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev);
+ struct intel_display *display = to_intel_display(plane_state);
/*
* The use of a CPU fence is one of two ways to detect writes by the
@@ -1398,12 +1480,13 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)
{
+ struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct intel_fbc *fbc = plane->fbc;
return intel_fbc_min_limit(plane_state) <= fbc->limit &&
intel_fbc_cfb_size(plane_state) <= fbc->limit *
- i915_gem_stolen_node_size(fbc->compressed_fb);
+ intel_parent_stolen_node_size(display, fbc->compressed_fb);
}
static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state)
@@ -1484,8 +1567,7 @@ static int _intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state)
static int intel_fbc_check_plane(struct intel_atomic_state *state,
struct intel_plane *plane)
{
- struct intel_display *display = to_intel_display(state->base.dev);
- struct drm_i915_private *i915 = to_i915(display->drm);
+ struct intel_display *display = to_intel_display(state);
struct intel_plane_state *plane_state =
intel_atomic_get_new_plane_state(state, plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
@@ -1496,12 +1578,12 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
if (!fbc)
return 0;
- if (!i915_gem_stolen_initialized(display->drm)) {
+ if (!intel_parent_stolen_initialized(display)) {
plane_state->no_fbc_reason = "stolen memory not initialised";
return 0;
}
- if (intel_vgpu_active(i915)) {
+ if (intel_parent_vgpu_active(display)) {
plane_state->no_fbc_reason = "VGPU active";
return 0;
}
@@ -1521,6 +1603,16 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
return 0;
}
+ /*
+ * Wa_15018326506:
+ * Fixes: Underrun during media decode
+ * Workaround: Do not enable FBC
+ */
+ if (intel_display_wa(display, 15018326506)) {
+ plane_state->no_fbc_reason = "Wa_15018326506";
+ return 0;
+ }
+
/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
if (intel_display_vtd_active(display) &&
(display->platform.skylake || display->platform.broxton)) {
@@ -1702,7 +1794,7 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_plane *plane)
{
- struct intel_display *display = to_intel_display(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_fbc *fbc = plane->fbc;
bool need_vblank_wait = false;
@@ -1775,6 +1867,8 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
__intel_fbc_cleanup_cfb(fbc);
+ fbc_sys_cache_disable(fbc);
+
/* wa_18038517565 Enable DPFC clock gating after FBC disable */
if (display->platform.dg2 || DISPLAY_VER(display) >= 14)
fbc_compressor_clkgate_disable_wa(fbc, false);
@@ -1915,7 +2009,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_plane *plane)
{
- struct intel_display *display = to_intel_display(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_plane_state *plane_state =
intel_atomic_get_new_plane_state(state, plane);
struct intel_fbc *fbc = plane->fbc;
@@ -1967,6 +2061,8 @@ static void __intel_fbc_enable(struct intel_atomic_state *state,
intel_fbc_program_workarounds(fbc);
intel_fbc_program_cfb(fbc);
+
+ fbc_sys_cache_enable(fbc);
}
/**
@@ -1977,7 +2073,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state,
*/
void intel_fbc_disable(struct intel_crtc *crtc)
{
- struct intel_display *display = to_intel_display(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
struct intel_plane *plane;
for_each_intel_plane(display->drm, plane) {
@@ -2119,6 +2215,37 @@ void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display)
__intel_fbc_handle_fifo_underrun_irq(fbc);
}
+/**
+ * intel_fbc_read_underrun_dbg_info - Read and log FBC-related FIFO underrun debug info
+ * @display: display device instance
+ * @pipe: the pipe possibly containing the FBC
+ * @log: log the info?
+ *
+ * If @pipe does not contain an FBC instance, this function bails early.
+ * Otherwise, FBC-related FIFO underrun is read and cleared, and then, if @log
+ * is true, printed with error level.
+ */
+void intel_fbc_read_underrun_dbg_info(struct intel_display *display,
+ enum pipe pipe, bool log)
+{
+ struct intel_fbc *fbc = intel_fbc_for_pipe(display, pipe);
+ u32 val;
+
+ if (!fbc)
+ return;
+
+ val = intel_de_read(display, FBC_DEBUG_STATUS(fbc->id));
+ if (!(val & FBC_UNDERRUN_DECMPR))
+ return;
+
+ intel_de_write(display, FBC_DEBUG_STATUS(fbc->id), FBC_UNDERRUN_DECMPR);
+
+ if (log)
+ drm_err(display->drm,
+ "Pipe %c FIFO underrun info: FBC decompressing\n",
+ pipe_name(pipe));
+}
+
/*
* The DDX driver changes its behavior depending on the value it reads from
* i915.enable_fbc, so sanitize it by translating the default value into either
@@ -2156,10 +2283,10 @@ static struct intel_fbc *intel_fbc_create(struct intel_display *display,
if (!fbc)
return NULL;
- fbc->compressed_fb = i915_gem_stolen_node_alloc(display->drm);
+ fbc->compressed_fb = intel_parent_stolen_node_alloc(display);
if (!fbc->compressed_fb)
goto err;
- fbc->compressed_llb = i915_gem_stolen_node_alloc(display->drm);
+ fbc->compressed_llb = intel_parent_stolen_node_alloc(display);
if (!fbc->compressed_llb)
goto err;
@@ -2184,8 +2311,8 @@ static struct intel_fbc *intel_fbc_create(struct intel_display *display,
return fbc;
err:
- i915_gem_stolen_node_free(fbc->compressed_llb);
- i915_gem_stolen_node_free(fbc->compressed_fb);
+ intel_parent_stolen_node_free(display, fbc->compressed_llb);
+ intel_parent_stolen_node_free(display, fbc->compressed_fb);
kfree(fbc);
return NULL;
@@ -2206,7 +2333,10 @@ void intel_fbc_init(struct intel_display *display)
display->params.enable_fbc);
for_each_fbc_id(display, fbc_id)
- display->fbc[fbc_id] = intel_fbc_create(display, fbc_id);
+ display->fbc.instances[fbc_id] = intel_fbc_create(display, fbc_id);
+
+ mutex_init(&display->fbc.sys_cache.lock);
+ display->fbc.sys_cache.id = FBC_SYS_CACHE_ID_NONE;
}
/**
@@ -2226,6 +2356,11 @@ void intel_fbc_sanitize(struct intel_display *display)
if (intel_fbc_hw_is_active(fbc))
intel_fbc_hw_deactivate(fbc);
}
+
+ /* Ensure the sys cache usage config is clear as well */
+ mutex_lock(&display->fbc.sys_cache.lock);
+ fbc_sys_cache_update_config(display, 0, FBC_SYS_CACHE_ID_NONE);
+ mutex_unlock(&display->fbc.sys_cache.lock);
}
static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
@@ -2244,6 +2379,11 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
seq_puts(m, "FBC enabled\n");
seq_printf(m, "Compressing: %s\n",
str_yes_no(intel_fbc_is_compressing(fbc)));
+
+ mutex_lock(&display->fbc.sys_cache.lock);
+ seq_printf(m, "Using system cache: %s\n",
+ str_yes_no(display->fbc.sys_cache.id == fbc->id));
+ mutex_unlock(&display->fbc.sys_cache.lock);
} else {
seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason);
}
@@ -2325,7 +2465,7 @@ void intel_fbc_debugfs_register(struct intel_display *display)
{
struct intel_fbc *fbc;
- fbc = display->fbc[INTEL_FBC_A];
+ fbc = display->fbc.instances[INTEL_FBC_A];
if (fbc)
intel_fbc_debugfs_add(fbc, display->drm->debugfs_root);
}
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
index 91424563206a..f0255ddae2b6 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc.h
@@ -9,6 +9,7 @@
#include <linux/types.h>
enum fb_op_origin;
+enum pipe;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
@@ -46,6 +47,8 @@ void intel_fbc_flush(struct intel_display *display,
unsigned int frontbuffer_bits, enum fb_op_origin origin);
void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane);
void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display);
+void intel_fbc_read_underrun_dbg_info(struct intel_display *display,
+ enum pipe, bool log);
void intel_fbc_reset_underrun(struct intel_display *display);
void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc);
void intel_fbc_debugfs_register(struct intel_display *display);
diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
index b1d0161a3196..4178e602d7d7 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
@@ -88,6 +88,8 @@
#define DPFC_FENCE_YOFF _MMIO(0x3218)
#define ILK_DPFC_FENCE_YOFF(fbc_id) _MMIO_PIPE((fbc_id), 0x43218, 0x43258)
#define DPFC_CHICKEN _MMIO(0x3224)
+#define FBC_DEBUG_STATUS(fbc_id) _MMIO_PIPE((fbc_id), 0x43220, 0x43260)
+#define FBC_UNDERRUN_DECMPR REG_BIT(27)
#define ILK_DPFC_CHICKEN(fbc_id) _MMIO_PIPE((fbc_id), 0x43224, 0x43264)
#define DPFC_HT_MODIFY REG_BIT(31) /* pre-ivb */
#define DPFC_NUKE_ON_ANY_MODIFICATION REG_BIT(23) /* bdw+ */
@@ -126,4 +128,14 @@
#define FBC_REND_NUKE REG_BIT(2)
#define FBC_REND_CACHE_CLEAN REG_BIT(1)
+#define XE3P_LPD_FBC_SYS_CACHE_USAGE_CFG _MMIO(0x1344E0)
+#define FBC_SYS_CACHE_START_BASE_MASK REG_GENMASK(31, 16)
+#define FBC_SYS_CACHE_START_BASE(base) REG_FIELD_PREP(FBC_SYS_CACHE_START_BASE_MASK, (base))
+#define FBC_SYS_CACHEABLE_RANGE_MASK REG_GENMASK(15, 4)
+#define FBC_SYS_CACHEABLE_RANGE(range) REG_FIELD_PREP(FBC_SYS_CACHEABLE_RANGE_MASK, (range))
+#define FBC_SYS_CACHE_TAG_MASK REG_GENMASK(3, 2)
+#define FBC_SYS_CACHE_TAG_DONT_CACHE REG_FIELD_PREP(FBC_SYS_CACHE_TAG_MASK, 0)
+#define FBC_SYS_CACHE_TAG_USE_RES_SPACE REG_FIELD_PREP(FBC_SYS_CACHE_TAG_MASK, 3)
+#define FBC_SYS_CACHE_READ_ENABLE REG_BIT(0)
+
#endif /* __INTEL_FBC_REGS__ */
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
index c2ce8461ac9e..b413b3e871d8 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
@@ -25,6 +25,8 @@
*
*/
+#include <linux/seq_buf.h>
+
#include <drm/drm_print.h>
#include "i915_reg.h"
@@ -57,6 +59,100 @@
* The code also supports underrun detection on the PCH transcoder.
*/
+#define UNDERRUN_DBG1_NUM_PLANES 6
+
+static void log_underrun_dbg1(struct intel_display *display, enum pipe pipe,
+ unsigned long plane_mask, const char *info)
+{
+ DECLARE_SEQ_BUF(planes_desc, 32);
+ unsigned int i;
+
+ if (!plane_mask)
+ return;
+
+ for_each_set_bit(i, &plane_mask, UNDERRUN_DBG1_NUM_PLANES) {
+ if (i == 0)
+ seq_buf_puts(&planes_desc, "[C]");
+ else
+ seq_buf_printf(&planes_desc, "[%d]", i);
+ }
+
+ drm_err(display->drm, "Pipe %c FIFO underrun info: %s on planes: %s\n",
+ pipe_name(pipe), info, seq_buf_str(&planes_desc));
+
+ drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
+}
+
+static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
+{
+ u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
+
+ if (!val)
+ return;
+
+ intel_de_write(display, UNDERRUN_DBG1(pipe), val);
+
+ if (!log)
+ return;
+
+ log_underrun_dbg1(display, pipe, REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val),
+ "DBUF block not valid");
+ log_underrun_dbg1(display, pipe, REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val),
+ "DDB empty");
+ log_underrun_dbg1(display, pipe, REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val),
+ "DBUF not completely filled");
+ log_underrun_dbg1(display, pipe, REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val),
+ "DBUF below WM0");
+}
+
+static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
+{
+ u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
+
+ if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
+ return;
+
+ intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
+
+ if (log)
+ drm_err(display->drm,
+ "Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
+ pipe_name(pipe),
+ REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
+ REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
+}
+
+static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
+{
+ u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
+
+ if (!(val & XE3P_UNDERRUN_PKGC))
+ return;
+
+ /*
+ * Note: If there are multiple pipes enabled, only one of them will see
+ * XE3P_UNDERRUN_PKGC set.
+ */
+ intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
+
+ if (log)
+ drm_err(display->drm,
+ "General FIFO underrun info: Package C-state blocking memory\n");
+}
+
+static void read_underrun_dbg_info(struct intel_display *display,
+ enum pipe pipe,
+ bool log)
+{
+ if (!HAS_UNDERRUN_DBG_INFO(display))
+ return;
+
+ read_underrun_dbg1(display, pipe, log);
+ read_underrun_dbg2(display, pipe, log);
+ intel_fbc_read_underrun_dbg_info(display, pipe, log);
+ read_underrun_dbg_pkgc(display, log);
+}
+
static bool ivb_can_enable_err_int(struct intel_display *display)
{
struct intel_crtc *crtc;
@@ -262,6 +358,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
old = !crtc->cpu_fifo_underrun_disabled;
crtc->cpu_fifo_underrun_disabled = !enable;
+ /*
+ * The debug bits get latched at the time of the FIFO underrun ISR bit
+ * getting set. That means that any non-zero debug bit that is read when
+ * handling a FIFO underrun interrupt has the potential to belong to
+ * another underrun event (past or future). To alleviate this problem,
+ * let's clear existing bits before enabling the interrupt, so that at
+ * least we don't get information that is too out-of-date.
+ */
+ if (enable && !old)
+ read_underrun_dbg_info(display, pipe, false);
+
if (HAS_GMCH(display))
i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
else if (display->platform.ironlake || display->platform.sandybridge)
@@ -379,6 +486,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
trace_intel_cpu_fifo_underrun(display, pipe);
drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
+
+ read_underrun_dbg_info(display, pipe, true);
}
intel_fbc_handle_fifo_underrun_irq(display);
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 795012d7c24c..2caff677600c 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -35,8 +35,6 @@
#include <drm/drm_print.h>
#include <drm/display/drm_hdcp_helper.h>
-#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
@@ -44,6 +42,7 @@
#include "intel_display_wa.h"
#include "intel_gmbus.h"
#include "intel_gmbus_regs.h"
+#include "intel_parent.h"
struct intel_gmbus {
struct i2c_adapter adapter;
@@ -391,12 +390,11 @@ intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg)
static bool has_gmbus_irq(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
/*
* encoder->shutdown() may want to use GMBUS
* after irqs have already been disabled.
*/
- return HAS_GMBUS_IRQ(display) && intel_irqs_enabled(i915);
+ return HAS_GMBUS_IRQ(display) && intel_parent_irq_enabled(display);
}
static int gmbus_wait(struct intel_display *display, u32 status, u32 irq_en)
@@ -791,7 +789,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
struct intel_display *display = bus->display;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int ret;
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
@@ -831,7 +829,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
.buf = buf,
}
};
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int ret;
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index 5e1a96223a9c..7114fc405c29 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -29,10 +29,10 @@
#include "intel_display_types.h"
#include "intel_dp_mst.h"
#include "intel_hdcp.h"
-#include "intel_hdcp_gsc.h"
#include "intel_hdcp_gsc_message.h"
#include "intel_hdcp_regs.h"
#include "intel_hdcp_shim.h"
+#include "intel_parent.h"
#include "intel_pcode.h"
#include "intel_step.h"
@@ -258,7 +258,7 @@ static bool intel_hdcp2_prerequisite(struct intel_connector *connector)
/* If MTL+ make sure gsc is loaded and proxy is setup */
if (USE_HDCP_GSC(display)) {
- if (!intel_hdcp_gsc_check_status(display->drm))
+ if (!intel_parent_hdcp_gsc_check_status(display))
return false;
}
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h
deleted file mode 100644
index 9305c14aaffe..000000000000
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef __INTEL_HDCP_GSC_H__
-#define __INTEL_HDCP_GSC_H__
-
-#include <linux/types.h>
-
-struct drm_device;
-struct intel_hdcp_gsc_context;
-
-ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
- void *msg_in, size_t msg_in_len,
- void *msg_out, size_t msg_out_len);
-bool intel_hdcp_gsc_check_status(struct drm_device *drm);
-
-struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm);
-void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context);
-
-#endif /* __INTEL_HDCP_GCS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c
index 98967bb148e3..781667b710b4 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c
@@ -10,8 +10,8 @@
#include "intel_display_core.h"
#include "intel_display_types.h"
-#include "intel_hdcp_gsc.h"
#include "intel_hdcp_gsc_message.h"
+#include "intel_parent.h"
static int
intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
@@ -44,10 +44,9 @@ intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
session_init_in.protocol = data->protocol;
- byte = intel_hdcp_gsc_msg_send(gsc_context, &session_init_in,
- sizeof(session_init_in),
- &session_init_out,
- sizeof(session_init_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &session_init_in, sizeof(session_init_in),
+ &session_init_out, sizeof(session_init_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -106,10 +105,9 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
- byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_rxcert_in,
- sizeof(verify_rxcert_in),
- &verify_rxcert_out,
- sizeof(verify_rxcert_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &verify_rxcert_in, sizeof(verify_rxcert_in),
+ &verify_rxcert_out, sizeof(verify_rxcert_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
return byte;
@@ -169,10 +167,9 @@ intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
HDCP_2_2_H_PRIME_LEN);
- byte = intel_hdcp_gsc_msg_send(gsc_context, &send_hprime_in,
- sizeof(send_hprime_in),
- &send_hprime_out,
- sizeof(send_hprime_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &send_hprime_in, sizeof(send_hprime_in),
+ &send_hprime_out, sizeof(send_hprime_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -220,10 +217,9 @@ intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *dat
memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
HDCP_2_2_E_KH_KM_LEN);
- byte = intel_hdcp_gsc_msg_send(gsc_context, &pairing_info_in,
- sizeof(pairing_info_in),
- &pairing_info_out,
- sizeof(pairing_info_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &pairing_info_in, sizeof(pairing_info_in),
+ &pairing_info_out, sizeof(pairing_info_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -269,8 +265,9 @@ intel_hdcp_gsc_initiate_locality_check(struct device *dev,
lc_init_in.port.physical_port = (u8)data->hdcp_ddi;
lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
- byte = intel_hdcp_gsc_msg_send(gsc_context, &lc_init_in, sizeof(lc_init_in),
- &lc_init_out, sizeof(lc_init_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &lc_init_in, sizeof(lc_init_in),
+ &lc_init_out, sizeof(lc_init_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -321,10 +318,9 @@ intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
HDCP_2_2_L_PRIME_LEN);
- byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_lprime_in,
- sizeof(verify_lprime_in),
- &verify_lprime_out,
- sizeof(verify_lprime_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &verify_lprime_in, sizeof(verify_lprime_in),
+ &verify_lprime_out, sizeof(verify_lprime_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -370,8 +366,9 @@ intel_hdcp_gsc_get_session_key(struct device *dev,
get_skey_in.port.physical_port = (u8)data->hdcp_ddi;
get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
- byte = intel_hdcp_gsc_msg_send(gsc_context, &get_skey_in, sizeof(get_skey_in),
- &get_skey_out, sizeof(get_skey_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &get_skey_in, sizeof(get_skey_in),
+ &get_skey_out, sizeof(get_skey_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -434,10 +431,9 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
HDCP_2_2_RECEIVER_IDS_MAX_LEN);
- byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_repeater_in,
- sizeof(verify_repeater_in),
- &verify_repeater_out,
- sizeof(verify_repeater_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &verify_repeater_in, sizeof(verify_repeater_in),
+ &verify_repeater_out, sizeof(verify_repeater_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -504,9 +500,9 @@ intel_hdcp_gsc_verify_mprime(struct device *dev,
verify_mprime_in->k = cpu_to_be16(data->k);
- byte = intel_hdcp_gsc_msg_send(gsc_context, verify_mprime_in, cmd_size,
- &verify_mprime_out,
- sizeof(verify_mprime_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ verify_mprime_in, cmd_size,
+ &verify_mprime_out, sizeof(verify_mprime_out));
kfree(verify_mprime_in);
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
@@ -552,10 +548,9 @@ static int intel_hdcp_gsc_enable_authentication(struct device *dev,
enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
enable_auth_in.stream_type = data->streams[0].stream_type;
- byte = intel_hdcp_gsc_msg_send(gsc_context, &enable_auth_in,
- sizeof(enable_auth_in),
- &enable_auth_out,
- sizeof(enable_auth_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &enable_auth_in, sizeof(enable_auth_in),
+ &enable_auth_out, sizeof(enable_auth_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -599,10 +594,9 @@ intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
session_close_in.port.physical_port = (u8)data->hdcp_ddi;
session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
- byte = intel_hdcp_gsc_msg_send(gsc_context, &session_close_in,
- sizeof(session_close_in),
- &session_close_out,
- sizeof(session_close_out));
+ byte = intel_parent_hdcp_gsc_msg_send(display, gsc_context,
+ &session_close_in, sizeof(session_close_in),
+ &session_close_out, sizeof(session_close_out));
if (byte < 0) {
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
@@ -645,7 +639,7 @@ int intel_hdcp_gsc_init(struct intel_display *display)
mutex_lock(&display->hdcp.hdcp_mutex);
- gsc_context = intel_hdcp_gsc_context_alloc(display->drm);
+ gsc_context = intel_parent_hdcp_gsc_context_alloc(display);
if (IS_ERR(gsc_context)) {
ret = PTR_ERR(gsc_context);
kfree(arbiter);
@@ -665,7 +659,7 @@ out:
void intel_hdcp_gsc_fini(struct intel_display *display)
{
- intel_hdcp_gsc_context_free(display->hdcp.gsc_context);
+ intel_parent_hdcp_gsc_context_free(display, display->hdcp.gsc_context);
display->hdcp.gsc_context = NULL;
kfree(display->hdcp.arbiter);
display->hdcp.arbiter = NULL;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 908faf17f93d..055e68810d0d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2518,7 +2518,7 @@ intel_hdmi_set_edid(struct drm_connector *_connector)
struct intel_display *display = to_intel_display(connector);
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct i2c_adapter *ddc = connector->base.ddc;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
const struct drm_edid *drm_edid;
bool connected = false;
@@ -2561,7 +2561,7 @@ intel_hdmi_detect(struct drm_connector *_connector, bool force)
enum drm_connector_status status = connector_status_disconnected;
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
connector->base.base.id, connector->base.name);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 235706229ffb..970aa95ee344 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -27,8 +27,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include "i915_drv.h"
-#include "i915_irq.h"
#include "intel_connector.h"
#include "intel_display_core.h"
#include "intel_display_power.h"
@@ -39,6 +37,7 @@
#include "intel_hdcp.h"
#include "intel_hotplug.h"
#include "intel_hotplug_irq.h"
+#include "intel_parent.h"
/**
* DOC: Hotplug
@@ -786,7 +785,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
container_of(work, typeof(*display), hotplug.poll_init_work);
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool enabled;
mutex_lock(&display->drm->mode_config.mutex);
@@ -1177,13 +1176,12 @@ bool intel_hpd_schedule_detection(struct intel_display *display)
static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
{
struct intel_display *display = m->private;
- struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_hotplug *hotplug = &display->hotplug;
/* Synchronize with everything first in case there's been an HPD
* storm, but we haven't finished handling it in the kernel yet
*/
- intel_synchronize_irq(dev_priv);
+ intel_parent_irq_synchronize(display);
flush_work(&display->hotplug.dig_port_work);
flush_delayed_work(&display->hotplug.hotplug_work);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
index 46c47b3d6f42..82c39e4ffa37 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
@@ -519,12 +519,9 @@ void xelpdp_pica_irq_handler(struct intel_display *display, u32 iir)
{
enum hpd_pin pin;
u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
- u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
+ u32 trigger_aux = iir & xelpdp_pica_aux_mask(display);
u32 pin_mask = 0, long_mask = 0;
- if (DISPLAY_VER(display) >= 20)
- trigger_aux |= iir & XE2LPD_AUX_DDI_MASK;
-
for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
u32 val;
diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c
index 42284e9928f2..5b41abe1c64d 100644
--- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c
@@ -71,7 +71,6 @@
#include <drm/drm_print.h>
#include <drm/intel/intel_lpe_audio.h>
-#include "i915_irq.h"
#include "intel_audio_regs.h"
#include "intel_de.h"
#include "intel_lpe_audio.h"
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c
index a67eb4f7f897..939c8975fd4c 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c
@@ -1324,11 +1324,11 @@ intel_lt_phy_config_changed(struct intel_encoder *encoder,
return true;
}
-static intel_wakeref_t intel_lt_phy_transaction_begin(struct intel_encoder *encoder)
+static struct ref_tracker *intel_lt_phy_transaction_begin(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
intel_psr_pause(intel_dp);
wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF);
@@ -1336,7 +1336,7 @@ static intel_wakeref_t intel_lt_phy_transaction_begin(struct intel_encoder *enco
return wakeref;
}
-static void intel_lt_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
+static void intel_lt_phy_transaction_end(struct intel_encoder *encoder, struct ref_tracker *wakeref)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -1932,7 +1932,7 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
enum port port = encoder->port;
- intel_wakeref_t wakeref = 0;
+ struct ref_tracker *wakeref = 0;
u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
? (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) |
XE3PLPDP_LANE_PHY_PULSE_STATUS(1))
@@ -2060,7 +2060,7 @@ void intel_lt_phy_pll_disable(struct intel_encoder *encoder)
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
enum port port = encoder->port;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
u32 lane_pipe_reset = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
? (XELPDP_LANE_PIPE_RESET(0) |
@@ -2137,7 +2137,7 @@ void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder,
struct intel_display *display = to_intel_display(encoder);
const struct intel_ddi_buf_trans *trans;
u8 owned_lane_mask;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int n_entries, ln;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
@@ -2222,7 +2222,7 @@ void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
{
u8 owned_lane_mask;
u8 lane;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
int i, j, k;
pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder));
@@ -2310,7 +2310,7 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
if (intel_tc_port_in_tbt_alt_mode(dig_port))
- intel_mtl_tbt_pll_enable(encoder, crtc_state);
+ intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock);
else
intel_lt_phy_pll_enable(encoder, crtc_state);
}
@@ -2320,7 +2320,7 @@ void intel_xe3plpd_pll_disable(struct intel_encoder *encoder)
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
if (intel_tc_port_in_tbt_alt_mode(dig_port))
- intel_mtl_tbt_pll_disable(encoder);
+ intel_mtl_tbt_pll_disable_clock(encoder);
else
intel_lt_phy_pll_disable(encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h
index b7911acd7dcd..7659c92b6c3c 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
@@ -42,6 +42,4 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_xe3plpd_pll_disable(struct intel_encoder *encoder);
-#define HAS_LT_PHY(display) (DISPLAY_VER(display) >= 35)
-
#endif /* __INTEL_LT_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 89aeb4fb340e..457d60863536 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -105,7 +105,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(display, encoder->power_domain);
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
index 0dcb0597879a..d10cbf69a5f8 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
@@ -940,7 +940,7 @@ void intel_modeset_setup_hw_state(struct intel_display *display,
{
struct intel_encoder *encoder;
struct intel_crtc *crtc;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT);
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index b361a77cd235..12a00121c274 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -246,7 +246,6 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state,
verify_crtc_state(state, crtc);
intel_dpll_state_verify(state, crtc);
intel_mpllb_state_verify(state, crtc);
- intel_cx0pll_state_verify(state, crtc);
intel_lt_phy_pll_state_verify(state, crtc);
}
diff --git a/drivers/gpu/drm/i915/display/intel_panic.c b/drivers/gpu/drm/i915/display/intel_panic.c
deleted file mode 100644
index 7311ce4e8b6c..000000000000
--- a/drivers/gpu/drm/i915/display/intel_panic.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: MIT
-/* Copyright © 2025 Intel Corporation */
-
-#include <drm/drm_panic.h>
-
-#include "gem/i915_gem_object.h"
-#include "intel_display_types.h"
-#include "intel_fb.h"
-#include "intel_panic.h"
-
-struct intel_panic *intel_panic_alloc(void)
-{
- return i915_gem_object_alloc_panic();
-}
-
-int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
-{
- struct intel_framebuffer *fb = sb->private;
- struct drm_gem_object *obj = intel_fb_bo(&fb->base);
-
- return i915_gem_object_panic_setup(panic, sb, obj, fb->panic_tiling);
-}
-
-void intel_panic_finish(struct intel_panic *panic)
-{
- return i915_gem_object_panic_finish(panic);
-}
diff --git a/drivers/gpu/drm/i915/display/intel_panic.h b/drivers/gpu/drm/i915/display/intel_panic.h
deleted file mode 100644
index afb472e924aa..000000000000
--- a/drivers/gpu/drm/i915/display/intel_panic.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/* Copyright © 2025 Intel Corporation */
-
-#ifndef __INTEL_PANIC_H__
-#define __INTEL_PANIC_H__
-
-struct drm_scanout_buffer;
-struct intel_panic;
-
-struct intel_panic *intel_panic_alloc(void);
-int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb);
-void intel_panic_finish(struct intel_panic *panic);
-
-#endif /* __INTEL_PANIC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c
new file mode 100644
index 000000000000..72ae553f79a4
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_parent.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+/*
+ * Convenience wrapper functions to call the parent interface functions:
+ *
+ * - display->parent->SUBSTRUCT->FUNCTION()
+ * - display->parent->FUNCTION()
+ *
+ * All functions here should be named accordingly:
+ *
+ * - intel_parent_SUBSTRUCT_FUNCTION()
+ * - intel_parent_FUNCTION()
+ *
+ * These functions may use display driver specific types for parameters and
+ * return values, translating them to and from the generic types used in the
+ * function pointer interface.
+ */
+
+#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
+
+#include "intel_display_core.h"
+#include "intel_parent.h"
+
+/* hdcp */
+ssize_t intel_parent_hdcp_gsc_msg_send(struct intel_display *display,
+ struct intel_hdcp_gsc_context *gsc_context,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len)
+{
+ return display->parent->hdcp->gsc_msg_send(gsc_context, msg_in, msg_in_len, msg_out, msg_out_len);
+}
+
+bool intel_parent_hdcp_gsc_check_status(struct intel_display *display)
+{
+ return display->parent->hdcp->gsc_check_status(display->drm);
+}
+
+struct intel_hdcp_gsc_context *intel_parent_hdcp_gsc_context_alloc(struct intel_display *display)
+{
+ return display->parent->hdcp->gsc_context_alloc(display->drm);
+}
+
+void intel_parent_hdcp_gsc_context_free(struct intel_display *display,
+ struct intel_hdcp_gsc_context *gsc_context)
+{
+ display->parent->hdcp->gsc_context_free(gsc_context);
+}
+
+/* irq */
+bool intel_parent_irq_enabled(struct intel_display *display)
+{
+ return display->parent->irq->enabled(display->drm);
+}
+
+void intel_parent_irq_synchronize(struct intel_display *display)
+{
+ display->parent->irq->synchronize(display->drm);
+}
+
+/* panic */
+struct intel_panic *intel_parent_panic_alloc(struct intel_display *display)
+{
+ return display->parent->panic->alloc();
+}
+
+int intel_parent_panic_setup(struct intel_display *display, struct intel_panic *panic, struct drm_scanout_buffer *sb)
+{
+ return display->parent->panic->setup(panic, sb);
+}
+
+void intel_parent_panic_finish(struct intel_display *display, struct intel_panic *panic)
+{
+ display->parent->panic->finish(panic);
+}
+
+/* pc8 */
+void intel_parent_pc8_block(struct intel_display *display)
+{
+ if (drm_WARN_ON_ONCE(display->drm, !display->parent->pc8))
+ return;
+
+ display->parent->pc8->block(display->drm);
+}
+
+void intel_parent_pc8_unblock(struct intel_display *display)
+{
+ if (drm_WARN_ON_ONCE(display->drm, !display->parent->pc8))
+ return;
+
+ display->parent->pc8->unblock(display->drm);
+}
+
+/* rps */
+bool intel_parent_rps_available(struct intel_display *display)
+{
+ return display->parent->rps;
+}
+
+void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence)
+{
+ if (display->parent->rps)
+ display->parent->rps->boost_if_not_started(fence);
+}
+
+void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive)
+{
+ if (display->parent->rps)
+ display->parent->rps->mark_interactive(display->drm, interactive);
+}
+
+void intel_parent_rps_ilk_irq_handler(struct intel_display *display)
+{
+ if (display->parent->rps)
+ display->parent->rps->ilk_irq_handler(display->drm);
+}
+
+/* stolen */
+int intel_parent_stolen_insert_node_in_range(struct intel_display *display,
+ struct intel_stolen_node *node, u64 size,
+ unsigned int align, u64 start, u64 end)
+{
+ return display->parent->stolen->insert_node_in_range(node, size, align, start, end);
+}
+
+int intel_parent_stolen_insert_node(struct intel_display *display, struct intel_stolen_node *node, u64 size,
+ unsigned int align)
+{
+ if (drm_WARN_ON_ONCE(display->drm, !display->parent->stolen->insert_node))
+ return -ENODEV;
+
+ return display->parent->stolen->insert_node(node, size, align);
+}
+
+void intel_parent_stolen_remove_node(struct intel_display *display,
+ struct intel_stolen_node *node)
+{
+ display->parent->stolen->remove_node(node);
+}
+
+bool intel_parent_stolen_initialized(struct intel_display *display)
+{
+ return display->parent->stolen->initialized(display->drm);
+}
+
+bool intel_parent_stolen_node_allocated(struct intel_display *display,
+ const struct intel_stolen_node *node)
+{
+ return display->parent->stolen->node_allocated(node);
+}
+
+u32 intel_parent_stolen_node_offset(struct intel_display *display, struct intel_stolen_node *node)
+{
+ return display->parent->stolen->node_offset(node);
+}
+
+u64 intel_parent_stolen_area_address(struct intel_display *display)
+{
+ if (drm_WARN_ON_ONCE(display->drm, !display->parent->stolen->area_address))
+ return 0;
+
+ return display->parent->stolen->area_address(display->drm);
+}
+
+u64 intel_parent_stolen_area_size(struct intel_display *display)
+{
+ if (drm_WARN_ON_ONCE(display->drm, !display->parent->stolen->area_size))
+ return 0;
+
+ return display->parent->stolen->area_size(display->drm);
+}
+
+u64 intel_parent_stolen_node_address(struct intel_display *display, struct intel_stolen_node *node)
+{
+ return display->parent->stolen->node_address(node);
+}
+
+u64 intel_parent_stolen_node_size(struct intel_display *display, const struct intel_stolen_node *node)
+{
+ return display->parent->stolen->node_size(node);
+}
+
+struct intel_stolen_node *intel_parent_stolen_node_alloc(struct intel_display *display)
+{
+ return display->parent->stolen->node_alloc(display->drm);
+}
+
+void intel_parent_stolen_node_free(struct intel_display *display, const struct intel_stolen_node *node)
+{
+ display->parent->stolen->node_free(node);
+}
+
+/* generic */
+void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence)
+{
+ if (display->parent->fence_priority_display)
+ display->parent->fence_priority_display(fence);
+}
+
+bool intel_parent_has_auxccs(struct intel_display *display)
+{
+ return display->parent->has_auxccs && display->parent->has_auxccs(display->drm);
+}
+
+bool intel_parent_has_fenced_regions(struct intel_display *display)
+{
+ return display->parent->has_fenced_regions && display->parent->has_fenced_regions(display->drm);
+}
+
+bool intel_parent_vgpu_active(struct intel_display *display)
+{
+ return display->parent->vgpu_active && display->parent->vgpu_active(display->drm);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h
new file mode 100644
index 000000000000..47cdc14f9aa2
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_parent.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __INTEL_PARENT_H__
+#define __INTEL_PARENT_H__
+
+#include <linux/types.h>
+
+struct dma_fence;
+struct drm_scanout_buffer;
+struct intel_display;
+struct intel_hdcp_gsc_context;
+struct intel_panic;
+struct intel_stolen_node;
+
+/* hdcp */
+ssize_t intel_parent_hdcp_gsc_msg_send(struct intel_display *display,
+ struct intel_hdcp_gsc_context *gsc_context,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len);
+bool intel_parent_hdcp_gsc_check_status(struct intel_display *display);
+struct intel_hdcp_gsc_context *intel_parent_hdcp_gsc_context_alloc(struct intel_display *display);
+void intel_parent_hdcp_gsc_context_free(struct intel_display *display,
+ struct intel_hdcp_gsc_context *gsc_context);
+
+/* irq */
+bool intel_parent_irq_enabled(struct intel_display *display);
+void intel_parent_irq_synchronize(struct intel_display *display);
+
+/* panic */
+struct intel_panic *intel_parent_panic_alloc(struct intel_display *display);
+int intel_parent_panic_setup(struct intel_display *display, struct intel_panic *panic, struct drm_scanout_buffer *sb);
+void intel_parent_panic_finish(struct intel_display *display, struct intel_panic *panic);
+
+/* pc8 */
+void intel_parent_pc8_block(struct intel_display *display);
+void intel_parent_pc8_unblock(struct intel_display *display);
+
+/* rps */
+bool intel_parent_rps_available(struct intel_display *display);
+void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence);
+void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive);
+void intel_parent_rps_ilk_irq_handler(struct intel_display *display);
+
+/* stolen */
+int intel_parent_stolen_insert_node_in_range(struct intel_display *display,
+ struct intel_stolen_node *node, u64 size,
+ unsigned int align, u64 start, u64 end);
+int intel_parent_stolen_insert_node(struct intel_display *display, struct intel_stolen_node *node, u64 size,
+ unsigned int align);
+void intel_parent_stolen_remove_node(struct intel_display *display,
+ struct intel_stolen_node *node);
+bool intel_parent_stolen_initialized(struct intel_display *display);
+bool intel_parent_stolen_node_allocated(struct intel_display *display,
+ const struct intel_stolen_node *node);
+u32 intel_parent_stolen_node_offset(struct intel_display *display, struct intel_stolen_node *node);
+u64 intel_parent_stolen_area_address(struct intel_display *display);
+u64 intel_parent_stolen_area_size(struct intel_display *display);
+u64 intel_parent_stolen_node_address(struct intel_display *display, struct intel_stolen_node *node);
+u64 intel_parent_stolen_node_size(struct intel_display *display, const struct intel_stolen_node *node);
+struct intel_stolen_node *intel_parent_stolen_node_alloc(struct intel_display *display);
+void intel_parent_stolen_node_free(struct intel_display *display, const struct intel_stolen_node *node);
+
+/* generic */
+bool intel_parent_has_auxccs(struct intel_display *display);
+bool intel_parent_has_fenced_regions(struct intel_display *display);
+bool intel_parent_vgpu_active(struct intel_display *display);
+void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence);
+
+#endif /* __INTEL_PARENT_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
index 1f27643412f1..57586c78582d 100644
--- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
@@ -30,13 +30,12 @@
#include <drm/drm_print.h>
-#include "i915_drv.h"
-#include "i915_irq.h"
#include "intel_atomic.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
+#include "intel_parent.h"
#include "intel_pipe_crc.h"
#include "intel_pipe_crc_regs.h"
@@ -589,7 +588,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *_crtc, const char *source_name)
enum intel_display_power_domain power_domain;
enum intel_pipe_crc_source source;
enum pipe pipe = crtc->pipe;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 val = 0; /* shut up gcc */
int ret = 0;
bool enable;
@@ -658,7 +657,6 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc)
void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
enum pipe pipe = crtc->pipe;
@@ -669,5 +667,5 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc)
intel_de_write(display, PIPE_CRC_CTL(display, pipe), 0);
intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe));
- intel_synchronize_irq(dev_priv);
+ intel_parent_irq_synchronize(display);
}
diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c
index ab6a58530b39..3dc2ed52147f 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_plane.c
@@ -45,7 +45,6 @@
#include <drm/drm_panic.h>
#include <drm/drm_print.h>
-#include "gem/i915_gem_object.h"
#include "i9xx_plane_regs.h"
#include "intel_cdclk.h"
#include "intel_cursor.h"
@@ -56,7 +55,7 @@
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_fbdev.h"
-#include "intel_panic.h"
+#include "intel_parent.h"
#include "intel_plane.h"
#include "intel_psr.h"
#include "skl_scaler.h"
@@ -179,25 +178,29 @@ bool intel_plane_needs_physical(struct intel_plane *plane)
DISPLAY_INFO(display)->cursor_needs_physical;
}
-bool intel_plane_can_async_flip(struct intel_plane *plane, u32 format,
+bool intel_plane_can_async_flip(struct intel_plane *plane,
+ const struct drm_format_info *info,
u64 modifier)
{
- if (intel_format_info_is_yuv_semiplanar(drm_format_info(format), modifier) ||
- format == DRM_FORMAT_C8)
+ if (intel_format_info_is_yuv_semiplanar(info, modifier) ||
+ info->format == DRM_FORMAT_C8)
return false;
return plane->can_async_flip && plane->can_async_flip(modifier);
}
-bool intel_plane_format_mod_supported_async(struct drm_plane *plane,
- u32 format,
- u64 modifier)
+bool intel_plane_format_mod_supported_async(struct drm_plane *_plane,
+ u32 format, u64 modifier)
{
- if (!plane->funcs->format_mod_supported(plane, format, modifier))
+ struct intel_plane *plane = to_intel_plane(_plane);
+ const struct drm_format_info *info;
+
+ if (!plane->base.funcs->format_mod_supported(&plane->base, format, modifier))
return false;
- return intel_plane_can_async_flip(to_intel_plane(plane),
- format, modifier);
+ info = drm_get_format_info(plane->base.dev, format, modifier);
+
+ return intel_plane_can_async_flip(plane, info, modifier);
}
unsigned int intel_adjusted_rate(const struct drm_rect *src,
@@ -651,11 +654,10 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
ilk_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state))
new_crtc_state->disable_cxsr = true;
- if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) {
+ if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state))
new_crtc_state->do_async_flip = true;
- new_crtc_state->async_flip_planes |= BIT(plane->id);
- } else if (plane->need_async_flip_toggle_wa &&
- new_crtc_state->uapi.async_flip) {
+
+ if (new_crtc_state->uapi.async_flip) {
/*
* On platforms with double buffered async flip bit we
* set the bit already one frame early during the sync
@@ -663,6 +665,9 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
* hardware will therefore be ready to perform a real
* async flip during the next commit, without having
* to wait yet another frame for the bit to latch.
+ *
+ * async_flip_planes bitmask is also used by selective
+ * fetch calculation to choose full frame update.
*/
new_crtc_state->async_flip_planes |= BIT(plane->id);
}
@@ -1235,8 +1240,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
goto unpin_fb;
if (new_plane_state->uapi.fence) {
- i915_gem_fence_wait_priority_display(new_plane_state->uapi.fence);
-
+ intel_parent_fence_priority_display(display, new_plane_state->uapi.fence);
intel_display_rps_boost_after_vblank(new_plane_state->hw.crtc,
new_plane_state->uapi.fence);
}
@@ -1330,33 +1334,33 @@ static unsigned int intel_4tile_get_offset(unsigned int width, unsigned int x, u
return offset;
}
-static void intel_panic_flush(struct drm_plane *plane)
+static void intel_panic_flush(struct drm_plane *_plane)
{
- struct intel_plane_state *plane_state = to_intel_plane_state(plane->state);
- struct intel_crtc_state *crtc_state = to_intel_crtc_state(plane->state->crtc->state);
- struct intel_plane *iplane = to_intel_plane(plane);
- struct intel_display *display = to_intel_display(iplane);
- struct drm_framebuffer *fb = plane_state->hw.fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+ struct intel_plane *plane = to_intel_plane(_plane);
+ struct intel_display *display = to_intel_display(plane);
+ const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state);
+ struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc);
+ const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
+ const struct intel_framebuffer *fb = to_intel_framebuffer(plane_state->hw.fb);
- intel_panic_finish(intel_fb->panic);
+ intel_parent_panic_finish(display, fb->panic);
if (crtc_state->enable_psr2_sel_fetch) {
/* Force a full update for psr2 */
- intel_psr2_panic_force_full_update(display, crtc_state);
+ intel_psr2_panic_force_full_update(crtc_state);
}
/* Flush the cache and don't disable tiling if it's the fbdev framebuffer.*/
- if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
+ if (fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
struct iosys_map map;
intel_fbdev_get_map(display->fbdev.fbdev, &map);
- drm_clflush_virt_range(map.vaddr, fb->pitches[0] * fb->height);
+ drm_clflush_virt_range(map.vaddr, fb->base.pitches[0] * fb->base.height);
return;
}
- if (fb->modifier && iplane->disable_tiling)
- iplane->disable_tiling(iplane);
+ if (fb->base.modifier != DRM_FORMAT_MOD_LINEAR && plane->disable_tiling)
+ plane->disable_tiling(plane);
}
static unsigned int (*intel_get_tiling_func(u64 fb_modifier))(unsigned int width,
@@ -1394,45 +1398,43 @@ static int intel_get_scanout_buffer(struct drm_plane *plane,
{
struct intel_plane_state *plane_state;
struct drm_gem_object *obj;
- struct drm_framebuffer *fb;
- struct intel_framebuffer *intel_fb;
+ struct intel_framebuffer *fb;
struct intel_display *display = to_intel_display(plane->dev);
if (!plane->state || !plane->state->fb || !plane->state->visible)
return -ENODEV;
plane_state = to_intel_plane_state(plane->state);
- fb = plane_state->hw.fb;
- intel_fb = to_intel_framebuffer(fb);
+ fb = to_intel_framebuffer(plane_state->hw.fb);
- obj = intel_fb_bo(fb);
+ obj = intel_fb_bo(&fb->base);
if (!obj)
return -ENODEV;
- if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
+ if (fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
intel_fbdev_get_map(display->fbdev.fbdev, &sb->map[0]);
} else {
int ret;
/* Can't disable tiling if DPT is in use */
- if (intel_fb_uses_dpt(fb)) {
- if (fb->format->cpp[0] != 4)
+ if (intel_fb_uses_dpt(&fb->base)) {
+ if (fb->base.format->cpp[0] != 4)
return -EOPNOTSUPP;
- intel_fb->panic_tiling = intel_get_tiling_func(fb->modifier);
- if (!intel_fb->panic_tiling)
+ fb->panic_tiling = intel_get_tiling_func(fb->base.modifier);
+ if (!fb->panic_tiling)
return -EOPNOTSUPP;
}
- sb->private = intel_fb;
- ret = intel_panic_setup(intel_fb->panic, sb);
+ sb->private = fb;
+ ret = intel_parent_panic_setup(display, fb->panic, sb);
if (ret)
return ret;
}
- sb->width = fb->width;
- sb->height = fb->height;
+ sb->width = fb->base.width;
+ sb->height = fb->base.height;
/* Use the generic linear format, because tiling, RC, CCS, CC
* will be disabled in disable_tiling()
*/
- sb->format = drm_format_info(fb->format->format);
- sb->pitch[0] = fb->pitches[0];
+ sb->format = drm_format_info(fb->base.format->format);
+ sb->pitch[0] = fb->base.pitches[0];
return 0;
}
@@ -1464,7 +1466,7 @@ void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_sta
old_plane_state->ggtt_vma == new_plane_state->ggtt_vma)
return;
- drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state->uapi.crtc,
+ drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state->hw.crtc,
intel_cursor_unpin_work);
}
diff --git a/drivers/gpu/drm/i915/display/intel_plane.h b/drivers/gpu/drm/i915/display/intel_plane.h
index 4e99df9de3e8..5a8f2f3baab5 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.h
+++ b/drivers/gpu/drm/i915/display/intel_plane.h
@@ -8,6 +8,7 @@
#include <linux/types.h>
+struct drm_format_info;
struct drm_plane;
struct drm_property;
struct drm_rect;
@@ -21,7 +22,8 @@ enum plane_id;
struct intel_plane *
intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id);
-bool intel_plane_can_async_flip(struct intel_plane *plane, u32 format,
+bool intel_plane_can_async_flip(struct intel_plane *plane,
+ const struct drm_format_info *info,
u64 modifier);
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c
index a1de1ec564d1..ff1afd3a8f20 100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
@@ -39,7 +39,7 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
- if (!crtc_state->uapi.active)
+ if (!crtc_state->hw.active)
continue;
if (!plane_state->ggtt_vma)
@@ -411,10 +411,12 @@ void intel_initial_plane_config(struct intel_display *display)
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 (!to_intel_crtc_state(crtc->base.state)->uapi.active)
+ if (!crtc_state->hw.active)
continue;
/*
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 25692a547764..b217ec7aa758 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -67,10 +67,10 @@ static const char *pps_name(struct intel_dp *intel_dp)
return "PPS <invalid>";
}
-intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
+struct ref_tracker *intel_pps_lock(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
/*
* See vlv_pps_reset_all() why we need a power domain reference here.
@@ -81,8 +81,7 @@ intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
return wakeref;
}
-intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp,
- intel_wakeref_t wakeref)
+struct ref_tracker *intel_pps_unlock(struct intel_dp *intel_dp, struct ref_tracker *wakeref)
{
struct intel_display *display = to_intel_display(intel_dp);
@@ -697,12 +696,10 @@ static void wait_panel_power_cycle(struct intel_dp *intel_dp)
void intel_pps_wait_power_cycle(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
wait_panel_power_cycle(intel_dp);
}
@@ -811,14 +808,13 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
void intel_pps_vdd_on(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_wakeref_t wakeref;
bool vdd;
if (!intel_dp_is_edp(intel_dp))
return;
vdd = false;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
vdd = intel_pps_vdd_on_unlocked(intel_dp);
INTEL_DISPLAY_STATE_WARN(display, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
dp_to_dig_port(intel_dp)->base.base.base.id,
@@ -873,8 +869,6 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
if (!intel_dp_is_edp(intel_dp))
return;
@@ -883,7 +877,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
* vdd might still be enabled due to the delayed vdd off.
* Make sure vdd is actually turned off here.
*/
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_pps_vdd_off_sync_unlocked(intel_dp);
}
@@ -892,9 +886,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
struct intel_pps *pps = container_of(to_delayed_work(__work),
struct intel_pps, panel_vdd_work);
struct intel_dp *intel_dp = container_of(pps, struct intel_dp, pps);
- intel_wakeref_t wakeref;
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
if (!intel_dp->pps.want_panel_vdd)
intel_pps_vdd_off_sync_unlocked(intel_dp);
}
@@ -952,12 +945,10 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
void intel_pps_vdd_off(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_pps_vdd_off_unlocked(intel_dp, false);
}
@@ -1026,12 +1017,10 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
void intel_pps_on(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_pps_on_unlocked(intel_dp);
}
@@ -1082,12 +1071,10 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
void intel_pps_off(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_pps_off_unlocked(intel_dp);
}
@@ -1095,7 +1082,6 @@ void intel_pps_off(struct intel_dp *intel_dp)
void intel_pps_backlight_on(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_wakeref_t wakeref;
/*
* If we enable the backlight right away following a panel power
@@ -1105,7 +1091,7 @@ void intel_pps_backlight_on(struct intel_dp *intel_dp)
*/
wait_backlight_on(intel_dp);
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
u32 pp;
@@ -1121,12 +1107,11 @@ void intel_pps_backlight_on(struct intel_dp *intel_dp)
void intel_pps_backlight_off(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_wakeref_t wakeref;
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
u32 pp;
@@ -1149,11 +1134,10 @@ void intel_pps_backlight_power(struct intel_connector *connector, bool enable)
{
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
- intel_wakeref_t wakeref;
bool is_enabled;
is_enabled = false;
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
if (is_enabled == enable)
return;
@@ -1251,9 +1235,7 @@ void vlv_pps_pipe_init(struct intel_dp *intel_dp)
/* Call on all DP, not just eDP */
void vlv_pps_pipe_reset(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_dp->pps.vlv_active_pipe = vlv_active_pipe(intel_dp);
}
@@ -1329,9 +1311,7 @@ void vlv_pps_port_disable(struct intel_encoder *encoder,
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- intel_wakeref_t wakeref;
-
- with_intel_pps_lock(intel_dp, wakeref)
+ with_intel_pps_lock(intel_dp)
intel_dp->pps.vlv_active_pipe = INVALID_PIPE;
}
@@ -1362,10 +1342,9 @@ static void pps_vdd_init(struct intel_dp *intel_dp)
bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
bool have_power = false;
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
have_power = edp_have_panel_power(intel_dp) ||
edp_have_panel_vdd(intel_dp);
}
@@ -1692,12 +1671,11 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
void intel_pps_encoder_reset(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_wakeref_t wakeref;
if (!intel_dp_is_edp(intel_dp))
return;
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
/*
* Reinit the power sequencer also on the resume path, in case
* BIOS did something nasty with it.
@@ -1716,7 +1694,6 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
bool intel_pps_init(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
bool ret;
intel_dp->pps.initializing = true;
@@ -1724,7 +1701,7 @@ bool intel_pps_init(struct intel_dp *intel_dp)
pps_init_timestamps(intel_dp);
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
ret = pps_initial_setup(intel_dp);
pps_init_delays(intel_dp);
@@ -1760,9 +1737,7 @@ static void pps_init_late(struct intel_dp *intel_dp)
void intel_pps_init_late(struct intel_dp *intel_dp)
{
- intel_wakeref_t wakeref;
-
- with_intel_pps_lock(intel_dp, wakeref) {
+ with_intel_pps_lock(intel_dp) {
/* Reinit delays after per-panel info has been parsed from VBT */
pps_init_late(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index c83007152f07..f7c96d75be45 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -8,20 +8,22 @@
#include <linux/types.h>
-#include "intel_wakeref.h"
-
enum pipe;
struct intel_connector;
struct intel_crtc_state;
struct intel_display;
struct intel_dp;
struct intel_encoder;
+struct ref_tracker;
+
+struct ref_tracker *intel_pps_lock(struct intel_dp *intel_dp);
+struct ref_tracker *intel_pps_unlock(struct intel_dp *intel_dp, struct ref_tracker *wakeref);
-intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp);
-intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
+#define __with_intel_pps_lock(dp, wf) \
+ for (struct ref_tracker *(wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))
-#define with_intel_pps_lock(dp, wf) \
- for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))
+#define with_intel_pps_lock(dp) \
+ __with_intel_pps_lock((dp), __UNIQUE_ID(wakeref))
void intel_pps_backlight_on(struct intel_dp *intel_dp);
void intel_pps_backlight_off(struct intel_dp *intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 08bca4573974..91f4ac86c7ad 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -494,82 +494,37 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
return val;
}
-static u8 intel_dp_get_su_capability(struct intel_dp *intel_dp)
-{
- u8 su_capability = 0;
-
- if (intel_dp->psr.sink_panel_replay_su_support) {
- if (drm_dp_dpcd_read_byte(&intel_dp->aux,
- DP_PANEL_REPLAY_CAP_CAPABILITY,
- &su_capability) < 0)
- return 0;
- } else {
- su_capability = intel_dp->psr_dpcd[1];
- }
-
- return su_capability;
-}
-
-static unsigned int
-intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp)
-{
- return intel_dp->psr.sink_panel_replay_su_support ?
- DP_PANEL_REPLAY_CAP_X_GRANULARITY :
- DP_PSR2_SU_X_GRANULARITY;
-}
-
-static unsigned int
-intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp)
-{
- return intel_dp->psr.sink_panel_replay_su_support ?
- DP_PANEL_REPLAY_CAP_Y_GRANULARITY :
- DP_PSR2_SU_Y_GRANULARITY;
-}
-
-/*
- * Note: Bits related to granularity are same in panel replay and psr
- * registers. Rely on PSR definitions on these "common" bits.
- */
-static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
+static void _psr_compute_su_granularity(struct intel_dp *intel_dp,
+ struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(intel_dp);
ssize_t r;
- u16 w;
+ __le16 w;
u8 y;
/*
- * TODO: Do we need to take into account panel supporting both PSR and
- * Panel replay?
- */
-
- /*
* If sink don't have specific granularity requirements set legacy
* ones.
*/
- if (!(intel_dp_get_su_capability(intel_dp) &
- DP_PSR2_SU_GRANULARITY_REQUIRED)) {
+ if (!(connector->dp.psr_caps.dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) {
/* As PSR2 HW sends full lines, we do not care about x granularity */
- w = 4;
+ w = cpu_to_le16(4);
y = 4;
goto exit;
}
- r = drm_dp_dpcd_read(&intel_dp->aux,
- intel_dp_get_su_x_granularity_offset(intel_dp),
- &w, 2);
- if (r != 2)
+ r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w));
+ if (r != sizeof(w))
drm_dbg_kms(display->drm,
"Unable to read selective update x granularity\n");
/*
* Spec says that if the value read is 0 the default granularity should
* be used instead.
*/
- if (r != 2 || w == 0)
- w = 4;
+ if (r != sizeof(w) || w == 0)
+ w = cpu_to_le16(4);
- r = drm_dp_dpcd_read(&intel_dp->aux,
- intel_dp_get_su_y_granularity_offset(intel_dp),
- &y, 1);
+ r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1);
if (r != 1) {
drm_dbg_kms(display->drm,
"Unable to read selective update y granularity\n");
@@ -579,17 +534,17 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
y = 1;
exit:
- intel_dp->psr.su_w_granularity = w;
- intel_dp->psr.su_y_granularity = y;
+ connector->dp.psr_caps.su_w_granularity = le16_to_cpu(w);
+ connector->dp.psr_caps.su_y_granularity = y;
}
static enum intel_panel_replay_dsc_support
-compute_pr_dsc_support(struct intel_dp *intel_dp)
+compute_pr_dsc_support(struct intel_connector *connector)
{
u8 pr_dsc_mode;
u8 val;
- val = intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)];
+ val = connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)];
pr_dsc_mode = REG_FIELD_GET8(DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK, val);
switch (pr_dsc_mode) {
@@ -621,7 +576,31 @@ static const char *panel_replay_dsc_support_str(enum intel_panel_replay_dsc_supp
};
}
-static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
+static void _panel_replay_compute_su_granularity(struct intel_connector *connector)
+{
+ u16 w;
+ u8 y;
+
+ if (!(connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
+ DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED)) {
+ w = 4;
+ y = 4;
+ goto exit;
+ }
+
+ /*
+ * Spec says that if the value read is 0 the default granularity should
+ * be used instead.
+ */
+ w = le16_to_cpu(*(__le16 *)&connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_X_GRANULARITY)]) ? : 4;
+ y = connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_Y_GRANULARITY)] ? : 1;
+
+exit:
+ connector->dp.panel_replay_caps.su_w_granularity = w;
+ connector->dp.panel_replay_caps.su_y_granularity = y;
+}
+
+static void _panel_replay_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(intel_dp);
int ret;
@@ -631,11 +610,12 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
return;
ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT,
- &intel_dp->pr_dpcd, sizeof(intel_dp->pr_dpcd));
+ &connector->dp.panel_replay_caps.dpcd,
+ sizeof(connector->dp.panel_replay_caps.dpcd));
if (ret < 0)
return;
- if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ if (!(connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
DP_PANEL_REPLAY_SUPPORT))
return;
@@ -646,7 +626,7 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
return;
}
- if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ if (!(connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)) {
drm_dbg_kms(display->drm,
"Panel doesn't support early transport, eDP Panel Replay not possible\n");
@@ -654,36 +634,40 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
}
}
+ connector->dp.panel_replay_caps.support = true;
intel_dp->psr.sink_panel_replay_support = true;
- if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
- DP_PANEL_REPLAY_SU_SUPPORT)
- intel_dp->psr.sink_panel_replay_su_support = true;
+ if (connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ DP_PANEL_REPLAY_SU_SUPPORT) {
+ connector->dp.panel_replay_caps.su_support = true;
+
+ _panel_replay_compute_su_granularity(connector);
+ }
- intel_dp->psr.sink_panel_replay_dsc_support = compute_pr_dsc_support(intel_dp);
+ connector->dp.panel_replay_caps.dsc_support = compute_pr_dsc_support(connector);
drm_dbg_kms(display->drm,
"Panel replay %sis supported by panel (in DSC mode: %s)\n",
- intel_dp->psr.sink_panel_replay_su_support ?
+ connector->dp.panel_replay_caps.su_support ?
"selective_update " : "",
- panel_replay_dsc_support_str(intel_dp->psr.sink_panel_replay_dsc_support));
+ panel_replay_dsc_support_str(connector->dp.panel_replay_caps.dsc_support));
}
-static void _psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(intel_dp);
int ret;
- ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
- sizeof(intel_dp->psr_dpcd));
+ ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PSR_SUPPORT, connector->dp.psr_caps.dpcd,
+ sizeof(connector->dp.psr_caps.dpcd));
if (ret < 0)
return;
- if (!intel_dp->psr_dpcd[0])
+ if (!connector->dp.psr_caps.dpcd[0])
return;
drm_dbg_kms(display->drm, "eDP panel supports PSR version %x\n",
- intel_dp->psr_dpcd[0]);
+ connector->dp.psr_caps.dpcd[0]);
if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
drm_dbg_kms(display->drm,
@@ -697,13 +681,14 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp)
return;
}
+ connector->dp.psr_caps.support = true;
intel_dp->psr.sink_support = true;
- intel_dp->psr.sink_sync_latency =
- intel_dp_get_sink_sync_latency(intel_dp);
+
+ connector->dp.psr_caps.sync_latency = intel_dp_get_sink_sync_latency(intel_dp);
if (DISPLAY_VER(display) >= 9 &&
- intel_dp->psr_dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
- bool y_req = intel_dp->psr_dpcd[1] &
+ connector->dp.psr_caps.dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
+ bool y_req = connector->dp.psr_caps.dpcd[1] &
DP_PSR2_SU_Y_COORDINATE_REQUIRED;
/*
@@ -717,22 +702,21 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp)
* Y-coordinate requirement panels we would need to enable
* GTC first.
*/
- intel_dp->psr.sink_psr2_support = y_req &&
+ connector->dp.psr_caps.su_support = y_req &&
intel_alpm_aux_wake_supported(intel_dp);
drm_dbg_kms(display->drm, "PSR2 %ssupported\n",
- intel_dp->psr.sink_psr2_support ? "" : "not ");
+ connector->dp.psr_caps.su_support ? "" : "not ");
}
+
+ if (connector->dp.psr_caps.su_support)
+ _psr_compute_su_granularity(intel_dp, connector);
}
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+void intel_psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
{
- _psr_init_dpcd(intel_dp);
+ _psr_init_dpcd(intel_dp, connector);
- _panel_replay_init_dpcd(intel_dp);
-
- if (intel_dp->psr.sink_psr2_support ||
- intel_dp->psr.sink_panel_replay_su_support)
- intel_dp_get_su_granularity(intel_dp);
+ _panel_replay_init_dpcd(intel_dp, connector);
}
static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
@@ -772,8 +756,9 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
aux_ctl);
}
-static bool psr2_su_region_et_valid(struct intel_dp *intel_dp, bool panel_replay)
+static bool psr2_su_region_et_valid(struct intel_connector *connector, bool panel_replay)
{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_display *display = to_intel_display(intel_dp);
if (DISPLAY_VER(display) < 20 || !intel_dp_is_edp(intel_dp) ||
@@ -781,9 +766,9 @@ static bool psr2_su_region_et_valid(struct intel_dp *intel_dp, bool panel_replay
return false;
return panel_replay ?
- intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT :
- intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED;
+ connector->dp.psr_caps.dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED;
}
static void _panel_replay_enable_sink(struct intel_dp *intel_dp,
@@ -924,7 +909,7 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp)
* off-by-one issue that HW has in some cases.
*/
idle_frames = max(6, connector->panel.vbt.psr.idle_frames);
- idle_frames = max(idle_frames, intel_dp->psr.sink_sync_latency + 1);
+ idle_frames = max(idle_frames, connector->dp.psr_caps.sync_latency + 1);
if (drm_WARN_ON(display->drm, idle_frames > 0xf))
idle_frames = 0xf;
@@ -1019,10 +1004,11 @@ static int psr2_block_count(struct intel_dp *intel_dp)
static u8 frames_before_su_entry(struct intel_dp *intel_dp)
{
+ struct intel_connector *connector = intel_dp->attached_connector;
u8 frames_before_su_entry;
frames_before_su_entry = max_t(u8,
- intel_dp->psr.sink_sync_latency + 1,
+ connector->dp.psr_caps.sync_latency + 1,
2);
/* Entry setup frames must be at least 1 less than frames before SU entry */
@@ -1304,25 +1290,32 @@ static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
return crtc_state->enable_psr2_sel_fetch = true;
}
-static bool psr2_granularity_check(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
+static bool psr2_granularity_check(struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector)
{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_display *display = to_intel_display(intel_dp);
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay;
const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
u16 y_granularity = 0;
+ u16 sink_y_granularity = crtc_state->has_panel_replay ?
+ connector->dp.panel_replay_caps.su_y_granularity :
+ connector->dp.psr_caps.su_y_granularity;
+ u16 sink_w_granularity = crtc_state->has_panel_replay ?
+ connector->dp.panel_replay_caps.su_w_granularity :
+ connector->dp.psr_caps.su_w_granularity;
/* PSR2 HW only send full lines so we only need to validate the width */
- if (crtc_hdisplay % intel_dp->psr.su_w_granularity)
+ if (crtc_hdisplay % sink_w_granularity)
return false;
- if (crtc_vdisplay % intel_dp->psr.su_y_granularity)
+ if (crtc_vdisplay % sink_y_granularity)
return false;
/* HW tracking is only aligned to 4 lines */
if (!crtc_state->enable_psr2_sel_fetch)
- return intel_dp->psr.su_y_granularity == 4;
+ return sink_y_granularity == 4;
/*
* adl_p and mtl platforms have 1 line granularity.
@@ -1330,11 +1323,11 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
* to match sink requirement if multiple of 4.
*/
if (display->platform.alderlake_p || DISPLAY_VER(display) >= 14)
- y_granularity = intel_dp->psr.su_y_granularity;
- else if (intel_dp->psr.su_y_granularity <= 2)
+ y_granularity = sink_y_granularity;
+ else if (sink_y_granularity <= 2)
y_granularity = 4;
- else if ((intel_dp->psr.su_y_granularity % 4) == 0)
- y_granularity = intel_dp->psr.su_y_granularity;
+ else if ((sink_y_granularity % 4) == 0)
+ y_granularity = sink_y_granularity;
if (y_granularity == 0 || crtc_vdisplay % y_granularity)
return false;
@@ -1372,16 +1365,18 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d
}
static int intel_psr_entry_setup_frames(struct intel_dp *intel_dp,
+ struct drm_connector_state *conn_state,
const struct drm_display_mode *adjusted_mode)
{
struct intel_display *display = to_intel_display(intel_dp);
- int psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ int psr_setup_time = drm_dp_psr_setup_time(connector->dp.psr_caps.dpcd);
int entry_setup_frames = 0;
if (psr_setup_time < 0) {
drm_dbg_kms(display->drm,
"PSR condition failed: Invalid PSR setup time (0x%02x)\n",
- intel_dp->psr_dpcd[1]);
+ connector->dp.psr_caps.dpcd[1]);
return -ETIME;
}
@@ -1522,14 +1517,16 @@ static bool alpm_config_valid(struct intel_dp *intel_dp,
}
static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
+ struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay;
int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
int psr_max_h = 0, psr_max_v = 0, max_bpp = 0;
- if (!intel_dp->psr.sink_psr2_support || display->params.enable_psr == 1)
+ if (!connector->dp.psr_caps.su_support || display->params.enable_psr == 1)
return false;
/* JSL and EHL only supports eDP 1.3 */
@@ -1621,9 +1618,11 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return true;
}
-static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
+static bool intel_sel_update_config_valid(struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_display *display = to_intel_display(intel_dp);
if (HAS_PSR2_SEL_FETCH(display) &&
@@ -1640,7 +1639,8 @@ static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
goto unsupported;
}
- if (!crtc_state->has_panel_replay && !intel_psr2_config_valid(intel_dp, crtc_state))
+ if (!crtc_state->has_panel_replay && !intel_psr2_config_valid(intel_dp, crtc_state,
+ conn_state))
goto unsupported;
if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) {
@@ -1653,11 +1653,11 @@ static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
if (DISPLAY_VER(display) < 14)
goto unsupported;
- if (!intel_dp->psr.sink_panel_replay_su_support)
+ if (!connector->dp.panel_replay_caps.su_support)
goto unsupported;
if (intel_dsc_enabled_on_link(crtc_state) &&
- intel_dp->psr.sink_panel_replay_dsc_support !=
+ connector->dp.panel_replay_caps.dsc_support !=
INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE) {
drm_dbg_kms(display->drm,
"Selective update with Panel Replay not enabled because it's not supported with DSC\n");
@@ -1671,14 +1671,14 @@ static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
goto unsupported;
}
- if (!psr2_granularity_check(intel_dp, crtc_state)) {
+ if (!psr2_granularity_check(crtc_state, connector)) {
drm_dbg_kms(display->drm,
"Selective update not enabled, SU granularity not compatible\n");
goto unsupported;
}
- crtc_state->enable_psr2_su_region_et =
- psr2_su_region_et_valid(intel_dp, crtc_state->has_panel_replay);
+ crtc_state->enable_psr2_su_region_et = psr2_su_region_et_valid(connector,
+ crtc_state->has_panel_replay);
return true;
@@ -1688,7 +1688,8 @@ unsupported:
}
static bool _psr_compute_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
+ struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(intel_dp);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
@@ -1703,7 +1704,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
if (crtc_state->vrr.enable)
return false;
- entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, adjusted_mode);
+ entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode);
if (entry_setup_frames >= 0) {
intel_dp->psr.entry_setup_frames = entry_setup_frames;
@@ -1717,19 +1718,33 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
return true;
}
-static bool
-_panel_replay_compute_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
+static inline bool compute_link_off_after_as_sdp_when_pr_active(struct intel_connector *connector)
+{
+ return (connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
+ DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP);
+}
+
+static inline bool compute_disable_as_sdp_when_pr_active(struct intel_connector *connector)
+{
+ return !(connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
+ DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR);
+}
+
+static bool _panel_replay_compute_config(struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
{
- struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct intel_display *display = to_intel_display(intel_dp);
struct intel_hdcp *hdcp = &connector->hdcp;
if (!CAN_PANEL_REPLAY(intel_dp))
return false;
+ if (!connector->dp.panel_replay_caps.support)
+ return false;
+
if (!panel_replay_global_enabled(intel_dp)) {
drm_dbg_kms(display->drm, "Panel Replay disabled by flag\n");
return false;
@@ -1742,13 +1757,16 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
}
if (intel_dsc_enabled_on_link(crtc_state) &&
- intel_dp->psr.sink_panel_replay_dsc_support ==
+ connector->dp.panel_replay_caps.dsc_support ==
INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED) {
drm_dbg_kms(display->drm,
"Panel Replay not enabled because it's not supported with DSC\n");
return false;
}
+ crtc_state->link_off_after_as_sdp_when_pr_active = compute_link_off_after_as_sdp_when_pr_active(connector);
+ crtc_state->disable_as_sdp_when_pr_active = compute_disable_as_sdp_when_pr_active(connector);
+
if (!intel_dp_is_edp(intel_dp))
return true;
@@ -1824,6 +1842,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
if (!psr_global_enabled(intel_dp)) {
@@ -1855,18 +1874,16 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
}
/* Only used for state verification. */
- crtc_state->panel_replay_dsc_support = intel_dp->psr.sink_panel_replay_dsc_support;
- crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp,
- crtc_state,
- conn_state);
+ crtc_state->panel_replay_dsc_support = connector->dp.panel_replay_caps.dsc_support;
+ crtc_state->has_panel_replay = _panel_replay_compute_config(crtc_state, conn_state);
crtc_state->has_psr = crtc_state->has_panel_replay ? true :
- _psr_compute_config(intel_dp, crtc_state);
+ _psr_compute_config(intel_dp, crtc_state, conn_state);
if (!crtc_state->has_psr)
return;
- crtc_state->has_sel_update = intel_sel_update_config_valid(intel_dp, crtc_state);
+ crtc_state->has_sel_update = intel_sel_update_config_valid(crtc_state, conn_state);
}
void intel_psr_get_config(struct intel_encoder *encoder,
@@ -2701,7 +2718,7 @@ intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state,
for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
struct drm_rect inter;
- if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+ if (new_plane_state->hw.crtc != crtc_state->uapi.crtc)
continue;
if (plane->id != PLANE_CURSOR)
@@ -2734,7 +2751,7 @@ static bool psr2_sel_fetch_plane_state_supported(const struct intel_plane_state
if (plane_state->uapi.dst.y1 < 0 ||
plane_state->uapi.dst.x1 < 0 ||
plane_state->scaler_id >= 0 ||
- plane_state->uapi.rotation != DRM_MODE_ROTATE_0)
+ plane_state->hw.rotation != DRM_MODE_ROTATE_0)
return false;
return true;
@@ -2749,7 +2766,8 @@ static bool psr2_sel_fetch_plane_state_supported(const struct intel_plane_state
*/
static bool psr2_sel_fetch_pipe_state_supported(const struct intel_crtc_state *crtc_state)
{
- if (crtc_state->scaler_state.scaler_id >= 0)
+ if (crtc_state->scaler_state.scaler_id >= 0 ||
+ crtc_state->async_flip_planes)
return false;
return true;
@@ -2838,7 +2856,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct drm_rect src, damaged_area = { .x1 = 0, .y1 = -1,
.x2 = INT_MAX };
- if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+ if (new_plane_state->hw.crtc != crtc_state->uapi.crtc)
continue;
if (!new_plane_state->uapi.visible &&
@@ -2937,7 +2955,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct drm_rect *sel_fetch_area, inter;
struct intel_plane *linked = new_plane_state->planar_linked_plane;
- if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc ||
+ if (new_plane_state->hw.crtc != crtc_state->uapi.crtc ||
!new_plane_state->uapi.visible)
continue;
@@ -2992,9 +3010,9 @@ skip_sel_fetch_set_loop:
return 0;
}
-void intel_psr2_panic_force_full_update(struct intel_display *display,
- struct intel_crtc_state *crtc_state)
+void intel_psr2_panic_force_full_update(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 transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 val = man_trk_ctl_enable_bit_get(display);
@@ -4109,24 +4127,22 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, val);
}
-static void intel_psr_sink_capability(struct intel_dp *intel_dp,
+static void intel_psr_sink_capability(struct intel_connector *connector,
struct seq_file *m)
{
- struct intel_psr *psr = &intel_dp->psr;
-
seq_printf(m, "Sink support: PSR = %s",
- str_yes_no(psr->sink_support));
+ str_yes_no(connector->dp.psr_caps.support));
- if (psr->sink_support)
- seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
- if (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED)
+ if (connector->dp.psr_caps.support)
+ seq_printf(m, " [0x%02x]", connector->dp.psr_caps.dpcd[0]);
+ if (connector->dp.psr_caps.dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED)
seq_printf(m, " (Early Transport)");
- seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support));
+ seq_printf(m, ", Panel Replay = %s", str_yes_no(connector->dp.panel_replay_caps.support));
seq_printf(m, ", Panel Replay Selective Update = %s",
- str_yes_no(psr->sink_panel_replay_su_support));
+ str_yes_no(connector->dp.panel_replay_caps.su_support));
seq_printf(m, ", Panel Replay DSC support = %s",
- panel_replay_dsc_support_str(psr->sink_panel_replay_dsc_support));
- if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ panel_replay_dsc_support_str(connector->dp.panel_replay_caps.dsc_support));
+ if (connector->dp.panel_replay_caps.dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)
seq_printf(m, " (Early Transport)");
seq_printf(m, "\n");
@@ -4164,7 +4180,8 @@ static void intel_psr_print_mode(struct intel_dp *intel_dp,
seq_printf(m, " %s\n", psr->no_psr_reason);
}
-static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
+static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp,
+ struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
@@ -4173,9 +4190,9 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
bool enabled;
u32 val, psr2_ctl;
- intel_psr_sink_capability(intel_dp, m);
+ intel_psr_sink_capability(connector, m);
- if (!(psr->sink_support || psr->sink_panel_replay_support))
+ if (!(connector->dp.psr_caps.support || connector->dp.panel_replay_caps.support))
return 0;
wakeref = intel_display_rpm_get(display);
@@ -4289,7 +4306,7 @@ static int i915_edp_psr_status_show(struct seq_file *m, void *data)
if (!intel_dp)
return -ENODEV;
- return intel_psr_status(m, intel_dp);
+ return intel_psr_status(m, intel_dp, intel_dp->attached_connector);
}
DEFINE_SHOW_ATTRIBUTE(i915_edp_psr_status);
@@ -4423,7 +4440,7 @@ static int i915_psr_status_show(struct seq_file *m, void *data)
struct intel_connector *connector = m->private;
struct intel_dp *intel_dp = intel_attached_dp(connector);
- return intel_psr_status(m, intel_dp);
+ return intel_psr_status(m, intel_dp, connector);
}
DEFINE_SHOW_ATTRIBUTE(i915_psr_status);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 620b35928832..b41dc4d44ff2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -28,7 +28,7 @@ struct intel_plane_state;
bool intel_encoder_can_psr(struct intel_encoder *encoder);
bool intel_psr_needs_aux_io_power(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
-void intel_psr_init_dpcd(struct intel_dp *intel_dp);
+void intel_psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector);
void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp);
void intel_psr_pre_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
@@ -59,8 +59,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
-void intel_psr2_panic_force_full_update(struct intel_display *display,
- struct intel_crtc_state *crtc_state);
+void intel_psr2_panic_force_full_update(const struct intel_crtc_state *crtc_state);
void intel_psr_pause(struct intel_dp *intel_dp);
void intel_psr_resume(struct intel_dp *intel_dp);
bool intel_psr_needs_vblank_notification(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/soc/intel_rom.c b/drivers/gpu/drm/i915/display/intel_rom.c
index 2f17dc856e7f..2f17dc856e7f 100644
--- a/drivers/gpu/drm/i915/soc/intel_rom.c
+++ b/drivers/gpu/drm/i915/display/intel_rom.c
diff --git a/drivers/gpu/drm/i915/soc/intel_rom.h b/drivers/gpu/drm/i915/display/intel_rom.h
index 4e59a375787e..4e59a375787e 100644
--- a/drivers/gpu/drm/i915/soc/intel_rom.h
+++ b/drivers/gpu/drm/i915/display/intel_rom.h
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 69b6873a6044..6a65f92e8a03 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -462,7 +462,7 @@ vlv_sprite_get_hw_state(struct intel_plane *plane,
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
enum plane_id plane_id = plane->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
@@ -893,7 +893,7 @@ ivb_sprite_get_hw_state(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
@@ -1233,7 +1233,7 @@ g4x_sprite_get_hw_state(struct intel_plane *plane,
{
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
@@ -1567,6 +1567,7 @@ static const struct drm_plane_funcs g4x_sprite_funcs = {
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = g4x_sprite_format_mod_supported,
+ .format_mod_supported_async = intel_plane_format_mod_supported_async,
};
static const struct drm_plane_funcs snb_sprite_funcs = {
@@ -1576,6 +1577,7 @@ static const struct drm_plane_funcs snb_sprite_funcs = {
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = snb_sprite_format_mod_supported,
+ .format_mod_supported_async = intel_plane_format_mod_supported_async,
};
static const struct drm_plane_funcs vlv_sprite_funcs = {
@@ -1585,6 +1587,7 @@ static const struct drm_plane_funcs vlv_sprite_funcs = {
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = vlv_sprite_format_mod_supported,
+ .format_mod_supported_async = intel_plane_format_mod_supported_async,
};
struct intel_plane *
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 1e21fd02685d..064f572bbc85 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -51,7 +51,7 @@ struct intel_tc_port {
const struct intel_tc_phy_ops *phy_ops;
struct mutex lock; /* protects the TypeC port mode */
- intel_wakeref_t lock_wakeref;
+ struct ref_tracker *lock_wakeref;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
enum intel_display_power_domain lock_power_domain;
#endif
@@ -182,7 +182,7 @@ bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
intel_display_power_legacy_aux_domain(display, dig_port->aux_ch);
}
-static intel_wakeref_t
+static struct ref_tracker *
__tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domain)
{
struct intel_display *display = to_intel_display(tc->dig_port);
@@ -192,11 +192,11 @@ __tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domai
return intel_display_power_get(display, *domain);
}
-static intel_wakeref_t
+static struct ref_tracker *
tc_cold_block(struct intel_tc_port *tc)
{
enum intel_display_power_domain domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
wakeref = __tc_cold_block(tc, &domain);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
@@ -207,7 +207,7 @@ tc_cold_block(struct intel_tc_port *tc)
static void
__tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain domain,
- intel_wakeref_t wakeref)
+ struct ref_tracker *wakeref)
{
struct intel_display *display = to_intel_display(tc->dig_port);
@@ -215,7 +215,7 @@ __tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain doma
}
static void
-tc_cold_unblock(struct intel_tc_port *tc, intel_wakeref_t wakeref)
+tc_cold_unblock(struct intel_tc_port *tc, struct ref_tracker *wakeref)
{
struct intel_display __maybe_unused *display = to_intel_display(tc->dig_port);
enum intel_display_power_domain domain = tc_phy_cold_off_domain(tc);
@@ -269,10 +269,9 @@ assert_tc_port_power_enabled(struct intel_tc_port *tc)
static u32 get_lane_mask(struct intel_tc_port *tc)
{
struct intel_display *display = to_intel_display(tc->dig_port);
- intel_wakeref_t wakeref;
u32 lane_mask;
- with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE)
lane_mask = intel_de_read(display, PORT_TX_DFLEXDPSP(tc->phy_fia));
drm_WARN_ON(display->drm, lane_mask == 0xffffffff);
@@ -296,7 +295,6 @@ get_pin_assignment(struct intel_tc_port *tc)
struct intel_display *display = to_intel_display(tc->dig_port);
enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base);
enum intel_tc_pin_assignment pin_assignment;
- intel_wakeref_t wakeref;
i915_reg_t reg;
u32 mask;
u32 val;
@@ -312,7 +310,7 @@ get_pin_assignment(struct intel_tc_port *tc)
mask = DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx);
}
- with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE)
val = intel_de_read(display, reg);
drm_WARN_ON(display->drm, val == 0xffffffff);
@@ -527,12 +525,11 @@ static u32 icl_tc_phy_hpd_live_status(struct intel_tc_port *tc)
struct intel_display *display = to_intel_display(tc->dig_port);
struct intel_digital_port *dig_port = tc->dig_port;
u32 isr_bit = display->hotplug.pch_hpd[dig_port->base.hpd_pin];
- intel_wakeref_t wakeref;
u32 fia_isr;
u32 pch_isr;
u32 mask = 0;
- with_intel_display_power(display, tc_phy_cold_off_domain(tc), wakeref) {
+ with_intel_display_power(display, tc_phy_cold_off_domain(tc)) {
fia_isr = intel_de_read(display, PORT_TX_DFLEXDPSP(tc->phy_fia));
pch_isr = intel_de_read(display, SDEISR);
}
@@ -628,7 +625,7 @@ static bool icl_tc_phy_is_owned(struct intel_tc_port *tc)
static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)
{
enum intel_display_power_domain domain;
- intel_wakeref_t tc_cold_wref;
+ struct ref_tracker *tc_cold_wref;
tc_cold_wref = __tc_cold_block(tc, &domain);
@@ -774,10 +771,9 @@ tgl_tc_phy_cold_off_domain(struct intel_tc_port *tc)
static void tgl_tc_phy_init(struct intel_tc_port *tc)
{
struct intel_display *display = to_intel_display(tc->dig_port);
- intel_wakeref_t wakeref;
u32 val;
- with_intel_display_power(display, tc_phy_cold_off_domain(tc), wakeref)
+ with_intel_display_power(display, tc_phy_cold_off_domain(tc))
val = intel_de_read(display, PORT_TX_DFLEXDPSP(FIA1));
drm_WARN_ON(display->drm, val == 0xffffffff);
@@ -819,12 +815,11 @@ static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
u32 cpu_isr_bits = display->hotplug.hpd[hpd_pin];
u32 pch_isr_bit = display->hotplug.pch_hpd[hpd_pin];
- intel_wakeref_t wakeref;
u32 cpu_isr;
u32 pch_isr;
u32 mask = 0;
- with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE) {
cpu_isr = intel_de_read(display, GEN11_DE_HPD_ISR);
pch_isr = intel_de_read(display, SDEISR);
}
@@ -897,7 +892,7 @@ static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)
struct intel_display *display = to_intel_display(tc->dig_port);
enum intel_display_power_domain port_power_domain =
tc_port_power_domain(tc);
- intel_wakeref_t port_wakeref;
+ struct ref_tracker *port_wakeref;
port_wakeref = intel_display_power_get(display, port_power_domain);
@@ -916,7 +911,7 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
struct intel_display *display = to_intel_display(tc->dig_port);
enum intel_display_power_domain port_power_domain =
tc_port_power_domain(tc);
- intel_wakeref_t port_wakeref;
+ struct ref_tracker *port_wakeref;
if (tc->mode == TC_PORT_TBT_ALT) {
tc->lock_wakeref = tc_cold_block(tc);
@@ -968,7 +963,7 @@ static void adlp_tc_phy_disconnect(struct intel_tc_port *tc)
struct intel_display *display = to_intel_display(tc->dig_port);
enum intel_display_power_domain port_power_domain =
tc_port_power_domain(tc);
- intel_wakeref_t port_wakeref;
+ struct ref_tracker *port_wakeref;
port_wakeref = intel_display_power_get(display, port_power_domain);
@@ -1015,12 +1010,11 @@ static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
u32 pica_isr_bits = display->hotplug.hpd[hpd_pin];
u32 pch_isr_bit = display->hotplug.pch_hpd[hpd_pin];
- intel_wakeref_t wakeref;
u32 pica_isr;
u32 pch_isr;
u32 mask = 0;
- with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE) {
pica_isr = intel_de_read(display, PICAINTERRUPT_ISR);
pch_isr = intel_de_read(display, SDEISR);
}
@@ -1175,7 +1169,7 @@ static bool xelpdp_tc_phy_is_owned(struct intel_tc_port *tc)
static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
{
struct intel_display *display = to_intel_display(tc->dig_port);
- intel_wakeref_t tc_cold_wref;
+ struct ref_tracker *tc_cold_wref;
enum intel_display_power_domain domain;
tc_cold_wref = __tc_cold_block(tc, &domain);
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index 70e31520c560..57fda5824c9c 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -554,7 +554,8 @@ struct child_device_config {
u8 dvo_function;
u8 dp_usb_type_c:1; /* 195+ */
u8 tbt:1; /* 209+ */
- u8 flags2_reserved:2; /* 195+ */
+ u8 dedicated_external:1; /* 264+ */
+ u8 dyn_port_over_tc:1; /* 264+ */
u8 dp_port_trace_length:4; /* 209+ */
u8 dp_gpio_index; /* 195+ */
u16 dp_gpio_pin_num; /* 195+ */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 0e727fc5e80c..ad5fe841e4b3 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -999,7 +999,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum intel_display_power_domain power_domain;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
u32 dss_ctl1, dss_ctl2;
if (!intel_dsc_source_support(crtc_state))
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c
index 6e125564db34..c45c4bbc3f95 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -9,12 +9,12 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
+#include <drm/intel/i915_drm.h>
#include <video/vga.h>
-#include "soc/intel_gmch.h"
-
#include "intel_de.h"
#include "intel_display.h"
+#include "intel_display_types.h"
#include "intel_vga.h"
#include "intel_vga_regs.h"
@@ -95,6 +95,46 @@ void intel_vga_reset_io_mem(struct intel_display *display)
vga_put(pdev, VGA_RSRC_LEGACY_IO);
}
+static int intel_gmch_vga_set_state(struct intel_display *display, bool enable_decode)
+{
+ struct pci_dev *pdev = to_pci_dev(display->drm->dev);
+ unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
+ u16 gmch_ctrl;
+
+ if (pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, &gmch_ctrl)) {
+ drm_err(display->drm, "failed to read control word\n");
+ return -EIO;
+ }
+
+ if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode)
+ return 0;
+
+ if (enable_decode)
+ gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
+ else
+ gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
+
+ if (pci_bus_write_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, gmch_ctrl)) {
+ drm_err(display->drm, "failed to write control word\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
+{
+ struct intel_display *display = to_intel_display(pdev);
+
+ intel_gmch_vga_set_state(display, enable_decode);
+
+ if (enable_decode)
+ return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
+ VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+ else
+ return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+}
+
int intel_vga_register(struct intel_display *display)
{
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index ee8e24497d2c..b3d41705448a 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -9,7 +9,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
-#include "pxp/intel_pxp.h"
#include "intel_bo.h"
#include "intel_color.h"
#include "intel_color_pipeline.h"
@@ -22,7 +21,7 @@
#include "intel_fb.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
-#include "intel_panic.h"
+#include "intel_parent.h"
#include "intel_plane.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
@@ -597,7 +596,7 @@ static u32 tgl_plane_min_alignment(struct intel_plane *plane,
* Figure out what's going on here...
*/
if (display->platform.alderlake_p &&
- intel_plane_can_async_flip(plane, fb->format->format, fb->modifier))
+ intel_plane_can_async_flip(plane, fb->format, fb->modifier))
return mult * 16 * 1024;
switch (fb->modifier) {
@@ -941,7 +940,7 @@ skl_plane_get_hw_state(struct intel_plane *plane,
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
enum plane_id plane_id = plane->id;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
@@ -1603,7 +1602,7 @@ icl_plane_update_noarm(struct intel_dsb *dsb,
}
/* FLAT CCS doesn't need to program AUX_DIST */
- if (HAS_AUX_CCS(display))
+ if (HAS_AUX_DIST(display))
intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
skl_plane_aux_dist(plane_state, color_plane));
@@ -2308,7 +2307,7 @@ static void check_protection(struct intel_plane_state *plane_state)
if (DISPLAY_VER(display) < 11)
return;
- plane_state->decrypt = intel_pxp_key_check(obj, false) == 0;
+ plane_state->decrypt = intel_bo_key_check(obj) == 0;
plane_state->force_black = intel_bo_is_protected(obj) &&
!plane_state->decrypt;
}
@@ -2462,7 +2461,7 @@ static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
if (skl_plane_has_fbc(display, fbc_id, plane_id))
- return display->fbc[fbc_id];
+ return display->fbc.instances[fbc_id];
else
return NULL;
}
@@ -2973,12 +2972,6 @@ skl_universal_plane_create(struct intel_display *display,
else
caps = skl_plane_caps(display, pipe, plane_id);
- /* FIXME: xe has problems with AUX */
- if (!IS_ENABLED(I915) && HAS_AUX_CCS(display))
- caps &= ~(INTEL_PLANE_CAP_CCS_RC |
- INTEL_PLANE_CAP_CCS_RC_CC |
- INTEL_PLANE_CAP_CCS_MC);
-
modifiers = intel_fb_plane_get_modifiers(display, caps);
ret = drm_universal_plane_init(display->drm, &plane->base,
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 54e9e0be019d..a6aab79812e5 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -8,7 +8,6 @@
#include <drm/drm_blend.h>
#include <drm/drm_print.h>
-#include "soc/intel_dram.h"
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "intel_atomic.h"
@@ -23,6 +22,7 @@
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
+#include "intel_dram.h"
#include "intel_fb.h"
#include "intel_fixed.h"
#include "intel_flipq.h"
@@ -718,7 +718,7 @@ static void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
struct intel_display *display = to_intel_display(crtc);
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum plane_id plane_id;
power_domain = POWER_DOMAIN_PIPE(pipe);
@@ -3125,7 +3125,7 @@ static bool skl_watermark_ipc_can_enable(struct intel_display *display)
if (display->platform.kabylake ||
display->platform.coffeelake ||
display->platform.cometlake) {
- const struct dram_info *dram_info = intel_dram_info(display->drm);
+ const struct dram_info *dram_info = intel_dram_info(display);
return dram_info->symmetric_memory;
}
@@ -3169,7 +3169,7 @@ static void increase_wm_latency(struct intel_display *display, int inc)
static bool need_16gb_dimm_wa(struct intel_display *display)
{
- const struct dram_info *dram_info = intel_dram_info(display->drm);
+ const struct dram_info *dram_info = intel_dram_info(display);
return (display->platform.skylake || display->platform.kabylake ||
display->platform.coffeelake || display->platform.cometlake ||
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 19bdd8662359..d705af3bf8ba 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -936,7 +936,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
- intel_wakeref_t wakeref;
+ struct ref_tracker *wakeref;
enum port port;
bool active = false;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index f859c99f969b..c3e0b8da485c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -8,6 +8,7 @@
#include <drm/drm_mm.h>
#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
#include <drm/intel/i915_drm.h>
#include "gem/i915_gem_lmem.h"
@@ -64,8 +65,8 @@ static int __i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915,
return ret;
}
-int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
- unsigned int alignment, u64 start, u64 end)
+static int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
+ unsigned int alignment, u64 start, u64 end)
{
return __i915_gem_stolen_insert_node_in_range(node->i915, &node->node,
size, alignment,
@@ -82,8 +83,8 @@ static int __i915_gem_stolen_insert_node(struct drm_i915_private *i915,
U64_MAX);
}
-int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size,
- unsigned int alignment)
+static int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size,
+ unsigned int alignment)
{
return __i915_gem_stolen_insert_node(node->i915, &node->node, size, alignment);
}
@@ -96,7 +97,7 @@ static void __i915_gem_stolen_remove_node(struct drm_i915_private *i915,
mutex_unlock(&i915->mm.stolen_lock);
}
-void i915_gem_stolen_remove_node(struct intel_stolen_node *node)
+static void i915_gem_stolen_remove_node(struct intel_stolen_node *node)
{
__i915_gem_stolen_remove_node(node->i915, &node->node);
}
@@ -1025,50 +1026,50 @@ bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj)
return obj->ops == &i915_gem_object_stolen_ops;
}
-bool i915_gem_stolen_initialized(struct drm_device *drm)
+static bool i915_gem_stolen_initialized(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
return drm_mm_initialized(&i915->mm.stolen);
}
-u64 i915_gem_stolen_area_address(struct drm_device *drm)
+static u64 i915_gem_stolen_area_address(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
return i915->dsm.stolen.start;
}
-u64 i915_gem_stolen_area_size(struct drm_device *drm)
+static u64 i915_gem_stolen_area_size(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
return resource_size(&i915->dsm.stolen);
}
-u64 i915_gem_stolen_node_address(const struct intel_stolen_node *node)
+static u64 i915_gem_stolen_node_offset(const struct intel_stolen_node *node)
+{
+ return node->node.start;
+}
+
+static u64 i915_gem_stolen_node_address(const struct intel_stolen_node *node)
{
struct drm_i915_private *i915 = node->i915;
return i915->dsm.stolen.start + i915_gem_stolen_node_offset(node);
}
-bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node)
+static bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node)
{
return drm_mm_node_allocated(&node->node);
}
-u64 i915_gem_stolen_node_offset(const struct intel_stolen_node *node)
-{
- return node->node.start;
-}
-
-u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node)
+static u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node)
{
return node->node.size;
}
-struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm)
+static struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
struct intel_stolen_node *node;
@@ -1082,7 +1083,22 @@ struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm)
return node;
}
-void i915_gem_stolen_node_free(const struct intel_stolen_node *node)
+static void i915_gem_stolen_node_free(const struct intel_stolen_node *node)
{
kfree(node);
}
+
+const struct intel_display_stolen_interface i915_display_stolen_interface = {
+ .insert_node_in_range = i915_gem_stolen_insert_node_in_range,
+ .insert_node = i915_gem_stolen_insert_node,
+ .remove_node = i915_gem_stolen_remove_node,
+ .initialized = i915_gem_stolen_initialized,
+ .node_allocated = i915_gem_stolen_node_allocated,
+ .node_offset = i915_gem_stolen_node_offset,
+ .area_address = i915_gem_stolen_area_address,
+ .area_size = i915_gem_stolen_area_size,
+ .node_address = i915_gem_stolen_node_address,
+ .node_size = i915_gem_stolen_node_size,
+ .node_alloc = i915_gem_stolen_node_alloc,
+ .node_free = i915_gem_stolen_node_free,
+};
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
index 7b0386002ed4..6db5262046a2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
@@ -8,17 +8,9 @@
#include <linux/types.h>
-struct drm_device;
struct drm_i915_gem_object;
struct drm_i915_private;
-struct intel_stolen_node;
-
-int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size,
- unsigned alignment);
-int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
- unsigned alignment, u64 start,
- u64 end);
-void i915_gem_stolen_remove_node(struct intel_stolen_node *node);
+
struct intel_memory_region *
i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type,
u16 instance);
@@ -34,17 +26,6 @@ bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj);
#define I915_GEM_STOLEN_BIAS SZ_128K
-bool i915_gem_stolen_initialized(struct drm_device *drm);
-u64 i915_gem_stolen_area_address(struct drm_device *drm);
-u64 i915_gem_stolen_area_size(struct drm_device *drm);
-
-u64 i915_gem_stolen_node_address(const struct intel_stolen_node *node);
-
-bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node);
-u64 i915_gem_stolen_node_offset(const struct intel_stolen_node *node);
-u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node);
-
-struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm);
-void i915_gem_stolen_node_free(const struct intel_stolen_node *node);
+extern const struct intel_display_stolen_interface i915_display_stolen_interface;
#endif /* __I915_GEM_STOLEN_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index b721bbd23356..98a3a7a9de50 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -963,9 +963,6 @@ int intel_engines_init_mmio(struct intel_gt *gt)
drm_WARN_ON(&i915->drm, engine_mask &
GENMASK(BITS_PER_TYPE(mask) - 1, I915_NUM_ENGINES));
- if (i915_inject_probe_failure(i915))
- return -ENODEV;
-
for (class = 0; class < MAX_ENGINE_CLASS + 1; ++class) {
setup_logical_ids(gt, logical_ids, class);
@@ -1007,6 +1004,7 @@ cleanup:
intel_engines_free(gt);
return err;
}
+ALLOW_ERROR_INJECTION(intel_engines_init_mmio, ERRNO);
void intel_engine_init_execlists(struct intel_engine_cs *engine)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 3d3b1ba76e2b..ac527d878820 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -686,10 +686,6 @@ int intel_gt_init(struct intel_gt *gt)
{
int err;
- err = i915_inject_probe_error(gt->i915, -ENODEV);
- if (err)
- return err;
-
intel_gt_init_workarounds(gt);
/*
@@ -740,10 +736,6 @@ int intel_gt_init(struct intel_gt *gt)
if (err)
goto err_gt;
- err = i915_inject_probe_error(gt->i915, -EIO);
- if (err)
- goto err_gt;
-
intel_uc_init_late(&gt->uc);
intel_migrate_init(&gt->migrate, gt);
@@ -766,6 +758,7 @@ out_fw:
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
return err;
}
+ALLOW_ERROR_INJECTION(intel_gt_init, ERRNO);
void intel_gt_driver_remove(struct intel_gt *gt)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
index c90b35881a26..aecd120972ea 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
@@ -4,12 +4,12 @@
*/
#include "i915_drv.h"
+#include "i915_freq.h"
#include "i915_reg.h"
#include "intel_gt.h"
#include "intel_gt_clock_utils.h"
#include "intel_gt_print.h"
#include "intel_gt_regs.h"
-#include "soc/intel_dram.h"
static u32 read_reference_ts_freq(struct intel_uncore *uncore)
{
@@ -148,7 +148,7 @@ static u32 gen4_read_clock_frequency(struct intel_uncore *uncore)
*
* Testing on actual hardware has shown there is no /16.
*/
- return DIV_ROUND_CLOSEST(intel_fsb_freq(uncore->i915), 4) * 1000;
+ return DIV_ROUND_CLOSEST(i9xx_fsb_freq(uncore->i915), 4) * 1000;
}
static u32 read_clock_frequency(struct intel_uncore *uncore)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_print.h b/drivers/gpu/drm/i915/gt/intel_gt_print.h
index 7fdc78c79273..48f0afd05fd8 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_print.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_print.h
@@ -36,10 +36,7 @@
#define gt_probe_error(_gt, _fmt, ...) \
do { \
- if (i915_error_injected()) \
- gt_dbg(_gt, _fmt, ##__VA_ARGS__); \
- else \
- gt_err(_gt, _fmt, ##__VA_ARGS__); \
+ gt_err(_gt, _fmt, ##__VA_ARGS__); \
} while (0)
#define gt_WARN(_gt, _condition, _fmt, ...) \
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index e8927ad49142..d36e543e98df 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1911,10 +1911,6 @@ retry:
__i915_gem_object_flush_map(wa_ctx->vma->obj, 0, batch_ptr - batch);
__i915_gem_object_release_map(wa_ctx->vma->obj);
- /* Verify that we can handle failure to setup the wa_ctx */
- if (!err)
- err = i915_inject_probe_error(engine->i915, -ENODEV);
-
err_unpin:
if (err)
i915_vma_unpin(wa_ctx->vma);
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index b01c837ab646..90b7eee78f1f 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -6,12 +6,13 @@
#include <linux/string_helpers.h>
#include <drm/intel/i915_drm.h>
+#include <drm/intel/display_parent_interface.h>
#include "display/intel_display_rps.h"
#include "display/vlv_clock.h"
-#include "soc/intel_dram.h"
#include "i915_drv.h"
+#include "i915_freq.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "i915_wait_util.h"
@@ -284,8 +285,8 @@ static void gen5_rps_init(struct intel_rps *rps)
u32 rgvmodectl;
int c_m, i;
- fsb_freq = intel_fsb_freq(i915);
- mem_freq = intel_mem_freq(i915);
+ fsb_freq = ilk_fsb_freq(i915);
+ mem_freq = ilk_mem_freq(i915);
if (fsb_freq <= 3200000)
c_m = 0;
@@ -2914,6 +2915,39 @@ bool i915_gpu_turbo_disable(void)
}
EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
+static void boost_if_not_started(struct dma_fence *fence)
+{
+ struct i915_request *rq;
+
+ if (!dma_fence_is_i915(fence))
+ return;
+
+ rq = to_request(fence);
+
+ if (!i915_request_started(rq))
+ intel_rps_boost(rq);
+}
+
+static void mark_interactive(struct drm_device *drm, bool interactive)
+{
+ struct drm_i915_private *i915 = to_i915(drm);
+
+ intel_rps_mark_interactive(&to_gt(i915)->rps, interactive);
+}
+
+static void ilk_irq_handler(struct drm_device *drm)
+{
+ struct drm_i915_private *i915 = to_i915(drm);
+
+ gen5_rps_irq_handler(&to_gt(i915)->rps);
+}
+
+const struct intel_display_rps_interface i915_display_rps_interface = {
+ .boost_if_not_started = boost_if_not_started,
+ .mark_interactive = mark_interactive,
+ .ilk_irq_handler = ilk_irq_handler,
+};
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_rps.c"
#include "selftest_slpc.c"
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
index 92fb01f5a452..5dbcebd7d4a5 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.h
+++ b/drivers/gpu/drm/i915/gt/intel_rps.h
@@ -128,4 +128,6 @@ static inline void intel_rps_clear_timer(struct intel_rps *rps)
clear_bit(INTEL_RPS_TIMER, &rps->flags);
}
+extern const struct intel_display_rps_interface i915_display_rps_interface;
+
#endif /* INTEL_RPS_H */
diff --git a/drivers/gpu/drm/i915/gt/intel_wopcm.c b/drivers/gpu/drm/i915/gt/intel_wopcm.c
index 1b26ff6488b3..602e088fe045 100644
--- a/drivers/gpu/drm/i915/gt/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/gt/intel_wopcm.c
@@ -253,9 +253,6 @@ void intel_wopcm_init(struct intel_wopcm *wopcm)
GEM_BUG_ON(huc_fw_size >= wopcm_size);
GEM_BUG_ON(ctx_rsvd + WOPCM_RESERVED_SIZE >= wopcm_size);
- if (i915_inject_probe_failure(i915))
- return;
-
if (__wopcm_regs_locked(gt->uncore, &guc_wopcm_base, &guc_wopcm_size)) {
drm_dbg(&i915->drm, "GuC WOPCM is already locked [%uK, %uK)\n",
guc_wopcm_base / SZ_1K, guc_wopcm_size / SZ_1K);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 2c651ec024ef..f1e53312ed90 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -266,10 +266,6 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
u32 *cmds;
int err;
- err = i915_inject_probe_error(guc_to_i915(guc), -ENXIO);
- if (err)
- return err;
-
GEM_BUG_ON(ct->vma);
blob_size = 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + CTB_G2H_BUFFER_SIZE;
@@ -306,6 +302,7 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
return 0;
}
+ALLOW_ERROR_INJECTION(intel_guc_ct_init, ERRNO);
/**
* intel_guc_ct_fini - Fini buffer-based communication
@@ -1394,9 +1391,6 @@ static void ct_dead_ct_worker_func(struct work_struct *w)
if (ct->dead_ct_reported)
return;
- if (i915_error_injected())
- return;
-
ct->dead_ct_reported = true;
guc_info(guc, "CTB is dead - reason=0x%X\n", ct->dead_ct_reason);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 456d3372eef8..f3249b98c992 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -541,10 +541,6 @@ int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type typ
if (intel_huc_is_authenticated(huc, type))
return -EEXIST;
- ret = i915_inject_probe_error(gt->i915, -ENXIO);
- if (ret)
- goto fail;
-
switch (type) {
case INTEL_HUC_AUTH_BY_GUC:
ret = intel_guc_auth_huc(guc, intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 4a3493e8d433..bd07c72a66fc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -60,10 +60,6 @@ static int __intel_uc_reset_hw(struct intel_uc *uc)
int ret;
u32 guc_status;
- ret = i915_inject_probe_error(gt->i915, -ENXIO);
- if (ret)
- return ret;
-
ret = intel_reset_guc(gt);
if (ret) {
gt_err(gt, "Failed to reset GuC, ret = %d\n", ret);
@@ -220,15 +216,10 @@ static void guc_handle_mmio_msg(struct intel_guc *guc)
static int guc_enable_communication(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
- struct drm_i915_private *i915 = gt->i915;
int ret;
GEM_BUG_ON(intel_guc_ct_enabled(&guc->ct));
- ret = i915_inject_probe_error(i915, -ENXIO);
- if (ret)
- return ret;
-
ret = intel_guc_ct_enable(&guc->ct);
if (ret)
return ret;
@@ -323,9 +314,6 @@ static int __uc_init(struct intel_uc *uc)
if (!intel_uc_uses_guc(uc))
return 0;
- if (i915_inject_probe_failure(uc_to_gt(uc)->i915))
- return -ENOMEM;
-
ret = intel_guc_init(guc);
if (ret)
return ret;
@@ -338,6 +326,7 @@ static int __uc_init(struct intel_uc *uc)
return 0;
}
+ALLOW_ERROR_INJECTION(__uc_init, ERRNO);
static void __uc_fini(struct intel_uc *uc)
{
@@ -381,10 +370,6 @@ static int uc_init_wopcm(struct intel_uc *uc)
GEM_BUG_ON(!(size & GUC_WOPCM_SIZE_MASK));
GEM_BUG_ON(size & ~GUC_WOPCM_SIZE_MASK);
- err = i915_inject_probe_error(gt->i915, -ENXIO);
- if (err)
- return err;
-
mask = GUC_WOPCM_SIZE_MASK | GUC_WOPCM_SIZE_LOCKED;
err = intel_uncore_write_and_verify(uncore, GUC_WOPCM_SIZE, size, mask,
size | GUC_WOPCM_SIZE_LOCKED);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index e848a04a80dc..fd04fe892c28 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -542,43 +542,6 @@ void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
INTEL_UC_FIRMWARE_NOT_SUPPORTED);
}
-static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
-{
- struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915;
- bool user = e == -EINVAL;
-
- if (i915_inject_probe_error(i915, e)) {
- /* non-existing blob */
- uc_fw->file_selected.path = "<invalid>";
- uc_fw->user_overridden = user;
- } else if (i915_inject_probe_error(i915, e)) {
- /* require next major version */
- uc_fw->file_wanted.ver.major += 1;
- uc_fw->file_wanted.ver.minor = 0;
- uc_fw->user_overridden = user;
- } else if (i915_inject_probe_error(i915, e)) {
- /* require next minor version */
- uc_fw->file_wanted.ver.minor += 1;
- uc_fw->user_overridden = user;
- } else if (uc_fw->file_wanted.ver.major &&
- i915_inject_probe_error(i915, e)) {
- /* require prev major version */
- uc_fw->file_wanted.ver.major -= 1;
- uc_fw->file_wanted.ver.minor = 0;
- uc_fw->user_overridden = user;
- } else if (uc_fw->file_wanted.ver.minor &&
- i915_inject_probe_error(i915, e)) {
- /* require prev minor version - hey, this should work! */
- uc_fw->file_wanted.ver.minor -= 1;
- uc_fw->user_overridden = user;
- } else if (user && i915_inject_probe_error(i915, e)) {
- /* officially unsupported platform */
- uc_fw->file_wanted.ver.major = 0;
- uc_fw->file_wanted.ver.minor = 0;
- uc_fw->user_overridden = true;
- }
-}
-
static void uc_unpack_css_version(struct intel_uc_fw_ver *ver, u32 css_value)
{
/* Get version numbers from the CSS header */
@@ -766,7 +729,7 @@ static int guc_check_version_range(struct intel_uc_fw *uc_fw)
return -EINVAL;
}
- return i915_inject_probe_error(gt->i915, -EINVAL);
+ return 0;
}
static int check_fw_header(struct intel_gt *gt,
@@ -905,13 +868,6 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
GEM_BUG_ON(!gt->wopcm.size);
GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw));
- err = i915_inject_probe_error(i915, -ENXIO);
- if (err)
- goto fail;
-
- __force_fw_fetch_failures(uc_fw, -EINVAL);
- __force_fw_fetch_failures(uc_fw, -ESTALE);
-
err = try_firmware_load(uc_fw, &fw);
memcpy(&file_ideal, &uc_fw->file_wanted, sizeof(file_ideal));
@@ -1088,10 +1044,6 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
u64 offset;
int ret;
- ret = i915_inject_probe_error(gt->i915, -ETIMEDOUT);
- if (ret)
- return ret;
-
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
/* Set the source address for the uCode */
@@ -1155,16 +1107,11 @@ int intel_uc_fw_mark_load_failed(struct intel_uc_fw *uc_fw, int err)
*/
int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
{
- struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
int err;
/* make sure the status was cleared the last time we reset the uc */
GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
- err = i915_inject_probe_error(gt->i915, -ENOEXEC);
- if (err)
- return err;
-
if (!intel_uc_fw_is_loadable(uc_fw))
return -ENOEXEC;
@@ -1198,10 +1145,6 @@ static int uc_fw_rsa_data_create(struct intel_uc_fw *uc_fw)
void *vaddr;
int err;
- err = i915_inject_probe_error(gt->i915, -ENXIO);
- if (err)
- return err;
-
if (!uc_fw_need_rsa_in_memory(uc_fw))
return 0;
@@ -1243,6 +1186,7 @@ unpin_out:
i915_vma_unpin_and_release(&vma, 0);
return err;
}
+ALLOW_ERROR_INJECTION(uc_fw_rsa_data_create, ERRNO);
static void uc_fw_rsa_data_destroy(struct intel_uc_fw *uc_fw)
{
diff --git a/drivers/gpu/drm/i915/i915_display_pc8.c b/drivers/gpu/drm/i915/i915_display_pc8.c
new file mode 100644
index 000000000000..2af5dbab20ef
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_display_pc8.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2025, Intel Corporation.
+ */
+
+#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
+
+#include "i915_display_pc8.h"
+#include "i915_drv.h"
+#include "intel_uncore.h"
+
+static void i915_display_pc8_block(struct drm_device *drm)
+{
+ struct intel_uncore *uncore = &to_i915(drm)->uncore;
+
+ /* to prevent PC8 state, just enable force_wake */
+ intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
+}
+
+static void i915_display_pc8_unblock(struct drm_device *drm)
+{
+ struct intel_uncore *uncore = &to_i915(drm)->uncore;
+
+ intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
+}
+
+const struct intel_display_pc8_interface i915_display_pc8_interface = {
+ .block = i915_display_pc8_block,
+ .unblock = i915_display_pc8_unblock,
+};
diff --git a/drivers/gpu/drm/i915/i915_display_pc8.h b/drivers/gpu/drm/i915/i915_display_pc8.h
new file mode 100644
index 000000000000..717f313d2a21
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_display_pc8.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_DISPLAY_PC8_H__
+#define __I915_DISPLAY_PC8_H__
+
+extern const struct intel_display_pc8_interface i915_display_pc8_interface;
+
+#endif /* __I915_DISPLAY_PC8_H__ */
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index c97b76771917..e025273e9ab1 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -59,6 +59,7 @@
#include "display/intel_dmc.h"
#include "display/intel_dp.h"
#include "display/intel_dpt.h"
+#include "display/intel_dram.h"
#include "display/intel_encoder.h"
#include "display/intel_fbdev.h"
#include "display/intel_gmbus.h"
@@ -81,25 +82,28 @@
#include "gt/intel_gt_pm.h"
#include "gt/intel_gt_print.h"
#include "gt/intel_rc6.h"
+#include "gt/intel_rps.h"
#include "pxp/intel_pxp.h"
#include "pxp/intel_pxp_debugfs.h"
#include "pxp/intel_pxp_pm.h"
-#include "soc/intel_dram.h"
-#include "soc/intel_gmch.h"
-
#include "i915_debugfs.h"
+#include "i915_display_pc8.h"
#include "i915_driver.h"
#include "i915_drm_client.h"
#include "i915_drv.h"
+#include "i915_edram.h"
#include "i915_file_private.h"
#include "i915_getparam.h"
+#include "i915_gmch.h"
+#include "i915_hdcp_gsc.h"
#include "i915_hwmon.h"
#include "i915_ioc32.h"
#include "i915_ioctl.h"
#include "i915_irq.h"
#include "i915_memcpy.h"
+#include "i915_panic.h"
#include "i915_perf.h"
#include "i915_query.h"
#include "i915_reg.h"
@@ -224,9 +228,6 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
int ret = 0;
- if (i915_inject_probe_failure(dev_priv))
- return -ENODEV;
-
intel_device_info_runtime_init_early(dev_priv);
intel_step_init(dev_priv);
@@ -262,7 +263,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
intel_irq_init(dev_priv);
intel_display_driver_early_probe(display);
- intel_clock_gating_hooks_init(dev_priv);
+ intel_clock_gating_hooks_init(&dev_priv->drm);
intel_detect_preproduction_hw(dev_priv);
@@ -276,6 +277,7 @@ err_workqueues:
i915_workqueues_cleanup(dev_priv);
return ret;
}
+ALLOW_ERROR_INJECTION(i915_driver_early_probe, ERRNO);
/**
* i915_driver_late_release - cleanup the setup done in
@@ -318,10 +320,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
struct intel_gt *gt;
int ret, i;
- if (i915_inject_probe_failure(dev_priv))
- return -ENODEV;
-
- ret = intel_gmch_bridge_setup(dev_priv);
+ ret = i915_gmch_bridge_setup(dev_priv);
if (ret < 0)
return ret;
@@ -338,7 +337,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
}
/* Try to make sure MCHBAR is enabled before poking at it */
- intel_gmch_bar_setup(dev_priv);
+ i915_gmch_bar_setup(dev_priv);
intel_device_info_runtime_init(dev_priv);
intel_display_device_info_runtime_init(display);
@@ -354,10 +353,11 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
return 0;
err_uncore:
- intel_gmch_bar_teardown(dev_priv);
+ i915_gmch_bar_teardown(dev_priv);
return ret;
}
+ALLOW_ERROR_INJECTION(i915_driver_mmio_probe, ERRNO);
/**
* i915_driver_mmio_release - cleanup the setup done in i915_driver_mmio_probe()
@@ -365,7 +365,7 @@ err_uncore:
*/
static void i915_driver_mmio_release(struct drm_i915_private *dev_priv)
{
- intel_gmch_bar_teardown(dev_priv);
+ i915_gmch_bar_teardown(dev_priv);
}
/**
@@ -465,9 +465,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
int ret;
- if (i915_inject_probe_failure(dev_priv))
- return -ENODEV;
-
if (HAS_PPGTT(dev_priv)) {
if (intel_vgpu_active(dev_priv) &&
!intel_vgpu_has_full_ppgtt(dev_priv)) {
@@ -492,7 +489,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
}
/* needs to be done before ggtt probe */
- intel_dram_edram_detect(dev_priv);
+ i915_edram_detect(dev_priv);
ret = i915_set_dma_info(dev_priv);
if (ret)
@@ -572,7 +569,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
* Fill the dram structure to get the system dram info. This will be
* used for memory latency calculation.
*/
- ret = intel_dram_detect(dev_priv);
+ ret = intel_dram_detect(display);
if (ret)
goto err_opregion;
@@ -595,6 +592,7 @@ err_perf:
i915_perf_fini(dev_priv);
return ret;
}
+ALLOW_ERROR_INJECTION(i915_driver_hw_probe, ERRNO);
/**
* i915_driver_hw_remove - cleanup the setup done in i915_driver_hw_probe()
@@ -739,8 +737,44 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv)
"DRM_I915_DEBUG_RUNTIME_PM enabled\n");
}
+static void fence_priority_display(struct dma_fence *fence)
+{
+ if (dma_fence_is_i915(fence))
+ i915_gem_fence_wait_priority_display(fence);
+}
+
+static bool has_auxccs(struct drm_device *drm)
+{
+ struct drm_i915_private *i915 = to_i915(drm);
+
+ return IS_GRAPHICS_VER(i915, 9, 12) ||
+ IS_ALDERLAKE_P(i915) ||
+ IS_METEORLAKE(i915);
+}
+
+static bool has_fenced_regions(struct drm_device *drm)
+{
+ return intel_gt_support_legacy_fencing(to_gt(to_i915(drm)));
+}
+
+static bool vgpu_active(struct drm_device *drm)
+{
+ return intel_vgpu_active(to_i915(drm));
+}
+
static const struct intel_display_parent_interface parent = {
+ .hdcp = &i915_display_hdcp_interface,
+ .irq = &i915_display_irq_interface,
+ .panic = &i915_display_panic_interface,
+ .pc8 = &i915_display_pc8_interface,
.rpm = &i915_display_rpm_interface,
+ .rps = &i915_display_rps_interface,
+ .stolen = &i915_display_stolen_interface,
+
+ .fence_priority_display = fence_priority_display,
+ .has_auxccs = has_auxccs,
+ .has_fenced_regions = has_fenced_regions,
+ .vgpu_active = vgpu_active,
};
const struct intel_display_parent_interface *i915_driver_parent_interface(void)
@@ -890,6 +924,7 @@ out_cleanup_hw:
i915_gem_drain_freed_objects(i915);
i915_ggtt_driver_late_release(i915);
out_cleanup_mmio:
+ intel_gvt_driver_remove(i915);
i915_driver_mmio_release(i915);
out_runtime_pm_put:
enable_rpm_wakeref_asserts(&i915->runtime_pm);
@@ -1254,7 +1289,7 @@ static int i915_drm_resume(struct drm_device *dev)
intel_display_driver_init_hw(display);
- intel_clock_gating_init(dev_priv);
+ intel_clock_gating_init(&dev_priv->drm);
if (intel_display_device_present(display))
intel_display_driver_resume_access(display);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 557fdb76ef19..44ba620325bc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -60,7 +60,6 @@
#include "intel_step.h"
#include "intel_uncore.h"
-struct dram_info;
struct drm_i915_clock_gating_funcs;
struct intel_display;
struct intel_pxp;
@@ -274,8 +273,6 @@ struct drm_i915_private {
u32 suspend_count;
struct vlv_s0ix_state *vlv_s0ix_state;
- const struct dram_info *dram_info;
-
struct intel_runtime_pm runtime_pm;
struct i915_perf perf;
diff --git a/drivers/gpu/drm/i915/i915_edram.c b/drivers/gpu/drm/i915/i915_edram.c
new file mode 100644
index 000000000000..5818ec396d1e
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_edram.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+#include <drm/drm_print.h>
+
+#include "i915_drv.h"
+#include "i915_edram.h"
+#include "i915_reg.h"
+
+static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap)
+{
+ static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 };
+ static const u8 sets[4] = { 1, 1, 2, 2 };
+
+ return EDRAM_NUM_BANKS(cap) *
+ ways[EDRAM_WAYS_IDX(cap)] *
+ sets[EDRAM_SETS_IDX(cap)];
+}
+
+void i915_edram_detect(struct drm_i915_private *i915)
+{
+ u32 edram_cap = 0;
+
+ if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9))
+ return;
+
+ edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP);
+
+ /* NB: We can't write IDICR yet because we don't have gt funcs set up */
+
+ if (!(edram_cap & EDRAM_ENABLED))
+ return;
+
+ /*
+ * The needed capability bits for size calculation are not there with
+ * pre gen9 so return 128MB always.
+ */
+ if (GRAPHICS_VER(i915) < 9)
+ i915->edram_size_mb = 128;
+ else
+ i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap);
+
+ drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb);
+}
diff --git a/drivers/gpu/drm/i915/i915_edram.h b/drivers/gpu/drm/i915/i915_edram.h
new file mode 100644
index 000000000000..8319422ace9d
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_edram.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_DRAM_H__
+#define __I915_DRAM_H__
+
+struct drm_i915_private;
+
+void i915_edram_detect(struct drm_i915_private *i915);
+
+#endif /* __I915_DRAM_H__ */
diff --git a/drivers/gpu/drm/i915/i915_freq.c b/drivers/gpu/drm/i915/i915_freq.c
new file mode 100644
index 000000000000..9bdaea34aef9
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_freq.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+#include <drm/drm_print.h>
+
+#include "i915_drv.h"
+#include "i915_freq.h"
+#include "intel_mchbar_regs.h"
+
+unsigned int i9xx_fsb_freq(struct drm_i915_private *i915)
+{
+ u32 fsb;
+
+ /*
+ * Note that this only reads the state of the FSB
+ * straps, not the actual FSB frequency. Some BIOSen
+ * let you configure each independently. Ideally we'd
+ * read out the actual FSB frequency but sadly we
+ * 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;
+
+ if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) {
+ switch (fsb) {
+ case CLKCFG_FSB_400:
+ return 400000;
+ case CLKCFG_FSB_533:
+ return 533333;
+ case CLKCFG_FSB_667:
+ return 666667;
+ case CLKCFG_FSB_800:
+ return 800000;
+ case CLKCFG_FSB_1067:
+ return 1066667;
+ case CLKCFG_FSB_1333:
+ return 1333333;
+ default:
+ MISSING_CASE(fsb);
+ return 1333333;
+ }
+ } else {
+ switch (fsb) {
+ case CLKCFG_FSB_400_ALT:
+ return 400000;
+ case CLKCFG_FSB_533:
+ return 533333;
+ case CLKCFG_FSB_667:
+ return 666667;
+ case CLKCFG_FSB_800:
+ return 800000;
+ case CLKCFG_FSB_1067_ALT:
+ return 1066667;
+ case CLKCFG_FSB_1333_ALT:
+ return 1333333;
+ case CLKCFG_FSB_1600_ALT:
+ return 1600000;
+ default:
+ MISSING_CASE(fsb);
+ return 1333333;
+ }
+ }
+}
+
+unsigned int ilk_fsb_freq(struct drm_i915_private *i915)
+{
+ u16 fsb;
+
+ fsb = intel_uncore_read16(&i915->uncore, CSIPLL0) & 0x3ff;
+
+ switch (fsb) {
+ case 0x00c:
+ return 3200000;
+ case 0x00e:
+ return 3733333;
+ case 0x010:
+ return 4266667;
+ case 0x012:
+ return 4800000;
+ case 0x014:
+ return 5333333;
+ case 0x016:
+ return 5866667;
+ case 0x018:
+ return 6400000;
+ default:
+ drm_dbg(&i915->drm, "unknown fsb frequency 0x%04x\n", fsb);
+ return 0;
+ }
+}
+
+unsigned int ilk_mem_freq(struct drm_i915_private *i915)
+{
+ u16 ddrpll;
+
+ ddrpll = intel_uncore_read16(&i915->uncore, DDRMPLL1);
+ switch (ddrpll & 0xff) {
+ case 0xc:
+ return 800000;
+ case 0x10:
+ return 1066667;
+ case 0x14:
+ return 1333333;
+ case 0x18:
+ return 1600000;
+ default:
+ drm_dbg(&i915->drm, "unknown memory frequency 0x%02x\n",
+ ddrpll & 0xff);
+ return 0;
+ }
+}
diff --git a/drivers/gpu/drm/i915/i915_freq.h b/drivers/gpu/drm/i915/i915_freq.h
new file mode 100644
index 000000000000..53b0ecb95440
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_freq.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_FREQ_H__
+#define __I915_FREQ_H__
+
+struct drm_i915_private;
+
+unsigned int i9xx_fsb_freq(struct drm_i915_private *i915);
+unsigned int ilk_fsb_freq(struct drm_i915_private *i915);
+unsigned int ilk_mem_freq(struct drm_i915_private *i915);
+
+#endif /* __I915_FREQ_H__ */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4c82c9544b93..b40d4d88de01 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1184,7 +1184,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
*
* FIXME: break up the workarounds and apply them at the right time!
*/
- intel_clock_gating_init(dev_priv);
+ intel_clock_gating_init(&dev_priv->drm);
for_each_gt(gt, dev_priv, i) {
ret = intel_gt_init(gt);
@@ -1235,7 +1235,7 @@ err_unlock:
/* Minimal basic recovery for KMS */
ret = i915_ggtt_enable_hw(dev_priv);
i915_ggtt_resume(to_gt(dev_priv)->ggtt);
- intel_clock_gating_init(dev_priv);
+ intel_clock_gating_init(&dev_priv->drm);
}
i915_gem_drain_freed_objects(dev_priv);
diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/i915_gmch.c
index 271da30c8290..2d55831b3c58 100644
--- a/drivers/gpu/drm/i915/soc/intel_gmch.c
+++ b/drivers/gpu/drm/i915/i915_gmch.c
@@ -1,28 +1,21 @@
// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2023 Intel Corporation
- */
+/* Copyright © 2025 Intel Corporation */
-#include <linux/pci.h>
#include <linux/pnp.h>
-#include <linux/vgaarb.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
-#include <drm/intel/i915_drm.h>
-
-#include "../display/intel_display_core.h" /* FIXME */
#include "i915_drv.h"
-#include "intel_gmch.h"
+#include "i915_gmch.h"
#include "intel_pci_config.h"
-static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge)
+static void i915_gmch_bridge_release(struct drm_device *dev, void *bridge)
{
pci_dev_put(bridge);
}
-int intel_gmch_bridge_setup(struct drm_i915_private *i915)
+int i915_gmch_bridge_setup(struct drm_i915_private *i915)
{
int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus);
@@ -32,7 +25,7 @@ int intel_gmch_bridge_setup(struct drm_i915_private *i915)
return -EIO;
}
- return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release,
+ return drmm_add_action_or_reset(&i915->drm, i915_gmch_bridge_release,
i915->gmch.pdev);
}
@@ -84,7 +77,7 @@ intel_alloc_mchbar_resource(struct drm_i915_private *i915)
}
/* Setup MCHBAR if possible, return true if we should disable it again */
-void intel_gmch_bar_setup(struct drm_i915_private *i915)
+void i915_gmch_bar_setup(struct drm_i915_private *i915)
{
u32 temp;
bool enabled;
@@ -121,7 +114,7 @@ void intel_gmch_bar_setup(struct drm_i915_private *i915)
}
}
-void intel_gmch_bar_teardown(struct drm_i915_private *i915)
+void i915_gmch_bar_teardown(struct drm_i915_private *i915)
{
if (i915->gmch.mchbar_need_disable) {
if (IS_I915G(i915) || IS_I915GM(i915)) {
@@ -146,43 +139,3 @@ void intel_gmch_bar_teardown(struct drm_i915_private *i915)
if (i915->gmch.mch_res.start)
release_resource(&i915->gmch.mch_res);
}
-
-int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode)
-{
- struct intel_display *display = i915->display;
- unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
- u16 gmch_ctrl;
-
- if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) {
- drm_err(&i915->drm, "failed to read control word\n");
- return -EIO;
- }
-
- if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode)
- return 0;
-
- if (enable_decode)
- gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
- else
- gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-
- if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) {
- drm_err(&i915->drm, "failed to write control word\n");
- return -EIO;
- }
-
- return 0;
-}
-
-unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
-{
- struct drm_i915_private *i915 = pdev_to_i915(pdev);
-
- intel_gmch_vga_set_state(i915, enable_decode);
-
- if (enable_decode)
- return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
- VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
- else
- return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
-}
diff --git a/drivers/gpu/drm/i915/i915_gmch.h b/drivers/gpu/drm/i915/i915_gmch.h
new file mode 100644
index 000000000000..3ae50bef04ea
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gmch.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_GMCH_H__
+#define __I915_GMCH_H__
+
+struct drm_i915_private;
+
+int i915_gmch_bridge_setup(struct drm_i915_private *i915);
+void i915_gmch_bar_setup(struct drm_i915_private *i915);
+void i915_gmch_bar_teardown(struct drm_i915_private *i915);
+
+#endif /* __I915_GMCH_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/i915_hdcp_gsc.c
index 3e7b480ee9f1..9906da2aef1c 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
+++ b/drivers/gpu/drm/i915/i915_hdcp_gsc.c
@@ -4,13 +4,14 @@
*/
#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
#include <drm/intel/i915_hdcp_interface.h>
#include "gem/i915_gem_region.h"
#include "gt/intel_gt.h"
#include "gt/uc/intel_gsc_uc_heci_cmd_submit.h"
#include "i915_drv.h"
-#include "intel_hdcp_gsc.h"
+#include "i915_hdcp_gsc.h"
struct intel_hdcp_gsc_context {
struct drm_i915_private *i915;
@@ -19,7 +20,7 @@ struct intel_hdcp_gsc_context {
void *hdcp_cmd_out;
};
-bool intel_hdcp_gsc_check_status(struct drm_device *drm)
+static bool intel_hdcp_gsc_check_status(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
struct intel_gt *gt = i915->media_gt;
@@ -87,7 +88,7 @@ out_unpin:
return err;
}
-struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm)
+static struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm)
{
struct drm_i915_private *i915 = to_i915(drm);
struct intel_hdcp_gsc_context *gsc_context;
@@ -111,7 +112,7 @@ struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *d
return gsc_context;
}
-void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context)
+static void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context)
{
if (!gsc_context)
return;
@@ -168,9 +169,9 @@ static int intel_gsc_send_sync(struct drm_i915_private *i915,
* gsc cs memory header as stated in specs after which the normal HDCP payload
* will follow
*/
-ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
- void *msg_in, size_t msg_in_len,
- void *msg_out, size_t msg_out_len)
+static ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len)
{
struct drm_i915_private *i915 = gsc_context->i915;
struct intel_gt *gt = i915->media_gt;
@@ -237,3 +238,10 @@ ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
err:
return ret;
}
+
+const struct intel_display_hdcp_interface i915_display_hdcp_interface = {
+ .gsc_msg_send = intel_hdcp_gsc_msg_send,
+ .gsc_check_status = intel_hdcp_gsc_check_status,
+ .gsc_context_alloc = intel_hdcp_gsc_context_alloc,
+ .gsc_context_free = intel_hdcp_gsc_context_free,
+};
diff --git a/drivers/gpu/drm/i915/i915_hdcp_gsc.h b/drivers/gpu/drm/i915/i915_hdcp_gsc.h
new file mode 100644
index 000000000000..e0b562cfcde3
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_hdcp_gsc.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_HDCP_GSC_H__
+#define __I915_HDCP_GSC_H__
+
+extern const struct intel_display_hdcp_interface i915_display_hdcp_interface;
+
+#endif /* __I915_HDCP_GSC_H__ */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1898be4ddc8b..3fe978d4ea53 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -33,6 +33,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
#include "display/intel_display_irq.h"
#include "display/intel_hotplug.h"
@@ -1252,3 +1253,18 @@ void intel_synchronize_hardirq(struct drm_i915_private *i915)
{
synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
}
+
+static bool _intel_irq_enabled(struct drm_device *drm)
+{
+ return intel_irqs_enabled(to_i915(drm));
+}
+
+static void _intel_irq_synchronize(struct drm_device *drm)
+{
+ return intel_synchronize_irq(to_i915(drm));
+}
+
+const struct intel_display_irq_interface i915_display_irq_interface = {
+ .enabled = _intel_irq_enabled,
+ .synchronize = _intel_irq_synchronize,
+};
diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h
index 58789b264575..5c87d6d41c74 100644
--- a/drivers/gpu/drm/i915/i915_irq.h
+++ b/drivers/gpu/drm/i915/i915_irq.h
@@ -51,4 +51,6 @@ void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs);
void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs,
u32 emr_val);
+extern const struct intel_display_irq_interface i915_display_irq_interface;
+
#endif /* __I915_IRQ_H__ */
diff --git a/drivers/gpu/drm/i915/i915_panic.c b/drivers/gpu/drm/i915/i915_panic.c
new file mode 100644
index 000000000000..728be077e8e8
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_panic.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+#include <drm/drm_panic.h>
+#include <drm/intel/display_parent_interface.h>
+
+#include "display/intel_display_types.h"
+#include "display/intel_fb.h"
+#include "gem/i915_gem_object.h"
+
+#include "i915_panic.h"
+
+static struct intel_panic *intel_panic_alloc(void)
+{
+ return i915_gem_object_alloc_panic();
+}
+
+static int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
+{
+ struct intel_framebuffer *fb = sb->private;
+ struct drm_gem_object *obj = intel_fb_bo(&fb->base);
+
+ return i915_gem_object_panic_setup(panic, sb, obj, fb->panic_tiling);
+}
+
+static void intel_panic_finish(struct intel_panic *panic)
+{
+ return i915_gem_object_panic_finish(panic);
+}
+
+const struct intel_display_panic_interface i915_display_panic_interface = {
+ .alloc = intel_panic_alloc,
+ .setup = intel_panic_setup,
+ .finish = intel_panic_finish,
+};
diff --git a/drivers/gpu/drm/i915/i915_panic.h b/drivers/gpu/drm/i915/i915_panic.h
new file mode 100644
index 000000000000..743d8c861c42
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_panic.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __I915_PANIC_H__
+#define __I915_PANIC_H__
+
+extern const struct intel_display_panic_interface i915_display_panic_interface;
+
+#endif /* __I915_PANIC_H__ */
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 37746dd619fd..34ed82bb1b1a 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -110,11 +110,6 @@ i915_param_named_unsafe(huc_firmware_path, charp, 0400,
i915_param_named_unsafe(gsc_firmware_path, charp, 0400,
"GSC firmware path to use instead of the default one");
-#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
-i915_param_named_unsafe(inject_probe_failure, uint, 0400,
- "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)");
-#endif
-
#if IS_ENABLED(CONFIG_DRM_I915_GVT)
i915_param_named(enable_gvt, bool, 0400,
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 0fbcb5b6d7bf..4d9d4cd3220d 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -55,7 +55,6 @@ struct drm_printer;
param(bool, memtest, false, 0400) \
param(int, mmio_debug, -IS_ENABLED(CONFIG_DRM_I915_DEBUG_MMIO), 0600) \
param(unsigned int, reset, 3, 0600) \
- param(unsigned int, inject_probe_failure, 0, 0) \
param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE, 0400) \
param(unsigned int, request_timeout_ms, CONFIG_DRM_I915_REQUEST_TIMEOUT, CONFIG_DRM_I915_REQUEST_TIMEOUT ? 0600 : 0) \
param(unsigned int, lmem_size, 0, 0400) \
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index b2e311f4791a..d966a00520f1 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -999,11 +999,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
return err;
- if (i915_inject_probe_failure(pdev_to_i915(pdev))) {
- i915_pci_remove(pdev);
- return -ENODEV;
- }
-
err = i915_live_selftests(pdev);
if (err) {
i915_pci_remove(pdev);
@@ -1018,6 +1013,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
}
+ALLOW_ERROR_INJECTION(i915_pci_probe, ERRNO);
static void i915_pci_shutdown(struct pci_dev *pdev)
{
diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c
index 89b920ccbccb..8c1aad312fd4 100644
--- a/drivers/gpu/drm/i915/i915_utils.c
+++ b/drivers/gpu/drm/i915/i915_utils.c
@@ -17,37 +17,9 @@ void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint)
drm_notice(&i915->drm, "CI tainted: %#x by %pS\n",
taint, __builtin_return_address(0));
- /* Failures that occur during fault injection testing are expected */
- if (!i915_error_injected())
- __add_taint_for_CI(taint);
+ __add_taint_for_CI(taint);
}
-#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
-static unsigned int i915_probe_fail_count;
-
-int __i915_inject_probe_error(struct drm_i915_private *i915, int err,
- const char *func, int line)
-{
- if (i915_probe_fail_count >= i915_modparams.inject_probe_failure)
- return 0;
-
- if (++i915_probe_fail_count < i915_modparams.inject_probe_failure)
- return 0;
-
- drm_info(&i915->drm, "Injecting failure %d at checkpoint %u [%s:%d]\n",
- err, i915_modparams.inject_probe_failure, func, line);
-
- i915_modparams.inject_probe_failure = 0;
- return err;
-}
-
-bool i915_error_injected(void)
-{
- return i915_probe_fail_count && !i915_modparams.inject_probe_failure;
-}
-
-#endif
-
bool i915_vtd_active(struct drm_i915_private *i915)
{
if (device_iommu_mapped(i915->drm.dev))
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 4f75115b87d6..9e5b7fcadbe2 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -43,28 +43,8 @@ struct drm_i915_private;
__stringify(x), (long)(x))
#endif
-#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
-
-int __i915_inject_probe_error(struct drm_i915_private *i915, int err,
- const char *func, int line);
-#define i915_inject_probe_error(_i915, _err) \
- __i915_inject_probe_error((_i915), (_err), __func__, __LINE__)
-bool i915_error_injected(void);
-
-#else
-
-#define i915_inject_probe_error(i915, e) ({ BUILD_BUG_ON_INVALID(i915); 0; })
-#define i915_error_injected() false
-
-#endif
-
-#define i915_inject_probe_failure(i915) i915_inject_probe_error((i915), -ENODEV)
-
#define i915_probe_error(i915, fmt, ...) ({ \
- if (i915_error_injected()) \
- drm_dbg(&(i915)->drm, fmt, ##__VA_ARGS__); \
- else \
- drm_err(&(i915)->drm, fmt, ##__VA_ARGS__); \
+ drm_err(&(i915)->drm, fmt, ##__VA_ARGS__); \
})
#ifndef fetch_and_zero
diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c
index 175a240ac848..7336934bb934 100644
--- a/drivers/gpu/drm/i915/intel_clock_gating.c
+++ b/drivers/gpu/drm/i915/intel_clock_gating.c
@@ -709,8 +709,10 @@ static void i830_init_clock_gating(struct drm_i915_private *i915)
_MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE));
}
-void intel_clock_gating_init(struct drm_i915_private *i915)
+void intel_clock_gating_init(struct drm_device *drm)
{
+ struct drm_i915_private *i915 = to_i915(drm);
+
i915->clock_gating_funcs->init_clock_gating(i915);
}
@@ -749,15 +751,17 @@ CG_FUNCS(nop);
/**
* intel_clock_gating_hooks_init - setup the clock gating hooks
- * @i915: device private
+ * @drm: drm device
*
* Setup the hooks that configure which clocks of a given platform can be
* gated and also apply various GT and display specific workarounds for these
* platforms. Note that some GT specific workarounds are applied separately
* when GPU contexts or batchbuffers start their execution.
*/
-void intel_clock_gating_hooks_init(struct drm_i915_private *i915)
+void intel_clock_gating_hooks_init(struct drm_device *drm)
{
+ struct drm_i915_private *i915 = to_i915(drm);
+
if (IS_DG2(i915))
i915->clock_gating_funcs = &dg2_clock_gating_funcs;
else if (IS_COFFEELAKE(i915) || IS_COMETLAKE(i915))
diff --git a/drivers/gpu/drm/i915/intel_clock_gating.h b/drivers/gpu/drm/i915/intel_clock_gating.h
index 5b4e4c55b2c2..3a4b443d9b8b 100644
--- a/drivers/gpu/drm/i915/intel_clock_gating.h
+++ b/drivers/gpu/drm/i915/intel_clock_gating.h
@@ -6,9 +6,9 @@
#ifndef __INTEL_CLOCK_GATING_H__
#define __INTEL_CLOCK_GATING_H__
-struct drm_i915_private;
+struct drm_device;
-void intel_clock_gating_init(struct drm_i915_private *i915);
-void intel_clock_gating_hooks_init(struct drm_i915_private *i915);
+void intel_clock_gating_init(struct drm_device *drm);
+void intel_clock_gating_hooks_init(struct drm_device *drm);
#endif /* __INTEL_CLOCK_GATING_H__ */
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c
index c3efc3454ec2..5f615ec0e580 100644
--- a/drivers/gpu/drm/i915/intel_gvt.c
+++ b/drivers/gpu/drm/i915/intel_gvt.c
@@ -238,9 +238,6 @@ EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, "I915_GVT");
*/
int intel_gvt_init(struct drm_i915_private *dev_priv)
{
- if (i915_inject_probe_failure(dev_priv))
- return -ENODEV;
-
mutex_lock(&intel_gvt_mutex);
list_add_tail(&dev_priv->vgpu.entry, &intel_gvt_devices);
if (intel_gvt_ops)
diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h
index dc2477179c3e..614d4017b57b 100644
--- a/drivers/gpu/drm/i915/intel_mchbar_regs.h
+++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h
@@ -130,11 +130,11 @@
#define DG1_DRAM_T_RAS_MASK REG_GENMASK(8, 1)
#define SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5000)
-#define SKL_DRAM_DDR_TYPE_MASK (0x3 << 0)
-#define SKL_DRAM_DDR_TYPE_DDR4 (0 << 0)
-#define SKL_DRAM_DDR_TYPE_DDR3 (1 << 0)
-#define SKL_DRAM_DDR_TYPE_LPDDR3 (2 << 0)
-#define SKL_DRAM_DDR_TYPE_LPDDR4 (3 << 0)
+#define SKL_DRAM_DDR_TYPE_MASK REG_GENMASK(1, 0)
+#define SKL_DRAM_DDR_TYPE_DDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 0)
+#define SKL_DRAM_DDR_TYPE_DDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 1)
+#define SKL_DRAM_DDR_TYPE_LPDDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 2)
+#define SKL_DRAM_DDR_TYPE_LPDDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 3)
/* snb MCH registers for reading the DRAM channel configuration */
#define MAD_DIMM_C0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5004)
@@ -160,30 +160,40 @@
#define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C)
#define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010)
-#define SKL_DRAM_S_SHIFT 16
-#define SKL_DRAM_SIZE_MASK 0x3F
-#define SKL_DRAM_WIDTH_MASK (0x3 << 8)
-#define SKL_DRAM_WIDTH_SHIFT 8
-#define SKL_DRAM_WIDTH_X8 (0x0 << 8)
-#define SKL_DRAM_WIDTH_X16 (0x1 << 8)
-#define SKL_DRAM_WIDTH_X32 (0x2 << 8)
-#define SKL_DRAM_RANK_MASK (0x1 << 10)
-#define SKL_DRAM_RANK_SHIFT 10
-#define SKL_DRAM_RANK_1 (0x0 << 10)
-#define SKL_DRAM_RANK_2 (0x1 << 10)
-#define SKL_DRAM_RANK_MASK (0x1 << 10)
-#define ICL_DRAM_SIZE_MASK 0x7F
-#define ICL_DRAM_WIDTH_MASK (0x3 << 7)
-#define ICL_DRAM_WIDTH_SHIFT 7
-#define ICL_DRAM_WIDTH_X8 (0x0 << 7)
-#define ICL_DRAM_WIDTH_X16 (0x1 << 7)
-#define ICL_DRAM_WIDTH_X32 (0x2 << 7)
-#define ICL_DRAM_RANK_MASK (0x3 << 9)
-#define ICL_DRAM_RANK_SHIFT 9
-#define ICL_DRAM_RANK_1 (0x0 << 9)
-#define ICL_DRAM_RANK_2 (0x1 << 9)
-#define ICL_DRAM_RANK_3 (0x2 << 9)
-#define ICL_DRAM_RANK_4 (0x3 << 9)
+#define SKL_DIMM_S_RANK_MASK REG_GENMASK(26, 26)
+#define SKL_DIMM_S_RANK_1 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 0)
+#define SKL_DIMM_S_RANK_2 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 1)
+#define SKL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24)
+#define SKL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 0)
+#define SKL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 1)
+#define SKL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 2)
+#define SKL_DIMM_S_SIZE_MASK REG_GENMASK(21, 16)
+#define SKL_DIMM_L_RANK_MASK REG_GENMASK(10, 10)
+#define SKL_DIMM_L_RANK_1 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 0)
+#define SKL_DIMM_L_RANK_2 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 1)
+#define SKL_DIMM_L_WIDTH_MASK REG_GENMASK(9, 8)
+#define SKL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 0)
+#define SKL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 1)
+#define SKL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 2)
+#define SKL_DIMM_L_SIZE_MASK REG_GENMASK(5, 0)
+#define ICL_DIMM_S_RANK_MASK REG_GENMASK(27, 26)
+#define ICL_DIMM_S_RANK_1 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 0)
+#define ICL_DIMM_S_RANK_2 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 1)
+#define ICL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24)
+#define ICL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 0)
+#define ICL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 1)
+#define ICL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 2)
+#define ICL_DIMM_S_SIZE_MASK REG_GENMASK(22, 16)
+#define ICL_DIMM_L_RANK_MASK REG_GENMASK(10, 9)
+#define ICL_DIMM_L_RANK_1 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 0)
+#define ICL_DIMM_L_RANK_2 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 1)
+#define ICL_DIMM_L_RANK_3 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 2)
+#define ICL_DIMM_L_RANK_4 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 3)
+#define ICL_DIMM_L_WIDTH_MASK REG_GENMASK(8, 7)
+#define ICL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 0)
+#define ICL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 1)
+#define ICL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 2)
+#define ICL_DIMM_L_SIZE_MASK REG_GENMASK(6, 0)
#define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918)
#define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2)
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 4adeb271fcbf..fdd2a940f983 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -2072,9 +2072,6 @@ static int __fw_domain_init(struct intel_uncore *uncore,
GEM_BUG_ON(domain_id >= FW_DOMAIN_ID_COUNT);
GEM_BUG_ON(uncore->fw_domain[domain_id]);
- if (i915_inject_probe_failure(uncore->i915))
- return -ENOMEM;
-
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
@@ -2118,6 +2115,7 @@ static int __fw_domain_init(struct intel_uncore *uncore,
return 0;
}
+ALLOW_ERROR_INJECTION(__fw_domain_init, ERRNO);
static void fw_domain_fini(struct intel_uncore *uncore,
enum forcewake_domain_id domain_id)
diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c
index b1883dccc22a..98e7cee4e1dc 100644
--- a/drivers/gpu/drm/i915/intel_wakeref.c
+++ b/drivers/gpu/drm/i915/intel_wakeref.c
@@ -80,7 +80,7 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags)
/* Assume we are not in process context and so cannot sleep. */
if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) {
mod_delayed_work(wf->i915->unordered_wq, &wf->work,
- FIELD_GET(INTEL_WAKEREF_PUT_DELAY, flags));
+ FIELD_GET(INTEL_WAKEREF_PUT_DELAY_MASK, flags));
return;
}
diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h
index a2894a56e18f..81308bac34ba 100644
--- a/drivers/gpu/drm/i915/intel_wakeref.h
+++ b/drivers/gpu/drm/i915/intel_wakeref.h
@@ -128,17 +128,16 @@ intel_wakeref_get_if_active(struct intel_wakeref *wf)
return atomic_inc_not_zero(&wf->count);
}
-enum {
- INTEL_WAKEREF_PUT_ASYNC_BIT = 0,
- __INTEL_WAKEREF_PUT_LAST_BIT__
-};
-
static inline void
intel_wakeref_might_get(struct intel_wakeref *wf)
{
might_lock(&wf->mutex);
}
+/* flags for __intel_wakeref_put() and __intel_wakeref_put_last */
+#define INTEL_WAKEREF_PUT_ASYNC BIT(0)
+#define INTEL_WAKEREF_PUT_DELAY_MASK GENMASK(BITS_PER_LONG - 1, 1)
+
/**
* __intel_wakeref_put: Release the wakeref
* @wf: the wakeref
@@ -154,9 +153,6 @@ intel_wakeref_might_get(struct intel_wakeref *wf)
*/
static inline void
__intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags)
-#define INTEL_WAKEREF_PUT_ASYNC BIT(INTEL_WAKEREF_PUT_ASYNC_BIT)
-#define INTEL_WAKEREF_PUT_DELAY \
- GENMASK(BITS_PER_LONG - 1, __INTEL_WAKEREF_PUT_LAST_BIT__)
{
INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
if (unlikely(!atomic_add_unless(&wf->count, -1, 1)))
@@ -181,7 +177,7 @@ intel_wakeref_put_delay(struct intel_wakeref *wf, unsigned long delay)
{
__intel_wakeref_put(wf,
INTEL_WAKEREF_PUT_ASYNC |
- FIELD_PREP(INTEL_WAKEREF_PUT_DELAY, delay));
+ FIELD_PREP(INTEL_WAKEREF_PUT_DELAY_MASK, delay));
}
static inline void
diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h
deleted file mode 100644
index 23be2d113afd..000000000000
--- a/drivers/gpu/drm/i915/soc/intel_gmch.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef __INTEL_GMCH_H__
-#define __INTEL_GMCH_H__
-
-#include <linux/types.h>
-
-struct pci_dev;
-struct drm_i915_private;
-
-int intel_gmch_bridge_setup(struct drm_i915_private *i915);
-void intel_gmch_bar_setup(struct drm_i915_private *i915);
-void intel_gmch_bar_teardown(struct drm_i915_private *i915);
-int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode);
-unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode);
-
-#endif /* __INTEL_GMCH_H__ */
diff --git a/drivers/gpu/drm/i915/vlv_suspend.c b/drivers/gpu/drm/i915/vlv_suspend.c
index 221e4c0b2c58..bace7b38329b 100644
--- a/drivers/gpu/drm/i915/vlv_suspend.c
+++ b/drivers/gpu/drm/i915/vlv_suspend.c
@@ -453,7 +453,7 @@ int vlv_resume_prepare(struct drm_i915_private *dev_priv, bool rpm_resume)
vlv_check_no_gt_access(dev_priv);
if (rpm_resume)
- intel_clock_gating_init(dev_priv);
+ intel_clock_gating_init(&dev_priv->drm);
return ret;
}
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 62be4a5227e4..35f71dbd1bac 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -195,16 +195,10 @@ endif
# i915 Display compat #defines and #includes
subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
- -I$(src)/display/ext \
-I$(src)/compat-i915-headers \
-I$(srctree)/drivers/gpu/drm/i915/display/ \
-Ddrm_i915_private=xe_device
-# Rule to build SOC code shared with i915
-$(obj)/i915-soc/%.o: $(srctree)/drivers/gpu/drm/i915/soc/%.c FORCE
- $(call cmd,force_checksrc)
- $(call if_changed_rule,cc_o_c)
-
# Rule to build display code shared with i915
$(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE
$(call cmd,force_checksrc)
@@ -212,12 +206,10 @@ $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE
# Display code specific to xe
xe-$(CONFIG_DRM_XE_DISPLAY) += \
- display/ext/i915_irq.o \
display/intel_bo.o \
display/intel_fb_bo.o \
display/intel_fbdev_fb.o \
display/xe_display.o \
- display/xe_display_misc.o \
display/xe_display_rpm.o \
display/xe_display_wa.o \
display/xe_dsb_buffer.o \
@@ -228,11 +220,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
display/xe_stolen.o \
display/xe_tdf.o
-# SOC code shared with i915
-xe-$(CONFIG_DRM_XE_DISPLAY) += \
- i915-soc/intel_dram.o \
- i915-soc/intel_rom.o
-
# Display code shared with i915
xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/icl_dsi.o \
@@ -267,6 +254,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_display_power_map.o \
i915-display/intel_display_power_well.o \
i915-display/intel_display_rpm.o \
+ i915-display/intel_display_rps.o \
i915-display/intel_display_trace.o \
i915-display/intel_display_utils.o \
i915-display/intel_display_wa.o \
@@ -283,6 +271,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_dpll.o \
i915-display/intel_dpll_mgr.o \
i915-display/intel_dpt_common.o \
+ i915-display/intel_dram.o \
i915-display/intel_drrs.o \
i915-display/intel_dsb.o \
i915-display/intel_dsi.o \
@@ -310,14 +299,16 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_modeset_setup.o \
i915-display/intel_modeset_verify.o \
i915-display/intel_panel.o \
+ i915-display/intel_parent.o \
+ i915-display/intel_pch.o \
i915-display/intel_pfit.o \
i915-display/intel_plane.o \
i915-display/intel_pmdemand.o \
- i915-display/intel_pch.o \
i915-display/intel_pps.o \
i915-display/intel_psr.o \
i915-display/intel_qp_tables.o \
i915-display/intel_quirks.o \
+ i915-display/intel_rom.o \
i915-display/intel_snps_hdmi_pll.o \
i915-display/intel_snps_phy.o \
i915-display/intel_tc.o \
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h
deleted file mode 100644
index 0548b2e0316f..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/* Copyright © 2025 Intel Corporation */
-
-#ifndef __I915_GEM_OBJECT_H__
-#define __I915_GEM_OBJECT_H__
-
-struct dma_fence;
-
-static inline void i915_gem_fence_wait_priority_display(struct dma_fence *fence)
-{
-}
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h
deleted file mode 100644
index 48e3256ba37e..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2024 Intel Corporation
- */
-
-#ifndef _I915_GEM_STOLEN_H_
-#define _I915_GEM_STOLEN_H_
-
-#include <linux/types.h>
-
-struct drm_device;
-struct intel_stolen_node;
-
-int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
- unsigned int align, u64 start, u64 end);
-
-int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size,
- unsigned int align);
-
-void i915_gem_stolen_remove_node(struct intel_stolen_node *node);
-
-bool i915_gem_stolen_initialized(struct drm_device *drm);
-
-bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node);
-
-u32 i915_gem_stolen_node_offset(struct intel_stolen_node *node);
-
-u64 i915_gem_stolen_area_address(struct drm_device *drm);
-
-u64 i915_gem_stolen_area_size(struct drm_device *drm);
-
-u64 i915_gem_stolen_node_address(struct intel_stolen_node *node);
-
-u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node);
-
-struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm);
-
-void i915_gem_stolen_node_free(const struct intel_stolen_node *node);
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h b/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h
deleted file mode 100644
index c15806d6c4f7..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef __INTEL_GT_TYPES__
-#define __INTEL_GT_TYPES__
-
-#define intel_gt_support_legacy_fencing(gt) 0
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_active.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_active.h
deleted file mode 100644
index 6f0ab3753563..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_active.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2022 Intel Corporation
- */
-
-#ifndef _I915_ACTIVE_H_
-#define _I915_ACTIVE_H_
-
-#include "i915_active_types.h"
-
-static inline void i915_active_init(struct i915_active *ref,
- int (*active)(struct i915_active *ref),
- void (*retire)(struct i915_active *ref),
- unsigned long flags)
-{
- (void) active;
- (void) retire;
-}
-
-#define i915_active_fini(active) do { } while (0)
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_active_types.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_active_types.h
deleted file mode 100644
index 8c31f9a8b168..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_active_types.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright © 2019 Intel Corporation
- */
-
-#ifndef _I915_ACTIVE_TYPES_H_
-#define _I915_ACTIVE_TYPES_H_
-
-struct i915_active {};
-#define I915_ACTIVE_RETIRE_SLEEPS 0
-
-#endif /* _I915_ACTIVE_TYPES_H_ */
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
index 3e79a74ff7de..04d1925f9a19 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
@@ -19,19 +19,4 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
return container_of(dev, struct drm_i915_private, drm);
}
-/* compat platform checks only for soc/ usage */
-#define IS_PLATFORM(xe, x) ((xe)->info.platform == x)
-#define IS_I915G(dev_priv) (dev_priv && 0)
-#define IS_I915GM(dev_priv) (dev_priv && 0)
-#define IS_PINEVIEW(dev_priv) (dev_priv && 0)
-#define IS_VALLEYVIEW(dev_priv) (dev_priv && 0)
-#define IS_CHERRYVIEW(dev_priv) (dev_priv && 0)
-#define IS_HASWELL(dev_priv) (dev_priv && 0)
-#define IS_BROADWELL(dev_priv) (dev_priv && 0)
-#define IS_BROXTON(dev_priv) (dev_priv && 0)
-#define IS_GEMINILAKE(dev_priv) (dev_priv && 0)
-#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, XE_DG2)
-
-#define IS_MOBILE(xe) (xe && 0)
-
#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h
deleted file mode 100644
index 61707a07f91f..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include "../../i915/i915_irq.h"
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
index bcd441dc0fce..3639721f0bf8 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
@@ -3,11 +3,5 @@
* Copyright © 2023 Intel Corporation
*/
-/* for soc/ */
-#ifndef MISSING_CASE
-#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
- __stringify(x), (long)(x))
-#endif
-
/* for a couple of users under i915/display */
#define i915_inject_probe_failure(unused) ((unused) && 0)
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h
deleted file mode 100644
index 4931c7198f13..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef _I915_VGPU_H_
-#define _I915_VGPU_H_
-
-#include <linux/types.h>
-
-struct drm_i915_private;
-
-static inline bool intel_vgpu_active(struct drm_i915_private *i915)
-{
- return false;
-}
-
-#endif /* _I915_VGPU_H_ */
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_wakeref.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_wakeref.h
deleted file mode 100644
index 2a32faea9db5..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/intel_wakeref.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include <linux/types.h>
-
-typedef struct ref_tracker *intel_wakeref_t;
-
-#define INTEL_WAKEREF_DEF ERR_PTR(-ENOENT)
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h b/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h
deleted file mode 100644
index 97fd0ddf0b3a..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef __INTEL_PXP_H__
-#define __INTEL_PXP_H__
-
-#include <linux/errno.h>
-#include <linux/types.h>
-
-#include "xe_pxp.h"
-
-struct drm_gem_object;
-
-static inline int intel_pxp_key_check(struct drm_gem_object *obj, bool assign)
-{
- /*
- * The assign variable is used in i915 to assign the key to the BO at
- * first submission time. In Xe the key is instead assigned at BO
- * creation time, so the assign variable must always be false.
- */
- if (assign)
- return -EINVAL;
-
- return xe_pxp_obj_key_check(obj);
-}
-
-#endif
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h
deleted file mode 100644
index 65707e20c557..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include "../../../i915/soc/intel_dram.h"
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h
deleted file mode 100644
index 33c5257b3a71..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include "../../../i915/soc/intel_gmch.h"
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h
deleted file mode 100644
index 05cbfb697b2b..000000000000
--- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2024 Intel Corporation
- */
-
-#include "../../../i915/soc/intel_rom.h"
diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c
deleted file mode 100644
index 3c6bca66ddab..000000000000
--- a/drivers/gpu/drm/xe/display/ext/i915_irq.c
+++ /dev/null
@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include "i915_irq.h"
-#include "i915_reg.h"
-#include "intel_uncore.h"
-
-void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
-{
- intel_uncore_write(uncore, regs.imr, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.imr);
-
- intel_uncore_write(uncore, regs.ier, 0);
-
- /* IIR can theoretically queue up two events. Be paranoid. */
- intel_uncore_write(uncore, regs.iir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.iir);
- intel_uncore_write(uncore, regs.iir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.iir);
-}
-
-/*
- * We should clear IMR at preinstall/uninstall, and just check at postinstall.
- */
-void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
-{
- struct xe_device *xe = container_of(uncore, struct xe_device, uncore);
- u32 val = intel_uncore_read(uncore, reg);
-
- if (val == 0)
- return;
-
- drm_WARN(&xe->drm, 1,
- "Interrupt register 0x%x is not zero: 0x%08x\n",
- i915_mmio_reg_offset(reg), val);
- intel_uncore_write(uncore, reg, 0xffffffff);
- intel_uncore_posting_read(uncore, reg);
- intel_uncore_write(uncore, reg, 0xffffffff);
- intel_uncore_posting_read(uncore, reg);
-}
-
-void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
- u32 imr_val, u32 ier_val)
-{
- gen2_assert_iir_is_zero(uncore, regs.iir);
-
- intel_uncore_write(uncore, regs.ier, ier_val);
- intel_uncore_write(uncore, regs.imr, imr_val);
- intel_uncore_posting_read(uncore, regs.imr);
-}
-
-void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs)
-{
- intel_uncore_write(uncore, regs.emr, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.emr);
-
- intel_uncore_write(uncore, regs.eir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.eir);
- intel_uncore_write(uncore, regs.eir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.eir);
-}
-
-void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs,
- u32 emr_val)
-{
- intel_uncore_write(uncore, regs.eir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.eir);
- intel_uncore_write(uncore, regs.eir, 0xffffffff);
- intel_uncore_posting_read(uncore, regs.eir);
-
- intel_uncore_write(uncore, regs.emr, emr_val);
- intel_uncore_posting_read(uncore, regs.emr);
-}
-
-bool intel_irqs_enabled(struct xe_device *xe)
-{
- return atomic_read(&xe->irq.enabled);
-}
-
-void intel_synchronize_irq(struct xe_device *xe)
-{
- synchronize_irq(to_pci_dev(xe->drm.dev)->irq);
-}
diff --git a/drivers/gpu/drm/xe/display/intel_bo.c b/drivers/gpu/drm/xe/display/intel_bo.c
index bad2243b9114..e8049a255d21 100644
--- a/drivers/gpu/drm/xe/display/intel_bo.c
+++ b/drivers/gpu/drm/xe/display/intel_bo.c
@@ -3,9 +3,10 @@
#include <drm/drm_gem.h>
-#include "xe_bo.h"
#include "intel_bo.h"
#include "intel_frontbuffer.h"
+#include "xe_bo.h"
+#include "xe_pxp.h"
bool intel_bo_is_tiled(struct drm_gem_object *obj)
{
@@ -29,6 +30,11 @@ bool intel_bo_is_protected(struct drm_gem_object *obj)
return xe_bo_is_protected(gem_to_xe_bo(obj));
}
+int intel_bo_key_check(struct drm_gem_object *obj)
+{
+ return xe_pxp_obj_key_check(obj);
+}
+
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
return drm_gem_prime_mmap(obj, vma);
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index 8b0afa270216..eda65a05f601 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -17,7 +17,6 @@
#include <drm/intel/display_parent_interface.h>
#include <uapi/drm/xe_drm.h>
-#include "soc/intel_dram.h"
#include "intel_acpi.h"
#include "intel_audio.h"
#include "intel_bw.h"
@@ -29,6 +28,7 @@
#include "intel_dmc.h"
#include "intel_dmc_wl.h"
#include "intel_dp.h"
+#include "intel_dram.h"
#include "intel_encoder.h"
#include "intel_fbdev.h"
#include "intel_hdcp.h"
@@ -36,7 +36,10 @@
#include "intel_opregion.h"
#include "skl_watermark.h"
#include "xe_display_rpm.h"
+#include "xe_hdcp_gsc.h"
#include "xe_module.h"
+#include "xe_panic.h"
+#include "xe_stolen.h"
/* Ensure drm and display members are placed properly. */
INTEL_DISPLAY_MEMBER_STATIC_ASSERT(struct xe_device, drm, display);
@@ -122,7 +125,7 @@ int xe_display_init_early(struct xe_device *xe)
* Fill the dram structure to get the system dram info. This will be
* used for memory latency calculation.
*/
- err = intel_dram_detect(xe);
+ err = intel_dram_detect(display);
if (err)
goto err_opregion;
@@ -516,8 +519,29 @@ static void display_device_remove(struct drm_device *dev, void *arg)
intel_display_device_remove(display);
}
+static bool irq_enabled(struct drm_device *drm)
+{
+ struct xe_device *xe = to_xe_device(drm);
+
+ return atomic_read(&xe->irq.enabled);
+}
+
+static void irq_synchronize(struct drm_device *drm)
+{
+ synchronize_irq(to_pci_dev(drm->dev)->irq);
+}
+
+static const struct intel_display_irq_interface xe_display_irq_interface = {
+ .enabled = irq_enabled,
+ .synchronize = irq_synchronize,
+};
+
static const struct intel_display_parent_interface parent = {
+ .hdcp = &xe_display_hdcp_interface,
+ .irq = &xe_display_irq_interface,
+ .panic = &xe_display_panic_interface,
.rpm = &xe_display_rpm_interface,
+ .stolen = &xe_display_stolen_interface,
};
/**
diff --git a/drivers/gpu/drm/xe/display/xe_display_misc.c b/drivers/gpu/drm/xe/display/xe_display_misc.c
deleted file mode 100644
index 242c2ef4ca93..000000000000
--- a/drivers/gpu/drm/xe/display/xe_display_misc.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#include "intel_display_types.h"
-
-struct pci_dev;
-
-unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode);
-
-unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
-{
- /* ToDo: Implement the actual handling of vga decode */
- return 0;
-}
diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c
index 340f65884812..b3db40035499 100644
--- a/drivers/gpu/drm/xe/display/xe_display_rpm.c
+++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c
@@ -9,6 +9,9 @@
#include "xe_device_types.h"
#include "xe_pm.h"
+/* -ENOENT means we got the ref, but there's no tracking */
+#define INTEL_WAKEREF_DEF ERR_PTR(-ENOENT)
+
static struct ref_tracker *xe_display_rpm_get(const struct drm_device *drm)
{
return xe_pm_runtime_resume_and_get(to_xe_device(drm)) ? INTEL_WAKEREF_DEF : NULL;
diff --git a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c
index 58581d7aaae6..fa0acb11eaad 100644
--- a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c
+++ b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c
@@ -3,44 +3,49 @@
* Copyright 2023, Intel Corporation.
*/
-#include "i915_vma.h"
-#include "intel_display_types.h"
#include "intel_dsb_buffer.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_device_types.h"
+struct intel_dsb_buffer {
+ u32 *cmd_buf;
+ struct xe_bo *bo;
+ size_t buf_size;
+};
+
u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf)
{
- return xe_bo_ggtt_addr(dsb_buf->vma->bo);
+ return xe_bo_ggtt_addr(dsb_buf->bo);
}
void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val)
{
- iosys_map_wr(&dsb_buf->vma->bo->vmap, idx * 4, u32, val);
+ iosys_map_wr(&dsb_buf->bo->vmap, idx * 4, u32, val);
}
u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx)
{
- return iosys_map_rd(&dsb_buf->vma->bo->vmap, idx * 4, u32);
+ return iosys_map_rd(&dsb_buf->bo->vmap, idx * 4, u32);
}
void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size)
{
WARN_ON(idx > (dsb_buf->buf_size - size) / sizeof(*dsb_buf->cmd_buf));
- iosys_map_memset(&dsb_buf->vma->bo->vmap, idx * 4, val, size);
+ iosys_map_memset(&dsb_buf->bo->vmap, idx * 4, val, size);
}
-bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size)
+struct intel_dsb_buffer *intel_dsb_buffer_create(struct drm_device *drm, size_t size)
{
- struct xe_device *xe = to_xe_device(crtc->base.dev);
+ struct xe_device *xe = to_xe_device(drm);
+ struct intel_dsb_buffer *dsb_buf;
struct xe_bo *obj;
- struct i915_vma *vma;
+ int ret;
- vma = kzalloc(sizeof(*vma), GFP_KERNEL);
- if (!vma)
- return false;
+ dsb_buf = kzalloc(sizeof(*dsb_buf), GFP_KERNEL);
+ if (!dsb_buf)
+ return ERR_PTR(-ENOMEM);
/* Set scanout flag for WC mapping */
obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe),
@@ -49,26 +54,30 @@ bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *d
XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) |
XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT, false);
if (IS_ERR(obj)) {
- kfree(vma);
- return false;
+ ret = PTR_ERR(obj);
+ goto err_pin_map;
}
- vma->bo = obj;
- dsb_buf->vma = vma;
+ dsb_buf->bo = obj;
dsb_buf->buf_size = size;
- return true;
+ return dsb_buf;
+
+err_pin_map:
+ kfree(dsb_buf);
+
+ return ERR_PTR(ret);
}
void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf)
{
- xe_bo_unpin_map_no_vm(dsb_buf->vma->bo);
- kfree(dsb_buf->vma);
+ xe_bo_unpin_map_no_vm(dsb_buf->bo);
+ kfree(dsb_buf);
}
void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf)
{
- struct xe_device *xe = dsb_buf->vma->bo->tile->xe;
+ struct xe_device *xe = dsb_buf->bo->tile->xe;
/*
* The memory barrier here is to ensure coherency of DSB vs MMIO,
diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
index 4ae847b628e2..4e5ccd50f69d 100644
--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
@@ -3,18 +3,20 @@
* Copyright 2023, Intel Corporation.
*/
+#include <linux/delay.h>
+
#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
#include <drm/intel/i915_hdcp_interface.h>
-#include <linux/delay.h>
#include "abi/gsc_command_header_abi.h"
-#include "intel_hdcp_gsc.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_device_types.h"
#include "xe_force_wake.h"
#include "xe_gsc_proxy.h"
#include "xe_gsc_submit.h"
+#include "xe_hdcp_gsc.h"
#include "xe_map.h"
#include "xe_pm.h"
#include "xe_uc_fw.h"
@@ -30,7 +32,7 @@ struct intel_hdcp_gsc_context {
#define HDCP_GSC_HEADER_SIZE sizeof(struct intel_gsc_mtl_header)
-bool intel_hdcp_gsc_check_status(struct drm_device *drm)
+static bool intel_hdcp_gsc_check_status(struct drm_device *drm)
{
struct xe_device *xe = to_xe_device(drm);
struct xe_tile *tile = xe_device_get_root_tile(xe);
@@ -96,7 +98,7 @@ out:
return ret;
}
-struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm)
+static struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm)
{
struct xe_device *xe = to_xe_device(drm);
struct intel_hdcp_gsc_context *gsc_context;
@@ -120,7 +122,7 @@ struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *d
return gsc_context;
}
-void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context)
+static void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context)
{
if (!gsc_context)
return;
@@ -155,9 +157,9 @@ static int xe_gsc_send_sync(struct xe_device *xe,
return ret;
}
-ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
- void *msg_in, size_t msg_in_len,
- void *msg_out, size_t msg_out_len)
+static ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len)
{
struct xe_device *xe = gsc_context->xe;
const size_t max_msg_size = PAGE_SIZE - HDCP_GSC_HEADER_SIZE;
@@ -211,3 +213,10 @@ out:
xe_pm_runtime_put(xe);
return ret;
}
+
+const struct intel_display_hdcp_interface xe_display_hdcp_interface = {
+ .gsc_msg_send = intel_hdcp_gsc_msg_send,
+ .gsc_check_status = intel_hdcp_gsc_check_status,
+ .gsc_context_alloc = intel_hdcp_gsc_context_alloc,
+ .gsc_context_free = intel_hdcp_gsc_context_free,
+};
diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.h b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.h
new file mode 100644
index 000000000000..c1062e4b62f7
--- /dev/null
+++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __XE_HDCP_GSC_H__
+#define __XE_HDCP_GSC_H__
+
+extern const struct intel_display_hdcp_interface xe_display_hdcp_interface;
+
+#endif
diff --git a/drivers/gpu/drm/xe/display/xe_panic.c b/drivers/gpu/drm/xe/display/xe_panic.c
index df663286092a..e078494dc8ba 100644
--- a/drivers/gpu/drm/xe/display/xe_panic.c
+++ b/drivers/gpu/drm/xe/display/xe_panic.c
@@ -3,11 +3,12 @@
#include <drm/drm_cache.h>
#include <drm/drm_panic.h>
+#include <drm/intel/display_parent_interface.h>
#include "intel_display_types.h"
#include "intel_fb.h"
-#include "intel_panic.h"
#include "xe_bo.h"
+#include "xe_panic.h"
#include "xe_res_cursor.h"
struct intel_panic {
@@ -74,7 +75,7 @@ static void xe_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int
iosys_map_wr(&panic->vmap, offset, u32, color);
}
-struct intel_panic *intel_panic_alloc(void)
+static struct intel_panic *xe_panic_alloc(void)
{
struct intel_panic *panic;
@@ -83,7 +84,7 @@ struct intel_panic *intel_panic_alloc(void)
return panic;
}
-int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
+static int xe_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
{
struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private;
struct xe_bo *bo = gem_to_xe_bo(intel_fb_bo(&fb->base));
@@ -96,7 +97,8 @@ int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
return 0;
}
-void intel_panic_finish(struct intel_panic *panic)
-{
- xe_panic_kunmap(panic);
-}
+const struct intel_display_panic_interface xe_display_panic_interface = {
+ .alloc = xe_panic_alloc,
+ .setup = xe_panic_setup,
+ .finish = xe_panic_kunmap,
+};
diff --git a/drivers/gpu/drm/xe/display/xe_panic.h b/drivers/gpu/drm/xe/display/xe_panic.h
new file mode 100644
index 000000000000..3054b511011b
--- /dev/null
+++ b/drivers/gpu/drm/xe/display/xe_panic.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __XE_PANIC_H__
+#define __XE_PANIC_H__
+
+extern const struct intel_display_panic_interface xe_display_panic_interface;
+
+#endif
diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c
index 12d25c5290fd..01c105a93bb9 100644
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
@@ -58,7 +58,7 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
- if (!crtc_state->uapi.active)
+ if (!crtc_state->hw.active)
continue;
if (!plane_state->ggtt_vma)
@@ -290,10 +290,12 @@ void intel_initial_plane_config(struct intel_display *display)
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 (!to_intel_crtc_state(crtc->base.state)->uapi.active)
+ if (!crtc_state->hw.active)
continue;
/*
diff --git a/drivers/gpu/drm/xe/display/xe_stolen.c b/drivers/gpu/drm/xe/display/xe_stolen.c
index 9f04ba36e930..12771709183a 100644
--- a/drivers/gpu/drm/xe/display/xe_stolen.c
+++ b/drivers/gpu/drm/xe/display/xe_stolen.c
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2025 Intel Corporation */
-#include "gem/i915_gem_stolen.h"
+#include <drm/intel/display_parent_interface.h>
+
#include "xe_res_cursor.h"
+#include "xe_stolen.h"
#include "xe_ttm_stolen_mgr.h"
#include "xe_validation.h"
@@ -11,8 +13,8 @@ struct intel_stolen_node {
struct xe_bo *bo;
};
-int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
- unsigned int align, u64 start, u64 end)
+static int xe_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size,
+ unsigned int align, u64 start, u64 end)
{
struct xe_device *xe = node->xe;
@@ -41,33 +43,25 @@ int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 siz
return err;
}
-int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size, unsigned int align)
-{
- /* Not used on xe */
- WARN_ON(1);
-
- return -ENODEV;
-}
-
-void i915_gem_stolen_remove_node(struct intel_stolen_node *node)
+static void xe_stolen_remove_node(struct intel_stolen_node *node)
{
xe_bo_unpin_map_no_vm(node->bo);
node->bo = NULL;
}
-bool i915_gem_stolen_initialized(struct drm_device *drm)
+static bool xe_stolen_initialized(struct drm_device *drm)
{
struct xe_device *xe = to_xe_device(drm);
return ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
}
-bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node)
+static bool xe_stolen_node_allocated(const struct intel_stolen_node *node)
{
return node->bo;
}
-u32 i915_gem_stolen_node_offset(struct intel_stolen_node *node)
+static u64 xe_stolen_node_offset(const struct intel_stolen_node *node)
{
struct xe_res_cursor res;
@@ -75,35 +69,19 @@ u32 i915_gem_stolen_node_offset(struct intel_stolen_node *node)
return res.start;
}
-/* Used for < gen4. These are not supported by Xe */
-u64 i915_gem_stolen_area_address(struct drm_device *drm)
-{
- WARN_ON(1);
-
- return 0;
-}
-
-/* Used for gen9 specific WA. Gen9 is not supported by Xe */
-u64 i915_gem_stolen_area_size(struct drm_device *drm)
-{
- WARN_ON(1);
-
- return 0;
-}
-
-u64 i915_gem_stolen_node_address(struct intel_stolen_node *node)
+static u64 xe_stolen_node_address(const struct intel_stolen_node *node)
{
struct xe_device *xe = node->xe;
- return xe_ttm_stolen_gpu_offset(xe) + i915_gem_stolen_node_offset(node);
+ return xe_ttm_stolen_gpu_offset(xe) + xe_stolen_node_offset(node);
}
-u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node)
+static u64 xe_stolen_node_size(const struct intel_stolen_node *node)
{
return node->bo->ttm.base.size;
}
-struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm)
+static struct intel_stolen_node *xe_stolen_node_alloc(struct drm_device *drm)
{
struct xe_device *xe = to_xe_device(drm);
struct intel_stolen_node *node;
@@ -117,7 +95,19 @@ struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm)
return node;
}
-void i915_gem_stolen_node_free(const struct intel_stolen_node *node)
+static void xe_stolen_node_free(const struct intel_stolen_node *node)
{
kfree(node);
}
+
+const struct intel_display_stolen_interface xe_display_stolen_interface = {
+ .insert_node_in_range = xe_stolen_insert_node_in_range,
+ .remove_node = xe_stolen_remove_node,
+ .initialized = xe_stolen_initialized,
+ .node_allocated = xe_stolen_node_allocated,
+ .node_offset = xe_stolen_node_offset,
+ .node_address = xe_stolen_node_address,
+ .node_size = xe_stolen_node_size,
+ .node_alloc = xe_stolen_node_alloc,
+ .node_free = xe_stolen_node_free,
+};
diff --git a/drivers/gpu/drm/xe/display/xe_stolen.h b/drivers/gpu/drm/xe/display/xe_stolen.h
new file mode 100644
index 000000000000..db86b9e01242
--- /dev/null
+++ b/drivers/gpu/drm/xe/display/xe_stolen.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2025 Intel Corporation */
+
+#ifndef __XE_STOLEN_H__
+#define __XE_STOLEN_H__
+
+extern const struct intel_display_stolen_interface xe_display_stolen_interface;
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 0b2fa7c56d38..6ce3247d1bd8 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -35,7 +35,6 @@
#define TEST_VM_OPS_ERROR
#endif
-struct dram_info;
struct intel_display;
struct intel_dg_nvm_dev;
struct xe_ggtt;
@@ -648,13 +647,6 @@ struct xe_device {
* drm_i915_private during build. After cleanup these should go away,
* migrating to the right sub-structs
*/
- const struct dram_info *dram_info;
-
- /*
- * edram size in MB.
- * Cannot be determined by PCIID. You must always read a register.
- */
- u32 edram_size_mb;
struct intel_uncore {
spinlock_t lock;