diff options
| author | Dave Airlie <airlied@redhat.com> | 2025-12-27 16:25:56 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2025-12-27 16:27:04 +1000 |
| commit | c5fb82d113c6266e65fee2a7e0dc8f48c3bd12cc (patch) | |
| tree | 75a2c2a5ee400b24950071148336275c614f6a3d /drivers | |
| parent | 7bc0f871f992f1469229ffcd2b40a45ec5f695b0 (diff) | |
| parent | 35ec71285c9311395b14bedc60fa94f6b7e24d2d (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')
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(¤t_config->name, \ - &pipe_config->name)) { \ - pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \ - ¤t_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(¤t_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(>->uc); intel_migrate_init(>->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; |
