diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
142 files changed, 7163 insertions, 4853 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index a0e86d29bf54..7ae3b7d67fcf 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -10,7 +10,10 @@ config DRM_I915 # the shmem_readpage() which depends upon tmpfs select SHMEM select TMPFS - select DRM_DP_HELPER + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL select DRM_MIPI_DSI diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 6672c4dadc2c..e83e4cd46968 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -222,6 +222,7 @@ i915-y += \ display/intel_combo_phy.o \ display/intel_connector.o \ display/intel_crtc.o \ + display/intel_crtc_state_dump.o \ display/intel_cursor.o \ display/intel_display.o \ display/intel_display_power.o \ @@ -244,6 +245,8 @@ i915-y += \ display/intel_hdcp.o \ display/intel_hotplug.o \ display/intel_lpe_audio.o \ + display/intel_modeset_verify.o \ + display/intel_modeset_setup.o \ display/intel_overlay.o \ display/intel_pch_display.o \ display/intel_pch_refclk.o \ diff --git a/drivers/gpu/drm/i915/TODO.txt b/drivers/gpu/drm/i915/TODO.txt index 81a82c9c203f..879b08ca32b3 100644 --- a/drivers/gpu/drm/i915/TODO.txt +++ b/drivers/gpu/drm/i915/TODO.txt @@ -37,5 +37,5 @@ Smaller things: https://lore.kernel.org/linux-mm/20210301083320.943079-1-hch@lst.de/ -- tasklet helpers in i915_gem.h also look a bit misplaced and should +- tasklet helpers in i915_tasklet.h also look a bit misplaced and should probably be moved to tasklet headers. diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 5a957acebfd6..e3e3d27ffb53 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -395,26 +395,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); - if (intel_dp_is_edp(intel_dp) && dev_priv->vbt.edp.bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { - /* - * This is a big fat ugly hack. - * - * Some machines in UEFI boot mode provide us a VBT that has 18 - * bpp and 1.62 GHz link bandwidth for eDP, which for reasons - * unknown we fail to light up. Yet the same BIOS boots up with - * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as - * max, not what it tells us to use. - * - * Note: This will still be broken if the eDP panel is not lit - * up by the BIOS, and thus we can't get the mode at module - * load. - */ - drm_dbg_kms(&dev_priv->drm, - "pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp); - dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; - } + if (intel_dp_is_edp(intel_dp)) + intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp); } static void @@ -1187,7 +1169,7 @@ intel_dp_hotplug(struct intel_encoder *encoder, static bool ibx_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.pch_hpd[encoder->hpd_pin]; + u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin]; return intel_de_read(dev_priv, SDEISR) & bit; } @@ -1241,7 +1223,7 @@ static bool gm45_digital_port_connected(struct intel_encoder *encoder) static bool ilk_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin]; + u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin]; return intel_de_read(dev_priv, DEISR) & bit; } diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 7fe1a4e57654..0f35f2facdfc 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -5,8 +5,8 @@ #include <linux/kernel.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "intel_atomic.h" #include "intel_atomic_plane.h" @@ -325,8 +325,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, return ret; ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, i9xx_plane_has_windowing(plane)); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index d29211b9807c..3e20b2f65887 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -25,6 +25,7 @@ * Jani Nikula <jani.nikula@intel.com> */ +#include <drm/display/drm_dsc_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_mipi_dsi.h> @@ -32,6 +33,7 @@ #include "icl_dsi_regs.h" #include "intel_atomic.h" #include "intel_backlight.h" +#include "intel_backlight_regs.h" #include "intel_combo_phy.h" #include "intel_combo_phy_regs.h" #include "intel_connector.h" @@ -640,13 +642,13 @@ static void gen11_dsi_gate_clocks(struct intel_encoder *encoder) u32 tmp; enum phy phy; - mutex_lock(&dev_priv->dpll.lock); + mutex_lock(&dev_priv->display.dpll.lock); tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0); for_each_dsi_phy(phy, intel_dsi->phys) tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp); - mutex_unlock(&dev_priv->dpll.lock); + mutex_unlock(&dev_priv->display.dpll.lock); } static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder) @@ -656,13 +658,13 @@ static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder) u32 tmp; enum phy phy; - mutex_lock(&dev_priv->dpll.lock); + mutex_lock(&dev_priv->display.dpll.lock); tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0); for_each_dsi_phy(phy, intel_dsi->phys) tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp); - mutex_unlock(&dev_priv->dpll.lock); + mutex_unlock(&dev_priv->display.dpll.lock); } static bool gen11_dsi_is_clock_enabled(struct intel_encoder *encoder) @@ -692,7 +694,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, enum phy phy; u32 val; - mutex_lock(&dev_priv->dpll.lock); + mutex_lock(&dev_priv->display.dpll.lock); val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0); for_each_dsi_phy(phy, intel_dsi->phys) { @@ -708,7 +710,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0); - mutex_unlock(&dev_priv->dpll.lock); + mutex_unlock(&dev_priv->display.dpll.lock); } static void @@ -1861,7 +1863,8 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; + struct intel_connector *connector = intel_dsi->attached_connector; + struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; u32 tlpx_ns; u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt; u32 ths_prepare_ns, tclk_trail_ns; @@ -2048,6 +2051,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) /* attach connector to encoder */ intel_connector_attach_encoder(intel_connector, encoder); + intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + mutex_lock(&dev->mode_config.mutex); intel_panel_add_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); @@ -2061,13 +2066,16 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) intel_backlight_setup(intel_connector, INVALID_PIPE); - if (dev_priv->vbt.dsi.config->dual_link) + if (intel_connector->panel.vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_B); else intel_dsi->ports = BIT(port); - intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports; - intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports; + if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; + + if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; for_each_dsi_port(port, intel_dsi->ports) { struct intel_dsi_host *host; diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 40da7910f845..b94973b5633f 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,7 +32,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "i915_drv.h" #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index efe8591619e3..dd876dbbaa39 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -33,7 +33,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "gt/intel_rps.h" diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index f0f0dfce27ce..a74fc79b7910 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -30,6 +30,7 @@ #include "i915_drv.h" #include "intel_atomic.h" #include "intel_audio.h" +#include "intel_audio_regs.h" #include "intel_cdclk.h" #include "intel_crtc.h" #include "intel_de.h" @@ -392,7 +393,7 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio.component; + struct i915_audio_component *acomp = dev_priv->display.audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; const struct dp_aud_n_m *nm; @@ -440,7 +441,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio.component; + struct i915_audio_component *acomp = dev_priv->display.audio.component; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum port port = encoder->port; int n, rate; @@ -495,7 +496,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; u32 tmp; - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); /* Disable timestamps */ tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder)); @@ -513,7 +514,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder); intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp); - mutex_unlock(&dev_priv->audio.mutex); + mutex_unlock(&dev_priv->display.audio.mutex); } static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, @@ -638,7 +639,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, u32 tmp; int len, i; - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); /* Enable Audio WA for 4k DSC usecases */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) @@ -676,7 +677,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); - mutex_unlock(&dev_priv->audio.mutex); + mutex_unlock(&dev_priv->display.audio.mutex); } static void ilk_audio_codec_disable(struct intel_encoder *encoder, @@ -813,7 +814,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio.component; + struct i915_audio_component *acomp = dev_priv->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = @@ -837,17 +838,17 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; - if (dev_priv->audio.funcs) - dev_priv->audio.funcs->audio_codec_enable(encoder, - crtc_state, - conn_state); + if (dev_priv->display.funcs.audio) + dev_priv->display.funcs.audio->audio_codec_enable(encoder, + crtc_state, + conn_state); - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); encoder->audio_connector = connector; /* referred in audio callbacks */ - dev_priv->audio.encoder_map[pipe] = encoder; - mutex_unlock(&dev_priv->audio.mutex); + dev_priv->display.audio.encoder_map[pipe] = encoder; + mutex_unlock(&dev_priv->display.audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -877,7 +878,7 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct i915_audio_component *acomp = dev_priv->audio.component; + struct i915_audio_component *acomp = dev_priv->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_connector *connector = old_conn_state->connector; enum port port = encoder->port; @@ -890,15 +891,15 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, connector->base.id, connector->name, encoder->base.base.id, encoder->base.name, pipe_name(pipe)); - if (dev_priv->audio.funcs) - dev_priv->audio.funcs->audio_codec_disable(encoder, - old_crtc_state, - old_conn_state); + if (dev_priv->display.funcs.audio) + dev_priv->display.funcs.audio->audio_codec_disable(encoder, + old_crtc_state, + old_conn_state); - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); encoder->audio_connector = NULL; - dev_priv->audio.encoder_map[pipe] = NULL; - mutex_unlock(&dev_priv->audio.mutex); + dev_priv->display.audio.encoder_map[pipe] = NULL; + mutex_unlock(&dev_priv->display.audio.mutex); if (acomp && acomp->base.audio_ops && acomp->base.audio_ops->pin_eld_notify) { @@ -934,13 +935,13 @@ static const struct intel_audio_funcs hsw_audio_funcs = { void intel_audio_hooks_init(struct drm_i915_private *dev_priv) { if (IS_G4X(dev_priv)) { - dev_priv->audio.funcs = &g4x_audio_funcs; + dev_priv->display.funcs.audio = &g4x_audio_funcs; } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - dev_priv->audio.funcs = &ilk_audio_funcs; + dev_priv->display.funcs.audio = &ilk_audio_funcs; } else if (IS_HASWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 8) { - dev_priv->audio.funcs = &hsw_audio_funcs; + dev_priv->display.funcs.audio = &hsw_audio_funcs; } else if (HAS_PCH_SPLIT(dev_priv)) { - dev_priv->audio.funcs = &ilk_audio_funcs; + dev_priv->display.funcs.audio = &ilk_audio_funcs; } } @@ -1045,13 +1046,13 @@ static unsigned long i915_audio_component_get_power(struct device *kdev) ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK); - if (dev_priv->audio.power_refcount++ == 0) { + if (dev_priv->display.audio.power_refcount++ == 0) { if (DISPLAY_VER(dev_priv) >= 9) { intel_de_write(dev_priv, AUD_FREQ_CNTRL, - dev_priv->audio.freq_cntrl); + dev_priv->display.audio.freq_cntrl); drm_dbg_kms(&dev_priv->drm, "restored AUD_FREQ_CNTRL to 0x%x\n", - dev_priv->audio.freq_cntrl); + dev_priv->display.audio.freq_cntrl); } /* Force CDCLK to 2*BCLK as long as we need audio powered. */ @@ -1072,7 +1073,7 @@ static void i915_audio_component_put_power(struct device *kdev, struct drm_i915_private *dev_priv = kdev_to_i915(kdev); /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ - if (--dev_priv->audio.power_refcount == 0) + if (--dev_priv->display.audio.power_refcount == 0) if (IS_GEMINILAKE(dev_priv)) glk_force_audio_cdclk(dev_priv, false); @@ -1139,10 +1140,10 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, /* MST */ if (pipe >= 0) { if (drm_WARN_ON(&dev_priv->drm, - pipe >= ARRAY_SIZE(dev_priv->audio.encoder_map))) + pipe >= ARRAY_SIZE(dev_priv->display.audio.encoder_map))) return NULL; - encoder = dev_priv->audio.encoder_map[pipe]; + encoder = dev_priv->display.audio.encoder_map[pipe]; /* * when bootup, audio driver may not know it is * MST or not. So it will poll all the port & pipe @@ -1158,7 +1159,7 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, return NULL; for_each_pipe(dev_priv, pipe) { - encoder = dev_priv->audio.encoder_map[pipe]; + encoder = dev_priv->display.audio.encoder_map[pipe]; if (encoder == NULL) continue; @@ -1176,7 +1177,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, int pipe, int rate) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct i915_audio_component *acomp = dev_priv->audio.component; + struct i915_audio_component *acomp = dev_priv->display.audio.component; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; @@ -1186,7 +1187,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, return 0; cookie = i915_audio_component_get_power(kdev); - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); /* 1. get the pipe */ encoder = get_saved_enc(dev_priv, port, pipe); @@ -1205,7 +1206,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, hsw_audio_config_update(encoder, crtc->config); unlock: - mutex_unlock(&dev_priv->audio.mutex); + mutex_unlock(&dev_priv->display.audio.mutex); i915_audio_component_put_power(kdev, cookie); return err; } @@ -1219,13 +1220,13 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, const u8 *eld; int ret = -EINVAL; - mutex_lock(&dev_priv->audio.mutex); + mutex_lock(&dev_priv->display.audio.mutex); intel_encoder = get_saved_enc(dev_priv, port, pipe); if (!intel_encoder) { drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n", port_name(port)); - mutex_unlock(&dev_priv->audio.mutex); + mutex_unlock(&dev_priv->display.audio.mutex); return ret; } @@ -1237,7 +1238,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, memcpy(buf, eld, min(max_bytes, ret)); } - mutex_unlock(&dev_priv->audio.mutex); + mutex_unlock(&dev_priv->display.audio.mutex); return ret; } @@ -1272,7 +1273,7 @@ static int i915_audio_component_bind(struct device *i915_kdev, BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; - dev_priv->audio.component = acomp; + dev_priv->display.audio.component = acomp; drm_modeset_unlock_all(&dev_priv->drm); return 0; @@ -1287,14 +1288,14 @@ static void i915_audio_component_unbind(struct device *i915_kdev, drm_modeset_lock_all(&dev_priv->drm); acomp->base.ops = NULL; acomp->base.dev = NULL; - dev_priv->audio.component = NULL; + dev_priv->display.audio.component = NULL; drm_modeset_unlock_all(&dev_priv->drm); device_link_remove(hda_kdev, i915_kdev); - if (dev_priv->audio.power_refcount) + if (dev_priv->display.audio.power_refcount) drm_err(&dev_priv->drm, "audio power refcount %d after unbind\n", - dev_priv->audio.power_refcount); + dev_priv->display.audio.power_refcount); } static const struct component_ops i915_audio_component_bind_ops = { @@ -1358,13 +1359,13 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", aud_freq, aud_freq_init); - dev_priv->audio.freq_cntrl = aud_freq; + dev_priv->display.audio.freq_cntrl = aud_freq; } /* init with current cdclk */ intel_audio_cdclk_change_post(dev_priv); - dev_priv->audio.component_registered = true; + dev_priv->display.audio.component_registered = true; } /** @@ -1376,11 +1377,11 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv) */ static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) { - if (!dev_priv->audio.component_registered) + if (!dev_priv->display.audio.component_registered) return; component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops); - dev_priv->audio.component_registered = false; + dev_priv->display.audio.component_registered = false; } /** @@ -1402,7 +1403,7 @@ void intel_audio_init(struct drm_i915_private *dev_priv) */ void intel_audio_deinit(struct drm_i915_private *dev_priv) { - if ((dev_priv)->audio.lpe.platdev != NULL) + if (dev_priv->display.audio.lpe.platdev != NULL) intel_lpe_audio_teardown(dev_priv); else i915_audio_component_cleanup(dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_audio_regs.h b/drivers/gpu/drm/i915/display/intel_audio_regs.h new file mode 100644 index 000000000000..d1e5844e3484 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_audio_regs.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_AUDIO_REGS_H__ +#define __INTEL_AUDIO_REGS_H__ + +#include "i915_reg_defs.h" + +#define G4X_AUD_VID_DID _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x62020) +#define INTEL_AUDIO_DEVCL 0x808629FB +#define INTEL_AUDIO_DEVBLC 0x80862801 +#define INTEL_AUDIO_DEVCTG 0x80862802 + +#define G4X_AUD_CNTL_ST _MMIO(0x620B4) +#define G4X_ELDV_DEVCL_DEVBLC (1 << 13) +#define G4X_ELDV_DEVCTG (1 << 14) +#define G4X_ELD_ADDR_MASK (0xf << 5) +#define G4X_ELD_ACK (1 << 4) +#define G4X_HDMIW_HDMIEDID _MMIO(0x6210C) + +#define _IBX_HDMIW_HDMIEDID_A 0xE2050 +#define _IBX_HDMIW_HDMIEDID_B 0xE2150 +#define IBX_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _IBX_HDMIW_HDMIEDID_A, \ + _IBX_HDMIW_HDMIEDID_B) +#define _IBX_AUD_CNTL_ST_A 0xE20B4 +#define _IBX_AUD_CNTL_ST_B 0xE21B4 +#define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \ + _IBX_AUD_CNTL_ST_B) +#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10) +#define IBX_ELD_ADDRESS_MASK (0x1f << 5) +#define IBX_ELD_ACK (1 << 4) +#define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0) +#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4)) +#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4)) + +#define _CPT_HDMIW_HDMIEDID_A 0xE5050 +#define _CPT_HDMIW_HDMIEDID_B 0xE5150 +#define CPT_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _CPT_HDMIW_HDMIEDID_A, _CPT_HDMIW_HDMIEDID_B) +#define _CPT_AUD_CNTL_ST_A 0xE50B4 +#define _CPT_AUD_CNTL_ST_B 0xE51B4 +#define CPT_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CNTL_ST_A, _CPT_AUD_CNTL_ST_B) +#define CPT_AUD_CNTRL_ST2 _MMIO(0xE50C0) + +#define _VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050) +#define _VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150) +#define VLV_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _VLV_HDMIW_HDMIEDID_A, _VLV_HDMIW_HDMIEDID_B) +#define _VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4) +#define _VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4) +#define VLV_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CNTL_ST_A, _VLV_AUD_CNTL_ST_B) +#define VLV_AUD_CNTL_ST2 _MMIO(VLV_DISPLAY_BASE + 0x620C0) + +#define _IBX_AUD_CONFIG_A 0xe2000 +#define _IBX_AUD_CONFIG_B 0xe2100 +#define IBX_AUD_CFG(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CONFIG_A, _IBX_AUD_CONFIG_B) +#define _CPT_AUD_CONFIG_A 0xe5000 +#define _CPT_AUD_CONFIG_B 0xe5100 +#define CPT_AUD_CFG(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CONFIG_A, _CPT_AUD_CONFIG_B) +#define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000) +#define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100) +#define VLV_AUD_CFG(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CONFIG_A, _VLV_AUD_CONFIG_B) + +#define AUD_CONFIG_N_VALUE_INDEX (1 << 29) +#define AUD_CONFIG_N_PROG_ENABLE (1 << 28) +#define AUD_CONFIG_UPPER_N_SHIFT 20 +#define AUD_CONFIG_UPPER_N_MASK (0xff << 20) +#define AUD_CONFIG_LOWER_N_SHIFT 4 +#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) +#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK) +#define AUD_CONFIG_N(n) \ + (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \ + (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT)) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 (10 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 (11 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 (12 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 (13 << 16) +#define AUD_CONFIG_DISABLE_NCTS (1 << 3) + +#define _HSW_AUD_CONFIG_A 0x65000 +#define _HSW_AUD_CONFIG_B 0x65100 +#define HSW_AUD_CFG(trans) _MMIO_TRANS(trans, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B) + +#define _HSW_AUD_MISC_CTRL_A 0x65010 +#define _HSW_AUD_MISC_CTRL_B 0x65110 +#define HSW_AUD_MISC_CTRL(trans) _MMIO_TRANS(trans, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B) + +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028 +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128 +#define HSW_AUD_M_CTS_ENABLE(trans) _MMIO_TRANS(trans, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B) +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21) +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20) +#define AUD_CONFIG_M_MASK 0xfffff + +#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 +#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 +#define HSW_AUD_DIP_ELD_CTRL(trans) _MMIO_TRANS(trans, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B) + +/* Audio Digital Converter */ +#define _HSW_AUD_DIG_CNVT_1 0x65080 +#define _HSW_AUD_DIG_CNVT_2 0x65180 +#define AUD_DIG_CNVT(trans) _MMIO_TRANS(trans, _HSW_AUD_DIG_CNVT_1, _HSW_AUD_DIG_CNVT_2) +#define DIP_PORT_SEL_MASK 0x3 + +#define _HSW_AUD_EDID_DATA_A 0x65050 +#define _HSW_AUD_EDID_DATA_B 0x65150 +#define HSW_AUD_EDID_DATA(trans) _MMIO_TRANS(trans, _HSW_AUD_EDID_DATA_A, _HSW_AUD_EDID_DATA_B) + +#define HSW_AUD_PIPE_CONV_CFG _MMIO(0x6507c) +#define HSW_AUD_PIN_ELD_CP_VLD _MMIO(0x650c0) +#define AUDIO_INACTIVE(trans) ((1 << 3) << ((trans) * 4)) +#define AUDIO_OUTPUT_ENABLE(trans) ((1 << 2) << ((trans) * 4)) +#define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4)) +#define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4)) + +#define _AUD_TCA_DP_2DOT0_CTRL 0x650bc +#define _AUD_TCB_DP_2DOT0_CTRL 0x651bc +#define AUD_DP_2DOT0_CTRL(trans) _MMIO_TRANS(trans, _AUD_TCA_DP_2DOT0_CTRL, _AUD_TCB_DP_2DOT0_CTRL) +#define AUD_ENABLE_SDP_SPLIT REG_BIT(31) + +#define HSW_AUD_CHICKENBIT _MMIO(0x65f10) +#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) + +#define AUD_FREQ_CNTRL _MMIO(0x65900) +#define AUD_PIN_BUF_CTL _MMIO(0x48414) +#define AUD_PIN_BUF_ENABLE REG_BIT(31) + +#define AUD_TS_CDCLK_M _MMIO(0x65ea0) +#define AUD_TS_CDCLK_M_EN REG_BIT(31) +#define AUD_TS_CDCLK_N _MMIO(0x65ea4) + +/* Display Audio Config Reg */ +#define AUD_CONFIG_BE _MMIO(0x65ef0) +#define HBLANK_EARLY_ENABLE_ICL(pipe) (0x1 << (20 - (pipe))) +#define HBLANK_EARLY_ENABLE_TGL(pipe) (0x1 << (24 + (pipe))) +#define HBLANK_START_COUNT_MASK(pipe) (0x7 << (3 + ((pipe) * 6))) +#define HBLANK_START_COUNT(pipe, val) (((val) & 0x7) << (3 + ((pipe)) * 6)) +#define NUMBER_SAMPLES_PER_LINE_MASK(pipe) (0x3 << ((pipe) * 6)) +#define NUMBER_SAMPLES_PER_LINE(pipe, val) (((val) & 0x3) << ((pipe) * 6)) + +#define HBLANK_START_COUNT_8 0 +#define HBLANK_START_COUNT_16 1 +#define HBLANK_START_COUNT_32 2 +#define HBLANK_START_COUNT_64 3 +#define HBLANK_START_COUNT_96 4 +#define HBLANK_START_COUNT_128 5 + +#endif /* __INTEL_AUDIO_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index c8e1fc53a881..681ebcda97ad 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -3,11 +3,13 @@ * Copyright © 2021 Intel Corporation */ +#include <linux/backlight.h> #include <linux/kernel.h> #include <linux/pwm.h> #include <linux/string_helpers.h> #include "intel_backlight.h" +#include "intel_backlight_regs.h" #include "intel_connector.h" #include "intel_de.h" #include "intel_display_types.h" @@ -15,6 +17,7 @@ #include "intel_dsi_dcs_backlight.h" #include "intel_panel.h" #include "intel_pci_config.h" +#include "intel_pps.h" /** * scale - scale values from one range to another @@ -970,26 +973,24 @@ int intel_backlight_device_register(struct intel_connector *connector) if (!name) return -ENOMEM; - bd = backlight_device_register(name, connector->base.kdev, connector, - &intel_backlight_device_ops, &props); - - /* - * Using the same name independent of the drm device or connector - * prevents registration of multiple backlight devices in the - * driver. However, we need to use the default name for backward - * compatibility. Use unique names for subsequent backlight devices as a - * fallback when the default name already exists. - */ - if (IS_ERR(bd) && PTR_ERR(bd) == -EEXIST) { + bd = backlight_device_get_by_name(name); + if (bd) { + put_device(&bd->dev); + /* + * Using the same name independent of the drm device or connector + * prevents registration of multiple backlight devices in the + * driver. However, we need to use the default name for backward + * compatibility. Use unique names for subsequent backlight devices as a + * fallback when the default name already exists. + */ kfree(name); name = kasprintf(GFP_KERNEL, "card%d-%s-backlight", i915->drm.primary->index, connector->base.name); if (!name) return -ENOMEM; - - bd = backlight_device_register(name, connector->base.kdev, connector, - &intel_backlight_device_ops, &props); } + bd = backlight_device_register(name, connector->base.kdev, connector, + &intel_backlight_device_ops, &props); if (IS_ERR(bd)) { drm_err(&i915->drm, @@ -1159,9 +1160,10 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul); } -static u16 get_vbt_pwm_freq(struct drm_i915_private *dev_priv) +static u16 get_vbt_pwm_freq(struct intel_connector *connector) { - u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + u16 pwm_freq_hz = connector->panel.vbt.backlight.pwm_freq_hz; if (pwm_freq_hz) { drm_dbg_kms(&dev_priv->drm, @@ -1181,7 +1183,7 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - u16 pwm_freq_hz = get_vbt_pwm_freq(dev_priv); + u16 pwm_freq_hz = get_vbt_pwm_freq(connector); u32 pwm; if (!panel->backlight.pwm_funcs->hz_to_pwm) { @@ -1218,11 +1220,11 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) * against this by letting the minimum be at most (arbitrarily chosen) * 25% of the max. */ - min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64); - if (min != dev_priv->vbt.backlight.min_brightness) { + min = clamp_t(int, connector->panel.vbt.backlight.min_brightness, 0, 64); + if (min != connector->panel.vbt.backlight.min_brightness) { drm_dbg_kms(&dev_priv->drm, "clamping VBT min backlight %d/255 to %d/255\n", - dev_priv->vbt.backlight.min_brightness, min); + connector->panel.vbt.backlight.min_brightness, min); } /* vbt value is a coefficient in range [0..255] */ @@ -1411,7 +1413,7 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; - panel->backlight.controller = dev_priv->vbt.backlight.controller; + panel->backlight.controller = connector->panel.vbt.backlight.controller; pwm_ctl = intel_de_read(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)); @@ -1484,7 +1486,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, u32 level; /* Get the right PWM chip for DSI backlight according to VBT */ - if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { + if (connector->panel.vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight"); desc = "PMIC"; } else { @@ -1513,11 +1515,11 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, drm_dbg_kms(&dev_priv->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period, - get_vbt_pwm_freq(dev_priv), level); + get_vbt_pwm_freq(connector), level); } else { /* Set period from VBT frequency, leave other settings at 0. */ panel->backlight.pwm_state.period = - NSEC_PER_SEC / get_vbt_pwm_freq(dev_priv); + NSEC_PER_SEC / get_vbt_pwm_freq(connector); } drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", @@ -1602,7 +1604,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) struct intel_panel *panel = &connector->panel; int ret; - if (!dev_priv->vbt.backlight.present) { + if (!connector->panel.vbt.backlight.present) { if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) { drm_dbg_kms(&dev_priv->drm, "no backlight present per VBT, but present per quirk\n"); @@ -1771,9 +1773,13 @@ void intel_backlight_init_funcs(struct intel_panel *panel) panel->backlight.pwm_funcs = &i9xx_pwm_funcs; } - if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP && - intel_dp_aux_init_backlight_funcs(connector) == 0) - return; + if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) { + if (intel_dp_aux_init_backlight_funcs(connector) == 0) + return; + + if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) + connector->panel.backlight.power = intel_pps_backlight_power; + } /* We're using a standard PWM backlight interface */ panel->backlight.funcs = &pwm_bl_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h new file mode 100644 index 000000000000..50c1210f6d5d --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_BACKLIGHT_REGS_H__ +#define __INTEL_BACKLIGHT_REGS_H__ + +#include "i915_reg_defs.h" + +#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250) +#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350) +#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ + _VLV_BLC_PWM_CTL2_B) + +#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254) +#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354) +#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ + _VLV_BLC_PWM_CTL_B) + +#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260) +#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360) +#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ + _VLV_BLC_HIST_CTL_B) + +/* Backlight control */ +#define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */ +#define BLM_PWM_ENABLE (1 << 31) +#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ +#define BLM_PIPE_SELECT (1 << 29) +#define BLM_PIPE_SELECT_IVB (3 << 29) +#define BLM_PIPE_A (0 << 29) +#define BLM_PIPE_B (1 << 29) +#define BLM_PIPE_C (2 << 29) /* ivb + */ +#define BLM_TRANSCODER_A BLM_PIPE_A /* hsw */ +#define BLM_TRANSCODER_B BLM_PIPE_B +#define BLM_TRANSCODER_C BLM_PIPE_C +#define BLM_TRANSCODER_EDP (3 << 29) +#define BLM_PIPE(pipe) ((pipe) << 29) +#define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ +#define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) +#define BLM_PHASE_IN_ENABLE (1 << 25) +#define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) +#define BLM_PHASE_IN_TIME_BASE_SHIFT (16) +#define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) +#define BLM_PHASE_IN_COUNT_SHIFT (8) +#define BLM_PHASE_IN_COUNT_MASK (0xff << 8) +#define BLM_PHASE_IN_INCR_SHIFT (0) +#define BLM_PHASE_IN_INCR_MASK (0xff << 0) +#define BLC_PWM_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254) +/* + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ +/* + * This is the number of cycles out of the backlight modulation cycle for which + * the backlight is on. + * + * This field must be no greater than the number of cycles in the complete + * backlight modulation cycle. + */ +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) +#define BLM_POLARITY_PNV (1 << 0) /* pnv only */ + +#define BLC_HIST_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260) +#define BLM_HISTOGRAM_ENABLE (1 << 31) + +/* New registers for PCH-split platforms. Safe where new bits show up, the + * register layout machtes with gen4 BLC_PWM_CTL[12]. */ +#define BLC_PWM_CPU_CTL2 _MMIO(0x48250) +#define BLC_PWM_CPU_CTL _MMIO(0x48254) + +#define HSW_BLC_PWM2_CTL _MMIO(0x48350) + +/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is + * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ +#define BLC_PWM_PCH_CTL1 _MMIO(0xc8250) +#define BLM_PCH_PWM_ENABLE (1 << 31) +#define BLM_PCH_OVERRIDE_ENABLE (1 << 30) +#define BLM_PCH_POLARITY (1 << 29) +#define BLC_PWM_PCH_CTL2 _MMIO(0xc8254) + +/* BXT backlight register definition. */ +#define _BXT_BLC_PWM_CTL1 0xC8250 +#define BXT_BLC_PWM_ENABLE (1 << 31) +#define BXT_BLC_PWM_POLARITY (1 << 29) +#define _BXT_BLC_PWM_FREQ1 0xC8254 +#define _BXT_BLC_PWM_DUTY1 0xC8258 + +#define _BXT_BLC_PWM_CTL2 0xC8350 +#define _BXT_BLC_PWM_FREQ2 0xC8354 +#define _BXT_BLC_PWM_DUTY2 0xC8358 + +#define BXT_BLC_PWM_CTL(controller) _MMIO_PIPE(controller, \ + _BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2) +#define BXT_BLC_PWM_FREQ(controller) _MMIO_PIPE(controller, \ + _BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2) +#define BXT_BLC_PWM_DUTY(controller) _MMIO_PIPE(controller, \ + _BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2) + +/* Utility pin */ +#define UTIL_PIN_CTL _MMIO(0x48400) +#define UTIL_PIN_ENABLE (1 << 31) +#define UTIL_PIN_PIPE_MASK (3 << 29) +#define UTIL_PIN_PIPE(x) ((x) << 29) +#define UTIL_PIN_MODE_MASK (0xf << 24) +#define UTIL_PIN_MODE_DATA (0 << 24) +#define UTIL_PIN_MODE_PWM (1 << 24) +#define UTIL_PIN_MODE_VBLANK (4 << 24) +#define UTIL_PIN_MODE_VSYNC (5 << 24) +#define UTIL_PIN_MODE_EYE_LEVEL (8 << 24) +#define UTIL_PIN_OUTPUT_DATA (1 << 23) +#define UTIL_PIN_POLARITY (1 << 22) +#define UTIL_PIN_DIRECTION_INPUT (1 << 19) +#define UTIL_PIN_INPUT_DATA (1 << 16) + +#endif /* __INTEL_BACKLIGHT_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index f7f49a03a2e4..81d6cfbd2615 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,7 +25,9 @@ * */ -#include <drm/dp/drm_dp_helper.h> +#include <drm/drm_edid.h> +#include <drm/display/drm_dp_helper.h> +#include <drm/display/drm_dsc_helper.h> #include "display/intel_display.h" #include "display/intel_display_types.h" @@ -122,7 +124,7 @@ find_raw_section(const void *_bdb, enum bdb_block_id section_id) * Offset from the start of BDB to the start of the * block data (just past the block header). */ -static u32 block_offset(const void *bdb, enum bdb_block_id section_id) +static u32 raw_block_offset(const void *bdb, enum bdb_block_id section_id) { const void *block; @@ -134,7 +136,7 @@ static u32 block_offset(const void *bdb, enum bdb_block_id section_id) } /* size of the block excluding the header */ -static u32 block_size(const void *bdb, enum bdb_block_id section_id) +static u32 raw_block_size(const void *bdb, enum bdb_block_id section_id) { const void *block; @@ -231,7 +233,7 @@ static bool validate_lfp_data_ptrs(const void *bdb, int data_block_size, lfp_data_size; int i; - data_block_size = block_size(bdb, BDB_LVDS_LFP_DATA); + data_block_size = raw_block_size(bdb, BDB_LVDS_LFP_DATA); if (data_block_size == 0) return false; @@ -308,7 +310,7 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block) u32 offset; int i; - offset = block_offset(bdb, BDB_LVDS_LFP_DATA); + offset = raw_block_offset(bdb, BDB_LVDS_LFP_DATA); for (i = 0; i < 16; i++) { if (ptrs->ptr[i].fp_timing.offset < offset || @@ -584,6 +586,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data, return (const void *)data + ptrs->ptr[index].fp_timing.offset; } +static const struct lvds_pnp_id * +get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data, + const struct bdb_lvds_lfp_data_ptrs *ptrs, + int index) +{ + return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset; +} + static const struct bdb_lvds_lfp_data_tail * get_lfp_data_tail(const struct bdb_lvds_lfp_data *data, const struct bdb_lvds_lfp_data_ptrs *ptrs) @@ -594,12 +604,16 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data, return NULL; } -static int opregion_get_panel_type(struct drm_i915_private *i915) +static int opregion_get_panel_type(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) { return intel_opregion_get_panel_type(i915); } -static int vbt_get_panel_type(struct drm_i915_private *i915) +static int vbt_get_panel_type(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) { const struct bdb_lvds_options *lvds_options; @@ -607,16 +621,71 @@ static int vbt_get_panel_type(struct drm_i915_private *i915) if (!lvds_options) return -1; - if (lvds_options->panel_type > 0xf) { + if (lvds_options->panel_type > 0xf && + lvds_options->panel_type != 0xff) { drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n", lvds_options->panel_type); return -1; } + if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2) + return lvds_options->panel_type2; + + drm_WARN_ON(&i915->drm, devdata && devdata->child.handle != DEVICE_HANDLE_LFP1); + return lvds_options->panel_type; } -static int fallback_get_panel_type(struct drm_i915_private *i915) +static int pnpid_get_panel_type(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) +{ + const struct bdb_lvds_lfp_data *data; + const struct bdb_lvds_lfp_data_ptrs *ptrs; + const struct lvds_pnp_id *edid_id; + struct lvds_pnp_id edid_id_nodate; + int i, best = -1; + + if (!edid) + return -1; + + edid_id = (const void *)&edid->mfg_id[0]; + + edid_id_nodate = *edid_id; + edid_id_nodate.mfg_week = 0; + edid_id_nodate.mfg_year = 0; + + ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS); + if (!ptrs) + return -1; + + data = find_section(i915, BDB_LVDS_LFP_DATA); + if (!data) + return -1; + + for (i = 0; i < 16; i++) { + const struct lvds_pnp_id *vbt_id = + get_lvds_pnp_id(data, ptrs, i); + + /* full match? */ + if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id))) + return i; + + /* + * Accept a match w/o date if no full match is found, + * and the VBT entry does not specify a date. + */ + if (best < 0 && + !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id))) + best = i; + } + + return best; +} + +static int fallback_get_panel_type(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) { return 0; } @@ -624,14 +693,19 @@ static int fallback_get_panel_type(struct drm_i915_private *i915) enum panel_type { PANEL_TYPE_OPREGION, PANEL_TYPE_VBT, + PANEL_TYPE_PNPID, PANEL_TYPE_FALLBACK, }; -static int get_panel_type(struct drm_i915_private *i915) +static int get_panel_type(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) { struct { const char *name; - int (*get_panel_type)(struct drm_i915_private *i915); + int (*get_panel_type)(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid); int panel_type; } panel_types[] = { [PANEL_TYPE_OPREGION] = { @@ -642,6 +716,10 @@ static int get_panel_type(struct drm_i915_private *i915) .name = "VBT", .get_panel_type = vbt_get_panel_type, }, + [PANEL_TYPE_PNPID] = { + .name = "PNPID", + .get_panel_type = pnpid_get_panel_type, + }, [PANEL_TYPE_FALLBACK] = { .name = "fallback", .get_panel_type = fallback_get_panel_type, @@ -650,9 +728,10 @@ static int get_panel_type(struct drm_i915_private *i915) int i; for (i = 0; i < ARRAY_SIZE(panel_types); i++) { - panel_types[i].panel_type = panel_types[i].get_panel_type(i915); + panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, edid); - drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf); + drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf && + panel_types[i].panel_type != 0xff); if (panel_types[i].panel_type >= 0) drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n", @@ -661,7 +740,11 @@ static int get_panel_type(struct drm_i915_private *i915) if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0) i = PANEL_TYPE_OPREGION; - else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0) + else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff && + panel_types[PANEL_TYPE_PNPID].panel_type >= 0) + i = PANEL_TYPE_PNPID; + else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff && + panel_types[PANEL_TYPE_VBT].panel_type >= 0) i = PANEL_TYPE_VBT; else i = PANEL_TYPE_FALLBACK; @@ -672,26 +755,41 @@ static int get_panel_type(struct drm_i915_private *i915) return panel_types[i].panel_type; } +static unsigned int panel_bits(unsigned int value, int panel_type, int num_bits) +{ + return (value >> (panel_type * num_bits)) & (BIT(num_bits) - 1); +} + +static bool panel_bool(unsigned int value, int panel_type) +{ + return panel_bits(value, panel_type, 1); +} + /* Parse general panel options */ static void -parse_panel_options(struct drm_i915_private *i915) +parse_panel_options(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_lvds_options *lvds_options; - int panel_type; + int panel_type = panel->vbt.panel_type; int drrs_mode; lvds_options = find_section(i915, BDB_LVDS_OPTIONS); if (!lvds_options) return; - i915->vbt.lvds_dither = lvds_options->pixel_dither; + panel->vbt.lvds_dither = lvds_options->pixel_dither; - panel_type = get_panel_type(i915); - - i915->vbt.panel_type = panel_type; + /* + * Empirical evidence indicates the block size can be + * either 4,14,16,24+ bytes. For older VBTs no clear + * relationship between the block size vs. BDB version. + */ + if (get_blocksize(lvds_options) < 16) + return; - drrs_mode = (lvds_options->dps_panel_type_bits - >> (panel_type * 2)) & MODE_MASK; + drrs_mode = panel_bits(lvds_options->dps_panel_type_bits, + panel_type, 2); /* * VBT has static DRRS = 0 and seamless DRRS = 2. * The below piece of code is required to adjust vbt.drrs_type @@ -699,16 +797,16 @@ parse_panel_options(struct drm_i915_private *i915) */ switch (drrs_mode) { case 0: - i915->vbt.drrs_type = DRRS_TYPE_STATIC; + panel->vbt.drrs_type = DRRS_TYPE_STATIC; drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n"); break; case 2: - i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS; + panel->vbt.drrs_type = DRRS_TYPE_SEAMLESS; drm_dbg_kms(&i915->drm, "DRRS supported mode is seamless\n"); break; default: - i915->vbt.drrs_type = DRRS_TYPE_NONE; + panel->vbt.drrs_type = DRRS_TYPE_NONE; drm_dbg_kms(&i915->drm, "DRRS not supported (VBT input)\n"); break; @@ -717,13 +815,14 @@ parse_panel_options(struct drm_i915_private *i915) static void parse_lfp_panel_dtd(struct drm_i915_private *i915, + struct intel_panel *panel, const struct bdb_lvds_lfp_data *lvds_lfp_data, const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs) { const struct lvds_dvo_timing *panel_dvo_timing; const struct lvds_fp_timing *fp_timing; struct drm_display_mode *panel_fixed_mode; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, lvds_lfp_data_ptrs, @@ -735,7 +834,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915, fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing); - i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; + panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n", @@ -748,20 +847,21 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915, /* check the resolution, just to be sure */ if (fp_timing->x_res == panel_fixed_mode->hdisplay && fp_timing->y_res == panel_fixed_mode->vdisplay) { - i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val; + panel->vbt.bios_lvds_val = fp_timing->lvds_reg_val; drm_dbg_kms(&i915->drm, "VBT initial LVDS value %x\n", - i915->vbt.bios_lvds_val); + panel->vbt.bios_lvds_val); } } static void -parse_lfp_data(struct drm_i915_private *i915) +parse_lfp_data(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_tail *tail; const struct bdb_lvds_lfp_data_ptrs *ptrs; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS); if (!ptrs) @@ -771,24 +871,25 @@ parse_lfp_data(struct drm_i915_private *i915) if (!data) return; - if (!i915->vbt.lfp_lvds_vbt_mode) - parse_lfp_panel_dtd(i915, data, ptrs); + if (!panel->vbt.lfp_lvds_vbt_mode) + parse_lfp_panel_dtd(i915, panel, data, ptrs); tail = get_lfp_data_tail(data, ptrs); if (!tail) return; if (i915->vbt.version >= 188) { - i915->vbt.seamless_drrs_min_refresh_rate = + panel->vbt.seamless_drrs_min_refresh_rate = tail->seamless_drrs_min_refresh_rate[panel_type]; drm_dbg_kms(&i915->drm, "Seamless DRRS min refresh rate: %d Hz\n", - i915->vbt.seamless_drrs_min_refresh_rate); + panel->vbt.seamless_drrs_min_refresh_rate); } } static void -parse_generic_dtd(struct drm_i915_private *i915) +parse_generic_dtd(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_generic_dtd *generic_dtd; const struct generic_dtd_entry *dtd; @@ -823,14 +924,14 @@ parse_generic_dtd(struct drm_i915_private *i915) num_dtd = (get_blocksize(generic_dtd) - sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size; - if (i915->vbt.panel_type >= num_dtd) { + if (panel->vbt.panel_type >= num_dtd) { drm_err(&i915->drm, "Panel type %d not found in table of %d DTD's\n", - i915->vbt.panel_type, num_dtd); + panel->vbt.panel_type, num_dtd); return; } - dtd = &generic_dtd->dtd[i915->vbt.panel_type]; + dtd = &generic_dtd->dtd[panel->vbt.panel_type]; panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); if (!panel_fixed_mode) @@ -873,15 +974,16 @@ parse_generic_dtd(struct drm_i915_private *i915) "Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n", DRM_MODE_ARG(panel_fixed_mode)); - i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; + panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; } static void -parse_lfp_backlight(struct drm_i915_private *i915) +parse_lfp_backlight(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_lfp_backlight_data *backlight_data; const struct lfp_backlight_data_entry *entry; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; u16 level; backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT); @@ -897,15 +999,15 @@ parse_lfp_backlight(struct drm_i915_private *i915) entry = &backlight_data->data[panel_type]; - i915->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; - if (!i915->vbt.backlight.present) { + panel->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; + if (!panel->vbt.backlight.present) { drm_dbg_kms(&i915->drm, "PWM backlight not present in VBT (type %u)\n", entry->type); return; } - i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI; + panel->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI; if (i915->vbt.version >= 191) { size_t exp_size; @@ -920,13 +1022,13 @@ parse_lfp_backlight(struct drm_i915_private *i915) const struct lfp_backlight_control_method *method; method = &backlight_data->backlight_control[panel_type]; - i915->vbt.backlight.type = method->type; - i915->vbt.backlight.controller = method->controller; + panel->vbt.backlight.type = method->type; + panel->vbt.backlight.controller = method->controller; } } - i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; - i915->vbt.backlight.active_low_pwm = entry->active_low_pwm; + panel->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; + panel->vbt.backlight.active_low_pwm = entry->active_low_pwm; if (i915->vbt.version >= 234) { u16 min_level; @@ -947,28 +1049,29 @@ parse_lfp_backlight(struct drm_i915_private *i915) drm_warn(&i915->drm, "Brightness min level > 255\n"); level = 255; } - i915->vbt.backlight.min_brightness = min_level; + panel->vbt.backlight.min_brightness = min_level; - i915->vbt.backlight.brightness_precision_bits = + panel->vbt.backlight.brightness_precision_bits = backlight_data->brightness_precision_bits[panel_type]; } else { level = backlight_data->level[panel_type]; - i915->vbt.backlight.min_brightness = entry->min_brightness; + panel->vbt.backlight.min_brightness = entry->min_brightness; } drm_dbg_kms(&i915->drm, "VBT backlight PWM modulation frequency %u Hz, " "active %s, min brightness %u, level %u, controller %u\n", - i915->vbt.backlight.pwm_freq_hz, - i915->vbt.backlight.active_low_pwm ? "low" : "high", - i915->vbt.backlight.min_brightness, + panel->vbt.backlight.pwm_freq_hz, + panel->vbt.backlight.active_low_pwm ? "low" : "high", + panel->vbt.backlight.min_brightness, level, - i915->vbt.backlight.controller); + panel->vbt.backlight.controller); } /* Try to find sdvo panel data */ static void -parse_sdvo_panel_data(struct drm_i915_private *i915) +parse_sdvo_panel_data(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_sdvo_panel_dtds *dtds; struct drm_display_mode *panel_fixed_mode; @@ -1001,7 +1104,7 @@ parse_sdvo_panel_data(struct drm_i915_private *i915) fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]); - i915->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode; + panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, "Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n", @@ -1180,6 +1283,17 @@ parse_driver_features(struct drm_i915_private *i915) driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS) i915->vbt.int_lvds_support = 0; } +} + +static void +parse_panel_driver_features(struct drm_i915_private *i915, + struct intel_panel *panel) +{ + const struct bdb_driver_features *driver; + + driver = find_section(i915, BDB_DRIVER_FEATURES); + if (!driver) + return; if (i915->vbt.version < 228) { drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n", @@ -1190,18 +1304,29 @@ parse_driver_features(struct drm_i915_private *i915) * static DRRS is 0 and DRRS not supported is represented by * driver->drrs_enabled=false */ - if (!driver->drrs_enabled) - i915->vbt.drrs_type = DRRS_TYPE_NONE; + if (!driver->drrs_enabled && panel->vbt.drrs_type != DRRS_TYPE_NONE) { + /* + * FIXME Should DMRRS perhaps be treated as seamless + * but without the automatic downclocking? + */ + if (driver->dmrrs_enabled) + panel->vbt.drrs_type = DRRS_TYPE_STATIC; + else + panel->vbt.drrs_type = DRRS_TYPE_NONE; + } - i915->vbt.psr.enable = driver->psr_enabled; + panel->vbt.psr.enable = driver->psr_enabled; } } static void -parse_power_conservation_features(struct drm_i915_private *i915) +parse_power_conservation_features(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_lfp_power *power; - u8 panel_type = i915->vbt.panel_type; + u8 panel_type = panel->vbt.panel_type; + + panel->vbt.vrr = true; /* matches Windows behaviour */ if (i915->vbt.version < 228) return; @@ -1210,7 +1335,7 @@ parse_power_conservation_features(struct drm_i915_private *i915) if (!power) return; - i915->vbt.psr.enable = power->psr & BIT(panel_type); + panel->vbt.psr.enable = panel_bool(power->psr, panel_type); /* * If DRRS is not supported, drrs_type has to be set to 0. @@ -1218,34 +1343,47 @@ parse_power_conservation_features(struct drm_i915_private *i915) * static DRRS is 0 and DRRS not supported is represented by * power->drrs & BIT(panel_type)=false */ - if (!(power->drrs & BIT(panel_type))) - i915->vbt.drrs_type = DRRS_TYPE_NONE; + if (!panel_bool(power->drrs, panel_type) && panel->vbt.drrs_type != DRRS_TYPE_NONE) { + /* + * FIXME Should DMRRS perhaps be treated as seamless + * but without the automatic downclocking? + */ + if (panel_bool(power->dmrrs, panel_type)) + panel->vbt.drrs_type = DRRS_TYPE_STATIC; + else + panel->vbt.drrs_type = DRRS_TYPE_NONE; + } if (i915->vbt.version >= 232) - i915->vbt.edp.hobl = power->hobl & BIT(panel_type); + panel->vbt.edp.hobl = panel_bool(power->hobl, panel_type); + + if (i915->vbt.version >= 233) + panel->vbt.vrr = panel_bool(power->vrr_feature_enabled, + panel_type); } static void -parse_edp(struct drm_i915_private *i915) +parse_edp(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_edp *edp; const struct edp_power_seq *edp_pps; const struct edp_fast_link_params *edp_link_params; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; edp = find_section(i915, BDB_EDP); if (!edp) return; - switch ((edp->color_depth >> (panel_type * 2)) & 3) { + switch (panel_bits(edp->color_depth, panel_type, 2)) { case EDP_18BPP: - i915->vbt.edp.bpp = 18; + panel->vbt.edp.bpp = 18; break; case EDP_24BPP: - i915->vbt.edp.bpp = 24; + panel->vbt.edp.bpp = 24; break; case EDP_30BPP: - i915->vbt.edp.bpp = 30; + panel->vbt.edp.bpp = 30; break; } @@ -1253,31 +1391,39 @@ parse_edp(struct drm_i915_private *i915) edp_pps = &edp->power_seqs[panel_type]; edp_link_params = &edp->fast_link_params[panel_type]; - i915->vbt.edp.pps = *edp_pps; + panel->vbt.edp.pps = *edp_pps; - switch (edp_link_params->rate) { - case EDP_RATE_1_62: - i915->vbt.edp.rate = DP_LINK_BW_1_62; - break; - case EDP_RATE_2_7: - i915->vbt.edp.rate = DP_LINK_BW_2_7; - break; - default: - drm_dbg_kms(&i915->drm, - "VBT has unknown eDP link rate value %u\n", - edp_link_params->rate); - break; + if (i915->vbt.version >= 224) { + panel->vbt.edp.rate = + edp->edp_fast_link_training_rate[panel_type] * 20; + } else { + switch (edp_link_params->rate) { + case EDP_RATE_1_62: + panel->vbt.edp.rate = 162000; + break; + case EDP_RATE_2_7: + panel->vbt.edp.rate = 270000; + break; + case EDP_RATE_5_4: + panel->vbt.edp.rate = 540000; + break; + default: + drm_dbg_kms(&i915->drm, + "VBT has unknown eDP link rate value %u\n", + edp_link_params->rate); + break; + } } switch (edp_link_params->lanes) { case EDP_LANE_1: - i915->vbt.edp.lanes = 1; + panel->vbt.edp.lanes = 1; break; case EDP_LANE_2: - i915->vbt.edp.lanes = 2; + panel->vbt.edp.lanes = 2; break; case EDP_LANE_4: - i915->vbt.edp.lanes = 4; + panel->vbt.edp.lanes = 4; break; default: drm_dbg_kms(&i915->drm, @@ -1288,16 +1434,16 @@ parse_edp(struct drm_i915_private *i915) switch (edp_link_params->preemphasis) { case EDP_PREEMPHASIS_NONE: - i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0; + panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0; break; case EDP_PREEMPHASIS_3_5dB: - i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1; + panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1; break; case EDP_PREEMPHASIS_6dB: - i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2; + panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2; break; case EDP_PREEMPHASIS_9_5dB: - i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3; + panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3; break; default: drm_dbg_kms(&i915->drm, @@ -1308,16 +1454,16 @@ parse_edp(struct drm_i915_private *i915) switch (edp_link_params->vswing) { case EDP_VSWING_0_4V: - i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; + panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; break; case EDP_VSWING_0_6V: - i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1; + panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1; break; case EDP_VSWING_0_8V: - i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2; + panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2; break; case EDP_VSWING_1_2V: - i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3; + panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3; break; default: drm_dbg_kms(&i915->drm, @@ -1331,24 +1477,29 @@ parse_edp(struct drm_i915_private *i915) /* Don't read from VBT if module parameter has valid value*/ if (i915->params.edp_vswing) { - i915->vbt.edp.low_vswing = + panel->vbt.edp.low_vswing = i915->params.edp_vswing == 1; } else { vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF; - i915->vbt.edp.low_vswing = vswing == 0; + panel->vbt.edp.low_vswing = vswing == 0; } } - i915->vbt.edp.drrs_msa_timing_delay = - (edp->sdrrs_msa_timing_delay >> (panel_type * 2)) & 3; + panel->vbt.edp.drrs_msa_timing_delay = + panel_bits(edp->sdrrs_msa_timing_delay, panel_type, 2); + + if (i915->vbt.version >= 244) + panel->vbt.edp.max_link_rate = + edp->edp_max_port_link_rate[panel_type] * 20; } static void -parse_psr(struct drm_i915_private *i915) +parse_psr(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_psr *psr; const struct psr_table *psr_table; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; psr = find_section(i915, BDB_PSR); if (!psr) { @@ -1358,11 +1509,11 @@ parse_psr(struct drm_i915_private *i915) psr_table = &psr->psr_table[panel_type]; - i915->vbt.psr.full_link = psr_table->full_link; - i915->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup; + panel->vbt.psr.full_link = psr_table->full_link; + panel->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup; /* Allowed VBT values goes from 0 to 15 */ - i915->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 : + panel->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 : psr_table->idle_frames > 15 ? 15 : psr_table->idle_frames; /* @@ -1373,13 +1524,13 @@ parse_psr(struct drm_i915_private *i915) (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) { switch (psr_table->tp1_wakeup_time) { case 0: - i915->vbt.psr.tp1_wakeup_time_us = 500; + panel->vbt.psr.tp1_wakeup_time_us = 500; break; case 1: - i915->vbt.psr.tp1_wakeup_time_us = 100; + panel->vbt.psr.tp1_wakeup_time_us = 100; break; case 3: - i915->vbt.psr.tp1_wakeup_time_us = 0; + panel->vbt.psr.tp1_wakeup_time_us = 0; break; default: drm_dbg_kms(&i915->drm, @@ -1387,19 +1538,19 @@ parse_psr(struct drm_i915_private *i915) psr_table->tp1_wakeup_time); fallthrough; case 2: - i915->vbt.psr.tp1_wakeup_time_us = 2500; + panel->vbt.psr.tp1_wakeup_time_us = 2500; break; } switch (psr_table->tp2_tp3_wakeup_time) { case 0: - i915->vbt.psr.tp2_tp3_wakeup_time_us = 500; + panel->vbt.psr.tp2_tp3_wakeup_time_us = 500; break; case 1: - i915->vbt.psr.tp2_tp3_wakeup_time_us = 100; + panel->vbt.psr.tp2_tp3_wakeup_time_us = 100; break; case 3: - i915->vbt.psr.tp2_tp3_wakeup_time_us = 0; + panel->vbt.psr.tp2_tp3_wakeup_time_us = 0; break; default: drm_dbg_kms(&i915->drm, @@ -1407,18 +1558,18 @@ parse_psr(struct drm_i915_private *i915) psr_table->tp2_tp3_wakeup_time); fallthrough; case 2: - i915->vbt.psr.tp2_tp3_wakeup_time_us = 2500; + panel->vbt.psr.tp2_tp3_wakeup_time_us = 2500; break; } } else { - i915->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100; - i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100; + panel->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100; + panel->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100; } if (i915->vbt.version >= 226) { u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time; - wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3; + wakeup_time = panel_bits(wakeup_time, panel_type, 2); switch (wakeup_time) { case 0: wakeup_time = 500; @@ -1434,62 +1585,66 @@ parse_psr(struct drm_i915_private *i915) wakeup_time = 2500; break; } - i915->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time; + panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time; } else { /* Reusing PSR1 wakeup time for PSR2 in older VBTs */ - i915->vbt.psr.psr2_tp2_tp3_wakeup_time_us = i915->vbt.psr.tp2_tp3_wakeup_time_us; + panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = panel->vbt.psr.tp2_tp3_wakeup_time_us; } } static void parse_dsi_backlight_ports(struct drm_i915_private *i915, - u16 version, enum port port) + struct intel_panel *panel, + enum port port) { - if (!i915->vbt.dsi.config->dual_link || version < 197) { - i915->vbt.dsi.bl_ports = BIT(port); - if (i915->vbt.dsi.config->cabc_supported) - i915->vbt.dsi.cabc_ports = BIT(port); + enum port port_bc = DISPLAY_VER(i915) >= 11 ? PORT_B : PORT_C; + + if (!panel->vbt.dsi.config->dual_link || i915->vbt.version < 197) { + panel->vbt.dsi.bl_ports = BIT(port); + if (panel->vbt.dsi.config->cabc_supported) + panel->vbt.dsi.cabc_ports = BIT(port); return; } - switch (i915->vbt.dsi.config->dl_dcs_backlight_ports) { + switch (panel->vbt.dsi.config->dl_dcs_backlight_ports) { case DL_DCS_PORT_A: - i915->vbt.dsi.bl_ports = BIT(PORT_A); + panel->vbt.dsi.bl_ports = BIT(PORT_A); break; case DL_DCS_PORT_C: - i915->vbt.dsi.bl_ports = BIT(PORT_C); + panel->vbt.dsi.bl_ports = BIT(port_bc); break; default: case DL_DCS_PORT_A_AND_C: - i915->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C); + panel->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(port_bc); break; } - if (!i915->vbt.dsi.config->cabc_supported) + if (!panel->vbt.dsi.config->cabc_supported) return; - switch (i915->vbt.dsi.config->dl_dcs_cabc_ports) { + switch (panel->vbt.dsi.config->dl_dcs_cabc_ports) { case DL_DCS_PORT_A: - i915->vbt.dsi.cabc_ports = BIT(PORT_A); + panel->vbt.dsi.cabc_ports = BIT(PORT_A); break; case DL_DCS_PORT_C: - i915->vbt.dsi.cabc_ports = BIT(PORT_C); + panel->vbt.dsi.cabc_ports = BIT(port_bc); break; default: case DL_DCS_PORT_A_AND_C: - i915->vbt.dsi.cabc_ports = - BIT(PORT_A) | BIT(PORT_C); + panel->vbt.dsi.cabc_ports = + BIT(PORT_A) | BIT(port_bc); break; } } static void -parse_mipi_config(struct drm_i915_private *i915) +parse_mipi_config(struct drm_i915_private *i915, + struct intel_panel *panel) { const struct bdb_mipi_config *start; const struct mipi_config *config; const struct mipi_pps_data *pps; - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; enum port port; /* parse MIPI blocks only if LFP type is MIPI */ @@ -1497,7 +1652,7 @@ parse_mipi_config(struct drm_i915_private *i915) return; /* Initialize this to undefined indicating no generic MIPI support */ - i915->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID; + panel->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID; /* Block #40 is already parsed and panel_fixed_mode is * stored in i915->lfp_lvds_vbt_mode @@ -1524,17 +1679,17 @@ parse_mipi_config(struct drm_i915_private *i915) pps = &start->pps[panel_type]; /* store as of now full data. Trim when we realise all is not needed */ - i915->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL); - if (!i915->vbt.dsi.config) + panel->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL); + if (!panel->vbt.dsi.config) return; - i915->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL); - if (!i915->vbt.dsi.pps) { - kfree(i915->vbt.dsi.config); + panel->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL); + if (!panel->vbt.dsi.pps) { + kfree(panel->vbt.dsi.config); return; } - parse_dsi_backlight_ports(i915, i915->vbt.version, port); + parse_dsi_backlight_ports(i915, panel, port); /* FIXME is the 90 vs. 270 correct? */ switch (config->rotation) { @@ -1543,25 +1698,25 @@ parse_mipi_config(struct drm_i915_private *i915) * Most (all?) VBTs claim 0 degrees despite having * an upside down panel, thus we do not trust this. */ - i915->vbt.dsi.orientation = + panel->vbt.dsi.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; break; case ENABLE_ROTATION_90: - i915->vbt.dsi.orientation = + panel->vbt.dsi.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; break; case ENABLE_ROTATION_180: - i915->vbt.dsi.orientation = + panel->vbt.dsi.orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; break; case ENABLE_ROTATION_270: - i915->vbt.dsi.orientation = + panel->vbt.dsi.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; break; } /* We have mandatory mipi config blocks. Initialize as generic panel */ - i915->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; + panel->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; } /* Find the sequence block and size for the given panel. */ @@ -1724,13 +1879,14 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) * Get len of pre-fixed deassert fragment from a v1 init OTP sequence, * skip all delay + gpio operands and stop at the first DSI packet op. */ -static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915) +static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915, + struct intel_panel *panel) { - const u8 *data = i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + const u8 *data = panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; int index, len; if (drm_WARN_ON(&i915->drm, - !data || i915->vbt.dsi.seq_version != 1)) + !data || panel->vbt.dsi.seq_version != 1)) return 0; /* index = 1 to skip sequence byte */ @@ -1758,7 +1914,8 @@ static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915) * these devices we split the init OTP sequence into a deassert sequence and * the actual init OTP part. */ -static void fixup_mipi_sequences(struct drm_i915_private *i915) +static void fixup_mipi_sequences(struct drm_i915_private *i915, + struct intel_panel *panel) { u8 *init_otp; int len; @@ -1768,18 +1925,18 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915) return; /* Limit this to v1 vid-mode sequences */ - if (i915->vbt.dsi.config->is_cmd_mode || - i915->vbt.dsi.seq_version != 1) + if (panel->vbt.dsi.config->is_cmd_mode || + panel->vbt.dsi.seq_version != 1) return; /* Only do this if there are otp and assert seqs and no deassert seq */ - if (!i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] || - !i915->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] || - i915->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) + if (!panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] || + !panel->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] || + panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) return; /* The deassert-sequence ends at the first DSI packet */ - len = get_init_otp_deassert_fragment_len(i915); + len = get_init_otp_deassert_fragment_len(i915, panel); if (!len) return; @@ -1787,25 +1944,26 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915) "Using init OTP fragment to deassert reset\n"); /* Copy the fragment, update seq byte and terminate it */ - init_otp = (u8 *)i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; - i915->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL); - if (!i915->vbt.dsi.deassert_seq) + init_otp = (u8 *)panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + panel->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL); + if (!panel->vbt.dsi.deassert_seq) return; - i915->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET; - i915->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END; + panel->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET; + panel->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END; /* Use the copy for deassert */ - i915->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] = - i915->vbt.dsi.deassert_seq; + panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] = + panel->vbt.dsi.deassert_seq; /* Replace the last byte of the fragment with init OTP seq byte */ init_otp[len - 1] = MIPI_SEQ_INIT_OTP; /* And make MIPI_MIPI_SEQ_INIT_OTP point to it */ - i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1; + panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1; } static void -parse_mipi_sequence(struct drm_i915_private *i915) +parse_mipi_sequence(struct drm_i915_private *i915, + struct intel_panel *panel) { - int panel_type = i915->vbt.panel_type; + int panel_type = panel->vbt.panel_type; const struct bdb_mipi_sequence *sequence; const u8 *seq_data; u32 seq_size; @@ -1813,7 +1971,7 @@ parse_mipi_sequence(struct drm_i915_private *i915) int index = 0; /* Only our generic panel driver uses the sequence block. */ - if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID) + if (panel->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID) return; sequence = find_section(i915, BDB_MIPI_SEQUENCE); @@ -1859,7 +2017,7 @@ parse_mipi_sequence(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "Unsupported sequence %u\n", seq_id); - i915->vbt.dsi.sequence[seq_id] = data + index; + panel->vbt.dsi.sequence[seq_id] = data + index; if (sequence->version >= 3) index = goto_next_sequence_v3(data, index, seq_size); @@ -1872,18 +2030,18 @@ parse_mipi_sequence(struct drm_i915_private *i915) } } - i915->vbt.dsi.data = data; - i915->vbt.dsi.size = seq_size; - i915->vbt.dsi.seq_version = sequence->version; + panel->vbt.dsi.data = data; + panel->vbt.dsi.size = seq_size; + panel->vbt.dsi.seq_version = sequence->version; - fixup_mipi_sequences(i915); + fixup_mipi_sequences(i915, panel); drm_dbg(&i915->drm, "MIPI related VBT parsing complete\n"); return; err: kfree(data); - memset(i915->vbt.dsi.sequence, 0, sizeof(i915->vbt.dsi.sequence)); + memset(panel->vbt.dsi.sequence, 0, sizeof(panel->vbt.dsi.sequence)); } static void @@ -2262,7 +2420,7 @@ static enum port dvo_port_to_port(struct drm_i915_private *i915, [PORT_TC4] = { DVO_PORT_HDMII, DVO_PORT_DPI, -1 }, }; - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) return __dvo_port_to_port(ARRAY_SIZE(xelpd_port_mapping), ARRAY_SIZE(xelpd_port_mapping[0]), xelpd_port_mapping, @@ -2342,10 +2500,10 @@ static void sanitize_device_type(struct intel_bios_encoder_data *devdata, if (port != PORT_A || DISPLAY_VER(i915) >= 12) return; - if (!(devdata->child.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING)) + if (!intel_bios_encoder_supports_dvi(devdata)) return; - is_hdmi = !(devdata->child.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT); + is_hdmi = intel_bios_encoder_supports_hdmi(devdata); drm_dbg_kms(&i915->drm, "VBT claims port A supports DVI%s, ignoring\n", is_hdmi ? "/HDMI" : ""); @@ -2431,33 +2589,13 @@ static bool is_port_valid(struct drm_i915_private *i915, enum port port) return true; } -static void parse_ddi_port(struct drm_i915_private *i915, - struct intel_bios_encoder_data *devdata) +static void print_ddi_port(const struct intel_bios_encoder_data *devdata, + enum port port) { + struct drm_i915_private *i915 = devdata->i915; const struct child_device_config *child = &devdata->child; bool is_dvi, is_hdmi, is_dp, is_edp, is_crt, supports_typec_usb, supports_tbt; int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; - enum port port; - - port = dvo_port_to_port(i915, child->dvo_port); - if (port == PORT_NONE) - return; - - if (!is_port_valid(i915, port)) { - drm_dbg_kms(&i915->drm, - "VBT reports port %c as supported, but that can't be true: skipping\n", - port_name(port)); - return; - } - - if (i915->vbt.ports[port]) { - drm_dbg_kms(&i915->drm, - "More than one child device for port %c in VBT, using the first.\n", - port_name(port)); - return; - } - - sanitize_device_type(devdata, port); is_dvi = intel_bios_encoder_supports_dvi(devdata); is_dp = intel_bios_encoder_supports_dp(devdata); @@ -2475,12 +2613,6 @@ static void parse_ddi_port(struct drm_i915_private *i915, supports_typec_usb, supports_tbt, devdata->dsc != NULL); - if (is_dvi) - sanitize_ddc_pin(devdata, port); - - if (is_dp) - sanitize_aux_ch(devdata, port); - hdmi_level_shift = _intel_bios_hdmi_level_shift(devdata); if (hdmi_level_shift >= 0) { drm_dbg_kms(&i915->drm, @@ -2512,6 +2644,39 @@ static void parse_ddi_port(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "Port %c VBT DP max link rate: %d\n", port_name(port), dp_max_link_rate); +} + +static void parse_ddi_port(struct intel_bios_encoder_data *devdata) +{ + struct drm_i915_private *i915 = devdata->i915; + const struct child_device_config *child = &devdata->child; + enum port port; + + port = dvo_port_to_port(i915, child->dvo_port); + if (port == PORT_NONE) + return; + + if (!is_port_valid(i915, port)) { + drm_dbg_kms(&i915->drm, + "VBT reports port %c as supported, but that can't be true: skipping\n", + port_name(port)); + return; + } + + if (i915->vbt.ports[port]) { + drm_dbg_kms(&i915->drm, + "More than one child device for port %c in VBT, using the first.\n", + port_name(port)); + return; + } + + sanitize_device_type(devdata, port); + + if (intel_bios_encoder_supports_dvi(devdata)) + sanitize_ddc_pin(devdata, port); + + if (intel_bios_encoder_supports_dp(devdata)) + sanitize_aux_ch(devdata, port); i915->vbt.ports[port] = devdata; } @@ -2524,12 +2689,18 @@ static bool has_ddi_port_info(struct drm_i915_private *i915) static void parse_ddi_ports(struct drm_i915_private *i915) { struct intel_bios_encoder_data *devdata; + enum port port; if (!has_ddi_port_info(i915)) return; list_for_each_entry(devdata, &i915->vbt.display_devices, node) - parse_ddi_port(i915, devdata); + parse_ddi_port(devdata); + + for_each_port(port) { + if (i915->vbt.ports[port]) + print_ddi_port(i915->vbt.ports[port], port); + } } static void @@ -2637,15 +2808,6 @@ init_vbt_defaults(struct drm_i915_private *i915) { i915->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC; - /* Default to having backlight */ - i915->vbt.backlight.present = true; - - /* LFP panel data */ - i915->vbt.lvds_dither = 1; - - /* SDVO panel data */ - i915->vbt.sdvo_lvds_vbt_mode = NULL; - /* general features */ i915->vbt.int_tv_support = 1; i915->vbt.int_crt_support = 1; @@ -2665,6 +2827,17 @@ init_vbt_defaults(struct drm_i915_private *i915) i915->vbt.lvds_ssc_freq); } +/* Common defaults which may be overridden by VBT. */ +static void +init_vbt_panel_defaults(struct intel_panel *panel) +{ + /* Default to having backlight */ + panel->vbt.backlight.present = true; + + /* LFP panel data */ + panel->vbt.lvds_dither = true; +} + /* Defaults to initialize only if there is no VBT. */ static void init_vbt_missing_defaults(struct drm_i915_private *i915) @@ -2951,17 +3124,7 @@ void intel_bios_init(struct drm_i915_private *i915) /* Grab useful general definitions */ parse_general_features(i915); parse_general_definitions(i915); - parse_panel_options(i915); - parse_generic_dtd(i915); - parse_lfp_data(i915); - parse_lfp_backlight(i915); - parse_sdvo_panel_data(i915); parse_driver_features(i915); - parse_power_conservation_features(i915); - parse_edp(i915); - parse_psr(i915); - parse_mipi_config(i915); - parse_mipi_sequence(i915); /* Depends on child device list */ parse_compression_parameters(i915); @@ -2980,6 +3143,28 @@ out: kfree(oprom_vbt); } +void intel_bios_init_panel(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) +{ + init_vbt_panel_defaults(panel); + + panel->vbt.panel_type = get_panel_type(i915, devdata, edid); + + parse_panel_options(i915, panel); + parse_generic_dtd(i915, panel); + parse_lfp_data(i915, panel); + parse_lfp_backlight(i915, panel); + parse_sdvo_panel_data(i915, panel); + parse_panel_driver_features(i915, panel); + parse_power_conservation_features(i915, panel); + parse_edp(i915, panel); + parse_psr(i915, panel); + parse_mipi_config(i915, panel); + parse_mipi_sequence(i915, panel); +} + /** * intel_bios_driver_remove - Free any resources allocated by intel_bios_init() * @i915: i915 device instance @@ -2999,19 +3184,22 @@ void intel_bios_driver_remove(struct drm_i915_private *i915) list_del(&entry->node); kfree(entry); } +} - kfree(i915->vbt.sdvo_lvds_vbt_mode); - i915->vbt.sdvo_lvds_vbt_mode = NULL; - kfree(i915->vbt.lfp_lvds_vbt_mode); - i915->vbt.lfp_lvds_vbt_mode = NULL; - kfree(i915->vbt.dsi.data); - i915->vbt.dsi.data = NULL; - kfree(i915->vbt.dsi.pps); - i915->vbt.dsi.pps = NULL; - kfree(i915->vbt.dsi.config); - i915->vbt.dsi.config = NULL; - kfree(i915->vbt.dsi.deassert_seq); - i915->vbt.dsi.deassert_seq = NULL; +void intel_bios_fini_panel(struct intel_panel *panel) +{ + kfree(panel->vbt.sdvo_lvds_vbt_mode); + panel->vbt.sdvo_lvds_vbt_mode = NULL; + kfree(panel->vbt.lfp_lvds_vbt_mode); + panel->vbt.lfp_lvds_vbt_mode = NULL; + kfree(panel->vbt.dsi.data); + panel->vbt.dsi.data = NULL; + kfree(panel->vbt.dsi.pps); + panel->vbt.dsi.pps = NULL; + kfree(panel->vbt.dsi.config); + panel->vbt.dsi.config = NULL; + kfree(panel->vbt.dsi.deassert_seq); + panel->vbt.dsi.deassert_seq = NULL; } /** @@ -3390,7 +3578,7 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, aux_ch = AUX_CH_C; break; case DP_AUX_D: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_D_XELPD; else if (IS_ALDERLAKE_S(i915)) aux_ch = AUX_CH_USBC3; @@ -3400,7 +3588,7 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, aux_ch = AUX_CH_D; break; case DP_AUX_E: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_E_XELPD; else if (IS_ALDERLAKE_S(i915)) aux_ch = AUX_CH_USBC4; @@ -3408,25 +3596,25 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915, aux_ch = AUX_CH_E; break; case DP_AUX_F: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_USBC1; else aux_ch = AUX_CH_F; break; case DP_AUX_G: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_USBC2; else aux_ch = AUX_CH_G; break; case DP_AUX_H: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_USBC3; else aux_ch = AUX_CH_H; break; case DP_AUX_I: - if (DISPLAY_VER(i915) == 13) + if (DISPLAY_VER(i915) >= 13) aux_ch = AUX_CH_USBC4; else aux_ch = AUX_CH_I; diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 4709c4d29805..e47582b0de0a 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -33,9 +33,11 @@ #include <linux/types.h> struct drm_i915_private; +struct edid; struct intel_bios_encoder_data; struct intel_crtc_state; struct intel_encoder; +struct intel_panel; enum port; enum intel_backlight_type { @@ -230,6 +232,11 @@ struct mipi_pps_data { } __packed; void intel_bios_init(struct drm_i915_private *dev_priv); +void intel_bios_init_panel(struct drm_i915_private *dev_priv, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid); +void intel_bios_fini_panel(struct intel_panel *panel); void intel_bios_driver_remove(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 79269d2c476b..c87bc3117ae4 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -147,7 +147,32 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, qi->num_points = dram_info->num_qgv_points; qi->num_psf_points = dram_info->num_psf_gv_points; - if (DISPLAY_VER(dev_priv) >= 12) + if (DISPLAY_VER(dev_priv) >= 14) { + switch (dram_info->type) { + case INTEL_DRAM_DDR4: + qi->t_bl = 4; + qi->max_numchannels = 2; + qi->channel_width = 64; + qi->deinterleave = 2; + break; + case INTEL_DRAM_DDR5: + qi->t_bl = 8; + qi->max_numchannels = 4; + qi->channel_width = 32; + qi->deinterleave = 2; + break; + case INTEL_DRAM_LPDDR4: + case INTEL_DRAM_LPDDR5: + qi->t_bl = 16; + qi->max_numchannels = 8; + qi->channel_width = 16; + qi->deinterleave = 4; + break; + default: + MISSING_CASE(dram_info->type); + return -EINVAL; + } + } else if (DISPLAY_VER(dev_priv) >= 12) { switch (dram_info->type) { case INTEL_DRAM_DDR4: qi->t_bl = is_y_tile ? 8 : 4; @@ -181,7 +206,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, qi->max_numchannels = 1; break; } - else if (DISPLAY_VER(dev_priv) == 11) { + } else if (DISPLAY_VER(dev_priv) == 11) { qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 8; qi->max_numchannels = 1; } @@ -284,6 +309,13 @@ static const struct intel_sa_info adlp_sa_info = { .derating = 20, }; +static const struct intel_sa_info mtl_sa_info = { + .deburst = 32, + .deprogbwlimit = 38, /* GB/s */ + .displayrtids = 256, + .derating = 20, +}; + static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa) { struct intel_qgv_info qi = {}; @@ -346,9 +378,9 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel * as it will fail and pointless anyway. */ if (qi.num_points == 1) - dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; + dev_priv->display.sagv.status = I915_SAGV_NOT_CONTROLLED; else - dev_priv->sagv_status = I915_SAGV_ENABLED; + dev_priv->display.sagv.status = I915_SAGV_ENABLED; return 0; } @@ -404,15 +436,17 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel int clpchgroup; int j; - if (i < num_groups - 1) - bi_next = &dev_priv->max_bw[i + 1]; - clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i; - if (i < num_groups - 1 && clpchgroup < clperchgroup) - bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1; - else - bi_next->num_planes = 0; + if (i < num_groups - 1) { + bi_next = &dev_priv->max_bw[i + 1]; + + if (clpchgroup < clperchgroup) + bi_next->num_planes = (ipqdepth - clpchgroup) / + clpchgroup + 1; + else + bi_next->num_planes = 0; + } bi->num_qgv_points = qi.num_points; bi->num_psf_gv_points = qi.num_psf_points; @@ -456,9 +490,9 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel * as it will fail and pointless anyway. */ if (qi.num_points == 1) - dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; + dev_priv->display.sagv.status = I915_SAGV_NOT_CONTROLLED; else - dev_priv->sagv_status = I915_SAGV_ENABLED; + dev_priv->display.sagv.status = I915_SAGV_ENABLED; return 0; } @@ -485,7 +519,7 @@ static void dg2_get_bw_info(struct drm_i915_private *i915) bi->deratedbw[0] = deratedbw; } - i915->sagv_status = I915_SAGV_NOT_CONTROLLED; + i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; } static unsigned int icl_max_bw(struct drm_i915_private *dev_priv, @@ -558,7 +592,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - if (IS_DG2(dev_priv)) + if (DISPLAY_VER(dev_priv) >= 14) + tgl_get_bw_info(dev_priv, &mtl_sa_info); + else if (IS_DG2(dev_priv)) dg2_get_bw_info(dev_priv); else if (IS_ALDERLAKE_P(dev_priv)) tgl_get_bw_info(dev_priv, &adlp_sa_info); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 6e80162632dd..d8f7bccf9ff9 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -79,26 +79,26 @@ struct intel_cdclk_funcs { void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv, struct intel_cdclk_config *cdclk_config) { - dev_priv->cdclk_funcs->get_cdclk(dev_priv, cdclk_config); + dev_priv->display.funcs.cdclk->get_cdclk(dev_priv, cdclk_config); } static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) { - dev_priv->cdclk_funcs->set_cdclk(dev_priv, cdclk_config, pipe); + dev_priv->display.funcs.cdclk->set_cdclk(dev_priv, cdclk_config, pipe); } static int intel_cdclk_modeset_calc_cdclk(struct drm_i915_private *dev_priv, struct intel_cdclk_state *cdclk_config) { - return dev_priv->cdclk_funcs->modeset_calc_cdclk(cdclk_config); + return dev_priv->display.funcs.cdclk->modeset_calc_cdclk(cdclk_config); } static u8 intel_cdclk_calc_voltage_level(struct drm_i915_private *dev_priv, int cdclk) { - return dev_priv->cdclk_funcs->calc_voltage_level(cdclk); + return dev_priv->display.funcs.cdclk->calc_voltage_level(cdclk); } static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv, @@ -2080,7 +2080,7 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config)) return; - if (drm_WARN_ON_ONCE(&dev_priv->drm, !dev_priv->cdclk_funcs->set_cdclk)) + if (drm_WARN_ON_ONCE(&dev_priv->drm, !dev_priv->display.funcs.cdclk->set_cdclk)) return; intel_cdclk_dump_config(dev_priv, cdclk_config, "Changing CDCLK to"); @@ -2098,12 +2098,12 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, * functions use cdclk. Not all platforms/ports do, * but we'll lock them all for simplicity. */ - mutex_lock(&dev_priv->gmbus_mutex); + mutex_lock(&dev_priv->display.gmbus.mutex); for_each_intel_dp(&dev_priv->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); mutex_lock_nest_lock(&intel_dp->aux.hw_mutex, - &dev_priv->gmbus_mutex); + &dev_priv->display.gmbus.mutex); } intel_cdclk_set_cdclk(dev_priv, cdclk_config, pipe); @@ -2113,7 +2113,7 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, mutex_unlock(&intel_dp->aux.hw_mutex); } - mutex_unlock(&dev_priv->gmbus_mutex); + mutex_unlock(&dev_priv->display.gmbus.mutex); for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -2300,7 +2300,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) min_cdclk = max(min_cdclk, (int)crtc_state->pixel_rate); /* - * HACK. Currently for TGL platforms we calculate + * HACK. Currently for TGL/DG2 platforms we calculate * min_cdclk initially based on pixel_rate divided * by 2, accounting for also plane requirements, * however in some cases the lowest possible CDCLK @@ -2308,7 +2308,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) * Explicitly stating here that this seems to be currently * rather a Hack, than final solution. */ - if (IS_TIGERLAKE(dev_priv)) { + if (IS_TIGERLAKE(dev_priv) || IS_DG2(dev_priv)) { /* * Clamp to max_cdclk_freq in case pixel rate is higher, * in order not to break an 8K, but still leave W/A at place. @@ -3036,6 +3036,13 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) freq = dg1_rawclk(dev_priv); + else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP) + /* + * MTL always uses a 38.4 MHz rawclk. The bspec tells us + * "RAWCLK_FREQ defaults to the values for 38.4 and does + * not need to be programmed." + */ + freq = 38400; else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) freq = cnp_rawclk(dev_priv); else if (HAS_PCH_SPLIT(dev_priv)) @@ -3187,78 +3194,78 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) { if (IS_DG2(dev_priv)) { - dev_priv->cdclk_funcs = &tgl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->cdclk.table = dg2_cdclk_table; } else if (IS_ALDERLAKE_P(dev_priv)) { - dev_priv->cdclk_funcs = &tgl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; /* Wa_22011320316:adl-p[a0] */ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) dev_priv->cdclk.table = adlp_a_step_cdclk_table; else dev_priv->cdclk.table = adlp_cdclk_table; } else if (IS_ROCKETLAKE(dev_priv)) { - dev_priv->cdclk_funcs = &tgl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->cdclk.table = rkl_cdclk_table; } else if (DISPLAY_VER(dev_priv) >= 12) { - dev_priv->cdclk_funcs = &tgl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->cdclk.table = icl_cdclk_table; } else if (IS_JSL_EHL(dev_priv)) { - dev_priv->cdclk_funcs = &ehl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &ehl_cdclk_funcs; dev_priv->cdclk.table = icl_cdclk_table; } else if (DISPLAY_VER(dev_priv) >= 11) { - dev_priv->cdclk_funcs = &icl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &icl_cdclk_funcs; dev_priv->cdclk.table = icl_cdclk_table; } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { - dev_priv->cdclk_funcs = &bxt_cdclk_funcs; + dev_priv->display.funcs.cdclk = &bxt_cdclk_funcs; if (IS_GEMINILAKE(dev_priv)) dev_priv->cdclk.table = glk_cdclk_table; else dev_priv->cdclk.table = bxt_cdclk_table; } else if (DISPLAY_VER(dev_priv) == 9) { - dev_priv->cdclk_funcs = &skl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &skl_cdclk_funcs; } else if (IS_BROADWELL(dev_priv)) { - dev_priv->cdclk_funcs = &bdw_cdclk_funcs; + dev_priv->display.funcs.cdclk = &bdw_cdclk_funcs; } else if (IS_HASWELL(dev_priv)) { - dev_priv->cdclk_funcs = &hsw_cdclk_funcs; + dev_priv->display.funcs.cdclk = &hsw_cdclk_funcs; } else if (IS_CHERRYVIEW(dev_priv)) { - dev_priv->cdclk_funcs = &chv_cdclk_funcs; + dev_priv->display.funcs.cdclk = &chv_cdclk_funcs; } else if (IS_VALLEYVIEW(dev_priv)) { - dev_priv->cdclk_funcs = &vlv_cdclk_funcs; + dev_priv->display.funcs.cdclk = &vlv_cdclk_funcs; } else if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) { - dev_priv->cdclk_funcs = &fixed_400mhz_cdclk_funcs; + dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs; } else if (IS_IRONLAKE(dev_priv)) { - dev_priv->cdclk_funcs = &ilk_cdclk_funcs; + dev_priv->display.funcs.cdclk = &ilk_cdclk_funcs; } else if (IS_GM45(dev_priv)) { - dev_priv->cdclk_funcs = &gm45_cdclk_funcs; + dev_priv->display.funcs.cdclk = &gm45_cdclk_funcs; } else if (IS_G45(dev_priv)) { - dev_priv->cdclk_funcs = &g33_cdclk_funcs; + dev_priv->display.funcs.cdclk = &g33_cdclk_funcs; } else if (IS_I965GM(dev_priv)) { - dev_priv->cdclk_funcs = &i965gm_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i965gm_cdclk_funcs; } else if (IS_I965G(dev_priv)) { - dev_priv->cdclk_funcs = &fixed_400mhz_cdclk_funcs; + dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs; } else if (IS_PINEVIEW(dev_priv)) { - dev_priv->cdclk_funcs = &pnv_cdclk_funcs; + dev_priv->display.funcs.cdclk = &pnv_cdclk_funcs; } else if (IS_G33(dev_priv)) { - dev_priv->cdclk_funcs = &g33_cdclk_funcs; + dev_priv->display.funcs.cdclk = &g33_cdclk_funcs; } else if (IS_I945GM(dev_priv)) { - dev_priv->cdclk_funcs = &i945gm_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i945gm_cdclk_funcs; } else if (IS_I945G(dev_priv)) { - dev_priv->cdclk_funcs = &fixed_400mhz_cdclk_funcs; + dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs; } else if (IS_I915GM(dev_priv)) { - dev_priv->cdclk_funcs = &i915gm_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i915gm_cdclk_funcs; } else if (IS_I915G(dev_priv)) { - dev_priv->cdclk_funcs = &i915g_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i915g_cdclk_funcs; } else if (IS_I865G(dev_priv)) { - dev_priv->cdclk_funcs = &i865g_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i865g_cdclk_funcs; } else if (IS_I85X(dev_priv)) { - dev_priv->cdclk_funcs = &i85x_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i85x_cdclk_funcs; } else if (IS_I845G(dev_priv)) { - dev_priv->cdclk_funcs = &i845g_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i845g_cdclk_funcs; } else if (IS_I830(dev_priv)) { - dev_priv->cdclk_funcs = &i830_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i830_cdclk_funcs; } - if (drm_WARN(&dev_priv->drm, !dev_priv->cdclk_funcs, + if (drm_WARN(&dev_priv->drm, !dev_priv->display.funcs.cdclk, "Unknown platform. Assuming i830\n")) - dev_priv->cdclk_funcs = &i830_cdclk_funcs; + dev_priv->display.funcs.cdclk = &i830_cdclk_funcs; } diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 34128c9c635c..ed98c732b24e 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -505,30 +505,19 @@ static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state) static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - u32 val; - - val = intel_de_read(dev_priv, PIPECONF(pipe)); - val &= ~PIPECONF_GAMMA_MODE_MASK_I9XX; - val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); - intel_de_write(dev_priv, PIPECONF(pipe), val); + /* update PIPECONF GAMMA_MODE */ + i9xx_set_pipeconf(crtc_state); } static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - u32 val; - val = intel_de_read(dev_priv, PIPECONF(pipe)); - val &= ~PIPECONF_GAMMA_MODE_MASK_ILK; - val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); - intel_de_write(dev_priv, PIPECONF(pipe), val); + /* update PIPECONF GAMMA_MODE */ + ilk_set_pipeconf(crtc_state); - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(pipe), + intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode); } @@ -852,7 +841,7 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data; /* @@ -894,7 +883,7 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; /* * When setting the auto-increment bit, the hardware seems to @@ -1178,22 +1167,22 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - dev_priv->color_funcs->load_luts(crtc_state); + dev_priv->display.funcs.color->load_luts(crtc_state); } void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - if (dev_priv->color_funcs->color_commit_noarm) - dev_priv->color_funcs->color_commit_noarm(crtc_state); + if (dev_priv->display.funcs.color->color_commit_noarm) + dev_priv->display.funcs.color->color_commit_noarm(crtc_state); } void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - dev_priv->color_funcs->color_commit_arm(crtc_state); + dev_priv->display.funcs.color->color_commit_arm(crtc_state); } static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) @@ -1249,15 +1238,15 @@ int intel_color_check(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - return dev_priv->color_funcs->color_check(crtc_state); + return dev_priv->display.funcs.color->color_check(crtc_state); } void intel_color_get_config(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - if (dev_priv->color_funcs->read_luts) - dev_priv->color_funcs->read_luts(crtc_state); + if (dev_priv->display.funcs.color->read_luts) + dev_priv->display.funcs.color->read_luts(crtc_state); } static bool need_plane_update(struct intel_plane *plane, @@ -1346,10 +1335,10 @@ static int check_luts(const struct intel_crtc_state *crtc_state) return -EINVAL; } - degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size; - gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size; - degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; - gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; + degamma_length = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; + gamma_length = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + degamma_tests = INTEL_INFO(dev_priv)->display.color.degamma_lut_tests; + gamma_tests = INTEL_INFO(dev_priv)->display.color.gamma_lut_tests; if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) @@ -1638,7 +1627,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) /* * Enable 10bit gamma for D13 * ToDo: Extend to Logarithmic Gamma once the new UAPI - * is acccepted and implemented by a userspace consumer + * is accepted and implemented by a userspace consumer */ else if (DISPLAY_VER(i915) >= 13) gamma_mode |= GAMMA_MODE_MODE_10BIT; @@ -1885,7 +1874,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; @@ -1928,7 +1917,7 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; @@ -1989,7 +1978,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc) static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; @@ -2040,7 +2029,7 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int i, hw_lut_size = ivb_lut_10_size(prec_index); - int lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + int lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; @@ -2093,7 +2082,7 @@ static struct drm_property_blob * icl_read_lut_multi_segment(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; @@ -2230,38 +2219,38 @@ static const struct intel_color_funcs ilk_color_funcs = { void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - bool has_ctm = INTEL_INFO(dev_priv)->color.degamma_lut_size != 0; + bool has_ctm = INTEL_INFO(dev_priv)->display.color.degamma_lut_size != 0; drm_mode_crtc_set_gamma_size(&crtc->base, 256); if (HAS_GMCH(dev_priv)) { if (IS_CHERRYVIEW(dev_priv)) { - dev_priv->color_funcs = &chv_color_funcs; + dev_priv->display.funcs.color = &chv_color_funcs; } else if (DISPLAY_VER(dev_priv) >= 4) { - dev_priv->color_funcs = &i965_color_funcs; + dev_priv->display.funcs.color = &i965_color_funcs; } else { - dev_priv->color_funcs = &i9xx_color_funcs; + dev_priv->display.funcs.color = &i9xx_color_funcs; } } else { if (DISPLAY_VER(dev_priv) >= 11) - dev_priv->color_funcs = &icl_color_funcs; + dev_priv->display.funcs.color = &icl_color_funcs; else if (DISPLAY_VER(dev_priv) == 10) - dev_priv->color_funcs = &glk_color_funcs; + dev_priv->display.funcs.color = &glk_color_funcs; else if (DISPLAY_VER(dev_priv) == 9) - dev_priv->color_funcs = &skl_color_funcs; + dev_priv->display.funcs.color = &skl_color_funcs; else if (DISPLAY_VER(dev_priv) == 8) - dev_priv->color_funcs = &bdw_color_funcs; + dev_priv->display.funcs.color = &bdw_color_funcs; else if (DISPLAY_VER(dev_priv) == 7) { if (IS_HASWELL(dev_priv)) - dev_priv->color_funcs = &hsw_color_funcs; + dev_priv->display.funcs.color = &hsw_color_funcs; else - dev_priv->color_funcs = &ivb_color_funcs; + dev_priv->display.funcs.color = &ivb_color_funcs; } else - dev_priv->color_funcs = &ilk_color_funcs; + dev_priv->display.funcs.color = &ilk_color_funcs; } drm_crtc_enable_color_mgmt(&crtc->base, - INTEL_INFO(dev_priv)->color.degamma_lut_size, + INTEL_INFO(dev_priv)->display.color.degamma_lut_size, has_ctm, - INTEL_INFO(dev_priv)->color.gamma_lut_size); + INTEL_INFO(dev_priv)->display.color.gamma_lut_size); } diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 4442aa355f86..6792a9056f46 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank_work.h> #include "i915_irq.h" diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c new file mode 100644 index 000000000000..e9212f69c360 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -0,0 +1,315 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "i915_drv.h" +#include "intel_crtc_state_dump.h" +#include "intel_display_types.h" +#include "intel_hdmi.h" +#include "intel_vrr.h" + +static void intel_dump_crtc_timings(struct drm_i915_private *i915, + const struct drm_display_mode *mode) +{ + drm_dbg_kms(&i915->drm, "crtc timings: %d %d %d %d %d %d %d %d %d, " + "type: 0x%x flags: 0x%x\n", + mode->crtc_clock, + mode->crtc_hdisplay, mode->crtc_hsync_start, + mode->crtc_hsync_end, mode->crtc_htotal, + mode->crtc_vdisplay, mode->crtc_vsync_start, + mode->crtc_vsync_end, mode->crtc_vtotal, + mode->type, mode->flags); +} + +static void +intel_dump_m_n_config(const struct intel_crtc_state *pipe_config, + const char *id, unsigned int lane_count, + const struct intel_link_m_n *m_n) +{ + struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); + + drm_dbg_kms(&i915->drm, + "%s: lanes: %i; data_m: %u, data_n: %u, link_m: %u, link_n: %u, tu: %u\n", + id, lane_count, + m_n->data_m, m_n->data_n, + m_n->link_m, m_n->link_n, m_n->tu); +} + +static void +intel_dump_infoframe(struct drm_i915_private *i915, + const union hdmi_infoframe *frame) +{ + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + hdmi_infoframe_log(KERN_DEBUG, i915->drm.dev, frame); +} + +static void +intel_dump_dp_vsc_sdp(struct drm_i915_private *i915, + const struct drm_dp_vsc_sdp *vsc) +{ + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + drm_dp_vsc_sdp_log(KERN_DEBUG, i915->drm.dev, vsc); +} + +#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x + +static const char * const output_type_str[] = { + OUTPUT_TYPE(UNUSED), + OUTPUT_TYPE(ANALOG), + OUTPUT_TYPE(DVO), + OUTPUT_TYPE(SDVO), + OUTPUT_TYPE(LVDS), + OUTPUT_TYPE(TVOUT), + OUTPUT_TYPE(HDMI), + OUTPUT_TYPE(DP), + OUTPUT_TYPE(EDP), + OUTPUT_TYPE(DSI), + OUTPUT_TYPE(DDI), + OUTPUT_TYPE(DP_MST), +}; + +#undef OUTPUT_TYPE + +static void snprintf_output_types(char *buf, size_t len, + unsigned int output_types) +{ + char *str = buf; + int i; + + str[0] = '\0'; + + for (i = 0; i < ARRAY_SIZE(output_type_str); i++) { + int r; + + if ((output_types & BIT(i)) == 0) + continue; + + r = snprintf(str, len, "%s%s", + str != buf ? "," : "", output_type_str[i]); + if (r >= len) + break; + str += r; + len -= r; + + output_types &= ~BIT(i); + } + + WARN_ON_ONCE(output_types != 0); +} + +static const char * const output_format_str[] = { + [INTEL_OUTPUT_FORMAT_RGB] = "RGB", + [INTEL_OUTPUT_FORMAT_YCBCR420] = "YCBCR4:2:0", + [INTEL_OUTPUT_FORMAT_YCBCR444] = "YCBCR4:4:4", +}; + +static const char *output_formats(enum intel_output_format format) +{ + if (format >= ARRAY_SIZE(output_format_str)) + return "invalid"; + return output_format_str[format]; +} + +static void intel_dump_plane_state(const struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *i915 = to_i915(plane->base.dev); + const struct drm_framebuffer *fb = plane_state->hw.fb; + + if (!fb) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] fb: [NOFB], visible: %s\n", + plane->base.base.id, plane->base.name, + str_yes_no(plane_state->uapi.visible)); + return; + } + + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n", + plane->base.base.id, plane->base.name, + fb->base.id, fb->width, fb->height, &fb->format->format, + fb->modifier, str_yes_no(plane_state->uapi.visible)); + drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d, scaling_filter: %d\n", + plane_state->hw.rotation, plane_state->scaler_id, plane_state->hw.scaling_filter); + if (plane_state->uapi.visible) + drm_dbg_kms(&i915->drm, + "\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", + DRM_RECT_FP_ARG(&plane_state->uapi.src), + DRM_RECT_ARG(&plane_state->uapi.dst)); +} + +void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, + struct intel_atomic_state *state, + const char *context) +{ + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + const struct intel_plane_state *plane_state; + struct intel_plane *plane; + char buf[64]; + int i; + + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] enable: %s [%s]\n", + crtc->base.base.id, crtc->base.name, + str_yes_no(pipe_config->hw.enable), context); + + if (!pipe_config->hw.enable) + goto dump_planes; + + snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); + drm_dbg_kms(&i915->drm, + "active: %s, output_types: %s (0x%x), output format: %s\n", + str_yes_no(pipe_config->hw.active), + buf, pipe_config->output_types, + output_formats(pipe_config->output_format)); + + drm_dbg_kms(&i915->drm, + "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", + transcoder_name(pipe_config->cpu_transcoder), + pipe_config->pipe_bpp, pipe_config->dither); + + drm_dbg_kms(&i915->drm, "MST master transcoder: %s\n", + transcoder_name(pipe_config->mst_master_transcoder)); + + drm_dbg_kms(&i915->drm, + "port sync: master transcoder: %s, slave transcoder bitmask = 0x%x\n", + transcoder_name(pipe_config->master_transcoder), + pipe_config->sync_mode_slaves_mask); + + drm_dbg_kms(&i915->drm, "bigjoiner: %s, pipes: 0x%x\n", + intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : + intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", + pipe_config->bigjoiner_pipes); + + drm_dbg_kms(&i915->drm, "splitter: %s, link count %d, overlap %d\n", + str_enabled_disabled(pipe_config->splitter.enable), + pipe_config->splitter.link_count, + pipe_config->splitter.pixel_overlap); + + if (pipe_config->has_pch_encoder) + intel_dump_m_n_config(pipe_config, "fdi", + pipe_config->fdi_lanes, + &pipe_config->fdi_m_n); + + if (intel_crtc_has_dp_encoder(pipe_config)) { + intel_dump_m_n_config(pipe_config, "dp m_n", + pipe_config->lane_count, + &pipe_config->dp_m_n); + intel_dump_m_n_config(pipe_config, "dp m2_n2", + pipe_config->lane_count, + &pipe_config->dp_m2_n2); + } + + drm_dbg_kms(&i915->drm, "framestart delay: %d, MSA timing delay: %d\n", + pipe_config->framestart_delay, pipe_config->msa_timing_delay); + + drm_dbg_kms(&i915->drm, + "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", + pipe_config->has_audio, pipe_config->has_infoframe, + pipe_config->infoframes.enable); + + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) + drm_dbg_kms(&i915->drm, "GCP: 0x%x\n", + pipe_config->infoframes.gcp); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI)) + intel_dump_infoframe(i915, &pipe_config->infoframes.avi); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD)) + intel_dump_infoframe(i915, &pipe_config->infoframes.spd); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR)) + intel_dump_infoframe(i915, &pipe_config->infoframes.hdmi); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM)) + intel_dump_infoframe(i915, &pipe_config->infoframes.drm); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA)) + intel_dump_infoframe(i915, &pipe_config->infoframes.drm); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_VSC)) + intel_dump_dp_vsc_sdp(i915, &pipe_config->infoframes.vsc); + + drm_dbg_kms(&i915->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", + str_yes_no(pipe_config->vrr.enable), + pipe_config->vrr.vmin, pipe_config->vrr.vmax, + pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, + pipe_config->vrr.flipline, + intel_vrr_vmin_vblank_start(pipe_config), + intel_vrr_vmax_vblank_start(pipe_config)); + + drm_dbg_kms(&i915->drm, "requested mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.mode)); + drm_dbg_kms(&i915->drm, "adjusted mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.adjusted_mode)); + intel_dump_crtc_timings(i915, &pipe_config->hw.adjusted_mode); + drm_dbg_kms(&i915->drm, "pipe mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); + intel_dump_crtc_timings(i915, &pipe_config->hw.pipe_mode); + drm_dbg_kms(&i915->drm, + "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", + pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), + pipe_config->pixel_rate); + + drm_dbg_kms(&i915->drm, "linetime: %d, ips linetime: %d\n", + pipe_config->linetime, pipe_config->ips_linetime); + + if (DISPLAY_VER(i915) >= 9) + drm_dbg_kms(&i915->drm, + "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d\n", + crtc->num_scalers, + pipe_config->scaler_state.scaler_users, + pipe_config->scaler_state.scaler_id, + pipe_config->hw.scaling_filter); + + if (HAS_GMCH(i915)) + drm_dbg_kms(&i915->drm, + "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", + pipe_config->gmch_pfit.control, + pipe_config->gmch_pfit.pgm_ratios, + pipe_config->gmch_pfit.lvds_border_bits); + else + drm_dbg_kms(&i915->drm, + "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", + DRM_RECT_ARG(&pipe_config->pch_pfit.dst), + str_enabled_disabled(pipe_config->pch_pfit.enabled), + str_yes_no(pipe_config->pch_pfit.force_thru)); + + drm_dbg_kms(&i915->drm, "ips: %i, double wide: %i, drrs: %i\n", + pipe_config->ips_enabled, pipe_config->double_wide, + pipe_config->has_drrs); + + intel_dpll_dump_hw_state(i915, &pipe_config->dpll_hw_state); + + if (IS_CHERRYVIEW(i915)) + drm_dbg_kms(&i915->drm, + "cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", + pipe_config->cgm_mode, pipe_config->gamma_mode, + pipe_config->gamma_enable, pipe_config->csc_enable); + else + drm_dbg_kms(&i915->drm, + "csc_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", + pipe_config->csc_mode, pipe_config->gamma_mode, + pipe_config->gamma_enable, pipe_config->csc_enable); + + drm_dbg_kms(&i915->drm, "degamma lut: %d entries, gamma lut: %d entries\n", + pipe_config->hw.degamma_lut ? + drm_color_lut_size(pipe_config->hw.degamma_lut) : 0, + pipe_config->hw.gamma_lut ? + drm_color_lut_size(pipe_config->hw.gamma_lut) : 0); + +dump_planes: + if (!state) + return; + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane->pipe == crtc->pipe) + intel_dump_plane_state(plane_state); + } +} diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h new file mode 100644 index 000000000000..9399c35b7e5e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_CRTC_STATE_DUMP_H__ +#define __INTEL_CRTC_STATE_DUMP_H__ + +struct intel_crtc_state; +struct intel_atomic_state; + +void intel_crtc_state_dump(const struct intel_crtc_state *crtc_state, + struct intel_atomic_state *state, + const char *context); + +#endif /* __INTEL_CRTC_STATE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 8c80de877605..16ac560eab49 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -6,8 +6,8 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_fourcc.h> #include "intel_atomic.h" @@ -143,8 +143,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, } ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index d9f238edf547..b7702c4581aa 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -27,11 +27,12 @@ #include <linux/string_helpers.h> +#include <drm/display/drm_scdc_helper.h> #include <drm/drm_privacy_screen_consumer.h> -#include <drm/drm_scdc_helper.h> #include "i915_drv.h" #include "intel_audio.h" +#include "intel_audio_regs.h" #include "intel_backlight.h" #include "intel_combo_phy.h" #include "intel_combo_phy_regs.h" @@ -322,14 +323,10 @@ static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv, } } -static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) +int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config) { int dotclock; - /* CRT dotclock is determined via other means */ - if (pipe_config->has_pch_encoder) - return; - if (intel_crtc_has_dp_encoder(pipe_config)) dotclock = intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); @@ -345,7 +342,17 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - pipe_config->hw.adjusted_mode.crtc_clock = dotclock; + return dotclock; +} + +static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) +{ + /* CRT dotclock is determined via other means */ + if (pipe_config->has_pch_encoder) + return; + + pipe_config->hw.adjusted_mode.crtc_clock = + intel_crtc_dotclock(pipe_config); } void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, @@ -455,6 +462,9 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder, temp |= TRANS_DDI_SELECT_PORT(port); switch (crtc_state->pipe_bpp) { + default: + MISSING_CASE(crtc_state->pipe_bpp); + fallthrough; case 18: temp |= TRANS_DDI_BPC_6; break; @@ -467,8 +477,6 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder, case 36: temp |= TRANS_DDI_BPC_12; break; - default: - BUG(); } if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) @@ -478,6 +486,9 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder, if (cpu_transcoder == TRANSCODER_EDP) { switch (pipe) { + default: + MISSING_CASE(pipe); + fallthrough; case PIPE_A: /* On Haswell, can only use the always-on power well for * eDP when not using the panel fitter, and when not @@ -494,9 +505,6 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder, case PIPE_C: temp |= TRANS_DDI_EDP_INPUT_C_ONOFF; break; - default: - BUG(); - break; } } @@ -1417,7 +1425,7 @@ hsw_set_signal_levels(struct intel_encoder *encoder, static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg, u32 clk_sel_mask, u32 clk_sel, u32 clk_off) { - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, reg, clk_sel_mask, clk_sel); @@ -1427,17 +1435,17 @@ static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg, */ intel_de_rmw(i915, reg, clk_off, 0); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); } static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg, u32 clk_off) { - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, reg, 0, clk_off); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); } static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg, @@ -1712,12 +1720,12 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder, intel_de_write(i915, DDI_CLK_SEL(port), icl_pll_to_ddi_clk_sel(encoder, crtc_state)); - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, ICL_DPCLKA_CFGCR0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port), 0); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); } static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder) @@ -1726,12 +1734,12 @@ static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder) enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); enum port port = encoder->port; - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, ICL_DPCLKA_CFGCR0, 0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port)); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE); } @@ -1816,7 +1824,7 @@ static void skl_ddi_enable_clock(struct intel_encoder *encoder, if (drm_WARN_ON(&i915->drm, !pll)) return; - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, DPLL_CTRL2, DPLL_CTRL2_DDI_CLK_OFF(port) | @@ -1824,7 +1832,7 @@ static void skl_ddi_enable_clock(struct intel_encoder *encoder, DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); } static void skl_ddi_disable_clock(struct intel_encoder *encoder) @@ -1832,12 +1840,12 @@ static void skl_ddi_disable_clock(struct intel_encoder *encoder) struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; - mutex_lock(&i915->dpll.lock); + mutex_lock(&i915->display.dpll.lock); intel_de_rmw(i915, DPLL_CTRL2, 0, DPLL_CTRL2_DDI_CLK_OFF(port)); - mutex_unlock(&i915->dpll.lock); + mutex_unlock(&i915->display.dpll.lock); } static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder) @@ -2683,10 +2691,14 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state, dig_port->set_infoframes(encoder, false, old_crtc_state, old_conn_state); - intel_ddi_disable_pipe_clock(old_crtc_state); + if (DISPLAY_VER(dev_priv) < 12) + intel_ddi_disable_pipe_clock(old_crtc_state); intel_disable_ddi_buf(encoder, old_crtc_state); + if (DISPLAY_VER(dev_priv) >= 12) + intel_ddi_disable_pipe_clock(old_crtc_state); + intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain, fetch_and_zero(&dig_port->ddi_io_wakeref)); @@ -2854,6 +2866,8 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_connector *connector = conn_state->connector; enum port port = encoder->port; + enum phy phy = intel_port_to_phy(dev_priv, port); + u32 buf_ctl; if (!intel_hdmi_handle_sink_scrambling(encoder, connector, crtc_state->hdmi_high_tmds_clock_ratio, @@ -2911,8 +2925,12 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, * On ADL_P the PHY link rate and lane count must be programmed but * these are both 0 for HDMI. */ - intel_de_write(dev_priv, DDI_BUF_CTL(port), - dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE); + buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE; + if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) { + drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port)); + buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; + } + intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl); intel_audio_codec_enable(encoder, crtc_state, conn_state); } @@ -3433,26 +3451,8 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, pipe_config->has_audio = intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); - if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { - /* - * This is a big fat ugly hack. - * - * Some machines in UEFI boot mode provide us a VBT that has 18 - * bpp and 1.62 GHz link bandwidth for eDP, which for reasons - * unknown we fail to light up. Yet the same BIOS boots up with - * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as - * max, not what it tells us to use. - * - * Note: This will still be broken if the eDP panel is not lit - * up by the BIOS, and thus we can't get the mode at module - * load. - */ - drm_dbg_kms(&dev_priv->drm, - "pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp); - dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; - } + if (encoder->type == INTEL_OUTPUT_EDP) + intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp); ddi_dotclock_get(pipe_config); @@ -4038,7 +4038,7 @@ intel_ddi_hotplug(struct intel_encoder *encoder, static bool lpt_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.pch_hpd[encoder->hpd_pin]; + u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin]; return intel_de_read(dev_priv, SDEISR) & bit; } @@ -4046,7 +4046,7 @@ static bool lpt_digital_port_connected(struct intel_encoder *encoder) static bool hsw_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin]; + u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin]; return intel_de_read(dev_priv, DEISR) & bit; } @@ -4054,7 +4054,7 @@ static bool hsw_digital_port_connected(struct intel_encoder *encoder) static bool bdw_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 bit = dev_priv->hotplug.hpd[encoder->hpd_pin]; + u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin]; return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit; } @@ -4189,7 +4189,7 @@ static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv, if (port == PORT_D) return HPD_PORT_A; - if (HAS_PCH_MCC(dev_priv)) + if (HAS_PCH_TGP(dev_priv)) return icl_hpd_pin(dev_priv, port); return HPD_PORT_A + port - PORT_A; diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 85f58dd3df72..006a2e979000 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -878,26 +878,6 @@ static const struct intel_ddi_buf_trans adls_combo_phy_trans_edp_hbr3 = { .num_entries = ARRAY_SIZE(_adls_combo_phy_trans_edp_hbr3), }; -static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_hdmi[] = { - /* NT mV Trans mV db */ - { .icl = { 0x6, 0x60, 0x3F, 0x00, 0x00 } }, /* 400 400 0.0 */ - { .icl = { 0x6, 0x68, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ - { .icl = { 0xA, 0x73, 0x3F, 0x00, 0x00 } }, /* 650 650 0.0 ALS */ - { .icl = { 0xA, 0x78, 0x3F, 0x00, 0x00 } }, /* 800 800 0.0 */ - { .icl = { 0xB, 0x7F, 0x3F, 0x00, 0x00 } }, /* 1000 1000 0.0 Re-timer */ - { .icl = { 0xB, 0x7F, 0x3B, 0x00, 0x04 } }, /* Full Red -1.5 */ - { .icl = { 0xB, 0x7F, 0x39, 0x00, 0x06 } }, /* Full Red -1.8 */ - { .icl = { 0xB, 0x7F, 0x37, 0x00, 0x08 } }, /* Full Red -2.0 CRLS */ - { .icl = { 0xB, 0x7F, 0x35, 0x00, 0x0A } }, /* Full Red -2.5 */ - { .icl = { 0xB, 0x7F, 0x33, 0x00, 0x0C } }, /* Full Red -3.0 */ -}; - -static const struct intel_ddi_buf_trans adlp_combo_phy_trans_hdmi = { - .entries = _adlp_combo_phy_trans_hdmi, - .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_hdmi), - .hdmi_default_entry = ARRAY_SIZE(_adlp_combo_phy_trans_hdmi) - 1, -}; - static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr[] = { /* NT mV Trans mV db */ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */ @@ -953,9 +933,9 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_edp_h { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */ - { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */ - { .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */ - { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */ + { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 500 900 5.1 */ + { .icl = { 0xC, 0x63, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */ + { .icl = { 0x6, 0x7F, 0x38, 0x00, 0x07 } }, /* 600 900 3.5 */ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */ }; @@ -1062,17 +1042,18 @@ bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table) static bool use_edp_hobl(struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_connector *connector = intel_dp->attached_connector; - return i915->vbt.edp.hobl && !intel_dp->hobl_failed; + return connector->panel.vbt.edp.hobl && !intel_dp->hobl_failed; } static bool use_edp_low_vswing(struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_connector *connector = intel_dp->attached_connector; - return i915->vbt.edp.low_vswing; + return connector->panel.vbt.edp.low_vswing; } static const struct intel_ddi_buf_trans * @@ -1556,7 +1537,7 @@ adlp_get_combo_buf_trans(struct intel_encoder *encoder, int *n_entries) { if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - return intel_get_buf_trans(&adlp_combo_phy_trans_hdmi, n_entries); + return intel_get_buf_trans(&icl_combo_phy_trans_hdmi, n_entries); else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) return adlp_get_combo_buf_trans_edp(encoder, crtc_state, n_entries); else diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 85866f9f50ee..def9613d0b3e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -27,7 +27,6 @@ #include <acpi/video.h> #include <linux/i2c.h> #include <linux/input.h> -#include <linux/intel-iommu.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/dma-resv.h> @@ -35,14 +34,13 @@ #include <linux/string_helpers.h> #include <linux/vga_switcheroo.h> +#include <drm/display/drm_dp_helper.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_damage_helper.h> -#include <drm/dp/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_privacy_screen_consumer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> @@ -87,6 +85,7 @@ #include "intel_cdclk.h" #include "intel_color.h" #include "intel_crtc.h" +#include "intel_crtc_state_dump.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dmc.h" @@ -99,6 +98,8 @@ #include "intel_frontbuffer.h" #include "intel_hdcp.h" #include "intel_hotplug.h" +#include "intel_modeset_verify.h" +#include "intel_modeset_setup.h" #include "intel_overlay.h" #include "intel_panel.h" #include "intel_pch_display.h" @@ -123,13 +124,9 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); -static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state); -static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state); static void hsw_set_transconf(const struct intel_crtc_state *crtc_state); static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state); static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state); -static void intel_modeset_setup_hw_state(struct drm_device *dev, - struct drm_modeset_acquire_ctx *ctx); /** * intel_update_watermarks - update FIFO watermark values based on current modes @@ -164,18 +161,18 @@ static void intel_modeset_setup_hw_state(struct drm_device *dev, * We don't use the sprite, so we can ignore that. And on Crestline we have * to set the non-SR watermarks to 8. */ -static void intel_update_watermarks(struct drm_i915_private *dev_priv) +void intel_update_watermarks(struct drm_i915_private *dev_priv) { - if (dev_priv->wm_disp->update_wm) - dev_priv->wm_disp->update_wm(dev_priv); + if (dev_priv->display.funcs.wm->update_wm) + dev_priv->display.funcs.wm->update_wm(dev_priv); } static int intel_compute_pipe_wm(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (dev_priv->wm_disp->compute_pipe_wm) - return dev_priv->wm_disp->compute_pipe_wm(state, crtc); + if (dev_priv->display.funcs.wm->compute_pipe_wm) + return dev_priv->display.funcs.wm->compute_pipe_wm(state, crtc); return 0; } @@ -183,20 +180,20 @@ static int intel_compute_intermediate_wm(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (!dev_priv->wm_disp->compute_intermediate_wm) + if (!dev_priv->display.funcs.wm->compute_intermediate_wm) return 0; if (drm_WARN_ON(&dev_priv->drm, - !dev_priv->wm_disp->compute_pipe_wm)) + !dev_priv->display.funcs.wm->compute_pipe_wm)) return 0; - return dev_priv->wm_disp->compute_intermediate_wm(state, crtc); + return dev_priv->display.funcs.wm->compute_intermediate_wm(state, crtc); } static bool intel_initial_watermarks(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (dev_priv->wm_disp->initial_watermarks) { - dev_priv->wm_disp->initial_watermarks(state, crtc); + if (dev_priv->display.funcs.wm->initial_watermarks) { + dev_priv->display.funcs.wm->initial_watermarks(state, crtc); return true; } return false; @@ -206,23 +203,23 @@ static void intel_atomic_update_watermarks(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (dev_priv->wm_disp->atomic_update_watermarks) - dev_priv->wm_disp->atomic_update_watermarks(state, crtc); + if (dev_priv->display.funcs.wm->atomic_update_watermarks) + dev_priv->display.funcs.wm->atomic_update_watermarks(state, crtc); } static void intel_optimize_watermarks(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (dev_priv->wm_disp->optimize_watermarks) - dev_priv->wm_disp->optimize_watermarks(state, crtc); + if (dev_priv->display.funcs.wm->optimize_watermarks) + dev_priv->display.funcs.wm->optimize_watermarks(state, crtc); } static int intel_compute_global_watermarks(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - if (dev_priv->wm_disp->compute_global_watermarks) - return dev_priv->wm_disp->compute_global_watermarks(state); + if (dev_priv->display.funcs.wm->compute_global_watermarks) + return dev_priv->display.funcs.wm->compute_global_watermarks(state); return 0; } @@ -500,6 +497,9 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, i915_reg_t dpll_reg; switch (dig_port->base.port) { + default: + MISSING_CASE(dig_port->base.port); + fallthrough; case PORT_B: port_mask = DPLL_PORTB_READY_MASK; dpll_reg = DPLL(0); @@ -513,8 +513,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, port_mask = DPLL_PORTD_READY_MASK; dpll_reg = DPIO_PHY_STATUS; break; - default: - BUG(); } if (intel_de_wait_for_register(dev_priv, dpll_reg, @@ -730,10 +728,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, DRM_MODE_ROTATE_0); } -static void -intel_set_plane_visible(struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state, - bool visible) +void intel_set_plane_visible(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state, + bool visible) { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); @@ -745,7 +742,7 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state, crtc_state->uapi.plane_mask &= ~drm_plane_mask(&plane->base); } -static void fixup_plane_bitmasks(struct intel_crtc_state *crtc_state) +void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct drm_plane *plane; @@ -780,7 +777,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, crtc->base.base.id, crtc->base.name); intel_set_plane_visible(crtc_state, plane_state, false); - fixup_plane_bitmasks(crtc_state); + intel_plane_fixup_bitmasks(crtc_state); crtc_state->data_rate[plane->id] = 0; crtc_state->data_rate_y[plane->id] = 0; crtc_state->rel_data_rate[plane->id] = 0; @@ -829,7 +826,7 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state) } static int -__intel_display_resume(struct drm_device *dev, +__intel_display_resume(struct drm_i915_private *i915, struct drm_atomic_state *state, struct drm_modeset_acquire_ctx *ctx) { @@ -837,8 +834,8 @@ __intel_display_resume(struct drm_device *dev, struct drm_crtc *crtc; int i, ret; - intel_modeset_setup_hw_state(dev, ctx); - intel_vga_redisable(to_i915(dev)); + intel_modeset_setup_hw_state(i915, ctx); + intel_vga_redisable(i915); if (!state) return 0; @@ -858,12 +855,13 @@ __intel_display_resume(struct drm_device *dev, } /* ignore any reset values/BIOS leftovers in the WM registers */ - if (!HAS_GMCH(to_i915(dev))) + if (!HAS_GMCH(i915)) to_intel_atomic_state(state)->skip_intermediate_wm = true; ret = drm_atomic_helper_commit_duplicated_state(state, ctx); - drm_WARN_ON(dev, ret == -EDEADLK); + drm_WARN_ON(&i915->drm, ret == -EDEADLK); + return ret; } @@ -936,56 +934,55 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) state->acquire_ctx = ctx; } -void intel_display_finish_reset(struct drm_i915_private *dev_priv) +void intel_display_finish_reset(struct drm_i915_private *i915) { - struct drm_device *dev = &dev_priv->drm; - struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; + struct drm_modeset_acquire_ctx *ctx = &i915->reset_ctx; struct drm_atomic_state *state; int ret; - if (!HAS_DISPLAY(dev_priv)) + if (!HAS_DISPLAY(i915)) return; /* reset doesn't touch the display */ - if (!test_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags)) + if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags)) return; - state = fetch_and_zero(&dev_priv->modeset_restore_state); + state = fetch_and_zero(&i915->modeset_restore_state); if (!state) goto unlock; /* reset doesn't touch the display */ - if (!gpu_reset_clobbers_display(dev_priv)) { + if (!gpu_reset_clobbers_display(i915)) { /* for testing only restore the display */ - ret = __intel_display_resume(dev, state, ctx); + ret = __intel_display_resume(i915, state, ctx); if (ret) - drm_err(&dev_priv->drm, + drm_err(&i915->drm, "Restoring old state failed with %i\n", ret); } else { /* * The display has been reset as well, * so need a full re-initialization. */ - intel_pps_unlock_regs_wa(dev_priv); - intel_modeset_init_hw(dev_priv); - intel_init_clock_gating(dev_priv); - intel_hpd_init(dev_priv); + intel_pps_unlock_regs_wa(i915); + intel_modeset_init_hw(i915); + intel_init_clock_gating(i915); + intel_hpd_init(i915); - ret = __intel_display_resume(dev, state, ctx); + ret = __intel_display_resume(i915, state, ctx); if (ret) - drm_err(&dev_priv->drm, + drm_err(&i915->drm, "Restoring old state failed with %i\n", ret); - intel_hpd_poll_disable(dev_priv); + intel_hpd_poll_disable(i915); } drm_atomic_state_put(state); unlock: drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx); - mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&i915->drm.mode_config.mutex); - clear_bit_unlock(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags); + clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags); } static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state) @@ -1489,7 +1486,7 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state) * Make sure the DPLL state is up-to-date for fastset TypeC ports after non-blocking commits. * TODO: Update the DPLL state for all cases in the encoder->update_prepare() hook. */ - if (i915->dpll.mgr) { + if (i915->display.dpll.mgr) { for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -2083,22 +2080,20 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) { if (phy == PHY_NONE) return false; - else if (IS_DG2(dev_priv)) - /* - * DG2 outputs labelled as "combo PHY" in the bspec use - * SNPS PHYs with completely different programming, - * hence we always return false here. - */ - return false; else if (IS_ALDERLAKE_S(dev_priv)) return phy <= PHY_E; else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return phy <= PHY_D; else if (IS_JSL_EHL(dev_priv)) return phy <= PHY_C; - else if (DISPLAY_VER(dev_priv) >= 11) + else if (IS_ALDERLAKE_P(dev_priv) || IS_DISPLAY_VER(dev_priv, 11, 12)) return phy <= PHY_B; else + /* + * DG2 outputs labelled as "combo PHY" in the bspec use + * SNPS PHYs with completely different programming, + * hence we always return false here. + */ return false; } @@ -2206,9 +2201,8 @@ static void get_crtc_power_domains(struct intel_crtc_state *crtc_state, set_bit(intel_dsc_power_domain(crtc, cpu_transcoder), mask->bits); } -static void -modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, - struct intel_power_domain_mask *old_domains) +void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, + struct intel_power_domain_mask *old_domains) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -2232,8 +2226,8 @@ modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, domain); } -static void modeset_put_crtc_power_domains(struct intel_crtc *crtc, - struct intel_power_domain_mask *domains) +void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc, + struct intel_power_domain_mask *domains) { intel_display_power_put_mask_in_set(to_i915(crtc->base.dev), &crtc->enabled_power_domains, @@ -2405,7 +2399,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state, if (DISPLAY_VER(dev_priv) != 2) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - if (!dev_priv->wm_disp->initial_watermarks) + if (!dev_priv->display.funcs.wm->initial_watermarks) intel_update_watermarks(dev_priv); /* clock the pipe down to 640x480@60 to potentially save power */ @@ -2413,89 +2407,6 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state, i830_enable_pipe(dev_priv, pipe); } -static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) -{ - struct intel_encoder *encoder; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_bw_state *bw_state = - to_intel_bw_state(dev_priv->bw_obj.state); - struct intel_cdclk_state *cdclk_state = - to_intel_cdclk_state(dev_priv->cdclk.obj.state); - struct intel_dbuf_state *dbuf_state = - to_intel_dbuf_state(dev_priv->dbuf.obj.state); - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - struct intel_plane *plane; - struct drm_atomic_state *state; - struct intel_crtc_state *temp_crtc_state; - enum pipe pipe = crtc->pipe; - int ret; - - if (!crtc_state->hw.active) - return; - - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - - if (plane_state->uapi.visible) - intel_plane_disable_noatomic(crtc, plane); - } - - state = drm_atomic_state_alloc(&dev_priv->drm); - if (!state) { - drm_dbg_kms(&dev_priv->drm, - "failed to disable [CRTC:%d:%s], out of memory", - crtc->base.base.id, crtc->base.name); - return; - } - - state->acquire_ctx = ctx; - - /* Everything's already locked, -EDEADLK can't happen. */ - temp_crtc_state = intel_atomic_get_crtc_state(state, crtc); - ret = drm_atomic_add_affected_connectors(state, &crtc->base); - - drm_WARN_ON(&dev_priv->drm, IS_ERR(temp_crtc_state) || ret); - - dev_priv->display->crtc_disable(to_intel_atomic_state(state), crtc); - - drm_atomic_state_put(state); - - drm_dbg_kms(&dev_priv->drm, - "[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", - crtc->base.base.id, crtc->base.name); - - crtc->active = false; - crtc->base.enabled = false; - - drm_WARN_ON(&dev_priv->drm, - drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0); - crtc_state->uapi.active = false; - crtc_state->uapi.connector_mask = 0; - crtc_state->uapi.encoder_mask = 0; - intel_crtc_free_hw_state(crtc_state); - memset(&crtc_state->hw, 0, sizeof(crtc_state->hw)); - - for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) - encoder->base.crtc = NULL; - - intel_fbc_disable(crtc); - intel_update_watermarks(dev_priv); - intel_disable_shared_dpll(crtc_state); - - intel_display_power_put_all_in_set(dev_priv, &crtc->enabled_power_domains); - - cdclk_state->min_cdclk[pipe] = 0; - cdclk_state->min_voltage_level[pipe] = 0; - cdclk_state->active_pipes &= ~BIT(pipe); - - dbuf_state->active_pipes &= ~BIT(pipe); - - bw_state->data_rate[pipe] = 0; - bw_state->num_active_planes[pipe] = 0; -} /* * turn all crtc's off, but do not adjust state @@ -2528,45 +2439,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder) kfree(intel_encoder); } -/* Cross check the actual hw state with our own modeset state tracking (and it's - * internal consistency). */ -static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *i915 = to_i915(connector->base.dev); - - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", - connector->base.base.id, connector->base.name); - - if (connector->get_hw_state(connector)) { - struct intel_encoder *encoder = intel_attached_encoder(connector); - - I915_STATE_WARN(!crtc_state, - "connector enabled without attached crtc\n"); - - if (!crtc_state) - return; - - I915_STATE_WARN(!crtc_state->hw.active, - "connector is active, but attached crtc isn't\n"); - - if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST) - return; - - I915_STATE_WARN(conn_state->best_encoder != &encoder->base, - "atomic encoder doesn't match attached encoder\n"); - - I915_STATE_WARN(conn_state->crtc != encoder->base.crtc, - "attached encoder crtc differs from connector crtc\n"); - } else { - I915_STATE_WARN(crtc_state && crtc_state->hw.active, - "attached crtc is active, but connector isn't\n"); - I915_STATE_WARN(!crtc_state && conn_state->best_encoder, - "best encoder set without crtc!\n"); - } -} - static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) { const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -2708,8 +2580,8 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state intel_crtc_compute_pixel_rate(crtc_state); } -static void intel_encoder_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) +void intel_encoder_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) { encoder->get_config(encoder, crtc_state); @@ -2811,9 +2683,11 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) return 0; } -static int intel_crtc_compute_config(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +static int intel_crtc_compute_config(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = intel_crtc_compute_pipe_src(crtc_state); @@ -3135,14 +3009,18 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, intel_bigjoiner_adjust_pipe_src(pipe_config); } -static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) +void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 pipeconf = 0; - /* we keep both pipes enabled on 830 */ - if (IS_I830(dev_priv)) + /* + * - We keep both pipes enabled on 830 + * - During modeset the pipe is still disabled and must remain so + * - During fastset the pipe is already enabled and must remain so + */ + if (IS_I830(dev_priv) || !intel_crtc_needs_modeset(crtc_state)) pipeconf |= PIPECONF_ENABLE; if (crtc_state->double_wide) @@ -3157,6 +3035,10 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) PIPECONF_DITHER_TYPE_SP; switch (crtc_state->pipe_bpp) { + default: + /* Case prevented by intel_choose_pipe_bpp_dither. */ + MISSING_CASE(crtc_state->pipe_bpp); + fallthrough; case 18: pipeconf |= PIPECONF_BPC_6; break; @@ -3166,9 +3048,6 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) case 30: pipeconf |= PIPECONF_BPC_10; break; - default: - /* Case prevented by intel_choose_pipe_bpp_dither. */ - BUG(); } } @@ -3454,16 +3333,25 @@ out: return ret; } -static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) +void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - u32 val; + u32 val = 0; - val = 0; + /* + * - During modeset the pipe is still disabled and must remain so + * - During fastset the pipe is already enabled and must remain so + */ + if (!intel_crtc_needs_modeset(crtc_state)) + val |= PIPECONF_ENABLE; switch (crtc_state->pipe_bpp) { + default: + /* Case prevented by intel_choose_pipe_bpp_dither. */ + MISSING_CASE(crtc_state->pipe_bpp); + fallthrough; case 18: val |= PIPECONF_BPC_6; break; @@ -3476,9 +3364,6 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) case 36: val |= PIPECONF_BPC_12; break; - default: - /* Case prevented by intel_choose_pipe_bpp_dither. */ - BUG(); } if (crtc_state->dither) @@ -3519,6 +3404,13 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state) enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 val = 0; + /* + * - During modeset the pipe is still disabled and must remain so + * - During fastset the pipe is already enabled and must remain so + */ + if (!intel_crtc_needs_modeset(crtc_state)) + val |= PIPECONF_ENABLE; + if (IS_HASWELL(dev_priv) && crtc_state->dither) val |= PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; @@ -4246,12 +4138,12 @@ out: return active; } -static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state) +bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - if (!i915->display->get_pipe_config(crtc, crtc_state)) + if (!i915->display.funcs.display->get_pipe_config(crtc, crtc_state)) return false; crtc_state->hw.active = true; @@ -4980,45 +4872,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, return 0; } -static void intel_modeset_update_connector_atomic_state(struct drm_device *dev) -{ - struct intel_connector *connector; - struct drm_connector_list_iter conn_iter; - - drm_connector_list_iter_begin(dev, &conn_iter); - for_each_intel_connector_iter(connector, &conn_iter) { - struct drm_connector_state *conn_state = connector->base.state; - struct intel_encoder *encoder = - to_intel_encoder(connector->base.encoder); - - if (conn_state->crtc) - drm_connector_put(&connector->base); - - if (encoder) { - struct intel_crtc *crtc = - to_intel_crtc(encoder->base.crtc); - const struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - conn_state->best_encoder = &encoder->base; - conn_state->crtc = &crtc->base; - conn_state->max_bpc = (crtc_state->pipe_bpp ?: 24) / 3; - - drm_connector_get(&connector->base); - } else { - conn_state->best_encoder = NULL; - conn_state->crtc = NULL; - } - } - drm_connector_list_iter_end(&conn_iter); -} - static int compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *crtc_state) { struct drm_connector *connector = conn_state->connector; - struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); const struct drm_display_info *info = &connector->display_info; int bpp; @@ -5040,27 +4899,28 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, return -EINVAL; } - if (bpp < pipe_config->pipe_bpp) { + if (bpp < crtc_state->pipe_bpp) { drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] Limiting display bpp to %d instead of " - "EDID bpp %d, requested bpp %d, max platform bpp %d\n", + "[CONNECTOR:%d:%s] Limiting display bpp to %d " + "(EDID bpp %d, max requested bpp %d, max platform bpp %d)\n", connector->base.id, connector->name, bpp, 3 * info->bpc, 3 * conn_state->max_requested_bpc, - pipe_config->pipe_bpp); + crtc_state->pipe_bpp); - pipe_config->pipe_bpp = bpp; + crtc_state->pipe_bpp = bpp; } return 0; } static int -compute_baseline_pipe_bpp(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +compute_baseline_pipe_bpp(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_atomic_state *state = pipe_config->uapi.state; + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_connector *connector; struct drm_connector_state *connector_state; int bpp, i; @@ -5073,16 +4933,16 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, else bpp = 8*3; - pipe_config->pipe_bpp = bpp; + crtc_state->pipe_bpp = bpp; /* Clamp display bpp to connector max bpp */ - for_each_new_connector_in_state(state, connector, connector_state, i) { + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { int ret; if (connector_state->crtc != &crtc->base) continue; - ret = compute_sink_pipe_bpp(connector_state, pipe_config); + ret = compute_sink_pipe_bpp(connector_state, crtc_state); if (ret) return ret; } @@ -5090,310 +4950,6 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, return 0; } -static void intel_dump_crtc_timings(struct drm_i915_private *i915, - const struct drm_display_mode *mode) -{ - drm_dbg_kms(&i915->drm, "crtc timings: %d %d %d %d %d %d %d %d %d, " - "type: 0x%x flags: 0x%x\n", - mode->crtc_clock, - mode->crtc_hdisplay, mode->crtc_hsync_start, - mode->crtc_hsync_end, mode->crtc_htotal, - mode->crtc_vdisplay, mode->crtc_vsync_start, - mode->crtc_vsync_end, mode->crtc_vtotal, - mode->type, mode->flags); -} - -static void -intel_dump_m_n_config(const struct intel_crtc_state *pipe_config, - const char *id, unsigned int lane_count, - const struct intel_link_m_n *m_n) -{ - struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); - - drm_dbg_kms(&i915->drm, - "%s: lanes: %i; data_m: %u, data_n: %u, link_m: %u, link_n: %u, tu: %u\n", - id, lane_count, - m_n->data_m, m_n->data_n, - m_n->link_m, m_n->link_n, m_n->tu); -} - -static void -intel_dump_infoframe(struct drm_i915_private *dev_priv, - const union hdmi_infoframe *frame) -{ - if (!drm_debug_enabled(DRM_UT_KMS)) - return; - - hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, frame); -} - -static void -intel_dump_dp_vsc_sdp(struct drm_i915_private *dev_priv, - const struct drm_dp_vsc_sdp *vsc) -{ - if (!drm_debug_enabled(DRM_UT_KMS)) - return; - - drm_dp_vsc_sdp_log(KERN_DEBUG, dev_priv->drm.dev, vsc); -} - -#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x - -static const char * const output_type_str[] = { - OUTPUT_TYPE(UNUSED), - OUTPUT_TYPE(ANALOG), - OUTPUT_TYPE(DVO), - OUTPUT_TYPE(SDVO), - OUTPUT_TYPE(LVDS), - OUTPUT_TYPE(TVOUT), - OUTPUT_TYPE(HDMI), - OUTPUT_TYPE(DP), - OUTPUT_TYPE(EDP), - OUTPUT_TYPE(DSI), - OUTPUT_TYPE(DDI), - OUTPUT_TYPE(DP_MST), -}; - -#undef OUTPUT_TYPE - -static void snprintf_output_types(char *buf, size_t len, - unsigned int output_types) -{ - char *str = buf; - int i; - - str[0] = '\0'; - - for (i = 0; i < ARRAY_SIZE(output_type_str); i++) { - int r; - - if ((output_types & BIT(i)) == 0) - continue; - - r = snprintf(str, len, "%s%s", - str != buf ? "," : "", output_type_str[i]); - if (r >= len) - break; - str += r; - len -= r; - - output_types &= ~BIT(i); - } - - WARN_ON_ONCE(output_types != 0); -} - -static const char * const output_format_str[] = { - [INTEL_OUTPUT_FORMAT_RGB] = "RGB", - [INTEL_OUTPUT_FORMAT_YCBCR420] = "YCBCR4:2:0", - [INTEL_OUTPUT_FORMAT_YCBCR444] = "YCBCR4:4:4", -}; - -static const char *output_formats(enum intel_output_format format) -{ - if (format >= ARRAY_SIZE(output_format_str)) - return "invalid"; - return output_format_str[format]; -} - -static void intel_dump_plane_state(const struct intel_plane_state *plane_state) -{ - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - struct drm_i915_private *i915 = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->hw.fb; - - if (!fb) { - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] fb: [NOFB], visible: %s\n", - plane->base.base.id, plane->base.name, - str_yes_no(plane_state->uapi.visible)); - return; - } - - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n", - plane->base.base.id, plane->base.name, - fb->base.id, fb->width, fb->height, &fb->format->format, - fb->modifier, str_yes_no(plane_state->uapi.visible)); - drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d\n", - plane_state->hw.rotation, plane_state->scaler_id); - if (plane_state->uapi.visible) - drm_dbg_kms(&i915->drm, - "\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", - DRM_RECT_FP_ARG(&plane_state->uapi.src), - DRM_RECT_ARG(&plane_state->uapi.dst)); -} - -static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, - struct intel_atomic_state *state, - const char *context) -{ - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct intel_plane_state *plane_state; - struct intel_plane *plane; - char buf[64]; - int i; - - drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] enable: %s %s\n", - crtc->base.base.id, crtc->base.name, - str_yes_no(pipe_config->hw.enable), context); - - if (!pipe_config->hw.enable) - goto dump_planes; - - snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); - drm_dbg_kms(&dev_priv->drm, - "active: %s, output_types: %s (0x%x), output format: %s\n", - str_yes_no(pipe_config->hw.active), - buf, pipe_config->output_types, - output_formats(pipe_config->output_format)); - - drm_dbg_kms(&dev_priv->drm, - "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", - transcoder_name(pipe_config->cpu_transcoder), - pipe_config->pipe_bpp, pipe_config->dither); - - drm_dbg_kms(&dev_priv->drm, "MST master transcoder: %s\n", - transcoder_name(pipe_config->mst_master_transcoder)); - - drm_dbg_kms(&dev_priv->drm, - "port sync: master transcoder: %s, slave transcoder bitmask = 0x%x\n", - transcoder_name(pipe_config->master_transcoder), - pipe_config->sync_mode_slaves_mask); - - drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s, pipes: 0x%x\n", - intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : - intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", - pipe_config->bigjoiner_pipes); - - drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n", - str_enabled_disabled(pipe_config->splitter.enable), - pipe_config->splitter.link_count, - pipe_config->splitter.pixel_overlap); - - if (pipe_config->has_pch_encoder) - intel_dump_m_n_config(pipe_config, "fdi", - pipe_config->fdi_lanes, - &pipe_config->fdi_m_n); - - if (intel_crtc_has_dp_encoder(pipe_config)) { - intel_dump_m_n_config(pipe_config, "dp m_n", - pipe_config->lane_count, - &pipe_config->dp_m_n); - intel_dump_m_n_config(pipe_config, "dp m2_n2", - pipe_config->lane_count, - &pipe_config->dp_m2_n2); - } - - drm_dbg_kms(&dev_priv->drm, "framestart delay: %d, MSA timing delay: %d\n", - pipe_config->framestart_delay, pipe_config->msa_timing_delay); - - drm_dbg_kms(&dev_priv->drm, - "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", - pipe_config->has_audio, pipe_config->has_infoframe, - pipe_config->infoframes.enable); - - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) - drm_dbg_kms(&dev_priv->drm, "GCP: 0x%x\n", - pipe_config->infoframes.gcp); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI)) - intel_dump_infoframe(dev_priv, &pipe_config->infoframes.avi); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD)) - intel_dump_infoframe(dev_priv, &pipe_config->infoframes.spd); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR)) - intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM)) - intel_dump_infoframe(dev_priv, &pipe_config->infoframes.drm); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA)) - intel_dump_infoframe(dev_priv, &pipe_config->infoframes.drm); - if (pipe_config->infoframes.enable & - intel_hdmi_infoframe_enable(DP_SDP_VSC)) - intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc); - - drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", - str_yes_no(pipe_config->vrr.enable), - pipe_config->vrr.vmin, pipe_config->vrr.vmax, - pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, - pipe_config->vrr.flipline, - intel_vrr_vmin_vblank_start(pipe_config), - intel_vrr_vmax_vblank_start(pipe_config)); - - drm_dbg_kms(&dev_priv->drm, "requested mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.mode)); - drm_dbg_kms(&dev_priv->drm, "adjusted mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.adjusted_mode)); - intel_dump_crtc_timings(dev_priv, &pipe_config->hw.adjusted_mode); - drm_dbg_kms(&dev_priv->drm, "pipe mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); - intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode); - drm_dbg_kms(&dev_priv->drm, - "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", - pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), - pipe_config->pixel_rate); - - drm_dbg_kms(&dev_priv->drm, "linetime: %d, ips linetime: %d\n", - pipe_config->linetime, pipe_config->ips_linetime); - - if (DISPLAY_VER(dev_priv) >= 9) - drm_dbg_kms(&dev_priv->drm, - "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n", - crtc->num_scalers, - pipe_config->scaler_state.scaler_users, - pipe_config->scaler_state.scaler_id); - - if (HAS_GMCH(dev_priv)) - drm_dbg_kms(&dev_priv->drm, - "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", - pipe_config->gmch_pfit.control, - pipe_config->gmch_pfit.pgm_ratios, - pipe_config->gmch_pfit.lvds_border_bits); - else - drm_dbg_kms(&dev_priv->drm, - "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", - DRM_RECT_ARG(&pipe_config->pch_pfit.dst), - str_enabled_disabled(pipe_config->pch_pfit.enabled), - str_yes_no(pipe_config->pch_pfit.force_thru)); - - drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i, drrs: %i\n", - pipe_config->ips_enabled, pipe_config->double_wide, - pipe_config->has_drrs); - - intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state); - - if (IS_CHERRYVIEW(dev_priv)) - drm_dbg_kms(&dev_priv->drm, - "cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", - pipe_config->cgm_mode, pipe_config->gamma_mode, - pipe_config->gamma_enable, pipe_config->csc_enable); - else - drm_dbg_kms(&dev_priv->drm, - "csc_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", - pipe_config->csc_mode, pipe_config->gamma_mode, - pipe_config->gamma_enable, pipe_config->csc_enable); - - drm_dbg_kms(&dev_priv->drm, "degamma lut: %d entries, gamma lut: %d entries\n", - pipe_config->hw.degamma_lut ? - drm_color_lut_size(pipe_config->hw.degamma_lut) : 0, - pipe_config->hw.gamma_lut ? - drm_color_lut_size(pipe_config->hw.gamma_lut) : 0); - -dump_planes: - if (!state) - return; - - for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - if (plane->pipe == crtc->pipe) - intel_dump_plane_state(plane_state); - } -} - static bool check_digital_port_conflicts(struct intel_atomic_state *state) { struct drm_device *dev = state->base.dev; @@ -5500,27 +5056,6 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); } -static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) -{ - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - return; - - crtc_state->uapi.enable = crtc_state->hw.enable; - crtc_state->uapi.active = crtc_state->hw.active; - drm_WARN_ON(crtc_state->uapi.crtc->dev, - drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0); - - crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; - crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; - - drm_property_replace_blob(&crtc_state->uapi.degamma_lut, - crtc_state->hw.degamma_lut); - drm_property_replace_blob(&crtc_state->uapi.gamma_lut, - crtc_state->hw.gamma_lut); - drm_property_replace_blob(&crtc_state->uapi.ctm, - crtc_state->hw.ctm); -} - static void copy_bigjoiner_crtc_state_nomodeset(struct intel_atomic_state *state, struct intel_crtc *slave_crtc) @@ -5636,40 +5171,39 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, static int intel_modeset_pipe_config(struct intel_atomic_state *state, - struct intel_crtc_state *pipe_config) + struct intel_crtc *crtc) { - struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_connector *connector; struct drm_connector_state *connector_state; int pipe_src_w, pipe_src_h; int base_bpp, ret, i; bool retry = true; - pipe_config->cpu_transcoder = - (enum transcoder) to_intel_crtc(crtc)->pipe; + crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->framestart_delay = 1; + crtc_state->framestart_delay = 1; /* * Sanitize sync polarity flags based on requested ones. If neither * positive or negative polarity is requested, treat this as meaning * negative polarity. */ - if (!(pipe_config->hw.adjusted_mode.flags & + if (!(crtc_state->hw.adjusted_mode.flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) - pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; + crtc_state->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; - if (!(pipe_config->hw.adjusted_mode.flags & + if (!(crtc_state->hw.adjusted_mode.flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) - pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; + crtc_state->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; - ret = compute_baseline_pipe_bpp(to_intel_crtc(crtc), - pipe_config); + ret = compute_baseline_pipe_bpp(state, crtc); if (ret) return ret; - base_bpp = pipe_config->pipe_bpp; + base_bpp = crtc_state->pipe_bpp; /* * Determine the real pipe dimensions. Note that stereo modes can @@ -5679,21 +5213,22 @@ intel_modeset_pipe_config(struct intel_atomic_state *state, * computation to clearly distinguish it from the adjusted mode, which * can be changed by the connectors in the below retry loop. */ - drm_mode_get_hv_timing(&pipe_config->hw.mode, + drm_mode_get_hv_timing(&crtc_state->hw.mode, &pipe_src_w, &pipe_src_h); - drm_rect_init(&pipe_config->pipe_src, 0, 0, + drm_rect_init(&crtc_state->pipe_src, 0, 0, pipe_src_w, pipe_src_h); for_each_new_connector_in_state(&state->base, connector, connector_state, i) { struct intel_encoder *encoder = to_intel_encoder(connector_state->best_encoder); - if (connector_state->crtc != crtc) + if (connector_state->crtc != &crtc->base) continue; - if (!check_single_encoder_cloning(state, to_intel_crtc(crtc), encoder)) { + if (!check_single_encoder_cloning(state, crtc, encoder)) { drm_dbg_kms(&i915->drm, - "rejecting invalid cloning configuration\n"); + "[ENCODER:%d:%s] rejecting invalid cloning configuration\n", + encoder->base.base.id, encoder->base.name); return -EINVAL; } @@ -5702,20 +5237,20 @@ intel_modeset_pipe_config(struct intel_atomic_state *state, * hooks so that the hooks can use this information safely. */ if (encoder->compute_output_type) - pipe_config->output_types |= - BIT(encoder->compute_output_type(encoder, pipe_config, + crtc_state->output_types |= + BIT(encoder->compute_output_type(encoder, crtc_state, connector_state)); else - pipe_config->output_types |= BIT(encoder->type); + crtc_state->output_types |= BIT(encoder->type); } encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ - pipe_config->port_clock = 0; - pipe_config->pixel_multiplier = 1; + crtc_state->port_clock = 0; + crtc_state->pixel_multiplier = 1; /* Fill in default crtc timings, allow encoders to overwrite them. */ - drm_mode_set_crtcinfo(&pipe_config->hw.adjusted_mode, + drm_mode_set_crtcinfo(&crtc_state->hw.adjusted_mode, CRTC_STEREO_DOUBLE); /* Pass our mode to the connectors and the CRTC to give them a chance to @@ -5726,39 +5261,43 @@ encoder_retry: struct intel_encoder *encoder = to_intel_encoder(connector_state->best_encoder); - if (connector_state->crtc != crtc) + if (connector_state->crtc != &crtc->base) continue; - ret = encoder->compute_config(encoder, pipe_config, + ret = encoder->compute_config(encoder, crtc_state, connector_state); if (ret == -EDEADLK) return ret; if (ret < 0) { - drm_dbg_kms(&i915->drm, "Encoder config failure: %d\n", ret); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] config failure: %d\n", + encoder->base.base.id, encoder->base.name, ret); return ret; } } /* Set default port clock if not overwritten by the encoder. Needs to be * done afterwards in case the encoder adjusts the mode. */ - if (!pipe_config->port_clock) - pipe_config->port_clock = pipe_config->hw.adjusted_mode.crtc_clock - * pipe_config->pixel_multiplier; + if (!crtc_state->port_clock) + crtc_state->port_clock = crtc_state->hw.adjusted_mode.crtc_clock + * crtc_state->pixel_multiplier; - ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); + ret = intel_crtc_compute_config(state, crtc); if (ret == -EDEADLK) return ret; if (ret == -EAGAIN) { if (drm_WARN(&i915->drm, !retry, - "loop in pipe configuration computation\n")) + "[CRTC:%d:%s] loop in pipe configuration computation\n", + crtc->base.base.id, crtc->base.name)) return -EINVAL; - drm_dbg_kms(&i915->drm, "CRTC bw constrained, retrying\n"); + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n", + crtc->base.base.id, crtc->base.name); retry = false; goto encoder_retry; } if (ret < 0) { - drm_dbg_kms(&i915->drm, "CRTC config failure: %d\n", ret); + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n", + crtc->base.base.id, crtc->base.name, ret); return ret; } @@ -5766,21 +5305,22 @@ encoder_retry: * only enable it on 6bpc panels and when its not a compliance * test requesting 6bpc video pattern. */ - pipe_config->dither = (pipe_config->pipe_bpp == 6*3) && - !pipe_config->dither_force_disable; + crtc_state->dither = (crtc_state->pipe_bpp == 6*3) && + !crtc_state->dither_force_disable; drm_dbg_kms(&i915->drm, - "hw max bpp: %i, pipe bpp: %i, dithering: %i\n", - base_bpp, pipe_config->pipe_bpp, pipe_config->dither); + "[CRTC:%d:%s] hw max bpp: %i, pipe bpp: %i, dithering: %i\n", + crtc->base.base.id, crtc->base.name, + base_bpp, crtc_state->pipe_bpp, crtc_state->dither); return 0; } static int -intel_modeset_pipe_config_late(struct intel_crtc_state *crtc_state) +intel_modeset_pipe_config_late(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->uapi.state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_connector_state *conn_state; struct drm_connector *connector; int i; @@ -5971,7 +5511,7 @@ static bool fastboot_enabled(struct drm_i915_private *dev_priv) return false; } -static bool +bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, bool fastset) @@ -6077,6 +5617,28 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) +#define PIPE_CONF_CHECK_TIMINGS(name) do { \ + PIPE_CONF_CHECK_I(name.crtc_hdisplay); \ + PIPE_CONF_CHECK_I(name.crtc_htotal); \ + PIPE_CONF_CHECK_I(name.crtc_hblank_start); \ + PIPE_CONF_CHECK_I(name.crtc_hblank_end); \ + PIPE_CONF_CHECK_I(name.crtc_hsync_start); \ + PIPE_CONF_CHECK_I(name.crtc_hsync_end); \ + PIPE_CONF_CHECK_I(name.crtc_vdisplay); \ + PIPE_CONF_CHECK_I(name.crtc_vtotal); \ + PIPE_CONF_CHECK_I(name.crtc_vblank_start); \ + PIPE_CONF_CHECK_I(name.crtc_vblank_end); \ + PIPE_CONF_CHECK_I(name.crtc_vsync_start); \ + PIPE_CONF_CHECK_I(name.crtc_vsync_end); \ +} while (0) + +#define PIPE_CONF_CHECK_RECT(name) do { \ + PIPE_CONF_CHECK_I(name.x1); \ + PIPE_CONF_CHECK_I(name.x2); \ + PIPE_CONF_CHECK_I(name.y1); \ + PIPE_CONF_CHECK_I(name.y2); \ +} while (0) + /* This is required for BDW+ where there is only one set of registers for * switching between high and low RR. * This macro can be used whenever a comparison has to be made between one @@ -6173,7 +5735,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_QUIRK(quirk) \ ((current_config->quirks | pipe_config->quirks) & (quirk)) + PIPE_CONF_CHECK_I(hw.enable); + PIPE_CONF_CHECK_I(hw.active); + PIPE_CONF_CHECK_I(cpu_transcoder); + PIPE_CONF_CHECK_I(mst_master_transcoder); PIPE_CONF_CHECK_BOOL(has_pch_encoder); PIPE_CONF_CHECK_I(fdi_lanes); @@ -6194,33 +5760,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(framestart_delay); PIPE_CONF_CHECK_I(msa_timing_delay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); - - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); - - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); - - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); + PIPE_CONF_CHECK_TIMINGS(hw.pipe_mode); + PIPE_CONF_CHECK_TIMINGS(hw.adjusted_mode); PIPE_CONF_CHECK_I(pixel_multiplier); @@ -6264,18 +5805,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(pch_pfit.force_thru); if (!fastset) { - PIPE_CONF_CHECK_I(pipe_src.x1); - PIPE_CONF_CHECK_I(pipe_src.y1); - PIPE_CONF_CHECK_I(pipe_src.x2); - PIPE_CONF_CHECK_I(pipe_src.y2); + PIPE_CONF_CHECK_RECT(pipe_src); PIPE_CONF_CHECK_BOOL(pch_pfit.enabled); - if (current_config->pch_pfit.enabled) { - PIPE_CONF_CHECK_I(pch_pfit.dst.x1); - PIPE_CONF_CHECK_I(pch_pfit.dst.y1); - PIPE_CONF_CHECK_I(pch_pfit.dst.x2); - PIPE_CONF_CHECK_I(pch_pfit.dst.y2); - } + PIPE_CONF_CHECK_RECT(pch_pfit.dst); PIPE_CONF_CHECK_I(scaler_state.scaler_id); PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); @@ -6305,7 +5838,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); - if (dev_priv->dpll.mgr) { + if (dev_priv->display.dpll.mgr) { PIPE_CONF_CHECK_P(shared_dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll); @@ -6379,8 +5912,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(splitter.link_count); PIPE_CONF_CHECK_I(splitter.pixel_overlap); - PIPE_CONF_CHECK_I(mst_master_transcoder); - PIPE_CONF_CHECK_BOOL(vrr.enable); PIPE_CONF_CHECK_I(vrr.vmin); PIPE_CONF_CHECK_I(vrr.vmax); @@ -6396,295 +5927,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #undef PIPE_CONF_CHECK_FLAGS #undef PIPE_CONF_CHECK_CLOCK_FUZZY #undef PIPE_CONF_CHECK_COLOR_LUT +#undef PIPE_CONF_CHECK_TIMINGS +#undef PIPE_CONF_CHECK_RECT #undef PIPE_CONF_QUIRK return ret; } -static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv, - const struct intel_crtc_state *pipe_config) -{ - if (pipe_config->has_pch_encoder) { - int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), - &pipe_config->fdi_m_n); - int dotclock = pipe_config->hw.adjusted_mode.crtc_clock; - - /* - * FDI already provided one idea for the dotclock. - * Yell if the encoder disagrees. - */ - drm_WARN(&dev_priv->drm, - !intel_fuzzy_clock_check(fdi_dotclock, dotclock), - "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", - fdi_dotclock, dotclock); - } -} - -static void verify_wm_state(struct intel_crtc *crtc, - struct intel_crtc_state *new_crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct skl_hw_state { - struct skl_ddb_entry ddb[I915_MAX_PLANES]; - struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; - struct skl_pipe_wm wm; - } *hw; - const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; - int level, max_level = ilk_wm_max_level(dev_priv); - struct intel_plane *plane; - u8 hw_enabled_slices; - - if (DISPLAY_VER(dev_priv) < 9 || !new_crtc_state->hw.active) - return; - - hw = kzalloc(sizeof(*hw), GFP_KERNEL); - if (!hw) - return; - - skl_pipe_wm_get_hw_state(crtc, &hw->wm); - - skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); - - hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv); - - if (DISPLAY_VER(dev_priv) >= 11 && - hw_enabled_slices != dev_priv->dbuf.enabled_slices) - drm_err(&dev_priv->drm, - "mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n", - dev_priv->dbuf.enabled_slices, - hw_enabled_slices); - - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { - const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; - const struct skl_wm_level *hw_wm_level, *sw_wm_level; - - /* Watermarks */ - for (level = 0; level <= max_level; level++) { - hw_wm_level = &hw->wm.planes[plane->id].wm[level]; - sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level); - - if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) - continue; - - drm_err(&dev_priv->drm, - "[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, level, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } - - hw_wm_level = &hw->wm.planes[plane->id].trans_wm; - sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id); - - if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(&dev_priv->drm, - "[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } - - hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0; - sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0; - - if (HAS_HW_SAGV_WM(dev_priv) && - !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(&dev_priv->drm, - "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } - - hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm; - sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm; - - if (HAS_HW_SAGV_WM(dev_priv) && - !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(&dev_priv->drm, - "[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } - - /* DDB */ - hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; - sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; - - if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { - drm_err(&dev_priv->drm, - "[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n", - plane->base.base.id, plane->base.name, - sw_ddb_entry->start, sw_ddb_entry->end, - hw_ddb_entry->start, hw_ddb_entry->end); - } - } - - kfree(hw); -} - -static void -verify_connector_state(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct drm_connector *connector; - struct drm_connector_state *new_conn_state; - int i; - - for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) { - struct drm_encoder *encoder = connector->encoder; - struct intel_crtc_state *crtc_state = NULL; - - if (new_conn_state->crtc != &crtc->base) - continue; - - if (crtc) - crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - - intel_connector_verify_state(crtc_state, new_conn_state); - - I915_STATE_WARN(new_conn_state->best_encoder != encoder, - "connector's atomic encoder doesn't match legacy encoder\n"); - } -} - -static void -verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_state *state) -{ - struct intel_encoder *encoder; - struct drm_connector *connector; - struct drm_connector_state *old_conn_state, *new_conn_state; - int i; - - for_each_intel_encoder(&dev_priv->drm, encoder) { - bool enabled = false, found = false; - enum pipe pipe; - - drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s]\n", - encoder->base.base.id, - encoder->base.name); - - for_each_oldnew_connector_in_state(&state->base, connector, old_conn_state, - new_conn_state, i) { - if (old_conn_state->best_encoder == &encoder->base) - found = true; - - if (new_conn_state->best_encoder != &encoder->base) - continue; - found = enabled = true; - - I915_STATE_WARN(new_conn_state->crtc != - encoder->base.crtc, - "connector's crtc doesn't match encoder crtc\n"); - } - - if (!found) - continue; - - I915_STATE_WARN(!!encoder->base.crtc != enabled, - "encoder's enabled state mismatch " - "(expected %i, found %i)\n", - !!encoder->base.crtc, enabled); - - if (!encoder->base.crtc) { - bool active; - - active = encoder->get_hw_state(encoder, &pipe); - I915_STATE_WARN(active, - "encoder detached but still enabled on pipe %c.\n", - pipe_name(pipe)); - } - } -} - -static void -verify_crtc_state(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_encoder *encoder; - struct intel_crtc_state *pipe_config = old_crtc_state; - struct drm_atomic_state *state = old_crtc_state->uapi.state; - struct intel_crtc *master_crtc; - - __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); - intel_crtc_free_hw_state(old_crtc_state); - intel_crtc_state_reset(old_crtc_state, crtc); - old_crtc_state->uapi.state = state; - - drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s]\n", crtc->base.base.id, - crtc->base.name); - - pipe_config->hw.enable = new_crtc_state->hw.enable; - - intel_crtc_get_pipe_config(pipe_config); - - /* we keep both pipes enabled on 830 */ - if (IS_I830(dev_priv) && pipe_config->hw.active) - pipe_config->hw.active = new_crtc_state->hw.active; - - I915_STATE_WARN(new_crtc_state->hw.active != pipe_config->hw.active, - "crtc active state doesn't match with hw state " - "(expected %i, found %i)\n", - new_crtc_state->hw.active, pipe_config->hw.active); - - I915_STATE_WARN(crtc->active != new_crtc_state->hw.active, - "transitional active state does not match atomic hw state " - "(expected %i, found %i)\n", - new_crtc_state->hw.active, crtc->active); - - master_crtc = intel_master_crtc(new_crtc_state); - - for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) { - enum pipe pipe; - bool active; - - active = encoder->get_hw_state(encoder, &pipe); - I915_STATE_WARN(active != new_crtc_state->hw.active, - "[ENCODER:%i] active %i with crtc active %i\n", - encoder->base.base.id, active, - new_crtc_state->hw.active); - - I915_STATE_WARN(active && master_crtc->pipe != pipe, - "Encoder connected to wrong pipe %c\n", - pipe_name(pipe)); - - if (active) - intel_encoder_get_config(encoder, pipe_config); - } - - if (!new_crtc_state->hw.active) - return; - - intel_pipe_config_sanity_check(dev_priv, pipe_config); - - if (!intel_pipe_config_compare(new_crtc_state, - pipe_config, false)) { - I915_STATE_WARN(1, "pipe state doesn't match!\n"); - intel_dump_pipe_config(pipe_config, NULL, "[hw state]"); - intel_dump_pipe_config(new_crtc_state, NULL, "[sw state]"); - } -} - static void intel_verify_planes(struct intel_atomic_state *state) { @@ -6698,167 +5947,6 @@ intel_verify_planes(struct intel_atomic_state *state) plane_state->uapi.visible); } -static void -verify_single_dpll_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_crtc *crtc, - struct intel_crtc_state *new_crtc_state) -{ - struct intel_dpll_hw_state dpll_hw_state; - u8 pipe_mask; - bool active; - - memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); - - drm_dbg_kms(&dev_priv->drm, "%s\n", pll->info->name); - - active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state); - - if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) { - I915_STATE_WARN(!pll->on && pll->active_mask, - "pll in active use but not on in sw tracking\n"); - I915_STATE_WARN(pll->on && !pll->active_mask, - "pll is on but not used by any active pipe\n"); - I915_STATE_WARN(pll->on != active, - "pll on state mismatch (expected %i, found %i)\n", - pll->on, active); - } - - if (!crtc) { - I915_STATE_WARN(pll->active_mask & ~pll->state.pipe_mask, - "more active pll users than references: 0x%x vs 0x%x\n", - pll->active_mask, pll->state.pipe_mask); - - return; - } - - pipe_mask = BIT(crtc->pipe); - - if (new_crtc_state->hw.active) - I915_STATE_WARN(!(pll->active_mask & pipe_mask), - "pll active mismatch (expected pipe %c in active mask 0x%x)\n", - pipe_name(crtc->pipe), pll->active_mask); - else - I915_STATE_WARN(pll->active_mask & pipe_mask, - "pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n", - pipe_name(crtc->pipe), pll->active_mask); - - I915_STATE_WARN(!(pll->state.pipe_mask & pipe_mask), - "pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n", - pipe_mask, pll->state.pipe_mask); - - I915_STATE_WARN(pll->on && memcmp(&pll->state.hw_state, - &dpll_hw_state, - sizeof(dpll_hw_state)), - "pll hw state mismatch\n"); -} - -static void -verify_shared_dpll_state(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - if (new_crtc_state->shared_dpll) - verify_single_dpll_state(dev_priv, new_crtc_state->shared_dpll, crtc, new_crtc_state); - - if (old_crtc_state->shared_dpll && - old_crtc_state->shared_dpll != new_crtc_state->shared_dpll) { - u8 pipe_mask = BIT(crtc->pipe); - struct intel_shared_dpll *pll = old_crtc_state->shared_dpll; - - I915_STATE_WARN(pll->active_mask & pipe_mask, - "pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n", - pipe_name(crtc->pipe), pll->active_mask); - I915_STATE_WARN(pll->state.pipe_mask & pipe_mask, - "pll enabled crtcs mismatch (found %x in enabled mask (0x%x))\n", - pipe_name(crtc->pipe), pll->state.pipe_mask); - } -} - -static void -verify_mpllb_state(struct intel_atomic_state *state, - struct intel_crtc_state *new_crtc_state) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - struct intel_mpllb_state mpllb_hw_state = { 0 }; - struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state; - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_encoder *encoder; - - if (!IS_DG2(i915)) - return; - - if (!new_crtc_state->hw.active) - return; - - encoder = intel_get_crtc_new_encoder(state, new_crtc_state); - intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state); - -#define MPLLB_CHECK(name) do { \ - if (mpllb_sw_state->name != mpllb_hw_state.name) { \ - pipe_config_mismatch(false, crtc, "MPLLB:" __stringify(name), \ - "(expected 0x%08x, found 0x%08x)", \ - mpllb_sw_state->name, \ - mpllb_hw_state.name); \ - } \ -} while (0) - - MPLLB_CHECK(mpllb_cp); - MPLLB_CHECK(mpllb_div); - MPLLB_CHECK(mpllb_div2); - MPLLB_CHECK(mpllb_fracn1); - MPLLB_CHECK(mpllb_fracn2); - MPLLB_CHECK(mpllb_sscen); - MPLLB_CHECK(mpllb_sscstep); - - /* - * ref_control is handled by the hardware/firemware and never - * programmed by the software, but the proper values are supplied - * in the bspec for verification purposes. - */ - MPLLB_CHECK(ref_control); - -#undef MPLLB_CHECK -} - -static void -intel_modeset_verify_crtc(struct intel_crtc *crtc, - struct intel_atomic_state *state, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) -{ - if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe) - return; - - verify_wm_state(crtc, new_crtc_state); - verify_connector_state(state, crtc); - verify_crtc_state(crtc, old_crtc_state, new_crtc_state); - verify_shared_dpll_state(crtc, old_crtc_state, new_crtc_state); - verify_mpllb_state(state, new_crtc_state); -} - -static void -verify_disabled_dpll_state(struct drm_i915_private *dev_priv) -{ - int i; - - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) - verify_single_dpll_state(dev_priv, - &dev_priv->dpll.shared_dplls[i], - NULL, NULL); -} - -static void -intel_modeset_verify_disabled(struct drm_i915_private *dev_priv, - struct intel_atomic_state *state) -{ - verify_encoder_state(dev_priv, state); - verify_connector_state(state, NULL); - verify_disabled_dpll_state(dev_priv); -} - int intel_modeset_all_pipes(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); @@ -6897,8 +5985,7 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state) return 0; } -static void -intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) +void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -7733,7 +6820,7 @@ static int intel_atomic_check(struct drm_device *dev, if (!new_crtc_state->hw.enable) continue; - ret = intel_modeset_pipe_config(state, new_crtc_state); + ret = intel_modeset_pipe_config(state, crtc); if (ret) goto fail; @@ -7747,7 +6834,7 @@ static int intel_atomic_check(struct drm_device *dev, if (!intel_crtc_needs_modeset(new_crtc_state)) continue; - ret = intel_modeset_pipe_config_late(new_crtc_state); + ret = intel_modeset_pipe_config_late(state, crtc); if (ret) goto fail; @@ -7871,9 +6958,9 @@ static int intel_atomic_check(struct drm_device *dev, !new_crtc_state->update_pipe) continue; - intel_dump_pipe_config(new_crtc_state, state, - intel_crtc_needs_modeset(new_crtc_state) ? - "[modeset]" : "[fastset]"); + intel_crtc_state_dump(new_crtc_state, state, + intel_crtc_needs_modeset(new_crtc_state) ? + "modeset" : "fastset"); } return 0; @@ -7888,7 +6975,7 @@ static int intel_atomic_check(struct drm_device *dev, */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) - intel_dump_pipe_config(new_crtc_state, state, "[failed]"); + intel_crtc_state_dump(new_crtc_state, state, "failed"); return ret; } @@ -8031,7 +7118,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state, intel_crtc_update_active_timings(new_crtc_state); - dev_priv->display->crtc_enable(state, crtc); + dev_priv->display.funcs.display->crtc_enable(state, crtc); if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) return; @@ -8110,7 +7197,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, */ intel_crtc_disable_pipe_crc(crtc); - dev_priv->display->crtc_disable(state, crtc); + dev_priv->display.funcs.display->crtc_disable(state, crtc); crtc->active = false; intel_fbc_disable(crtc); intel_disable_shared_dpll(old_crtc_state); @@ -8442,6 +7529,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_atomic_commit_fence_wait(state); drm_atomic_helper_wait_for_dependencies(&state->base); + drm_dp_mst_atomic_wait_for_dependencies(&state->base); if (state->modeset) wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); @@ -8452,7 +7540,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) new_crtc_state, i) { if (intel_crtc_needs_modeset(new_crtc_state) || new_crtc_state->update_pipe) { - modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]); + intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]); } } @@ -8498,7 +7586,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ - dev_priv->display->commit_modeset_enables(state); + dev_priv->display.funcs.display->commit_modeset_enables(state); intel_encoders_update_complete(state); @@ -8552,7 +7640,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { intel_post_plane_update(state, crtc); - modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]); + intel_modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]); intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); @@ -9229,7 +8317,7 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { .atomic_state_free = intel_atomic_state_free, }; -static const struct drm_i915_display_funcs skl_display_funcs = { +static const struct intel_display_funcs skl_display_funcs = { .get_pipe_config = hsw_get_pipe_config, .crtc_enable = hsw_crtc_enable, .crtc_disable = hsw_crtc_disable, @@ -9237,7 +8325,7 @@ static const struct drm_i915_display_funcs skl_display_funcs = { .get_initial_plane_config = skl_get_initial_plane_config, }; -static const struct drm_i915_display_funcs ddi_display_funcs = { +static const struct intel_display_funcs ddi_display_funcs = { .get_pipe_config = hsw_get_pipe_config, .crtc_enable = hsw_crtc_enable, .crtc_disable = hsw_crtc_disable, @@ -9245,7 +8333,7 @@ static const struct drm_i915_display_funcs ddi_display_funcs = { .get_initial_plane_config = i9xx_get_initial_plane_config, }; -static const struct drm_i915_display_funcs pch_split_display_funcs = { +static const struct intel_display_funcs pch_split_display_funcs = { .get_pipe_config = ilk_get_pipe_config, .crtc_enable = ilk_crtc_enable, .crtc_disable = ilk_crtc_disable, @@ -9253,7 +8341,7 @@ static const struct drm_i915_display_funcs pch_split_display_funcs = { .get_initial_plane_config = i9xx_get_initial_plane_config, }; -static const struct drm_i915_display_funcs vlv_display_funcs = { +static const struct intel_display_funcs vlv_display_funcs = { .get_pipe_config = i9xx_get_pipe_config, .crtc_enable = valleyview_crtc_enable, .crtc_disable = i9xx_crtc_disable, @@ -9261,7 +8349,7 @@ static const struct drm_i915_display_funcs vlv_display_funcs = { .get_initial_plane_config = i9xx_get_initial_plane_config, }; -static const struct drm_i915_display_funcs i9xx_display_funcs = { +static const struct intel_display_funcs i9xx_display_funcs = { .get_pipe_config = i9xx_get_pipe_config, .crtc_enable = i9xx_crtc_enable, .crtc_disable = i9xx_crtc_disable, @@ -9284,16 +8372,16 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) intel_dpll_init_clock_hook(dev_priv); if (DISPLAY_VER(dev_priv) >= 9) { - dev_priv->display = &skl_display_funcs; + dev_priv->display.funcs.display = &skl_display_funcs; } else if (HAS_DDI(dev_priv)) { - dev_priv->display = &ddi_display_funcs; + dev_priv->display.funcs.display = &ddi_display_funcs; } else if (HAS_PCH_SPLIT(dev_priv)) { - dev_priv->display = &pch_split_display_funcs; + dev_priv->display.funcs.display = &pch_split_display_funcs; } else if (IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv)) { - dev_priv->display = &vlv_display_funcs; + dev_priv->display.funcs.display = &vlv_display_funcs; } else { - dev_priv->display = &i9xx_display_funcs; + dev_priv->display.funcs.display = &i9xx_display_funcs; } intel_fdi_init_hook(dev_priv); @@ -9366,7 +8454,7 @@ static void sanitize_watermarks(struct drm_i915_private *dev_priv) int i; /* Only supported on platforms that use atomic watermark design */ - if (!dev_priv->wm_disp->optimize_watermarks) + if (!dev_priv->display.funcs.wm->optimize_watermarks) return; state = drm_atomic_state_alloc(&dev_priv->drm); @@ -9510,6 +8598,10 @@ out: return ret; } +static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = { + .atomic_commit_setup = drm_dp_mst_atomic_setup_commit, +}; + static void intel_mode_config_init(struct drm_i915_private *i915) { struct drm_mode_config *mode_config = &i915->drm.mode_config; @@ -9524,6 +8616,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915) mode_config->prefer_shadow = 1; mode_config->funcs = &intel_mode_funcs; + mode_config->helper_private = &intel_mode_config_funcs; mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); @@ -9597,8 +8690,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI | WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); - i915->window2_delay = 0; /* No DSB so no window2 delay */ - intel_mode_config_init(i915); ret = intel_cdclk_init(i915); @@ -9689,7 +8780,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) intel_setup_outputs(i915); drm_modeset_lock_all(dev); - intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx); + intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx); intel_acpi_assign_connector_fwnodes(i915); drm_modeset_unlock_all(dev); @@ -9842,580 +8933,17 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) intel_de_posting_read(dev_priv, DPLL(pipe)); } -static void -intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv) -{ - struct intel_crtc *crtc; - - if (DISPLAY_VER(dev_priv) >= 4) - return; - - for_each_intel_crtc(&dev_priv->drm, crtc) { - struct intel_plane *plane = - to_intel_plane(crtc->base.primary); - struct intel_crtc *plane_crtc; - enum pipe pipe; - - if (!plane->get_hw_state(plane, &pipe)) - continue; - - if (pipe == crtc->pipe) - continue; - - drm_dbg_kms(&dev_priv->drm, - "[PLANE:%d:%s] attached to the wrong pipe, disabling plane\n", - plane->base.base.id, plane->base.name); - - plane_crtc = intel_crtc_for_pipe(dev_priv, pipe); - intel_plane_disable_noatomic(plane_crtc, plane); - } -} - -static bool intel_crtc_has_encoders(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct intel_encoder *encoder; - - for_each_encoder_on_crtc(dev, &crtc->base, encoder) - return true; - - return false; -} - -static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) -{ - struct drm_device *dev = encoder->base.dev; - struct intel_connector *connector; - - for_each_connector_on_encoder(dev, &encoder->base, connector) - return connector; - - return NULL; -} - -static void intel_sanitize_crtc(struct intel_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - - if (crtc_state->hw.active) { - struct intel_plane *plane; - - /* Disable everything but the primary plane */ - for_each_intel_plane_on_crtc(dev, crtc, plane) { - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - - if (plane_state->uapi.visible && - plane->base.type != DRM_PLANE_TYPE_PRIMARY) - intel_plane_disable_noatomic(crtc, plane); - } - - /* Disable any background color/etc. set by the BIOS */ - intel_color_commit_noarm(crtc_state); - intel_color_commit_arm(crtc_state); - } - - /* Adjust the state of the output pipe according to whether we - * have active connectors/encoders. */ - if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) && - !intel_crtc_is_bigjoiner_slave(crtc_state)) - intel_crtc_disable_noatomic(crtc, ctx); - - if (crtc_state->hw.active || HAS_GMCH(dev_priv)) { - /* - * We start out with underrun reporting disabled to avoid races. - * For correct bookkeeping mark this on active crtcs. - * - * Also on gmch platforms we dont have any hardware bits to - * disable the underrun reporting. Which means we need to start - * out with underrun reporting disabled also on inactive pipes, - * since otherwise we'll complain about the garbage we read when - * e.g. coming up after runtime pm. - * - * No protection against concurrent access is required - at - * worst a fifo underrun happens which also sets this to false. - */ - crtc->cpu_fifo_underrun_disabled = true; - /* - * We track the PCH trancoder underrun reporting state - * within the crtc. With crtc for pipe A housing the underrun - * reporting state for PCH transcoder A, crtc for pipe B housing - * it for PCH transcoder B, etc. LPT-H has only PCH transcoder A, - * and marking underrun reporting as disabled for the non-existing - * PCH transcoders B and C would prevent enabling the south - * error interrupt (see cpt_can_enable_serr_int()). - */ - if (intel_has_pch_trancoder(dev_priv, crtc->pipe)) - crtc->pch_fifo_underrun_disabled = true; - } -} - -static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - - /* - * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram - * the hardware when a high res displays plugged in. DPLL P - * divider is zero, and the pipe timings are bonkers. We'll - * try to disable everything in that case. - * - * FIXME would be nice to be able to sanitize this state - * without several WARNs, but for now let's take the easy - * road. - */ - return IS_SANDYBRIDGE(dev_priv) && - crtc_state->hw.active && - crtc_state->shared_dpll && - crtc_state->port_clock == 0; -} - -static void intel_sanitize_encoder(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_connector *connector; - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - struct intel_crtc_state *crtc_state = crtc ? - to_intel_crtc_state(crtc->base.state) : NULL; - - /* We need to check both for a crtc link (meaning that the - * encoder is active and trying to read from a pipe) and the - * pipe itself being active. */ - bool has_active_crtc = crtc_state && - crtc_state->hw.active; - - if (crtc_state && has_bogus_dpll_config(crtc_state)) { - drm_dbg_kms(&dev_priv->drm, - "BIOS has misprogrammed the hardware. Disabling pipe %c\n", - pipe_name(crtc->pipe)); - has_active_crtc = false; - } - - connector = intel_encoder_find_connector(encoder); - if (connector && !has_active_crtc) { - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] has active connectors but no active pipe!\n", - encoder->base.base.id, - encoder->base.name); - - /* Connector is active, but has no active pipe. This is - * fallout from our resume register restoring. Disable - * the encoder manually again. */ - if (crtc_state) { - struct drm_encoder *best_encoder; - - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] manually disabled\n", - encoder->base.base.id, - encoder->base.name); - - /* avoid oopsing in case the hooks consult best_encoder */ - best_encoder = connector->base.state->best_encoder; - connector->base.state->best_encoder = &encoder->base; - - /* FIXME NULL atomic state passed! */ - if (encoder->disable) - encoder->disable(NULL, encoder, crtc_state, - connector->base.state); - if (encoder->post_disable) - encoder->post_disable(NULL, encoder, crtc_state, - connector->base.state); - - connector->base.state->best_encoder = best_encoder; - } - encoder->base.crtc = NULL; - - /* Inconsistent output/port/pipe state happens presumably due to - * a bug in one of the get_hw_state functions. Or someplace else - * in our code, like the register restore mess on resume. Clamp - * things to off as a safer default. */ - - connector->base.dpms = DRM_MODE_DPMS_OFF; - connector->base.encoder = NULL; - } - - /* notify opregion of the sanitized encoder state */ - intel_opregion_notify_encoder(encoder, connector && has_active_crtc); - - if (HAS_DDI(dev_priv)) - intel_ddi_sanitize_encoder_pll_mapping(encoder); -} - -/* FIXME read out full plane state for all planes */ -static void readout_plane_state(struct drm_i915_private *dev_priv) -{ - struct intel_plane *plane; - struct intel_crtc *crtc; - - for_each_intel_plane(&dev_priv->drm, plane) { - struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - struct intel_crtc_state *crtc_state; - enum pipe pipe = PIPE_A; - bool visible; - - visible = plane->get_hw_state(plane, &pipe); - - crtc = intel_crtc_for_pipe(dev_priv, pipe); - crtc_state = to_intel_crtc_state(crtc->base.state); - - intel_set_plane_visible(crtc_state, plane_state, visible); - - drm_dbg_kms(&dev_priv->drm, - "[PLANE:%d:%s] hw state readout: %s, pipe %c\n", - plane->base.base.id, plane->base.name, - str_enabled_disabled(visible), pipe_name(pipe)); - } - - for_each_intel_crtc(&dev_priv->drm, crtc) { - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - fixup_plane_bitmasks(crtc_state); - } -} - -static void intel_modeset_readout_hw_state(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_cdclk_state *cdclk_state = - to_intel_cdclk_state(dev_priv->cdclk.obj.state); - struct intel_dbuf_state *dbuf_state = - to_intel_dbuf_state(dev_priv->dbuf.obj.state); - enum pipe pipe; - struct intel_crtc *crtc; - struct intel_encoder *encoder; - struct intel_connector *connector; - struct drm_connector_list_iter conn_iter; - u8 active_pipes = 0; - - for_each_intel_crtc(dev, crtc) { - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); - intel_crtc_free_hw_state(crtc_state); - intel_crtc_state_reset(crtc_state, crtc); - - intel_crtc_get_pipe_config(crtc_state); - - crtc_state->hw.enable = crtc_state->hw.active; - - crtc->base.enabled = crtc_state->hw.enable; - crtc->active = crtc_state->hw.active; - - if (crtc_state->hw.active) - active_pipes |= BIT(crtc->pipe); - - drm_dbg_kms(&dev_priv->drm, - "[CRTC:%d:%s] hw state readout: %s\n", - crtc->base.base.id, crtc->base.name, - str_enabled_disabled(crtc_state->hw.active)); - } - - cdclk_state->active_pipes = dbuf_state->active_pipes = active_pipes; - - readout_plane_state(dev_priv); - - for_each_intel_encoder(dev, encoder) { - struct intel_crtc_state *crtc_state = NULL; - - pipe = 0; - - if (encoder->get_hw_state(encoder, &pipe)) { - crtc = intel_crtc_for_pipe(dev_priv, pipe); - crtc_state = to_intel_crtc_state(crtc->base.state); - - encoder->base.crtc = &crtc->base; - intel_encoder_get_config(encoder, crtc_state); - - /* read out to slave crtc as well for bigjoiner */ - if (crtc_state->bigjoiner_pipes) { - struct intel_crtc *slave_crtc; - - /* encoder should read be linked to bigjoiner master */ - WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); - - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(crtc_state)) { - struct intel_crtc_state *slave_crtc_state; - - slave_crtc_state = to_intel_crtc_state(slave_crtc->base.state); - intel_encoder_get_config(encoder, slave_crtc_state); - } - } - } else { - encoder->base.crtc = NULL; - } - - if (encoder->sync_state) - encoder->sync_state(encoder, crtc_state); - - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", - encoder->base.base.id, encoder->base.name, - str_enabled_disabled(encoder->base.crtc), - pipe_name(pipe)); - } - - intel_dpll_readout_hw_state(dev_priv); - - drm_connector_list_iter_begin(dev, &conn_iter); - for_each_intel_connector_iter(connector, &conn_iter) { - if (connector->get_hw_state(connector)) { - struct intel_crtc_state *crtc_state; - struct intel_crtc *crtc; - - connector->base.dpms = DRM_MODE_DPMS_ON; - - encoder = intel_attached_encoder(connector); - connector->base.encoder = &encoder->base; - - crtc = to_intel_crtc(encoder->base.crtc); - crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL; - - if (crtc_state && crtc_state->hw.active) { - /* - * This has to be done during hardware readout - * because anything calling .crtc_disable may - * rely on the connector_mask being accurate. - */ - crtc_state->uapi.connector_mask |= - drm_connector_mask(&connector->base); - crtc_state->uapi.encoder_mask |= - drm_encoder_mask(&encoder->base); - } - } else { - connector->base.dpms = DRM_MODE_DPMS_OFF; - connector->base.encoder = NULL; - } - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] hw state readout: %s\n", - connector->base.base.id, connector->base.name, - str_enabled_disabled(connector->base.encoder)); - } - drm_connector_list_iter_end(&conn_iter); - - for_each_intel_crtc(dev, crtc) { - struct intel_bw_state *bw_state = - to_intel_bw_state(dev_priv->bw_obj.state); - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - struct intel_plane *plane; - int min_cdclk = 0; - - if (crtc_state->hw.active) { - /* - * The initial mode needs to be set in order to keep - * the atomic core happy. It wants a valid mode if the - * crtc's enabled, so we do the above call. - * - * But we don't set all the derived state fully, hence - * set a flag to indicate that a full recalculation is - * needed on the next commit. - */ - crtc_state->inherited = true; - - intel_crtc_update_active_timings(crtc_state); - - intel_crtc_copy_hw_to_uapi_state(crtc_state); - } - - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - - /* - * FIXME don't have the fb yet, so can't - * use intel_plane_data_rate() :( - */ - if (plane_state->uapi.visible) - crtc_state->data_rate[plane->id] = - 4 * crtc_state->pixel_rate; - /* - * FIXME don't have the fb yet, so can't - * use plane->min_cdclk() :( - */ - if (plane_state->uapi.visible && plane->min_cdclk) { - if (crtc_state->double_wide || DISPLAY_VER(dev_priv) >= 10) - crtc_state->min_cdclk[plane->id] = - DIV_ROUND_UP(crtc_state->pixel_rate, 2); - else - crtc_state->min_cdclk[plane->id] = - crtc_state->pixel_rate; - } - drm_dbg_kms(&dev_priv->drm, - "[PLANE:%d:%s] min_cdclk %d kHz\n", - plane->base.base.id, plane->base.name, - crtc_state->min_cdclk[plane->id]); - } - - if (crtc_state->hw.active) { - min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); - if (drm_WARN_ON(dev, min_cdclk < 0)) - min_cdclk = 0; - } - - cdclk_state->min_cdclk[crtc->pipe] = min_cdclk; - cdclk_state->min_voltage_level[crtc->pipe] = - crtc_state->min_voltage_level; - - intel_bw_crtc_update(bw_state, crtc_state); - - intel_pipe_config_sanity_check(dev_priv, crtc_state); - } -} - -static void -get_encoder_power_domains(struct drm_i915_private *dev_priv) -{ - struct intel_encoder *encoder; - - for_each_intel_encoder(&dev_priv->drm, encoder) { - struct intel_crtc_state *crtc_state; - - if (!encoder->get_power_domains) - continue; - - /* - * MST-primary and inactive encoders don't have a crtc state - * and neither of these require any power domain references. - */ - if (!encoder->base.crtc) - continue; - - crtc_state = to_intel_crtc_state(encoder->base.crtc->state); - encoder->get_power_domains(encoder, crtc_state); - } -} - -static void intel_early_display_was(struct drm_i915_private *dev_priv) -{ - /* - * Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl - * Also known as Wa_14010480278. - */ - if (IS_DISPLAY_VER(dev_priv, 10, 12)) - intel_de_write(dev_priv, GEN9_CLKGATE_DIS_0, - intel_de_read(dev_priv, GEN9_CLKGATE_DIS_0) | DARBF_GATING_DIS); - - if (IS_HASWELL(dev_priv)) { - /* - * WaRsPkgCStateDisplayPMReq:hsw - * System hang if this isn't done before disabling all planes! - */ - intel_de_write(dev_priv, CHICKEN_PAR1_1, - intel_de_read(dev_priv, CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); - } - - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv)) { - /* Display WA #1142:kbl,cfl,cml */ - intel_de_rmw(dev_priv, CHICKEN_PAR1_1, - KBL_ARB_FILL_SPARE_22, KBL_ARB_FILL_SPARE_22); - intel_de_rmw(dev_priv, CHICKEN_MISC_2, - KBL_ARB_FILL_SPARE_13 | KBL_ARB_FILL_SPARE_14, - KBL_ARB_FILL_SPARE_14); - } -} - - -/* Scan out the current hw modeset state, - * and sanitizes it to the current state - */ -static void -intel_modeset_setup_hw_state(struct drm_device *dev, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_encoder *encoder; - struct intel_crtc *crtc; - intel_wakeref_t wakeref; - - wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); - - intel_early_display_was(dev_priv); - intel_modeset_readout_hw_state(dev); - - /* HW state is read out, now we need to sanitize this mess. */ - get_encoder_power_domains(dev_priv); - - intel_pch_sanitize(dev_priv); - - /* - * intel_sanitize_plane_mapping() may need to do vblank - * waits, so we need vblank interrupts restored beforehand. - */ - for_each_intel_crtc(&dev_priv->drm, crtc) { - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - drm_crtc_vblank_reset(&crtc->base); - - if (crtc_state->hw.active) - intel_crtc_vblank_on(crtc_state); - } - - intel_fbc_sanitize(dev_priv); - - intel_sanitize_plane_mapping(dev_priv); - - for_each_intel_encoder(dev, encoder) - intel_sanitize_encoder(encoder); - - for_each_intel_crtc(&dev_priv->drm, crtc) { - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - intel_sanitize_crtc(crtc, ctx); - intel_dump_pipe_config(crtc_state, NULL, "[setup_hw_state]"); - } - - intel_modeset_update_connector_atomic_state(dev); - - intel_dpll_sanitize_state(dev_priv); - - if (IS_G4X(dev_priv)) { - g4x_wm_get_hw_state(dev_priv); - g4x_wm_sanitize(dev_priv); - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - vlv_wm_get_hw_state(dev_priv); - vlv_wm_sanitize(dev_priv); - } else if (DISPLAY_VER(dev_priv) >= 9) { - skl_wm_get_hw_state(dev_priv); - skl_wm_sanitize(dev_priv); - } else if (HAS_PCH_SPLIT(dev_priv)) { - ilk_wm_get_hw_state(dev_priv); - } - - for_each_intel_crtc(dev, crtc) { - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - struct intel_power_domain_mask put_domains; - - modeset_get_crtc_power_domains(crtc_state, &put_domains); - if (drm_WARN_ON(dev, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM))) - modeset_put_crtc_power_domains(crtc, &put_domains); - } - - intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); - - intel_power_domains_sanitize_state(dev_priv); -} - void intel_display_resume(struct drm_device *dev) { - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = dev_priv->modeset_restore_state; + struct drm_i915_private *i915 = to_i915(dev); + struct drm_atomic_state *state = i915->modeset_restore_state; struct drm_modeset_acquire_ctx ctx; int ret; - if (!HAS_DISPLAY(dev_priv)) + if (!HAS_DISPLAY(i915)) return; - dev_priv->modeset_restore_state = NULL; + i915->modeset_restore_state = NULL; if (state) state->acquire_ctx = &ctx; @@ -10430,14 +8958,14 @@ void intel_display_resume(struct drm_device *dev) } if (!ret) - ret = __intel_display_resume(dev, state, &ctx); + ret = __intel_display_resume(i915, state, &ctx); - intel_enable_ipc(dev_priv); + intel_enable_ipc(i915); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); if (ret) - drm_err(&dev_priv->drm, + drm_err(&i915->drm, "Restoring old state failed with %i\n", ret); if (state) drm_atomic_state_put(state); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index e1daa7df3e58..e322011877bb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -56,6 +56,7 @@ struct intel_initial_plane_config; struct intel_load_detect_pipe; struct intel_plane; struct intel_plane_state; +struct intel_power_domain_mask; struct intel_remapped_info; struct intel_rotation_info; struct pci_dev; @@ -192,7 +193,7 @@ enum plane_id { #define for_each_dbuf_slice(__dev_priv, __slice) \ for ((__slice) = DBUF_S1; (__slice) < I915_MAX_DBUF_SLICES; (__slice)++) \ - for_each_if(INTEL_INFO(__dev_priv)->dbuf.slice_mask & BIT(__slice)) + for_each_if(INTEL_INFO(__dev_priv)->display.dbuf.slice_mask & BIT(__slice)) #define for_each_dbuf_slice_in_mask(__dev_priv, __slice, __mask) \ for_each_dbuf_slice((__dev_priv), (__slice)) \ @@ -374,7 +375,7 @@ enum hpd_pin { #define for_each_pipe(__dev_priv, __p) \ for ((__p) = 0; (__p) < I915_MAX_PIPES; (__p)++) \ - for_each_if(INTEL_INFO(__dev_priv)->display.pipe_mask & BIT(__p)) + for_each_if(RUNTIME_INFO(__dev_priv)->pipe_mask & BIT(__p)) #define for_each_pipe_masked(__dev_priv, __p, __mask) \ for_each_pipe(__dev_priv, __p) \ @@ -382,7 +383,7 @@ enum hpd_pin { #define for_each_cpu_transcoder(__dev_priv, __t) \ for ((__t) = 0; (__t) < I915_MAX_TRANSCODERS; (__t)++) \ - for_each_if (INTEL_INFO(__dev_priv)->display.cpu_transcoder_mask & BIT(__t)) + for_each_if (RUNTIME_INFO(__dev_priv)->cpu_transcoder_mask & BIT(__t)) #define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \ for_each_cpu_transcoder(__dev_priv, __t) \ @@ -559,8 +560,15 @@ bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state); bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state); u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state); struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state); +bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state); +bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, + const struct intel_crtc_state *pipe_config, + bool fastset); +void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state); void intel_plane_destroy(struct drm_plane *plane); +void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state); +void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state); void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state); void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); @@ -583,6 +591,8 @@ int intel_display_suspend(struct drm_device *dev); void intel_encoder_destroy(struct drm_encoder *encoder); struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder); +void intel_encoder_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy); bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy); bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy); @@ -635,6 +645,7 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc, void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); +int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config); enum intel_display_power_domain intel_port_to_power_domain(struct intel_digital_port *dig_port); enum intel_display_power_domain intel_aux_power_domain(struct intel_digital_port *dig_port); @@ -652,10 +663,16 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state); void intel_plane_disable_noatomic(struct intel_crtc *crtc, struct intel_plane *plane); +void intel_set_plane_visible(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state, + bool visible); +void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state); void intel_display_driver_register(struct drm_i915_private *i915); void intel_display_driver_unregister(struct drm_i915_private *i915); +void intel_update_watermarks(struct drm_i915_private *i915); + /* modesetting */ bool intel_modeset_probe_defer(struct pci_dev *pdev); void intel_modeset_init_hw(struct drm_i915_private *i915); @@ -667,6 +684,10 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915); void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915); void intel_display_resume(struct drm_device *dev); int intel_modeset_all_pipes(struct intel_atomic_state *state); +void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, + struct intel_power_domain_mask *old_domains); +void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc, + struct intel_power_domain_mask *domains); /* modesetting asserts */ void assert_transcoder(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h new file mode 100644 index 000000000000..fbe329e90c1e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DISPLAY_CORE_H__ +#define __INTEL_DISPLAY_CORE_H__ + +#include <linux/mutex.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/workqueue.h> + +#include "intel_display.h" +#include "intel_dmc.h" +#include "intel_dpll_mgr.h" +#include "intel_gmbus.h" +#include "intel_pm_types.h" + +struct drm_i915_private; +struct i915_audio_component; +struct intel_atomic_state; +struct intel_audio_funcs; +struct intel_cdclk_funcs; +struct intel_color_funcs; +struct intel_crtc; +struct intel_crtc_state; +struct intel_dpll_funcs; +struct intel_dpll_mgr; +struct intel_fbdev; +struct intel_fdi_funcs; +struct intel_hotplug_funcs; +struct intel_initial_plane_config; +struct intel_overlay; + +struct intel_display_funcs { + /* + * Returns the active state of the crtc, and if the crtc is active, + * fills out the pipe-config with the hw state. + */ + bool (*get_pipe_config)(struct intel_crtc *, + struct intel_crtc_state *); + void (*get_initial_plane_config)(struct intel_crtc *, + struct intel_initial_plane_config *); + void (*crtc_enable)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*crtc_disable)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*commit_modeset_enables)(struct intel_atomic_state *state); +}; + +/* functions used for watermark calcs for display. */ +struct intel_wm_funcs { + /* update_wm is for legacy wm management */ + void (*update_wm)(struct drm_i915_private *dev_priv); + int (*compute_pipe_wm)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + int (*compute_intermediate_wm)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*initial_watermarks)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*atomic_update_watermarks)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*optimize_watermarks)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + int (*compute_global_watermarks)(struct intel_atomic_state *state); +}; + +struct intel_audio { + /* hda/i915 audio component */ + struct i915_audio_component *component; + bool component_registered; + /* mutex for audio/video sync */ + struct mutex mutex; + int power_refcount; + u32 freq_cntrl; + + /* Used to save the pipe-to-encoder mapping for audio */ + struct intel_encoder *encoder_map[I915_MAX_PIPES]; + + /* necessary resource sharing with HDMI LPE audio driver. */ + struct { + struct platform_device *platdev; + int irq; + } lpe; +}; + +/* + * dpll and cdclk state is protected by connection_mutex dpll.lock serializes + * intel_{prepare,enable,disable}_shared_dpll. Must be global rather than per + * dpll, because on some platforms plls share registers. + */ +struct intel_dpll { + struct mutex lock; + + int num_shared_dpll; + struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; + const struct intel_dpll_mgr *mgr; + + struct { + int nssc; + int ssc; + } ref_clks; +}; + +struct intel_hotplug { + struct delayed_work hotplug_work; + + const u32 *hpd, *pch_hpd; + + struct { + unsigned long last_jiffies; + int count; + enum { + HPD_ENABLED = 0, + HPD_DISABLED = 1, + HPD_MARK_DISABLED = 2 + } state; + } stats[HPD_NUM_PINS]; + u32 event_bits; + u32 retry_bits; + struct delayed_work reenable_work; + + u32 long_port_mask; + u32 short_port_mask; + struct work_struct dig_port_work; + + struct work_struct poll_init_work; + bool poll_enabled; + + unsigned int hpd_storm_threshold; + /* Whether or not to count short HPD IRQs in HPD storms */ + u8 hpd_short_storm_enabled; + + /* + * if we get a HPD irq from DP and a HPD irq from non-DP + * the non-DP HPD could block the workqueue on a mode config + * mutex getting, that userspace may have taken. However + * userspace is waiting on the DP workqueue to run which is + * blocked behind the non-DP one. + */ + struct workqueue_struct *dp_wq; +}; + +struct intel_wm { + /* + * Raw watermark latency values: + * in 0.1us units for WM0, + * in 0.5us units for WM1+. + */ + /* primary */ + u16 pri_latency[5]; + /* sprite */ + u16 spr_latency[5]; + /* cursor */ + u16 cur_latency[5]; + /* + * Raw watermark memory latency values + * for SKL for all 8 levels + * in 1us units. + */ + u16 skl_latency[8]; + + /* current hardware state */ + union { + struct ilk_wm_values hw; + struct vlv_wm_values vlv; + struct g4x_wm_values g4x; + }; + + u8 max_level; + + /* + * Should be held around atomic WM register writing; also + * protects * intel_crtc->wm.active and + * crtc_state->wm.need_postvbl_update. + */ + struct mutex wm_mutex; +}; + +struct intel_display { + /* Display functions */ + struct { + /* Top level crtc-ish functions */ + const struct intel_display_funcs *display; + + /* Display CDCLK functions */ + const struct intel_cdclk_funcs *cdclk; + + /* Display pll funcs */ + const struct intel_dpll_funcs *dpll; + + /* irq display functions */ + const struct intel_hotplug_funcs *hotplug; + + /* pm display functions */ + const struct intel_wm_funcs *wm; + + /* fdi display functions */ + const struct intel_fdi_funcs *fdi; + + /* Display internal color functions */ + const struct intel_color_funcs *color; + + /* Display internal audio functions */ + const struct intel_audio_funcs *audio; + } funcs; + + /* Grouping using anonymous structs. Keep sorted. */ + struct { + /* list of fbdev register on this device */ + struct intel_fbdev *fbdev; + struct work_struct suspend_work; + } fbdev; + + struct { + /* + * Base address of where the gmbus and gpio blocks are located + * (either on PCH or on SoC for platforms without PCH). + */ + u32 mmio_base; + + /* + * gmbus.mutex protects against concurrent usage of the single + * hw gmbus controller on different i2c buses. + */ + struct mutex mutex; + + struct intel_gmbus *bus[GMBUS_NUM_PINS]; + + wait_queue_head_t wait_queue; + } gmbus; + + struct { + u32 mmio_base; + + /* protects panel power sequencer state */ + struct mutex mutex; + } pps; + + struct { + enum { + I915_SAGV_UNKNOWN = 0, + I915_SAGV_DISABLED, + I915_SAGV_ENABLED, + I915_SAGV_NOT_CONTROLLED + } status; + + u32 block_time_us; + } sagv; + + /* Grouping using named structs. Keep sorted. */ + struct intel_audio audio; + struct intel_dmc dmc; + struct intel_dpll dpll; + struct intel_hotplug hotplug; + struct intel_overlay *overlay; + struct intel_wm wm; +}; + +#endif /* __INTEL_DISPLAY_CORE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 452d773fd4e3..13c855b59f7d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -129,7 +129,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) struct drm_framebuffer *drm_fb; #ifdef CONFIG_DRM_FBDEV_EMULATION - fbdev_fb = intel_fbdev_framebuffer(dev_priv->fbdev); + fbdev_fb = intel_fbdev_framebuffer(dev_priv->display.fbdev.fbdev); if (fbdev_fb) { seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", fbdev_fb->base.width, @@ -590,6 +590,8 @@ static void intel_connector_info(struct seq_file *m, seq_puts(m, "\tHDCP version: "); intel_hdcp_info(m, intel_connector); + seq_printf(m, "\tmax bpc: %u\n", connector->display_info.bpc); + intel_panel_info(m, intel_connector); seq_printf(m, "\tmodes:\n"); @@ -720,10 +722,11 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc) /* Not all platformas have a scaler */ if (num_scalers) { - seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d", + seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d", num_scalers, crtc_state->scaler_state.scaler_users, - crtc_state->scaler_state.scaler_id); + crtc_state->scaler_state.scaler_id, + crtc_state->hw.scaling_filter); for (i = 0; i < num_scalers; i++) { const struct intel_scaler *sc = @@ -930,11 +933,11 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) drm_modeset_lock_all(dev); seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n", - dev_priv->dpll.ref_clks.nssc, - dev_priv->dpll.ref_clks.ssc); + dev_priv->display.dpll.ref_clks.nssc, + dev_priv->display.dpll.ref_clks.ssc); - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { - struct intel_shared_dpll *pll = &dev_priv->dpll.shared_dplls[i]; + for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { + struct intel_shared_dpll *pll = &dev_priv->display.dpll.shared_dplls[i]; seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name, pll->info->id); @@ -1425,9 +1428,9 @@ static int pri_wm_latency_show(struct seq_file *m, void *data) const u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.pri_latency; + latencies = dev_priv->display.wm.pri_latency; wm_latency_show(m, latencies); @@ -1440,9 +1443,9 @@ static int spr_wm_latency_show(struct seq_file *m, void *data) const u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.spr_latency; + latencies = dev_priv->display.wm.spr_latency; wm_latency_show(m, latencies); @@ -1455,9 +1458,9 @@ static int cur_wm_latency_show(struct seq_file *m, void *data) const u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.cur_latency; + latencies = dev_priv->display.wm.cur_latency; wm_latency_show(m, latencies); @@ -1548,9 +1551,9 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf, u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.pri_latency; + latencies = dev_priv->display.wm.pri_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -1563,9 +1566,9 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf, u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.spr_latency; + latencies = dev_priv->display.wm.spr_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -1578,9 +1581,9 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf, u16 *latencies; if (DISPLAY_VER(dev_priv) >= 9) - latencies = dev_priv->wm.skl_latency; + latencies = dev_priv->display.wm.skl_latency; else - latencies = dev_priv->wm.cur_latency; + latencies = dev_priv->display.wm.cur_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -1615,14 +1618,14 @@ static const struct file_operations i915_cur_wm_latency_fops = { static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = m->private; - struct i915_hotplug *hotplug = &dev_priv->hotplug; + struct intel_hotplug *hotplug = &dev_priv->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); - flush_work(&dev_priv->hotplug.dig_port_work); - flush_delayed_work(&dev_priv->hotplug.hotplug_work); + flush_work(&dev_priv->display.hotplug.dig_port_work); + flush_delayed_work(&dev_priv->display.hotplug.hotplug_work); seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold); seq_printf(m, "Detected: %s\n", @@ -1637,7 +1640,7 @@ static ssize_t i915_hpd_storm_ctl_write(struct file *file, { struct seq_file *m = file->private_data; struct drm_i915_private *dev_priv = m->private; - struct i915_hotplug *hotplug = &dev_priv->hotplug; + struct intel_hotplug *hotplug = &dev_priv->display.hotplug; unsigned int new_threshold; int i; char *newline; @@ -1676,7 +1679,7 @@ static ssize_t i915_hpd_storm_ctl_write(struct file *file, spin_unlock_irq(&dev_priv->irq_lock); /* Re-enable hpd immediately if we were in an irq storm */ - flush_delayed_work(&dev_priv->hotplug.reenable_work); + flush_delayed_work(&dev_priv->display.hotplug.reenable_work); return len; } @@ -1700,7 +1703,7 @@ static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = m->private; seq_printf(m, "Enabled: %s\n", - str_yes_no(dev_priv->hotplug.hpd_short_storm_enabled)); + str_yes_no(dev_priv->display.hotplug.hpd_short_storm_enabled)); return 0; } @@ -1718,7 +1721,7 @@ static ssize_t i915_hpd_short_storm_ctl_write(struct file *file, { struct seq_file *m = file->private_data; struct drm_i915_private *dev_priv = m->private; - struct i915_hotplug *hotplug = &dev_priv->hotplug; + struct intel_hotplug *hotplug = &dev_priv->display.hotplug; char *newline; char tmp[16]; int i; @@ -1754,7 +1757,7 @@ static ssize_t i915_hpd_short_storm_ctl_write(struct file *file, spin_unlock_irq(&dev_priv->irq_lock); /* Re-enable hpd immediately if we were in an irq storm */ - flush_delayed_work(&dev_priv->hotplug.reenable_work); + flush_delayed_work(&dev_priv->display.hotplug.reenable_work); return len; } @@ -2202,6 +2205,29 @@ static const struct file_operations i915_dsc_bpp_fops = { .write = i915_dsc_bpp_write }; +/* + * Returns the Current CRTC's bpc. + * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc + */ +static int i915_current_bpc_show(struct seq_file *m, void *data) +{ + struct intel_crtc *crtc = to_intel_crtc(m->private); + struct intel_crtc_state *crtc_state; + int ret; + + ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); + if (ret) + return ret; + + crtc_state = to_intel_crtc_state(crtc->base.state); + seq_printf(m, "Current: %u\n", crtc_state->pipe_bpp / 3); + + drm_modeset_unlock(&crtc->base.mutex); + + return ret; +} +DEFINE_SHOW_ATTRIBUTE(i915_current_bpc); + /** * intel_connector_debugfs_add - add i915 specific connector debugfs files * @connector: pointer to a registered drm_connector @@ -2272,4 +2298,7 @@ void intel_crtc_debugfs_add(struct drm_crtc *crtc) crtc_updates_add(crtc); intel_fbc_crtc_debugfs_add(to_intel_crtc(crtc)); + + debugfs_create_file("i915_current_bpc", 0444, crtc->debugfs_entry, crtc, + &i915_current_bpc_fops); } diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index fb17439bd4f8..b19a1bc26277 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -7,6 +7,7 @@ #include "i915_drv.h" #include "i915_irq.h" +#include "intel_backlight_regs.h" #include "intel_cdclk.h" #include "intel_combo_phy.h" #include "intel_de.h" @@ -268,7 +269,7 @@ sanitize_target_dc_state(struct drm_i915_private *dev_priv, if (target_dc_state != states[i]) continue; - if (dev_priv->dmc.allowed_dc_mask & target_dc_state) + if (dev_priv->display.dmc.allowed_dc_mask & target_dc_state) break; target_dc_state = states[i + 1]; @@ -301,7 +302,7 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv, state = sanitize_target_dc_state(dev_priv, state); - if (state == dev_priv->dmc.target_dc_state) + if (state == dev_priv->display.dmc.target_dc_state) goto unlock; dc_off_enabled = intel_power_well_is_enabled(dev_priv, power_well); @@ -312,7 +313,7 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv, if (!dc_off_enabled) intel_power_well_enable(dev_priv, power_well); - dev_priv->dmc.target_dc_state = state; + dev_priv->display.dmc.target_dc_state = state; if (!dc_off_enabled) intel_power_well_disable(dev_priv, power_well); @@ -908,7 +909,7 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, return 0; if (IS_DG2(dev_priv)) - max_dc = 0; + max_dc = 1; else if (IS_DG1(dev_priv)) max_dc = 3; else if (DISPLAY_VER(dev_priv) >= 12) @@ -981,10 +982,10 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) dev_priv->params.disable_power_well = sanitize_disable_power_well_option(dev_priv, dev_priv->params.disable_power_well); - dev_priv->dmc.allowed_dc_mask = + dev_priv->display.dmc.allowed_dc_mask = get_allowed_dc_mask(dev_priv, dev_priv->params.enable_dc); - dev_priv->dmc.target_dc_state = + dev_priv->display.dmc.target_dc_state = sanitize_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); mutex_init(&power_domains->lock); @@ -1038,7 +1039,7 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, u8 req_slices) { struct i915_power_domains *power_domains = &dev_priv->power_domains; - u8 slice_mask = INTEL_INFO(dev_priv)->dbuf.slice_mask; + u8 slice_mask = INTEL_INFO(dev_priv)->display.dbuf.slice_mask; enum dbuf_slice slice; drm_WARN(&dev_priv->drm, req_slices & ~slice_mask, @@ -1101,7 +1102,7 @@ static void icl_mbus_init(struct drm_i915_private *dev_priv) unsigned long abox_regs = INTEL_INFO(dev_priv)->display.abox_mask; u32 mask, val, i; - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) return; mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK | @@ -1381,6 +1382,9 @@ static void intel_pch_reset_handshake(struct drm_i915_private *dev_priv, reset_bits = RESET_PCH_HANDSHAKE_ENABLE; } + if (DISPLAY_VER(dev_priv) >= 14) + reset_bits |= MTL_RESET_PICA_HANDSHAKE_EN; + val = intel_de_read(dev_priv, reg); if (enable) @@ -1433,6 +1437,7 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv) return; gen9_disable_dc_states(dev_priv); + /* TODO: disable DMC program */ gen9_dbuf_disable(dev_priv); @@ -1500,6 +1505,7 @@ static void bxt_display_core_uninit(struct drm_i915_private *dev_priv) return; gen9_disable_dc_states(dev_priv); + /* TODO: disable DMC program */ gen9_dbuf_disable(dev_priv); @@ -1608,7 +1614,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); /* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */ - if (INTEL_PCH_TYPE(dev_priv) >= PCH_JSP && + if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && INTEL_PCH_TYPE(dev_priv) < PCH_DG1) intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, 0, PCH_DPMGUNIT_CLOCK_GATE_DISABLE); @@ -1675,6 +1681,7 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv) return; gen9_disable_dc_states(dev_priv); + intel_dmc_disable_program(dev_priv); /* 1. Disable all display engine functions -> aready done */ @@ -2039,7 +2046,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915, * resources as required and also enable deeper system power states * that would be blocked if the firmware was inactive. */ - if (!(i915->dmc.allowed_dc_mask & DC_STATE_EN_DC9) && + if (!(i915->display.dmc.allowed_dc_mask & DC_STATE_EN_DC9) && suspend_mode == I915_DRM_SUSPEND_IDLE && intel_dmc_has_payload(i915)) { intel_display_power_flush_work(i915); @@ -2232,10 +2239,10 @@ void intel_display_power_resume(struct drm_i915_private *i915) bxt_disable_dc9(i915); icl_display_core_init(i915, true); if (intel_dmc_has_payload(i915)) { - if (i915->dmc.allowed_dc_mask & + if (i915->display.dmc.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) skl_enable_dc6(i915); - else if (i915->dmc.allowed_dc_mask & + else if (i915->display.dmc.allowed_dc_mask & DC_STATE_EN_UPTO_DC5) gen9_enable_dc5(i915); } @@ -2243,7 +2250,7 @@ void intel_display_power_resume(struct drm_i915_private *i915) bxt_disable_dc9(i915); bxt_display_core_init(i915, true); if (intel_dmc_has_payload(i915) && - (i915->dmc.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)) + (i915->display.dmc.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)) gen9_enable_dc5(i915); } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { hsw_disable_pc8(i915); 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 91cfd5890f46..e442055f1d6c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -5,6 +5,7 @@ #include "i915_drv.h" #include "i915_irq.h" +#include "intel_backlight_regs.h" #include "intel_combo_phy.h" #include "intel_combo_phy_regs.h" #include "intel_crt.h" @@ -710,8 +711,8 @@ void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "Resetting DC state tracking from %02x to %02x\n", - dev_priv->dmc.dc_state, val); - dev_priv->dmc.dc_state = val; + dev_priv->display.dmc.dc_state, val); + dev_priv->display.dmc.dc_state = val; } /** @@ -746,8 +747,8 @@ void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state) return; if (drm_WARN_ON_ONCE(&dev_priv->drm, - state & ~dev_priv->dmc.allowed_dc_mask)) - state &= dev_priv->dmc.allowed_dc_mask; + state & ~dev_priv->display.dmc.allowed_dc_mask)) + state &= dev_priv->display.dmc.allowed_dc_mask; val = intel_de_read(dev_priv, DC_STATE_EN); mask = gen9_dc_mask(dev_priv); @@ -755,16 +756,16 @@ void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state) val & mask, state); /* Check if DMC is ignoring our DC state requests */ - if ((val & mask) != dev_priv->dmc.dc_state) + if ((val & mask) != dev_priv->display.dmc.dc_state) drm_err(&dev_priv->drm, "DC state mismatch (0x%x -> 0x%x)\n", - dev_priv->dmc.dc_state, val & mask); + dev_priv->display.dmc.dc_state, val & mask); val &= ~mask; val |= state; gen9_write_dc_state(dev_priv, val); - dev_priv->dmc.dc_state = val & mask; + dev_priv->display.dmc.dc_state = val & mask; } static void tgl_enable_dc3co(struct drm_i915_private *dev_priv) @@ -958,7 +959,7 @@ void gen9_disable_dc_states(struct drm_i915_private *dev_priv) { struct intel_cdclk_config cdclk_config = {}; - if (dev_priv->dmc.target_dc_state == DC_STATE_EN_DC3CO) { + if (dev_priv->display.dmc.target_dc_state == DC_STATE_EN_DC3CO) { tgl_disable_dc3co(dev_priv); return; } @@ -1000,7 +1001,7 @@ static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, if (!intel_dmc_has_payload(dev_priv)) return; - switch (dev_priv->dmc.target_dc_state) { + switch (dev_priv->display.dmc.target_dc_state) { case DC_STATE_EN_DC3CO: tgl_enable_dc3co(dev_priv); break; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e7da4a154c06..01977cd237eb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -31,13 +31,14 @@ #include <linux/pwm.h> #include <linux/sched/clock.h> -#include <drm/dp/drm_dp_dual_mode_helper.h> -#include <drm/dp/drm_dp_mst_helper.h> +#include <drm/display/drm_dp_dual_mode_helper.h> +#include <drm/display/drm_dp_mst_helper.h> +#include <drm/display/drm_dsc.h> #include <drm/drm_atomic.h> #include <drm/drm_crtc.h> -#include <drm/drm_dsc.h> #include <drm/drm_encoder.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> @@ -279,6 +280,76 @@ struct intel_panel_bl_funcs { u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz); }; +enum drrs_type { + DRRS_TYPE_NONE, + DRRS_TYPE_STATIC, + DRRS_TYPE_SEAMLESS, +}; + +struct intel_vbt_panel_data { + struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ + struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ + + /* Feature bits */ + unsigned int panel_type:4; + unsigned int lvds_dither:1; + unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ + + bool vrr; + + u8 seamless_drrs_min_refresh_rate; + enum drrs_type drrs_type; + + struct { + int max_link_rate; + int rate; + int lanes; + int preemphasis; + int vswing; + int bpp; + struct edp_power_seq pps; + u8 drrs_msa_timing_delay; + bool low_vswing; + bool initialized; + bool hobl; + } edp; + + struct { + bool enable; + bool full_link; + bool require_aux_wakeup; + int idle_frames; + int tp1_wakeup_time_us; + int tp2_tp3_wakeup_time_us; + int psr2_tp2_tp3_wakeup_time_us; + } psr; + + struct { + u16 pwm_freq_hz; + u16 brightness_precision_bits; + bool present; + bool active_low_pwm; + u8 min_brightness; /* min_brightness/255 of max */ + u8 controller; /* brightness controller number */ + enum intel_backlight_type type; + } backlight; + + /* MIPI DSI */ + struct { + u16 panel_id; + struct mipi_config *config; + struct mipi_pps_data *pps; + u16 bl_ports; + u16 cabc_ports; + u8 seq_version; + u32 size; + u8 *data; + const u8 *sequence[MIPI_SEQ_MAX]; + u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ + enum drm_panel_orientation orientation; + } dsi; +}; + struct intel_panel { struct list_head fixed_modes; @@ -318,6 +389,8 @@ struct intel_panel { const struct intel_panel_bl_funcs *pwm_funcs; void (*power)(struct intel_connector *, bool enable); } backlight; + + struct intel_vbt_panel_data vbt; }; struct intel_digital_port; @@ -1474,6 +1547,7 @@ struct intel_pps { int backlight_off_delay; struct delayed_work panel_vdd_work; bool want_panel_vdd; + bool initializing; unsigned long last_power_on; unsigned long last_backlight_off; ktime_t panel_power_off_time; @@ -1496,6 +1570,7 @@ struct intel_pps { */ bool pps_reset; struct edp_power_seq pps_delays; + struct edp_power_seq bios_pps_delays; }; struct intel_psr { @@ -1727,13 +1802,14 @@ static inline enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port) { switch (dig_port->base.port) { + default: + MISSING_CASE(dig_port->base.port); + fallthrough; case PORT_B: case PORT_D: return DPIO_CH0; case PORT_C: return DPIO_CH1; - default: - BUG(); } } @@ -1741,13 +1817,14 @@ static inline enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port) { switch (dig_port->base.port) { + default: + MISSING_CASE(dig_port->base.port); + fallthrough; case PORT_B: case PORT_C: return DPIO_PHY0; case PORT_D: return DPIO_PHY1; - default: - BUG(); } } @@ -1755,13 +1832,14 @@ static inline enum dpio_channel vlv_pipe_to_channel(enum pipe pipe) { switch (pipe) { + default: + MISSING_CASE(pipe); + fallthrough; case PIPE_A: case PIPE_C: return DPIO_CH0; case PIPE_B: return DPIO_CH1; - default: - BUG(); } } diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 34d00f5aff25..e52ecc0738a6 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -52,8 +52,8 @@ #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define DG2_DMC_PATH DMC_PATH(dg2, 2, 06) -#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 06) +#define DG2_DMC_PATH DMC_PATH(dg2, 2, 07) +#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 07) MODULE_FIRMWARE(DG2_DMC_PATH); #define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) @@ -248,9 +248,14 @@ struct stepping_info { char substepping; }; +static bool has_dmc_id_fw(struct drm_i915_private *i915, int dmc_id) +{ + return i915->display.dmc.dmc_info[dmc_id].payload; +} + bool intel_dmc_has_payload(struct drm_i915_private *i915) { - return i915->dmc.dmc_info[DMC_FW_MAIN].payload; + return has_dmc_id_fw(i915, DMC_FW_MAIN); } static const struct stepping_info * @@ -272,6 +277,136 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) intel_de_posting_read(dev_priv, DC_STATE_DEBUG); } +static void disable_event_handler(struct drm_i915_private *i915, + i915_reg_t ctl_reg, i915_reg_t htp_reg) +{ + intel_de_write(i915, ctl_reg, + REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, + DMC_EVT_CTL_TYPE_EDGE_0_1) | + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, + DMC_EVT_CTL_EVENT_ID_FALSE)); + intel_de_write(i915, htp_reg, 0); +} + +static void +disable_flip_queue_event(struct drm_i915_private *i915, + i915_reg_t ctl_reg, i915_reg_t htp_reg) +{ + u32 event_ctl; + u32 event_htp; + + event_ctl = intel_de_read(i915, ctl_reg); + event_htp = intel_de_read(i915, htp_reg); + if (event_ctl != (DMC_EVT_CTL_ENABLE | + DMC_EVT_CTL_RECURRING | + REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, + DMC_EVT_CTL_TYPE_EDGE_0_1) | + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, + DMC_EVT_CTL_EVENT_ID_CLK_MSEC)) || + !event_htp) { + drm_dbg_kms(&i915->drm, + "Unexpected DMC event configuration (control %08x htp %08x)\n", + event_ctl, event_htp); + return; + } + + disable_event_handler(i915, ctl_reg, htp_reg); +} + +static bool +get_flip_queue_event_regs(struct drm_i915_private *i915, int dmc_id, + i915_reg_t *ctl_reg, i915_reg_t *htp_reg) +{ + switch (dmc_id) { + case DMC_FW_MAIN: + if (DISPLAY_VER(i915) == 12) { + *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 3); + *htp_reg = DMC_EVT_HTP(i915, dmc_id, 3); + + return true; + } + break; + case DMC_FW_PIPEA ... DMC_FW_PIPED: + if (IS_DG2(i915)) { + *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 2); + *htp_reg = DMC_EVT_HTP(i915, dmc_id, 2); + + return true; + } + break; + } + + return false; +} + +static void +disable_all_flip_queue_events(struct drm_i915_private *i915) +{ + int dmc_id; + + /* TODO: check if the following applies to all D13+ platforms. */ + if (!IS_DG2(i915) && !IS_TIGERLAKE(i915)) + return; + + for (dmc_id = 0; dmc_id < DMC_FW_MAX; dmc_id++) { + i915_reg_t ctl_reg; + i915_reg_t htp_reg; + + if (!has_dmc_id_fw(i915, dmc_id)) + continue; + + if (!get_flip_queue_event_regs(i915, dmc_id, &ctl_reg, &htp_reg)) + continue; + + disable_flip_queue_event(i915, ctl_reg, htp_reg); + } +} + +static void disable_all_event_handlers(struct drm_i915_private *i915) +{ + int id; + + /* TODO: disable the event handlers on pre-GEN12 platforms as well */ + if (DISPLAY_VER(i915) < 12) + return; + + for (id = DMC_FW_MAIN; id < DMC_FW_MAX; id++) { + int handler; + + if (!has_dmc_id_fw(i915, id)) + continue; + + for (handler = 0; handler < DMC_EVENT_HANDLER_COUNT_GEN12; handler++) + disable_event_handler(i915, + DMC_EVT_CTL(i915, id, handler), + DMC_EVT_HTP(i915, id, handler)); + } +} + +static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) +{ + enum pipe pipe; + + if (DISPLAY_VER(i915) != 13) + return; + + /* + * Wa_16015201720:adl-p,dg2 + * The WA requires clock gating to be disabled all the time + * for pipe A and B. + * For pipe C and D clock gating needs to be disabled only + * during initializing the firmware. + */ + if (enable) + for (pipe = PIPE_A; pipe <= PIPE_D; pipe++) + intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe), + 0, PIPEDMC_GATING_DIS); + else + for (pipe = PIPE_C; pipe <= PIPE_D; pipe++) + intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe), + PIPEDMC_GATING_DIS, 0); +} + /** * intel_dmc_load_program() - write the firmware from memory to register. * @dev_priv: i915 drm device. @@ -282,12 +417,16 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) */ void intel_dmc_load_program(struct drm_i915_private *dev_priv) { - struct intel_dmc *dmc = &dev_priv->dmc; + struct intel_dmc *dmc = &dev_priv->display.dmc; u32 id, i; if (!intel_dmc_has_payload(dev_priv)) return; + pipedmc_clock_gating_wa(dev_priv, true); + + disable_all_event_handlers(dev_priv); + assert_rpm_wakelock_held(&dev_priv->runtime_pm); preempt_disable(); @@ -309,15 +448,41 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv) } } - dev_priv->dmc.dc_state = 0; + dev_priv->display.dmc.dc_state = 0; gen9_set_dc_state_debugmask(dev_priv); + + /* + * Flip queue events need to be disabled before enabling DC5/6. + * i915 doesn't use the flip queue feature, so disable it already + * here. + */ + disable_all_flip_queue_events(dev_priv); + + pipedmc_clock_gating_wa(dev_priv, false); +} + +/** + * intel_dmc_disable_program() - disable the firmware + * @i915: i915 drm device + * + * Disable all event handlers in the firmware, making sure the firmware is + * inactive after the display is uninitialized. + */ +void intel_dmc_disable_program(struct drm_i915_private *i915) +{ + if (!intel_dmc_has_payload(i915)) + return; + + pipedmc_clock_gating_wa(i915, true); + disable_all_event_handlers(i915); + pipedmc_clock_gating_wa(i915, false); } void assert_dmc_loaded(struct drm_i915_private *i915) { drm_WARN_ONCE(&i915->drm, - !intel_de_read(i915, DMC_PROGRAM(i915->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)), + !intel_de_read(i915, DMC_PROGRAM(i915->display.dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)), "DMC program storage start is NULL\n"); drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE), "DMC SSP Base Not fine\n"); @@ -354,7 +519,7 @@ static void dmc_set_fw_offset(struct intel_dmc *dmc, { unsigned int i, id; - struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc); + struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), display.dmc); for (i = 0; i < num_entries; i++) { id = package_ver <= 1 ? DMC_FW_MAIN : fw_info[i].dmc_id; @@ -382,7 +547,7 @@ static bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc, const u32 *mmioaddr, u32 mmio_count, int header_ver, u8 dmc_id) { - struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc); + struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), display.dmc); u32 start_range, end_range; int i; @@ -420,7 +585,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc, const struct intel_dmc_header_base *dmc_header, size_t rem_size, u8 dmc_id) { - struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc); + struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), display.dmc); struct dmc_fw_info *dmc_info = &dmc->dmc_info[dmc_id]; unsigned int header_len_bytes, dmc_header_size, payload_size, i; const u32 *mmioaddr, *mmiodata; @@ -531,7 +696,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc, const struct stepping_info *si, size_t rem_size) { - struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc); + struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), display.dmc); u32 package_size = sizeof(struct intel_package_header); u32 num_entries, max_entries; const struct intel_fw_info *fw_info; @@ -585,7 +750,7 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc, struct intel_css_header *css_header, size_t rem_size) { - struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc); + struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), display.dmc); if (rem_size < sizeof(struct intel_css_header)) { drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n"); @@ -622,7 +787,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv, struct intel_css_header *css_header; struct intel_package_header *package_header; struct intel_dmc_header_base *dmc_header; - struct intel_dmc *dmc = &dev_priv->dmc; + struct intel_dmc *dmc = &dev_priv->display.dmc; struct stepping_info display_info = { '*', '*'}; const struct stepping_info *si = intel_get_stepping_info(dev_priv, &display_info); u32 readcount = 0; @@ -649,7 +814,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv, readcount += r; for (id = 0; id < DMC_FW_MAX; id++) { - if (!dev_priv->dmc.dmc_info[id].present) + if (!dev_priv->display.dmc.dmc_info[id].present) continue; offset = readcount + dmc->dmc_info[id].dmc_offset * 4; @@ -665,15 +830,15 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv, static void intel_dmc_runtime_pm_get(struct drm_i915_private *dev_priv) { - drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref); - dev_priv->dmc.wakeref = + drm_WARN_ON(&dev_priv->drm, dev_priv->display.dmc.wakeref); + dev_priv->display.dmc.wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); } static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv) { intel_wakeref_t wakeref __maybe_unused = - fetch_and_zero(&dev_priv->dmc.wakeref); + fetch_and_zero(&dev_priv->display.dmc.wakeref); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); } @@ -684,10 +849,10 @@ static void dmc_load_work_fn(struct work_struct *work) struct intel_dmc *dmc; const struct firmware *fw = NULL; - dev_priv = container_of(work, typeof(*dev_priv), dmc.work); - dmc = &dev_priv->dmc; + dev_priv = container_of(work, typeof(*dev_priv), display.dmc.work); + dmc = &dev_priv->display.dmc; - request_firmware(&fw, dev_priv->dmc.fw_path, dev_priv->drm.dev); + request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); parse_dmc_fw(dev_priv, fw); if (intel_dmc_has_payload(dev_priv)) { @@ -696,7 +861,7 @@ static void dmc_load_work_fn(struct work_struct *work) drm_info(&dev_priv->drm, "Finished loading DMC firmware %s (v%u.%u)\n", - dev_priv->dmc.fw_path, DMC_VERSION_MAJOR(dmc->version), + dev_priv->display.dmc.fw_path, DMC_VERSION_MAJOR(dmc->version), DMC_VERSION_MINOR(dmc->version)); } else { drm_notice(&dev_priv->drm, @@ -719,9 +884,9 @@ static void dmc_load_work_fn(struct work_struct *work) */ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) { - struct intel_dmc *dmc = &dev_priv->dmc; + struct intel_dmc *dmc = &dev_priv->display.dmc; - INIT_WORK(&dev_priv->dmc.work, dmc_load_work_fn); + INIT_WORK(&dev_priv->display.dmc.work, dmc_load_work_fn); if (!HAS_DMC(dev_priv)) return; @@ -804,7 +969,7 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) } drm_dbg_kms(&dev_priv->drm, "Loading %s\n", dmc->fw_path); - schedule_work(&dev_priv->dmc.work); + schedule_work(&dev_priv->display.dmc.work); } /** @@ -820,7 +985,7 @@ void intel_dmc_ucode_suspend(struct drm_i915_private *dev_priv) if (!HAS_DMC(dev_priv)) return; - flush_work(&dev_priv->dmc.work); + flush_work(&dev_priv->display.dmc.work); /* Drop the reference held in case DMC isn't loaded. */ if (!intel_dmc_has_payload(dev_priv)) @@ -862,16 +1027,16 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv) return; intel_dmc_ucode_suspend(dev_priv); - drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref); + drm_WARN_ON(&dev_priv->drm, dev_priv->display.dmc.wakeref); for (id = 0; id < DMC_FW_MAX; id++) - kfree(dev_priv->dmc.dmc_info[id].payload); + kfree(dev_priv->display.dmc.dmc_info[id].payload); } void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, struct drm_i915_private *i915) { - struct intel_dmc *dmc = &i915->dmc; + struct intel_dmc *dmc = &i915->display.dmc; if (!HAS_DMC(i915)) return; @@ -893,7 +1058,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) if (!HAS_DMC(i915)) return -ENODEV; - dmc = &i915->dmc; + dmc = &i915->display.dmc; wakeref = intel_runtime_pm_get(&i915->runtime_pm); diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 41091aee3b47..67e03315ef99 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -47,6 +47,7 @@ struct intel_dmc { void intel_dmc_ucode_init(struct drm_i915_private *i915); void intel_dmc_load_program(struct drm_i915_private *i915); +void intel_dmc_disable_program(struct drm_i915_private *i915); void intel_dmc_ucode_fini(struct drm_i915_private *i915); void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index 67e14eb96a7a..5e5e41644ddf 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -10,6 +10,49 @@ #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 + +#define _ADLP_PIPEDMC_REG_MMIO_BASE_A 0x5f000 +#define _TGL_PIPEDMC_REG_MMIO_BASE_A 0x92000 + +#define __PIPEDMC_REG_MMIO_BASE(i915, dmc_id) \ + ((DISPLAY_VER(i915) >= 13 ? _ADLP_PIPEDMC_REG_MMIO_BASE_A : \ + _TGL_PIPEDMC_REG_MMIO_BASE_A) + \ + 0x400 * ((dmc_id) - 1)) + +#define __DMC_REG_MMIO_BASE 0x8f000 + +#define _DMC_REG_MMIO_BASE(i915, dmc_id) \ + ((dmc_id) == DMC_FW_MAIN ? __DMC_REG_MMIO_BASE : \ + __PIPEDMC_REG_MMIO_BASE(i915, dmc_id)) + +#define _DMC_REG(i915, dmc_id, reg) \ + ((reg) - __DMC_REG_MMIO_BASE + _DMC_REG_MMIO_BASE(i915, dmc_id)) + +#define DMC_EVENT_HANDLER_COUNT_GEN12 8 + +#define _DMC_EVT_HTP_0 0x8f004 + +#define DMC_EVT_HTP(i915, dmc_id, handler) \ + _MMIO(_DMC_REG(i915, dmc_id, _DMC_EVT_HTP_0) + 4 * (handler)) + +#define _DMC_EVT_CTL_0 0x8f034 + +#define DMC_EVT_CTL(i915, dmc_id, handler) \ + _MMIO(_DMC_REG(i915, dmc_id, _DMC_EVT_CTL_0) + 4 * (handler)) + +#define DMC_EVT_CTL_ENABLE REG_BIT(31) +#define DMC_EVT_CTL_RECURRING REG_BIT(30) +#define DMC_EVT_CTL_TYPE_MASK REG_GENMASK(17, 16) +#define DMC_EVT_CTL_TYPE_LEVEL_0 0 +#define DMC_EVT_CTL_TYPE_LEVEL_1 1 +#define DMC_EVT_CTL_TYPE_EDGE_1_0 2 +#define DMC_EVT_CTL_TYPE_EDGE_0_1 3 + +#define DMC_EVT_CTL_EVENT_ID_MASK REG_GENMASK(15, 8) +#define DMC_EVT_CTL_EVENT_ID_FALSE 0x01 +/* An event handler scheduled to run at a 1 kHz frequency. */ +#define DMC_EVT_CTL_EVENT_ID_CLK_MSEC 0xbf + #define DMC_HTP_ADDR_SKL 0x00500034 #define DMC_SSP_BASE _MMIO(0x8F074) #define DMC_HTP_SKL _MMIO(0x8F004) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d55acc4a028a..6cb695e506f5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -35,9 +35,11 @@ #include <asm/byteorder.h> +#include <drm/display/drm_dp_helper.h> +#include <drm/display/drm_dsc_helper.h> +#include <drm/display/drm_hdmi_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/dp/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> @@ -387,13 +389,23 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp) return intel_dp_is_edp(intel_dp) ? 810000 : 1350000; } +static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy) +{ + u32 voltage; + + voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK; + + return voltage == VOLTAGE_INFO_0_85V; +} + static int icl_max_source_rate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); - if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp)) + if (intel_phy_is_combo(dev_priv, phy) && + (is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp))) return 540000; return 810000; @@ -401,12 +413,48 @@ static int icl_max_source_rate(struct intel_dp *intel_dp) static int ehl_max_source_rate(struct intel_dp *intel_dp) { - if (intel_dp_is_edp(intel_dp)) + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); + + if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy)) + return 540000; + + return 810000; +} + +static int dg1_max_source_rate(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + + if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy)) return 540000; return 810000; } +static int vbt_max_link_rate(struct intel_dp *intel_dp) +{ + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + int max_rate; + + max_rate = intel_bios_dp_max_link_rate(encoder); + + if (intel_dp_is_edp(intel_dp)) { + struct intel_connector *connector = intel_dp->attached_connector; + int edp_max_rate = connector->panel.vbt.edp.max_link_rate; + + if (max_rate && edp_max_rate) + max_rate = min(max_rate, edp_max_rate); + else if (edp_max_rate) + max_rate = edp_max_rate; + } + + return max_rate; +} + static void intel_dp_set_source_rates(struct intel_dp *intel_dp) { @@ -428,7 +476,6 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) 162000, 270000 }; struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *encoder = &dig_port->base; struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); const int *source_rates; int size, max_rate = 0, vbt_max_rate; @@ -444,7 +491,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) max_rate = dg2_max_source_rate(intel_dp); else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) - max_rate = 810000; + max_rate = dg1_max_source_rate(intel_dp); else if (IS_JSL_EHL(dev_priv)) max_rate = ehl_max_source_rate(intel_dp); else @@ -464,7 +511,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) size = ARRAY_SIZE(g4x_rates); } - vbt_max_rate = intel_bios_dp_max_link_rate(encoder); + vbt_max_rate = vbt_max_link_rate(intel_dp); if (max_rate && vbt_max_rate) max_rate = min(max_rate, vbt_max_rate); else if (vbt_max_rate) @@ -657,7 +704,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, */ bits_per_pixel = (link_clock * lane_count * 8) / intel_dp_mode_to_fec_clock(mode_clock); - drm_dbg_kms(&i915->drm, "Max link bpp: %u\n", bits_per_pixel); /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / @@ -666,9 +712,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, if (bigjoiner) max_bpp_small_joiner_ram *= 2; - drm_dbg_kms(&i915->drm, "Max small joiner bpp: %u\n", - max_bpp_small_joiner_ram); - /* * Greatest allowed DSC BPP = MIN (output BPP from available Link BW * check, output bpp from small joiner RAM check) @@ -680,7 +723,6 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, i915->max_cdclk_freq * 48 / intel_dp_mode_to_fec_clock(mode_clock); - drm_dbg_kms(&i915->drm, "Max big joiner bpp: %u\n", max_bpp_bigjoiner); bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner); } @@ -1219,11 +1261,12 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp, if (intel_dp_is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ if (intel_connector->base.display_info.bpc == 0 && - dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp) { + intel_connector->panel.vbt.edp.bpp && + intel_connector->panel.vbt.edp.bpp < bpp) { drm_dbg_kms(&dev_priv->drm, "clamping bpp for eDP panel to BIOS-provided %i\n", - dev_priv->vbt.edp.bpp); - bpp = dev_priv->vbt.edp.bpp; + intel_connector->panel.vbt.edp.bpp); + bpp = intel_connector->panel.vbt.edp.bpp; } } @@ -1334,7 +1377,18 @@ static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc) return 0; } -#define DSC_SUPPORTED_VERSION_MIN 1 +static int intel_dp_source_dsc_version_minor(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + return DISPLAY_VER(i915) >= 14 ? 2 : 1; +} + +static int intel_dp_sink_dsc_version_minor(struct intel_dp *intel_dp) +{ + return (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MINOR_MASK) >> + DP_DSC_MINOR_SHIFT; +} static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) @@ -1373,9 +1427,8 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT; vdsc_cfg->dsc_version_minor = - min(DSC_SUPPORTED_VERSION_MIN, - (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & - DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT); + min(intel_dp_source_dsc_version_minor(intel_dp), + intel_dp_sink_dsc_version_minor(intel_dp)); vdsc_cfg->convert_rgb = intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & DP_DSC_RGB; @@ -1879,7 +1932,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, } if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) - pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; + pipe_config->msa_timing_delay = connector->panel.vbt.edp.drrs_msa_timing_delay; pipe_config->has_drrs = true; @@ -2709,6 +2762,33 @@ static void intel_edp_mso_mode_fixup(struct intel_connector *connector, DRM_MODE_ARG(mode)); } +void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_connector *connector = intel_dp->attached_connector; + + if (connector->panel.vbt.edp.bpp && pipe_bpp > connector->panel.vbt.edp.bpp) { + /* + * This is a big fat ugly hack. + * + * Some machines in UEFI boot mode provide us a VBT that has 18 + * bpp and 1.62 GHz link bandwidth for eDP, which for reasons + * unknown we fail to light up. Yet the same BIOS boots up with + * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as + * max, not what it tells us to use. + * + * Note: This will still be broken if the eDP panel is not lit + * up by the BIOS, and thus we can't get the mode at module + * load. + */ + drm_dbg_kms(&dev_priv->drm, + "pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", + pipe_bpp, connector->panel.vbt.edp.bpp); + connector->panel.vbt.edp.bpp = pipe_bpp; + } +} + static void intel_edp_mso_init(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -2823,9 +2903,6 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_sink_rates(intel_dp); intel_dp_set_max_sink_lane_count(intel_dp); - intel_dp_set_common_rates(intel_dp); - intel_dp_reset_max_link_params(intel_dp); - /* Read the eDP DSC DPCD registers */ if (DISPLAY_VER(dev_priv) >= 10) intel_dp_get_dsc_sink_cap(intel_dp); @@ -4523,7 +4600,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp) edid = intel_dp_get_edid(intel_dp); connector->detect_edid = edid; - vrr_capable = intel_vrr_is_capable(&connector->base); + vrr_capable = intel_vrr_is_capable(connector); drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] VRR capable: %s\n", connector->base.base.id, connector->base.name, str_yes_no(vrr_capable)); drm_connector_set_vrr_capable_property(&connector->base, vrr_capable); @@ -4925,12 +5002,21 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, { struct drm_i915_private *dev_priv = to_i915(conn->dev); struct intel_atomic_state *state = to_intel_atomic_state(_state); + struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(_state, conn); + struct intel_connector *intel_conn = to_intel_connector(conn); + struct intel_dp *intel_dp = enc_to_intel_dp(intel_conn->encoder); int ret; ret = intel_digital_connector_atomic_check(conn, &state->base); if (ret) return ret; + if (intel_dp_mst_source_support(intel_dp)) { + ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst_mgr); + if (ret) + return ret; + } + /* * We don't enable port sync on BDW due to missing w/as and * due to not having adjusted the modeset sequence appropriately. @@ -4956,9 +5042,9 @@ static void intel_dp_oob_hotplug_event(struct drm_connector *connector) struct drm_i915_private *i915 = to_i915(connector->dev); spin_lock_irq(&i915->irq_lock); - i915->hotplug.event_bits |= BIT(encoder->hpd_pin); + i915->display.hotplug.event_bits |= BIT(encoder->hpd_pin); spin_unlock_irq(&i915->irq_lock); - queue_delayed_work(system_wq, &i915->hotplug.hotplug_work, 0); + queue_delayed_work(system_wq, &i915->display.hotplug.hotplug_work, 0); } static const struct drm_connector_funcs intel_dp_connector_funcs = { @@ -5128,6 +5214,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector = &intel_connector->base; struct drm_display_mode *fixed_mode; + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; bool has_dpcd; enum pipe pipe = INVALID_PIPE; struct edid *edid; @@ -5184,8 +5271,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; + intel_bios_init_panel(dev_priv, &intel_connector->panel, + encoder->devdata, IS_ERR(edid) ? NULL : edid); + intel_panel_add_edid_fixed_modes(intel_connector, - dev_priv->vbt.drrs_type != DRRS_TYPE_NONE); + intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, + intel_vrr_is_capable(intel_connector)); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); @@ -5221,12 +5312,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_init(intel_connector); - if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) - intel_connector->panel.backlight.power = intel_pps_backlight_power; intel_backlight_setup(intel_connector, pipe); intel_edp_add_properties(intel_dp); + intel_pps_init_late(intel_dp); + return true; out_vdd_off: @@ -5307,11 +5398,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, type = DRM_MODE_CONNECTOR_DisplayPort; } - intel_dp_set_source_rates(intel_dp); intel_dp_set_default_sink_rates(intel_dp); intel_dp_set_default_max_sink_lane_count(intel_dp); - intel_dp_set_common_rates(intel_dp); - intel_dp_reset_max_link_params(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); @@ -5339,16 +5427,19 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, else intel_connector->get_hw_state = intel_connector_get_hw_state; - /* init MST on ports that can support it */ - intel_dp_mst_encoder_init(dig_port, - intel_connector->base.base.id); - if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); - intel_dp_mst_encoder_cleanup(dig_port); goto fail; } + intel_dp_set_source_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); + + /* init MST on ports that can support it */ + intel_dp_mst_encoder_init(dig_port, + intel_connector->base.base.id); + intel_dp_add_properties(intel_dp, connector); if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index d457e17bdc57..a54902c713a3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -29,6 +29,7 @@ struct link_config_limits { int min_bpp, max_bpp; }; +void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp); void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct link_config_limits *limits); @@ -63,6 +64,7 @@ enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port, void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); void intel_edp_backlight_off(const struct drm_connector_state *conn_state); +void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp); void intel_dp_mst_suspend(struct drm_i915_private *dev_priv); void intel_dp_mst_resume(struct drm_i915_private *dev_priv); int intel_dp_max_link_rate(struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 2bc119374555..227fbee88b89 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -42,7 +42,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp) bool done; #define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) - done = wait_event_timeout(i915->gmbus_wait_queue, C, + done = wait_event_timeout(i915->display.gmbus.wait_queue, C, msecs_to_jiffies_timeout(timeout_ms)); /* just trace the final value */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index fb6cf30ee628..83af95bce98d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -278,6 +278,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; + struct drm_luminance_range_info *luminance_range = + &connector->base.display_info.luminance_range; int ret; if (panel->backlight.edp.intel.sdr_uses_aux) { @@ -293,8 +295,17 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi } } - panel->backlight.max = 512; - panel->backlight.min = 0; + if (luminance_range->max_luminance) { + panel->backlight.max = luminance_range->max_luminance; + panel->backlight.min = luminance_range->min_luminance; + } else { + panel->backlight.max = 512; + panel->backlight.min = 0; + } + + drm_dbg_kms(&i915->drm, "Using backlight range %d..%d\n", panel->backlight.min, + panel->backlight.max); + panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; @@ -370,7 +381,7 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, int ret; ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info, - i915->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd, + panel->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd, ¤t_level, ¤t_mode); if (ret < 0) return ret; @@ -454,7 +465,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) case INTEL_DP_AUX_BACKLIGHT_OFF: return -ENODEV; case INTEL_DP_AUX_BACKLIGHT_AUTO: - switch (i915->vbt.backlight.type) { + switch (panel->vbt.backlight.type) { case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE: try_vesa_interface = true; break; @@ -466,7 +477,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) } break; case INTEL_DP_AUX_BACKLIGHT_ON: - if (i915->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) + if (panel->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) try_intel_interface = true; try_vesa_interface = true; diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 82d024dafe7b..88689124c013 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -6,9 +6,9 @@ * Sean Paul <seanpaul@chromium.org> */ -#include <drm/dp/drm_dp_helper.h> -#include <drm/dp/drm_dp_mst_helper.h> -#include <drm/drm_hdcp.h> +#include <drm/display/drm_dp_helper.h> +#include <drm/display/drm_dp_mst_helper.h> +#include <drm/display/drm_hdcp_helper.h> #include <drm/drm_print.h> #include "intel_ddi.h" @@ -17,6 +17,7 @@ #include "intel_dp.h" #include "intel_dp_hdcp.h" #include "intel_hdcp.h" +#include "intel_hdcp_regs.h" static unsigned int transcoder_to_stream_enc_status(enum transcoder cpu_transcoder) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h index dc1556b46b85..7fa1c0833096 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h @@ -6,7 +6,7 @@ #ifndef __INTEL_DP_LINK_TRAINING_H__ #define __INTEL_DP_LINK_TRAINING_H__ -#include <drm/dp/drm_dp_helper.h> +#include <drm/display/drm_dp_helper.h> struct intel_crtc_state; struct intel_dp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 061b277e5ce7..7713c19042f3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -52,6 +52,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_dp *intel_dp = &intel_mst->primary->dp; + struct drm_dp_mst_topology_state *mst_state; struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -60,22 +61,28 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N); int bpp, slots = -EINVAL; + mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; + // TODO: Handle pbn_div changes by adding a new MST helper + if (!mst_state->pbn_div) { + mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, + limits->max_rate, + limits->max_lane_count); + } + for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { crtc_state->pipe_bpp = bpp; crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, crtc_state->pipe_bpp, false); - - slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, - connector->port, - crtc_state->pbn, - drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, - crtc_state->port_clock, - crtc_state->lane_count)); + slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, + connector->port, crtc_state->pbn); if (slots == -EDEADLK) return slots; if (slots >= 0) @@ -308,14 +315,8 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, struct drm_atomic_state *_state) { struct intel_atomic_state *state = to_intel_atomic_state(_state); - struct drm_connector_state *new_conn_state = - drm_atomic_get_new_connector_state(&state->base, connector); - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(&state->base, connector); struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_crtc *new_crtc = new_conn_state->crtc; - struct drm_dp_mst_topology_mgr *mgr; int ret; ret = intel_digital_connector_atomic_check(connector, &state->base); @@ -326,28 +327,9 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, if (ret) return ret; - if (!old_conn_state->crtc) - return 0; - - /* We only want to free VCPI if this state disables the CRTC on this - * connector - */ - if (new_crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc); - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - - if (!crtc_state || - !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) || - crtc_state->uapi.enable) - return 0; - } - - mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder))->primary->dp.mst_mgr; - ret = drm_dp_atomic_release_vcpi_slots(&state->base, mgr, - intel_connector->port); - - return ret; + return drm_dp_atomic_release_time_slots(&state->base, + &intel_connector->mst_port->mst_mgr, + intel_connector->port); } static void clear_act_sent(struct intel_encoder *encoder, @@ -383,21 +365,17 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr); struct drm_i915_private *i915 = to_i915(connector->base.dev); - int start_slot = intel_dp_is_uhbr(old_crtc_state) ? 0 : 1; - int ret; drm_dbg_kms(&i915->drm, "active links %d\n", intel_dp->active_mst_links); intel_hdcp_disable(intel_mst->connector); - drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); - - ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot); - if (ret) { - drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret); - } + drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); } @@ -425,8 +403,6 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_disable_transcoder(old_crtc_state); - drm_dp_update_payload_part2(&intel_dp->mst_mgr); - clear_act_sent(encoder, old_crtc_state); intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), @@ -434,8 +410,6 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, wait_for_act_sent(encoder, old_crtc_state); - drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); - intel_ddi_disable_transcoder_func(old_crtc_state); if (DISPLAY_VER(dev_priv) >= 9) @@ -502,7 +476,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_connector *connector = to_intel_connector(conn_state->connector); - int start_slot = intel_dp_is_uhbr(pipe_config) ? 0 : 1; + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); int ret; bool first_mst_stream; @@ -528,16 +503,13 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, dig_port->base.pre_enable(state, &dig_port->base, pipe_config, NULL); - ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, - connector->port, - pipe_config->pbn, - pipe_config->dp_m_n.tu); - if (!ret) - drm_err(&dev_priv->drm, "failed to allocate vcpi\n"); - intel_dp->active_mst_links++; - ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr, start_slot); + ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); + if (ret < 0) + drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n", + connector->base.name, ret); /* * Before Gen 12 this is not done as part of @@ -560,7 +532,10 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_digital_port *dig_port = intel_mst->primary; struct intel_dp *intel_dp = &dig_port->dp; + struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); enum transcoder trans = pipe_config->cpu_transcoder; drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder); @@ -588,7 +563,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, wait_for_act_sent(encoder, pipe_config); - drm_dp_update_payload_part2(&intel_dp->mst_mgr); + drm_dp_add_payload_part2(&intel_dp->mst_mgr, &state->base, + drm_atomic_get_mst_payload_state(mst_state, connector->port)); if (DISPLAY_VER(dev_priv) >= 12 && pipe_config->fec_enable) intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0, @@ -839,6 +815,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); if (ret) { + drm_dp_mst_put_port_malloc(port); intel_connector_free(intel_connector); return NULL; } @@ -971,8 +948,6 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) struct intel_dp *intel_dp = &dig_port->dp; enum port port = dig_port->base.port; int ret; - int max_source_rate = - intel_dp->source_rates[intel_dp->num_source_rates - 1]; if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp)) return 0; @@ -988,10 +963,7 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) /* create encoders */ intel_dp_create_fake_mst_encoders(dig_port); ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm, - &intel_dp->aux, 16, 3, - dig_port->max_lanes, - max_source_rate, - conn_base_id); + &intel_dp->aux, 16, 3, conn_base_id); if (ret) { intel_dp->mst_mgr.cbs = NULL; return ret; diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 6eef0b8a91eb..87899702a522 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -933,7 +933,17 @@ static void i8xx_compute_dpll(struct intel_crtc_state *crtc_state, static int hsw_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { - return 0; + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + 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); + + if (DISPLAY_VER(dev_priv) < 11 && + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) + return 0; + + return intel_compute_shared_dplls(state, crtc, encoder); } static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, @@ -944,21 +954,12 @@ static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct intel_encoder *encoder = intel_get_crtc_new_encoder(state, crtc_state); - int ret; if (DISPLAY_VER(dev_priv) < 11 && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - ret = intel_reserve_shared_dplls(state, crtc, encoder); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "failed to find PLL for pipe %c\n", - pipe_name(crtc->pipe)); - return ret; - } - - return 0; + return intel_reserve_shared_dplls(state, crtc, encoder); } static int dg2_crtc_compute_clock(struct intel_atomic_state *state, @@ -1125,39 +1126,26 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&dev_priv->drm, - "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } ilk_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); - return 0; + return intel_compute_shared_dplls(state, crtc, NULL); } static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - int ret; /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ if (!crtc_state->has_pch_encoder) return 0; - ret = intel_reserve_shared_dplls(state, crtc, NULL); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "failed to find PLL for pipe %c\n", - pipe_name(crtc->pipe)); - return ret; - } - - return 0; + return intel_reserve_shared_dplls(state, crtc, NULL); } void vlv_compute_dpll(struct intel_crtc_state *crtc_state) @@ -1198,7 +1186,6 @@ void chv_compute_dpll(struct intel_crtc_state *crtc_state) static int chv_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); const struct intel_limit *limit = &intel_limits_chv; @@ -1206,10 +1193,8 @@ static int chv_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&i915->drm, "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } chv_compute_dpll(crtc_state); @@ -1219,7 +1204,6 @@ static int chv_crtc_compute_clock(struct intel_atomic_state *state, static int vlv_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); const struct intel_limit *limit = &intel_limits_vlv; @@ -1228,7 +1212,6 @@ static int vlv_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, refclk, NULL, &crtc_state->dpll)) { - drm_err(&i915->drm, "Couldn't find PLL settings for mode!\n"); return -EINVAL; } @@ -1270,11 +1253,8 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&dev_priv->drm, - "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } i9xx_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); @@ -1306,11 +1286,8 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&dev_priv->drm, - "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } i9xx_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); @@ -1342,11 +1319,8 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&dev_priv->drm, - "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } i9xx_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); @@ -1380,11 +1354,8 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->clock_set && !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &crtc_state->dpll)) { - drm_err(&dev_priv->drm, - "Couldn't find PLL settings for mode!\n"); + refclk, NULL, &crtc_state->dpll)) return -EINVAL; - } i8xx_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); @@ -1436,6 +1407,7 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + int ret; drm_WARN_ON(&i915->drm, !intel_crtc_needs_modeset(crtc_state)); @@ -1448,7 +1420,14 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->hw.enable) return 0; - return i915->dpll_funcs->crtc_compute_clock(state, crtc); + ret = i915->display.funcs.dpll->crtc_compute_clock(state, crtc); + if (ret) { + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Couldn't calculate DPLL settings\n", + crtc->base.base.id, crtc->base.name); + return ret; + } + + return 0; } int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, @@ -1457,6 +1436,7 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + int ret; drm_WARN_ON(&i915->drm, !intel_crtc_needs_modeset(crtc_state)); @@ -1466,33 +1446,40 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, if (!crtc_state->hw.enable) return 0; - if (!i915->dpll_funcs->crtc_get_shared_dpll) + if (!i915->display.funcs.dpll->crtc_get_shared_dpll) return 0; - return i915->dpll_funcs->crtc_get_shared_dpll(state, crtc); + ret = i915->display.funcs.dpll->crtc_get_shared_dpll(state, crtc); + if (ret) { + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n", + crtc->base.base.id, crtc->base.name); + return ret; + } + + return 0; } void intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv) { if (IS_DG2(dev_priv)) - dev_priv->dpll_funcs = &dg2_dpll_funcs; + dev_priv->display.funcs.dpll = &dg2_dpll_funcs; else if (DISPLAY_VER(dev_priv) >= 9 || HAS_DDI(dev_priv)) - dev_priv->dpll_funcs = &hsw_dpll_funcs; + dev_priv->display.funcs.dpll = &hsw_dpll_funcs; else if (HAS_PCH_SPLIT(dev_priv)) - dev_priv->dpll_funcs = &ilk_dpll_funcs; + dev_priv->display.funcs.dpll = &ilk_dpll_funcs; else if (IS_CHERRYVIEW(dev_priv)) - dev_priv->dpll_funcs = &chv_dpll_funcs; + dev_priv->display.funcs.dpll = &chv_dpll_funcs; else if (IS_VALLEYVIEW(dev_priv)) - dev_priv->dpll_funcs = &vlv_dpll_funcs; + dev_priv->display.funcs.dpll = &vlv_dpll_funcs; else if (IS_G4X(dev_priv)) - dev_priv->dpll_funcs = &g4x_dpll_funcs; + dev_priv->display.funcs.dpll = &g4x_dpll_funcs; else if (IS_PINEVIEW(dev_priv)) - dev_priv->dpll_funcs = &pnv_dpll_funcs; + dev_priv->display.funcs.dpll = &pnv_dpll_funcs; else if (DISPLAY_VER(dev_priv) != 2) - dev_priv->dpll_funcs = &i9xx_dpll_funcs; + dev_priv->display.funcs.dpll = &i9xx_dpll_funcs; else - dev_priv->dpll_funcs = &i8xx_dpll_funcs; + dev_priv->display.funcs.dpll = &i8xx_dpll_funcs; } static bool i9xx_has_pps(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 22f55574a35c..bbe142056c7c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -90,6 +90,9 @@ struct intel_shared_dpll_funcs { struct intel_dpll_mgr { const struct dpll_info *dpll_info; + int (*compute_dplls)(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); int (*get_dplls)(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); @@ -110,8 +113,8 @@ intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv, enum intel_dpll_id i; /* Copy shared dpll state */ - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { - struct intel_shared_dpll *pll = &dev_priv->dpll.shared_dplls[i]; + for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { + struct intel_shared_dpll *pll = &dev_priv->display.dpll.shared_dplls[i]; shared_dpll[i] = pll->state; } @@ -146,7 +149,7 @@ struct intel_shared_dpll * intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, enum intel_dpll_id id) { - return &dev_priv->dpll.shared_dplls[id]; + return &dev_priv->display.dpll.shared_dplls[id]; } /** @@ -161,11 +164,11 @@ enum intel_dpll_id intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { - long pll_idx = pll - dev_priv->dpll.shared_dplls; + long pll_idx = pll - dev_priv->display.dpll.shared_dplls; if (drm_WARN_ON(&dev_priv->drm, pll_idx < 0 || - pll_idx >= dev_priv->dpll.num_shared_dpll)) + pll_idx >= dev_priv->display.dpll.num_shared_dpll)) return -1; return pll_idx; @@ -242,7 +245,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) if (drm_WARN_ON(&dev_priv->drm, pll == NULL)) return; - mutex_lock(&dev_priv->dpll.lock); + mutex_lock(&dev_priv->display.dpll.lock); old_mask = pll->active_mask; if (drm_WARN_ON(&dev_priv->drm, !(pll->state.pipe_mask & pipe_mask)) || @@ -268,7 +271,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) pll->on = true; out: - mutex_unlock(&dev_priv->dpll.lock); + mutex_unlock(&dev_priv->display.dpll.lock); } /** @@ -291,7 +294,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) if (pll == NULL) return; - mutex_lock(&dev_priv->dpll.lock); + mutex_lock(&dev_priv->display.dpll.lock); if (drm_WARN(&dev_priv->drm, !(pll->active_mask & pipe_mask), "%s not used by [CRTC:%d:%s]\n", pll->info->name, crtc->base.base.id, crtc->base.name)) @@ -314,7 +317,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) pll->on = false; out: - mutex_unlock(&dev_priv->dpll.lock); + mutex_unlock(&dev_priv->display.dpll.lock); } static struct intel_shared_dpll * @@ -333,7 +336,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, drm_WARN_ON(&dev_priv->drm, dpll_mask & ~(BIT(I915_NUM_PLLS) - 1)); for_each_set_bit(i, &dpll_mask, I915_NUM_PLLS) { - pll = &dev_priv->dpll.shared_dplls[i]; + pll = &dev_priv->display.dpll.shared_dplls[i]; /* Only want to check enabled timings first */ if (shared_dpll[i].pipe_mask == 0) { @@ -433,9 +436,9 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) if (!state->dpll_set) return; - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { + for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { struct intel_shared_dpll *pll = - &dev_priv->dpll.shared_dplls[i]; + &dev_priv->display.dpll.shared_dplls[i]; swap(pll->state, shared_dpll[i]); } @@ -514,6 +517,13 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, udelay(200); } +static int ibx_compute_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + return 0; +} + static int ibx_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -527,7 +537,7 @@ static int ibx_get_dpll(struct intel_atomic_state *state, if (HAS_PCH_IBX(dev_priv)) { /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ i = (enum intel_dpll_id) crtc->pipe; - pll = &dev_priv->dpll.shared_dplls[i]; + pll = &dev_priv->display.dpll.shared_dplls[i]; drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] using pre-allocated %s\n", @@ -578,6 +588,7 @@ static const struct dpll_info pch_plls[] = { static const struct intel_dpll_mgr pch_pll_mgr = { .dpll_info = pch_plls, + .compute_dplls = ibx_compute_dpll, .get_dplls = ibx_get_dpll, .put_dplls = intel_put_dpll, .dump_hw_state = ibx_dump_hw_state, @@ -894,33 +905,35 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, *r2_out = best.r2; } -static struct intel_shared_dpll * -hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int +hsw_ddi_wrpll_compute_dpll(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_shared_dpll *pll; - u32 val; unsigned int p, n2, r2; hsw_ddi_calculate_wrpll(crtc_state->port_clock * 1000, &r2, &n2, &p); - val = WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL | - WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | - WRPLL_DIVIDER_POST(p); - - crtc_state->dpll_hw_state.wrpll = val; + crtc_state->dpll_hw_state.wrpll = + WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL | + WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | + WRPLL_DIVIDER_POST(p); - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_WRPLL2) | - BIT(DPLL_ID_WRPLL1)); + return 0; +} - if (!pll) - return NULL; +static struct intel_shared_dpll * +hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); - return pll; + return intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_WRPLL2) | + BIT(DPLL_ID_WRPLL1)); } static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, @@ -935,7 +948,7 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, case WRPLL_REF_SPECIAL_HSW: /* Muxed-SSC for BDW, non-SSC for non-ULT HSW. */ if (IS_HASWELL(dev_priv) && !IS_HSW_ULT(dev_priv)) { - refclk = dev_priv->dpll.ref_clks.nssc; + refclk = dev_priv->display.dpll.ref_clks.nssc; break; } fallthrough; @@ -945,7 +958,7 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, * code only cares about 5% accuracy, and spread is a max of * 0.5% downspread. */ - refclk = dev_priv->dpll.ref_clks.ssc; + refclk = dev_priv->display.dpll.ref_clks.ssc; break; case WRPLL_REF_LCPLL: refclk = 2700000; @@ -963,6 +976,24 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, return (refclk * n / 10) / (p * r) * 2; } +static int +hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + int clock = crtc_state->port_clock; + + switch (clock / 2) { + case 81000: + case 135000: + case 270000: + return 0; + default: + drm_dbg_kms(&dev_priv->drm, "Invalid clock for DP: %d\n", + clock); + return -EINVAL; + } +} + static struct intel_shared_dpll * hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) { @@ -982,8 +1013,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) pll_id = DPLL_ID_LCPLL_2700; break; default: - drm_dbg_kms(&dev_priv->drm, "Invalid clock for DP: %d\n", - clock); + MISSING_CASE(clock / 2); return NULL; } @@ -1019,18 +1049,28 @@ static int hsw_ddi_lcpll_get_freq(struct drm_i915_private *i915, return link_clock * 2; } -static struct intel_shared_dpll * -hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int +hsw_ddi_spll_compute_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); if (drm_WARN_ON(crtc->base.dev, crtc_state->port_clock / 2 != 135000)) - return NULL; + return -EINVAL; - crtc_state->dpll_hw_state.spll = SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | - SPLL_REF_MUXED_SSC; + crtc_state->dpll_hw_state.spll = + SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC; + + return 0; +} + +static struct intel_shared_dpll * +hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); return intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, BIT(DPLL_ID_SPLL)); @@ -1060,6 +1100,23 @@ static int hsw_ddi_spll_get_freq(struct drm_i915_private *i915, return link_clock * 2; } +static int hsw_compute_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); + + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + return hsw_ddi_wrpll_compute_dpll(state, crtc); + else if (intel_crtc_has_dp_encoder(crtc_state)) + return hsw_ddi_lcpll_compute_dpll(crtc_state); + else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) + return hsw_ddi_spll_compute_dpll(state, crtc); + else + return -EINVAL; +} + static int hsw_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -1088,12 +1145,12 @@ static int hsw_get_dpll(struct intel_atomic_state *state, static void hsw_update_dpll_ref_clks(struct drm_i915_private *i915) { - i915->dpll.ref_clks.ssc = 135000; + i915->display.dpll.ref_clks.ssc = 135000; /* Non-SSC is only used on non-ULT HSW. */ if (intel_de_read(i915, FUSE_STRAP3) & HSW_REF_CLK_SELECT) - i915->dpll.ref_clks.nssc = 24000; + i915->display.dpll.ref_clks.nssc = 24000; else - i915->dpll.ref_clks.nssc = 135000; + i915->display.dpll.ref_clks.nssc = 135000; } static void hsw_dump_hw_state(struct drm_i915_private *dev_priv, @@ -1153,6 +1210,7 @@ static const struct dpll_info hsw_plls[] = { static const struct intel_dpll_mgr hsw_pll_mgr = { .dpll_info = hsw_plls, + .compute_dplls = hsw_compute_dpll, .get_dplls = hsw_get_dpll, .put_dplls = intel_put_dpll, .update_ref_clks = hsw_update_dpll_ref_clks, @@ -1545,10 +1603,8 @@ skip_remaining_dividers: break; } - if (!ctx.p) { - DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock); + if (!ctx.p) return -EINVAL; - } /* * gcc incorrectly analyses that these can be used without being @@ -1578,7 +1634,7 @@ static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); ret = skl_ddi_calculate_wrpll(crtc_state->port_clock * 1000, - i915->dpll.ref_clks.nssc, &wrpll_params); + i915->display.dpll.ref_clks.nssc, &wrpll_params); if (ret) return ret; @@ -1603,7 +1659,7 @@ static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, const struct intel_dpll_hw_state *pll_state) { - int ref_clock = i915->dpll.ref_clks.nssc; + int ref_clock = i915->display.dpll.ref_clks.nssc; u32 p0, p1, p2, dco_freq; p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK; @@ -1741,23 +1797,28 @@ static int skl_ddi_lcpll_get_freq(struct drm_i915_private *i915, return link_clock * 2; } -static int skl_get_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +static int skl_compute_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 intel_shared_dpll *pll; - int ret; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - ret = skl_ddi_hdmi_pll_dividers(crtc_state); + return skl_ddi_hdmi_pll_dividers(crtc_state); else if (intel_crtc_has_dp_encoder(crtc_state)) - ret = skl_ddi_dp_set_dpll_hw_state(crtc_state); + return skl_ddi_dp_set_dpll_hw_state(crtc_state); else - ret = -EINVAL; - if (ret) - return ret; + return -EINVAL; +} + +static int skl_get_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 intel_shared_dpll *pll; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) pll = intel_find_shared_dpll(state, crtc, @@ -1797,7 +1858,7 @@ static int skl_ddi_pll_get_freq(struct drm_i915_private *i915, static void skl_update_dpll_ref_clks(struct drm_i915_private *i915) { /* No SSC ref */ - i915->dpll.ref_clks.nssc = i915->cdclk.hw.ref; + i915->display.dpll.ref_clks.nssc = i915->cdclk.hw.ref; } static void skl_dump_hw_state(struct drm_i915_private *dev_priv, @@ -1834,6 +1895,7 @@ static const struct dpll_info skl_plls[] = { static const struct intel_dpll_mgr skl_pll_mgr = { .dpll_info = skl_plls, + .compute_dplls = skl_compute_dpll, .get_dplls = skl_get_dpll, .put_dplls = intel_put_dpll, .update_ref_clks = skl_update_dpll_ref_clks, @@ -2081,19 +2143,14 @@ bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, struct dpll *clk_div) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); /* Calculate HDMI div */ /* * FIXME: tie the following calculation into * i9xx_crtc_compute_clock */ - if (!bxt_find_best_dpll(crtc_state, clk_div)) { - drm_dbg(&i915->drm, "no PLL dividers found for clock %d pipe %c\n", - crtc_state->port_clock, - pipe_name(crtc->pipe)); + if (!bxt_find_best_dpll(crtc_state, clk_div)) return -EINVAL; - } drm_WARN_ON(&i915->drm, clk_div->m1 != 2); @@ -2114,7 +2171,7 @@ static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state, } } - chv_calc_dpll_params(i915->dpll.ref_clks.nssc, clk_div); + chv_calc_dpll_params(i915->display.dpll.ref_clks.nssc, clk_div); drm_WARN_ON(&i915->drm, clk_div->vco == 0 || clk_div->dot != crtc_state->port_clock); @@ -2222,7 +2279,22 @@ static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915, clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0); clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0); - return chv_calc_dpll_params(i915->dpll.ref_clks.nssc, &clock); + return chv_calc_dpll_params(i915->display.dpll.ref_clks.nssc, &clock); +} + +static int bxt_compute_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); + + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + return bxt_ddi_hdmi_set_dpll_hw_state(crtc_state); + else if (intel_crtc_has_dp_encoder(crtc_state)) + return bxt_ddi_dp_set_dpll_hw_state(crtc_state); + else + return -EINVAL; } static int bxt_get_dpll(struct intel_atomic_state *state, @@ -2234,16 +2306,6 @@ static int bxt_get_dpll(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; enum intel_dpll_id id; - int ret; - - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - ret = bxt_ddi_hdmi_set_dpll_hw_state(crtc_state); - else if (intel_crtc_has_dp_encoder(crtc_state)) - ret = bxt_ddi_dp_set_dpll_hw_state(crtc_state); - else - ret = -EINVAL; - if (ret) - return ret; /* 1:1 mapping between ports and PLLs */ id = (enum intel_dpll_id) encoder->port; @@ -2262,8 +2324,8 @@ static int bxt_get_dpll(struct intel_atomic_state *state, static void bxt_update_dpll_ref_clks(struct drm_i915_private *i915) { - i915->dpll.ref_clks.ssc = 100000; - i915->dpll.ref_clks.nssc = 100000; + i915->display.dpll.ref_clks.ssc = 100000; + i915->display.dpll.ref_clks.nssc = 100000; /* DSI non-SSC ref 19.2MHz */ } @@ -2302,6 +2364,7 @@ static const struct dpll_info bxt_plls[] = { static const struct intel_dpll_mgr bxt_pll_mgr = { .dpll_info = bxt_plls, + .compute_dplls = bxt_compute_dpll, .get_dplls = bxt_get_dpll, .put_dplls = intel_put_dpll, .update_ref_clks = bxt_update_dpll_ref_clks, @@ -2396,7 +2459,7 @@ static void icl_wrpll_params_populate(struct skl_wrpll_params *params, } /* - * Display WA #22010492432: ehl, tgl, adl-p + * Display WA #22010492432: ehl, tgl, adl-s, adl-p * Program half of the nominal DCO divider fraction value. */ static bool @@ -2404,8 +2467,8 @@ ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) { return ((IS_PLATFORM(i915, INTEL_ELKHARTLAKE) && IS_JSL_EHL_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) || - IS_TIGERLAKE(i915) || IS_ALDERLAKE_P(i915)) && - i915->dpll.ref_clks.nssc == 38400; + IS_TIGERLAKE(i915) || IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) && + i915->display.dpll.ref_clks.nssc == 38400; } struct icl_combo_pll_params { @@ -2499,7 +2562,7 @@ static int icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); const struct icl_combo_pll_params *params = - dev_priv->dpll.ref_clks.nssc == 24000 ? + dev_priv->display.dpll.ref_clks.nssc == 24000 ? icl_dp_combo_pll_24MHz_values : icl_dp_combo_pll_19_2MHz_values; int clock = crtc_state->port_clock; @@ -2522,9 +2585,9 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (DISPLAY_VER(dev_priv) >= 12) { - switch (dev_priv->dpll.ref_clks.nssc) { + switch (dev_priv->display.dpll.ref_clks.nssc) { default: - MISSING_CASE(dev_priv->dpll.ref_clks.nssc); + MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc); fallthrough; case 19200: case 38400: @@ -2535,9 +2598,9 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, break; } } else { - switch (dev_priv->dpll.ref_clks.nssc) { + switch (dev_priv->display.dpll.ref_clks.nssc) { default: - MISSING_CASE(dev_priv->dpll.ref_clks.nssc); + MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc); fallthrough; case 19200: case 38400: @@ -2567,7 +2630,7 @@ static int icl_ddi_tbt_pll_get_freq(struct drm_i915_private *i915, static int icl_wrpll_ref_clock(struct drm_i915_private *i915) { - int ref_clock = i915->dpll.ref_clks.nssc; + int ref_clock = i915->display.dpll.ref_clks.nssc; /* * For ICL+, the spec states: if reference frequency is 38.4, @@ -2794,7 +2857,7 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, struct intel_dpll_hw_state *pll_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - int refclk_khz = dev_priv->dpll.ref_clks.nssc; + int refclk_khz = dev_priv->display.dpll.ref_clks.nssc; int clock = crtc_state->port_clock; u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; u32 iref_ndiv, iref_trim, iref_pulse_w; @@ -2809,11 +2872,8 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, ret = icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz, pll_state, is_dkl); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "Failed to find divisors for clock %d\n", clock); + if (ret) return ret; - } m1div = 2; m2div_int = dco_khz / (refclk_khz * m1div); @@ -2823,12 +2883,8 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, m2div_int = dco_khz / (refclk_khz * m1div); } - if (m2div_int > 255) { - drm_dbg_kms(&dev_priv->drm, - "Failed to find mdiv for clock %d\n", - clock); + if (m2div_int > 255) return -EINVAL; - } } m2div_rem = dco_khz % (refclk_khz * m1div); @@ -3007,7 +3063,7 @@ static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *dev_priv, u32 m1, m2_int, m2_frac, div1, div2, ref_clock; u64 tmp; - ref_clock = dev_priv->dpll.ref_clks.nssc; + ref_clock = dev_priv->display.dpll.ref_clks.nssc; if (DISPLAY_VER(dev_priv) >= 12) { m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK; @@ -3119,18 +3175,15 @@ static u32 intel_get_hti_plls(struct drm_i915_private *i915) return REG_FIELD_GET(HDPORT_DPLL_USED_MASK, i915->hti_state); } -static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +static int icl_compute_combo_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct skl_wrpll_params pll_params = { }; struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum port port = encoder->port; - unsigned long dpll_mask; + struct skl_wrpll_params pll_params = {}; int ret; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) || @@ -3139,14 +3192,26 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, else ret = icl_calc_dp_combo_pll(crtc_state, &pll_params); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "Could not calculate combo PHY PLL state.\n"); + if (ret) return ret; - } icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); + return 0; +} + +static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + 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 port port = encoder->port; + unsigned long dpll_mask; + if (IS_ALDERLAKE_S(dev_priv)) { dpll_mask = BIT(DPLL_ID_DG1_DPLL3) | @@ -3183,12 +3248,8 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, dpll_mask); - if (!port_dpll->pll) { - drm_dbg_kms(&dev_priv->drm, - "No combo PHY PLL found for [ENCODER:%d:%s]\n", - encoder->base.base.id, encoder->base.name); + if (!port_dpll->pll) return -EINVAL; - } intel_reference_shared_dpll(state, crtc, port_dpll->pll, &port_dpll->hw_state); @@ -3198,47 +3259,55 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, return 0; } -static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct skl_wrpll_params pll_params = { }; - struct icl_port_dpll *port_dpll; - enum intel_dpll_id dpll_id; + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + struct skl_wrpll_params pll_params = {}; int ret; port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; ret = icl_calc_tbt_pll(crtc_state, &pll_params); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "Could not calculate TBT PLL state.\n"); + if (ret) return ret; - } icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; + ret = icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state); + if (ret) + return ret; + + return 0; +} + +static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + 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 dpll_id; + int ret; + + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, BIT(DPLL_ID_ICL_TBTPLL)); - if (!port_dpll->pll) { - drm_dbg_kms(&dev_priv->drm, "No TBT-ALT PLL found\n"); + if (!port_dpll->pll) return -EINVAL; - } intel_reference_shared_dpll(state, crtc, port_dpll->pll, &port_dpll->hw_state); port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; - ret = icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state); - if (ret) { - drm_dbg_kms(&dev_priv->drm, - "Could not calculate MG PHY PLL state.\n"); - goto err_unreference_tbt_pll; - } - dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv, encoder->port)); port_dpll->pll = intel_find_shared_dpll(state, crtc, @@ -3246,7 +3315,6 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, BIT(dpll_id)); if (!port_dpll->pll) { ret = -EINVAL; - drm_dbg_kms(&dev_priv->drm, "No MG PHY PLL found\n"); goto err_unreference_tbt_pll; } intel_reference_shared_dpll(state, crtc, @@ -3263,6 +3331,23 @@ err_unreference_tbt_pll: return ret; } +static int icl_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + + if (intel_phy_is_combo(dev_priv, phy)) + return icl_compute_combo_phy_dpll(state, crtc); + else if (intel_phy_is_tc(dev_priv, phy)) + return icl_compute_tc_phy_dplls(state, crtc); + + MISSING_CASE(phy); + + return 0; +} + static int icl_get_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -3355,7 +3440,7 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->mg_pll_tdc_coldst_bias = intel_de_read(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port)); - if (dev_priv->dpll.ref_clks.nssc == 38400) { + if (dev_priv->display.dpll.ref_clks.nssc == 38400) { hw_state->mg_pll_tdc_coldst_bias_mask = MG_PLL_TDC_COLDST_COLDSTART; hw_state->mg_pll_bias_mask = 0; } else { @@ -3882,7 +3967,7 @@ static void mg_pll_disable(struct drm_i915_private *dev_priv, static void icl_update_dpll_ref_clks(struct drm_i915_private *i915) { /* No SSC ref */ - i915->dpll.ref_clks.nssc = i915->cdclk.hw.ref; + i915->display.dpll.ref_clks.nssc = i915->cdclk.hw.ref; } static void icl_dump_hw_state(struct drm_i915_private *dev_priv, @@ -3943,6 +4028,7 @@ static const struct dpll_info icl_plls[] = { static const struct intel_dpll_mgr icl_pll_mgr = { .dpll_info = icl_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, @@ -3959,6 +4045,7 @@ static const struct dpll_info ehl_plls[] = { static const struct intel_dpll_mgr ehl_pll_mgr = { .dpll_info = ehl_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, @@ -3987,6 +4074,7 @@ static const struct dpll_info tgl_plls[] = { static const struct intel_dpll_mgr tgl_pll_mgr = { .dpll_info = tgl_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, @@ -4003,6 +4091,7 @@ static const struct dpll_info rkl_plls[] = { static const struct intel_dpll_mgr rkl_pll_mgr = { .dpll_info = rkl_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, @@ -4019,6 +4108,7 @@ static const struct dpll_info dg1_plls[] = { static const struct intel_dpll_mgr dg1_pll_mgr = { .dpll_info = dg1_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, @@ -4035,6 +4125,7 @@ static const struct dpll_info adls_plls[] = { static const struct intel_dpll_mgr adls_pll_mgr = { .dpll_info = adls_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, @@ -4054,6 +4145,7 @@ static const struct dpll_info adlp_plls[] = { static const struct intel_dpll_mgr adlp_pll_mgr = { .dpll_info = adlp_plls, + .compute_dplls = icl_compute_dplls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, @@ -4100,7 +4192,7 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv) dpll_mgr = &pch_pll_mgr; if (!dpll_mgr) { - dev_priv->dpll.num_shared_dpll = 0; + dev_priv->display.dpll.num_shared_dpll = 0; return; } @@ -4108,14 +4200,41 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv) for (i = 0; dpll_info[i].name; i++) { drm_WARN_ON(&dev_priv->drm, i != dpll_info[i].id); - dev_priv->dpll.shared_dplls[i].info = &dpll_info[i]; + dev_priv->display.dpll.shared_dplls[i].info = &dpll_info[i]; } - dev_priv->dpll.mgr = dpll_mgr; - dev_priv->dpll.num_shared_dpll = i; - mutex_init(&dev_priv->dpll.lock); + dev_priv->display.dpll.mgr = dpll_mgr; + dev_priv->display.dpll.num_shared_dpll = i; + mutex_init(&dev_priv->display.dpll.lock); - BUG_ON(dev_priv->dpll.num_shared_dpll > I915_NUM_PLLS); + BUG_ON(dev_priv->display.dpll.num_shared_dpll > I915_NUM_PLLS); +} + +/** + * intel_compute_shared_dplls - compute DPLL state CRTC and encoder combination + * @state: atomic state + * @crtc: CRTC to compute DPLLs for + * @encoder: encoder + * + * This function computes the DPLL state for the given CRTC and encoder. + * + * The new configuration in the atomic commit @state is made effective by + * calling intel_shared_dpll_swap_state(). + * + * Returns: + * 0 on success, negative error code on falure. + */ +int intel_compute_shared_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; + + if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) + return -EINVAL; + + return dpll_mgr->compute_dplls(state, crtc, encoder); } /** @@ -4143,7 +4262,7 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state, struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll.mgr; + const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) return -EINVAL; @@ -4166,7 +4285,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll.mgr; + const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; /* * FIXME: this function is called for every platform having a @@ -4195,7 +4314,7 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll.mgr; + const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) return; @@ -4266,16 +4385,16 @@ static void readout_dpll_hw_state(struct drm_i915_private *i915, void intel_dpll_update_ref_clks(struct drm_i915_private *i915) { - if (i915->dpll.mgr && i915->dpll.mgr->update_ref_clks) - i915->dpll.mgr->update_ref_clks(i915); + if (i915->display.dpll.mgr && i915->display.dpll.mgr->update_ref_clks) + i915->display.dpll.mgr->update_ref_clks(i915); } void intel_dpll_readout_hw_state(struct drm_i915_private *i915) { int i; - for (i = 0; i < i915->dpll.num_shared_dpll; i++) - readout_dpll_hw_state(i915, &i915->dpll.shared_dplls[i]); + for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) + readout_dpll_hw_state(i915, &i915->display.dpll.shared_dplls[i]); } static void sanitize_dpll_state(struct drm_i915_private *i915, @@ -4301,8 +4420,8 @@ void intel_dpll_sanitize_state(struct drm_i915_private *i915) { int i; - for (i = 0; i < i915->dpll.num_shared_dpll; i++) - sanitize_dpll_state(i915, &i915->dpll.shared_dplls[i]); + for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) + sanitize_dpll_state(i915, &i915->display.dpll.shared_dplls[i]); } /** @@ -4315,8 +4434,8 @@ void intel_dpll_sanitize_state(struct drm_i915_private *i915) void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, const struct intel_dpll_hw_state *hw_state) { - if (dev_priv->dpll.mgr) { - dev_priv->dpll.mgr->dump_hw_state(dev_priv, hw_state); + if (dev_priv->display.dpll.mgr) { + dev_priv->display.dpll.mgr->dump_hw_state(dev_priv, hw_state); } else { /* fallback for platforms that don't use the shared dpll * infrastructure @@ -4330,3 +4449,91 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, hw_state->fp1); } } + +static void +verify_single_dpll_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc, + struct intel_crtc_state *new_crtc_state) +{ + struct intel_dpll_hw_state dpll_hw_state; + u8 pipe_mask; + bool active; + + memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); + + drm_dbg_kms(&dev_priv->drm, "%s\n", pll->info->name); + + active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state); + + if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) { + I915_STATE_WARN(!pll->on && pll->active_mask, + "pll in active use but not on in sw tracking\n"); + I915_STATE_WARN(pll->on && !pll->active_mask, + "pll is on but not used by any active pipe\n"); + I915_STATE_WARN(pll->on != active, + "pll on state mismatch (expected %i, found %i)\n", + pll->on, active); + } + + if (!crtc) { + I915_STATE_WARN(pll->active_mask & ~pll->state.pipe_mask, + "more active pll users than references: 0x%x vs 0x%x\n", + pll->active_mask, pll->state.pipe_mask); + + return; + } + + pipe_mask = BIT(crtc->pipe); + + if (new_crtc_state->hw.active) + I915_STATE_WARN(!(pll->active_mask & pipe_mask), + "pll active mismatch (expected pipe %c in active mask 0x%x)\n", + pipe_name(crtc->pipe), pll->active_mask); + else + I915_STATE_WARN(pll->active_mask & pipe_mask, + "pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n", + pipe_name(crtc->pipe), pll->active_mask); + + I915_STATE_WARN(!(pll->state.pipe_mask & pipe_mask), + "pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n", + pipe_mask, pll->state.pipe_mask); + + I915_STATE_WARN(pll->on && memcmp(&pll->state.hw_state, + &dpll_hw_state, + sizeof(dpll_hw_state)), + "pll hw state mismatch\n"); +} + +void intel_shared_dpll_state_verify(struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + if (new_crtc_state->shared_dpll) + verify_single_dpll_state(dev_priv, new_crtc_state->shared_dpll, + crtc, new_crtc_state); + + if (old_crtc_state->shared_dpll && + old_crtc_state->shared_dpll != new_crtc_state->shared_dpll) { + u8 pipe_mask = BIT(crtc->pipe); + struct intel_shared_dpll *pll = old_crtc_state->shared_dpll; + + I915_STATE_WARN(pll->active_mask & pipe_mask, + "pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n", + pipe_name(crtc->pipe), pll->active_mask); + I915_STATE_WARN(pll->state.pipe_mask & pipe_mask, + "pll enabled crtcs mismatch (found %x in enabled mask (0x%x))\n", + pipe_name(crtc->pipe), pll->state.pipe_mask); + } +} + +void intel_shared_dpll_verify_disabled(struct drm_i915_private *i915) +{ + int i; + + for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) + verify_single_dpll_state(i915, &i915->display.dpll.shared_dplls[i], + NULL, NULL); +} diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index f7c96a1f13c8..3247dc300ae4 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -336,6 +336,9 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, bool state); #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) +int intel_compute_shared_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); int intel_reserve_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); @@ -365,4 +368,9 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port); bool intel_dpll_is_combophy(enum intel_dpll_id id); +void intel_shared_dpll_state_verify(struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state); +void intel_shared_dpll_verify_disabled(struct drm_i915_private *i915); + #endif /* _INTEL_DPLL_MGR_H_ */ diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 166caf293f7b..7da4a9cbe4ba 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -217,9 +217,6 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, { struct intel_crtc *crtc; - if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) - return; - for_each_intel_crtc(&dev_priv->drm, crtc) { unsigned int frontbuffer_bits; diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index 389a8c24cdc1..35e121cd226c 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -102,7 +102,7 @@ intel_dsi_get_panel_orientation(struct intel_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->base.dev); enum drm_panel_orientation orientation; - orientation = dev_priv->vbt.dsi.orientation; + orientation = connector->panel.vbt.dsi.orientation; if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) return orientation; diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index eafef0a87fea..ce80bd8be519 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -89,9 +89,6 @@ struct intel_dsi { u8 escape_clk_div; u8 dual_link; - u16 dcs_backlight_ports; - u16 dcs_cabc_ports; - /* RGB or BGR */ bool bgr_enabled; diff --git a/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c b/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c index 7d234429e71e..20e466d843ce 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c @@ -53,7 +53,7 @@ static u32 dcs_get_backlight(struct intel_connector *connector, enum pipe unused enum port port; size_t len = panel->backlight.max > U8_MAX ? 2 : 1; - for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) { + for_each_dsi_port(port, panel->vbt.dsi.bl_ports) { dsi_device = intel_dsi->dsi_hosts[port]->device; mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, &data, len); @@ -80,7 +80,7 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 data[1] = level; } - for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) { + for_each_dsi_port(port, panel->vbt.dsi.bl_ports) { dsi_device = intel_dsi->dsi_hosts[port]->device; mode_flags = dsi_device->mode_flags; dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM; @@ -93,12 +93,13 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 static void dcs_disable_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder)); + struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel; struct mipi_dsi_device *dsi_device; enum port port; dcs_set_backlight(conn_state, 0); - for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) { + for_each_dsi_port(port, panel->vbt.dsi.cabc_ports) { u8 cabc = POWER_SAVE_OFF; dsi_device = intel_dsi->dsi_hosts[port]->device; @@ -106,7 +107,7 @@ static void dcs_disable_backlight(const struct drm_connector_state *conn_state, &cabc, sizeof(cabc)); } - for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) { + for_each_dsi_port(port, panel->vbt.dsi.bl_ports) { u8 ctrl = 0; dsi_device = intel_dsi->dsi_hosts[port]->device; @@ -127,10 +128,11 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder)); + struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel; struct mipi_dsi_device *dsi_device; enum port port; - for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) { + for_each_dsi_port(port, panel->vbt.dsi.bl_ports) { u8 ctrl = 0; dsi_device = intel_dsi->dsi_hosts[port]->device; @@ -146,7 +148,7 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state, &ctrl, sizeof(ctrl)); } - for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) { + for_each_dsi_port(port, panel->vbt.dsi.cabc_ports) { u8 cabc = POWER_SAVE_MEDIUM; dsi_device = intel_dsi->dsi_hosts[port]->device; @@ -160,12 +162,10 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state, static int dcs_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_panel *panel = &connector->panel; - if (dev_priv->vbt.backlight.brightness_precision_bits > 8) - panel->backlight.max = (1 << dev_priv->vbt.backlight.brightness_precision_bits) - 1; + if (panel->vbt.backlight.brightness_precision_bits > 8) + panel->backlight.max = (1 << panel->vbt.backlight.brightness_precision_bits) - 1; else panel->backlight.max = PANEL_PWM_MAX_VALUE; @@ -185,11 +185,10 @@ static const struct intel_panel_bl_funcs dcs_bl_funcs = { int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector) { struct drm_device *dev = intel_connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_encoder *encoder = intel_attached_encoder(intel_connector); struct intel_panel *panel = &intel_connector->panel; - if (dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS) + if (panel->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS) return -ENODEV; if (drm_WARN_ON(dev, encoder->type != INTEL_OUTPUT_DSI)) diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index f370e9c4350d..75e8cc4337c9 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -125,9 +125,25 @@ struct i2c_adapter_lookup { #define ICL_GPIO_DDPA_CTRLCLK_2 8 #define ICL_GPIO_DDPA_CTRLDATA_2 9 -static enum port intel_dsi_seq_port_to_port(u8 port) +static enum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi, + u8 seq_port) { - return port ? PORT_C : PORT_A; + /* + * If single link DSI is being used on any port, the VBT sequence block + * send packet apparently always has 0 for the port. Just use the port + * we have configured, and ignore the sequence block port. + */ + if (hweight8(intel_dsi->ports) == 1) + return ffs(intel_dsi->ports) - 1; + + if (seq_port) { + if (intel_dsi->ports & PORT_B) + return PORT_B; + else if (intel_dsi->ports & PORT_C) + return PORT_C; + } + + return PORT_A; } static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, @@ -149,15 +165,10 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, seq_port = (flags >> MIPI_PORT_SHIFT) & 3; - /* For DSI single link on Port A & C, the seq_port value which is - * parsed from Sequence Block#53 of VBT has been set to 0 - * Now, read/write of packets for the DSI single link on Port A and - * Port C will based on the DVO port from VBT block 2. - */ - if (intel_dsi->ports == (1 << PORT_C)) - port = PORT_C; - else - port = intel_dsi_seq_port_to_port(seq_port); + port = intel_dsi_seq_port_to_port(intel_dsi, seq_port); + + if (drm_WARN_ON(&dev_priv->drm, !intel_dsi->dsi_hosts[port])) + goto out; dsi_device = intel_dsi->dsi_hosts[port]->device; if (!dsi_device) { @@ -229,9 +240,10 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) return data; } -static void vlv_exec_gpio(struct drm_i915_private *dev_priv, +static void vlv_exec_gpio(struct intel_connector *connector, u8 gpio_source, u8 gpio_index, bool value) { + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct gpio_map *map; u16 pconf0, padval; u32 tmp; @@ -245,7 +257,7 @@ static void vlv_exec_gpio(struct drm_i915_private *dev_priv, map = &vlv_gpio_table[gpio_index]; - if (dev_priv->vbt.dsi.seq_version >= 3) { + if (connector->panel.vbt.dsi.seq_version >= 3) { /* XXX: this assumes vlv_gpio_table only has NC GPIOs. */ port = IOSF_PORT_GPIO_NC; } else { @@ -276,14 +288,15 @@ static void vlv_exec_gpio(struct drm_i915_private *dev_priv, vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO)); } -static void chv_exec_gpio(struct drm_i915_private *dev_priv, +static void chv_exec_gpio(struct intel_connector *connector, u8 gpio_source, u8 gpio_index, bool value) { + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u16 cfg0, cfg1; u16 family_num; u8 port; - if (dev_priv->vbt.dsi.seq_version >= 3) { + if (connector->panel.vbt.dsi.seq_version >= 3) { if (gpio_index >= CHV_GPIO_IDX_START_SE) { /* XXX: it's unclear whether 255->57 is part of SE. */ gpio_index -= CHV_GPIO_IDX_START_SE; @@ -329,9 +342,10 @@ static void chv_exec_gpio(struct drm_i915_private *dev_priv, vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO)); } -static void bxt_exec_gpio(struct drm_i915_private *dev_priv, +static void bxt_exec_gpio(struct intel_connector *connector, u8 gpio_source, u8 gpio_index, bool value) { + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); /* XXX: this table is a quick ugly hack. */ static struct gpio_desc *bxt_gpio_table[U8_MAX + 1]; struct gpio_desc *gpio_desc = bxt_gpio_table[gpio_index]; @@ -355,9 +369,11 @@ static void bxt_exec_gpio(struct drm_i915_private *dev_priv, gpiod_set_value(gpio_desc, value); } -static void icl_exec_gpio(struct drm_i915_private *dev_priv, +static void icl_exec_gpio(struct intel_connector *connector, u8 gpio_source, u8 gpio_index, bool value) { + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n"); } @@ -365,18 +381,19 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_connector *connector = intel_dsi->attached_connector; u8 gpio_source, gpio_index = 0, gpio_number; bool value; drm_dbg_kms(&dev_priv->drm, "\n"); - if (dev_priv->vbt.dsi.seq_version >= 3) + if (connector->panel.vbt.dsi.seq_version >= 3) gpio_index = *data++; gpio_number = *data++; /* gpio source in sequence v2 only */ - if (dev_priv->vbt.dsi.seq_version == 2) + if (connector->panel.vbt.dsi.seq_version == 2) gpio_source = (*data >> 1) & 3; else gpio_source = 0; @@ -385,13 +402,13 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) value = *data++ & 1; if (DISPLAY_VER(dev_priv) >= 11) - icl_exec_gpio(dev_priv, gpio_source, gpio_index, value); + icl_exec_gpio(connector, gpio_source, gpio_index, value); else if (IS_VALLEYVIEW(dev_priv)) - vlv_exec_gpio(dev_priv, gpio_source, gpio_number, value); + vlv_exec_gpio(connector, gpio_source, gpio_number, value); else if (IS_CHERRYVIEW(dev_priv)) - chv_exec_gpio(dev_priv, gpio_source, gpio_number, value); + chv_exec_gpio(connector, gpio_source, gpio_number, value); else - bxt_exec_gpio(dev_priv, gpio_source, gpio_index, value); + bxt_exec_gpio(connector, gpio_source, gpio_index, value); return data; } @@ -574,14 +591,15 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi, enum mipi_seq seq_id) { struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); + struct intel_connector *connector = intel_dsi->attached_connector; const u8 *data; fn_mipi_elem_exec mipi_elem_exec; if (drm_WARN_ON(&dev_priv->drm, - seq_id >= ARRAY_SIZE(dev_priv->vbt.dsi.sequence))) + seq_id >= ARRAY_SIZE(connector->panel.vbt.dsi.sequence))) return; - data = dev_priv->vbt.dsi.sequence[seq_id]; + data = connector->panel.vbt.dsi.sequence[seq_id]; if (!data) return; @@ -594,7 +612,7 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi, data++; /* Skip Size of Sequence. */ - if (dev_priv->vbt.dsi.seq_version >= 3) + if (connector->panel.vbt.dsi.seq_version >= 3) data += 4; while (1) { @@ -610,7 +628,7 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi, mipi_elem_exec = NULL; /* Size of Operation. */ - if (dev_priv->vbt.dsi.seq_version >= 3) + if (connector->panel.vbt.dsi.seq_version >= 3) operation_size = *data++; if (mipi_elem_exec) { @@ -658,10 +676,10 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi, void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) { - struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); + struct intel_connector *connector = intel_dsi->attached_connector; /* For v3 VBTs in vid-mode the delays are part of the VBT sequences */ - if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3) + if (is_vid_mode(intel_dsi) && connector->panel.vbt.dsi.seq_version >= 3) return; msleep(msec); @@ -723,9 +741,10 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; - struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps; - struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode; + struct intel_connector *connector = intel_dsi->attached_connector; + struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; + struct mipi_pps_data *pps = connector->panel.vbt.dsi.pps; + struct drm_display_mode *mode = connector->panel.vbt.lfp_lvds_vbt_mode; u16 burst_mode_ratio; enum port port; @@ -861,7 +880,8 @@ void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; + struct intel_connector *connector = intel_dsi->attached_connector; + struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; bool want_backlight_gpio = false; bool want_panel_gpio = false; @@ -916,7 +936,8 @@ void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; + struct intel_connector *connector = intel_dsi->attached_connector; + struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; if (intel_dsi->gpio_panel) { gpiod_put(intel_dsi->gpio_panel); diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index ff69e5510a13..eefa33c555ac 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -3,6 +3,7 @@ * Copyright © 2021 Intel Corporation */ +#include <drm/drm_blend.h> #include <drm/drm_framebuffer.h> #include <drm/drm_modeset_helper.h> diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index bbdc34a23d54..0ece995ae766 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -40,6 +40,7 @@ #include <linux/string_helpers.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include "i915_drv.h" @@ -54,7 +55,7 @@ #define for_each_fbc_id(__dev_priv, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ - for_each_if(INTEL_INFO(__dev_priv)->display.fbc_mask & BIT(__fbc_id)) + for_each_if(RUNTIME_INFO(__dev_priv)->fbc_mask & BIT(__fbc_id)) #define for_each_intel_fbc(__dev_priv, __fbc, __fbc_id) \ for_each_fbc_id((__dev_priv), (__fbc_id)) \ @@ -813,8 +814,8 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc) static void intel_fbc_program_workarounds(struct intel_fbc *fbc) { - /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,dg2,adlp */ - if (DISPLAY_VER(fbc->i915) >= 11) + /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp */ + if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915)) intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); } @@ -1097,6 +1098,12 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } + /* Wa_14016291713 */ + if (IS_DISPLAY_VER(i915, 12, 13) && crtc_state->has_psr) { + plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)"; + return 0; + } + if (!pixel_format_is_valid(plane_state)) { plane_state->no_fbc_reason = "pixel format not supported"; return 0; @@ -1703,10 +1710,10 @@ void intel_fbc_init(struct drm_i915_private *i915) enum intel_fbc_id fbc_id; if (!drm_mm_initialized(&i915->mm.stolen)) - mkwrite_device_info(i915)->display.fbc_mask = 0; + RUNTIME_INFO(i915)->fbc_mask = 0; if (need_fbc_vtd_wa(i915)) - mkwrite_device_info(i915)->display.fbc_mask = 0; + RUNTIME_INFO(i915)->fbc_mask = 0; i915->params.enable_fbc = intel_sanitize_fbc_option(i915); drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n", diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index db60143295ec..4adb98afe6ff 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -19,6 +19,7 @@ struct intel_plane_state; enum intel_fbc_id { INTEL_FBC_A, + INTEL_FBC_B, I915_MAX_FBCS, }; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 1922f62d04c0..94081bf05b99 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -500,7 +500,7 @@ static void intel_fbdev_suspend_worker(struct work_struct *work) { intel_fbdev_set_suspend(&container_of(work, struct drm_i915_private, - fbdev_suspend_work)->drm, + display.fbdev.suspend_work)->drm, FBINFO_STATE_RUNNING, true); } @@ -530,8 +530,8 @@ int intel_fbdev_init(struct drm_device *dev) return ret; } - dev_priv->fbdev = ifbdev; - INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker); + dev_priv->display.fbdev.fbdev = ifbdev; + INIT_WORK(&dev_priv->display.fbdev.suspend_work, intel_fbdev_suspend_worker); return 0; } @@ -548,7 +548,7 @@ static void intel_fbdev_initial_config(void *data, async_cookie_t cookie) void intel_fbdev_initial_config_async(struct drm_device *dev) { - struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; + struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev; if (!ifbdev) return; @@ -568,12 +568,12 @@ static void intel_fbdev_sync(struct intel_fbdev *ifbdev) void intel_fbdev_unregister(struct drm_i915_private *dev_priv) { - struct intel_fbdev *ifbdev = dev_priv->fbdev; + struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev; if (!ifbdev) return; - cancel_work_sync(&dev_priv->fbdev_suspend_work); + cancel_work_sync(&dev_priv->display.fbdev.suspend_work); if (!current_is_async()) intel_fbdev_sync(ifbdev); @@ -582,7 +582,7 @@ void intel_fbdev_unregister(struct drm_i915_private *dev_priv) void intel_fbdev_fini(struct drm_i915_private *dev_priv) { - struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->fbdev); + struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->display.fbdev.fbdev); if (!ifbdev) return; @@ -596,7 +596,7 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv) */ static void intel_fbdev_hpd_set_suspend(struct drm_i915_private *i915, int state) { - struct intel_fbdev *ifbdev = i915->fbdev; + struct intel_fbdev *ifbdev = i915->display.fbdev.fbdev; bool send_hpd = false; mutex_lock(&ifbdev->hpd_lock); @@ -614,7 +614,7 @@ static void intel_fbdev_hpd_set_suspend(struct drm_i915_private *i915, int state void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_fbdev *ifbdev = dev_priv->fbdev; + struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev; struct fb_info *info; if (!ifbdev || !ifbdev->vma) @@ -631,7 +631,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous * ourselves, so only flush outstanding work upon suspend! */ if (state != FBINFO_STATE_RUNNING) - flush_work(&dev_priv->fbdev_suspend_work); + flush_work(&dev_priv->display.fbdev.suspend_work); console_lock(); } else { @@ -645,7 +645,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous /* Don't block our own workqueue as this can * be run in parallel with other i915.ko tasks. */ - schedule_work(&dev_priv->fbdev_suspend_work); + schedule_work(&dev_priv->display.fbdev.suspend_work); return; } } @@ -666,7 +666,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous void intel_fbdev_output_poll_changed(struct drm_device *dev) { - struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; + struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev; bool send_hpd; if (!ifbdev) @@ -685,7 +685,7 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev) void intel_fbdev_restore_mode(struct drm_device *dev) { - struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; + struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev; if (!ifbdev) return; diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 67d2484afbaa..03ad5f5c8417 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -113,7 +113,7 @@ void intel_fdi_link_train(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - dev_priv->fdi_funcs->fdi_link_train(crtc, crtc_state); + dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state); } /* units of 100MHz */ @@ -1066,11 +1066,11 @@ void intel_fdi_init_hook(struct drm_i915_private *dev_priv) { if (IS_IRONLAKE(dev_priv)) { - dev_priv->fdi_funcs = &ilk_funcs; + dev_priv->display.funcs.fdi = &ilk_funcs; } else if (IS_SANDYBRIDGE(dev_priv)) { - dev_priv->fdi_funcs = &gen6_funcs; + dev_priv->display.funcs.fdi = &gen6_funcs; } else if (IS_IVYBRIDGE(dev_priv)) { /* FIXME: detect B0+ stepping and use auto training */ - dev_priv->fdi_funcs = &ivb_funcs; + dev_priv->display.funcs.fdi = &ivb_funcs; } } diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 791248f812aa..1463493824b8 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -311,6 +311,8 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old, */ BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > BITS_PER_TYPE(atomic_t)); + BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 32); + BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); if (old) { drm_WARN_ON(old->obj->base.dev, diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h index ff0c37b079aa..3c474ed937fb 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h @@ -25,6 +25,7 @@ #define __INTEL_FRONTBUFFER_H__ #include <linux/atomic.h> +#include <linux/bits.h> #include <linux/kref.h> #include "gem/i915_gem_object_types.h" @@ -48,6 +49,23 @@ struct intel_frontbuffer { struct rcu_head rcu; }; +/* + * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is + * considered to be the frontbuffer for the given plane interface-wise. This + * doesn't mean that the hw necessarily already scans it out, but that any + * rendering (by the cpu or gpu) will land in the frontbuffer eventually. + * + * We have one bit per pipe and per scanout plane type. + */ +#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 +#define INTEL_FRONTBUFFER(pipe, plane_id) \ + BIT((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)); +#define INTEL_FRONTBUFFER_OVERLAY(pipe) \ + BIT(INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) +#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ + GENMASK(INTEL_FRONTBUFFER_BITS_PER_PIPE * ((pipe) + 1) - 1, \ + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) + void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915, unsigned frontbuffer_bits); void intel_frontbuffer_flip_complete(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 21281a7bdc17..c3992b1ca842 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -31,7 +31,7 @@ #include <linux/i2c-algo-bit.h> #include <linux/i2c.h> -#include <drm/drm_hdcp.h> +#include <drm/display/drm_hdcp_helper.h> #include "i915_drv.h" #include "intel_de.h" @@ -369,7 +369,7 @@ static int gmbus_wait(struct drm_i915_private *dev_priv, u32 status, u32 irq_en) if (!has_gmbus_irq(dev_priv)) irq_en = 0; - add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + add_wait_queue(&dev_priv->display.gmbus.wait_queue, &wait); intel_de_write_fw(dev_priv, GMBUS4, irq_en); status |= GMBUS_SATOER; @@ -380,7 +380,7 @@ static int gmbus_wait(struct drm_i915_private *dev_priv, u32 status, u32 irq_en) 50); intel_de_write_fw(dev_priv, GMBUS4, 0); - remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + remove_wait_queue(&dev_priv->display.gmbus.wait_queue, &wait); if (gmbus2 & GMBUS_SATOER) return -ENXIO; @@ -400,7 +400,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) if (has_gmbus_irq(dev_priv)) irq_enable = GMBUS_IDLE_EN; - add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + add_wait_queue(&dev_priv->display.gmbus.wait_queue, &wait); intel_de_write_fw(dev_priv, GMBUS4, irq_enable); ret = intel_wait_for_register_fw(&dev_priv->uncore, @@ -408,7 +408,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) 10); intel_de_write_fw(dev_priv, GMBUS4, 0); - remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + remove_wait_queue(&dev_priv->display.gmbus.wait_queue, &wait); return ret; } @@ -791,7 +791,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter) int ret; wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - mutex_lock(&dev_priv->gmbus_mutex); + mutex_lock(&dev_priv->display.gmbus.mutex); /* * In order to output Aksv to the receiver, use an indexed write to @@ -800,7 +800,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter) */ ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT); - mutex_unlock(&dev_priv->gmbus_mutex); + mutex_unlock(&dev_priv->display.gmbus.mutex); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref); return ret; @@ -826,7 +826,7 @@ static void gmbus_lock_bus(struct i2c_adapter *adapter, struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; - mutex_lock(&dev_priv->gmbus_mutex); + mutex_lock(&dev_priv->display.gmbus.mutex); } static int gmbus_trylock_bus(struct i2c_adapter *adapter, @@ -835,7 +835,7 @@ static int gmbus_trylock_bus(struct i2c_adapter *adapter, struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; - return mutex_trylock(&dev_priv->gmbus_mutex); + return mutex_trylock(&dev_priv->display.gmbus.mutex); } static void gmbus_unlock_bus(struct i2c_adapter *adapter, @@ -844,7 +844,7 @@ static void gmbus_unlock_bus(struct i2c_adapter *adapter, struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; - mutex_unlock(&dev_priv->gmbus_mutex); + mutex_unlock(&dev_priv->display.gmbus.mutex); } static const struct i2c_lock_operations gmbus_lock_ops = { @@ -864,18 +864,18 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) int ret; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; + dev_priv->display.gmbus.mmio_base = VLV_DISPLAY_BASE; else if (!HAS_GMCH(dev_priv)) /* * Broxton uses the same PCH offsets for South Display Engine, * even though it doesn't have a PCH. */ - dev_priv->gpio_mmio_base = PCH_DISPLAY_BASE; + dev_priv->display.gmbus.mmio_base = PCH_DISPLAY_BASE; - mutex_init(&dev_priv->gmbus_mutex); - init_waitqueue_head(&dev_priv->gmbus_wait_queue); + mutex_init(&dev_priv->display.gmbus.mutex); + init_waitqueue_head(&dev_priv->display.gmbus.wait_queue); - for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { + for (pin = 0; pin < ARRAY_SIZE(dev_priv->display.gmbus.bus); pin++) { const struct gmbus_pin *gmbus_pin; struct intel_gmbus *bus; @@ -922,7 +922,7 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) goto err; } - dev_priv->gmbus[pin] = bus; + dev_priv->display.gmbus.bus[pin] = bus; } intel_gmbus_reset(dev_priv); @@ -938,11 +938,11 @@ err: struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin) { - if (drm_WARN_ON(&dev_priv->drm, pin >= ARRAY_SIZE(dev_priv->gmbus) || - !dev_priv->gmbus[pin])) + if (drm_WARN_ON(&dev_priv->drm, pin >= ARRAY_SIZE(dev_priv->display.gmbus.bus) || + !dev_priv->display.gmbus.bus[pin])) return NULL; - return &dev_priv->gmbus[pin]->adapter; + return &dev_priv->display.gmbus.bus[pin]->adapter; } void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) @@ -950,7 +950,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; - mutex_lock(&dev_priv->gmbus_mutex); + mutex_lock(&dev_priv->display.gmbus.mutex); bus->force_bit += force_bit ? 1 : -1; drm_dbg_kms(&dev_priv->drm, @@ -958,7 +958,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) force_bit ? "en" : "dis", adapter->name, bus->force_bit); - mutex_unlock(&dev_priv->gmbus_mutex); + mutex_unlock(&dev_priv->display.gmbus.mutex); } bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) @@ -972,16 +972,16 @@ void intel_gmbus_teardown(struct drm_i915_private *dev_priv) { unsigned int pin; - for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { + for (pin = 0; pin < ARRAY_SIZE(dev_priv->display.gmbus.bus); pin++) { struct intel_gmbus *bus; - bus = dev_priv->gmbus[pin]; + bus = dev_priv->display.gmbus.bus[pin]; if (!bus) continue; i2c_del_adapter(&bus->adapter); kfree(bus); - dev_priv->gmbus[pin] = NULL; + dev_priv->display.gmbus.bus[pin] = NULL; } } diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index ed5dab8427d6..638495991c49 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -12,7 +12,7 @@ #include <linux/i2c.h> #include <linux/random.h> -#include <drm/drm_hdcp.h> +#include <drm/display/drm_hdcp_helper.h> #include <drm/i915_component.h> #include "i915_drv.h" @@ -23,6 +23,7 @@ #include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_hdcp.h" +#include "intel_hdcp_regs.h" #include "intel_pcode.h" #define KEY_LOAD_TRIES 5 @@ -30,8 +31,30 @@ static int intel_conn_to_vcpi(struct intel_connector *connector) { + struct drm_dp_mst_topology_mgr *mgr; + struct drm_dp_mst_atomic_payload *payload; + struct drm_dp_mst_topology_state *mst_state; + int vcpi = 0; + /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */ - return connector->port ? connector->port->vcpi.vcpi : 0; + if (!connector->port) + return 0; + mgr = connector->port->mgr; + + drm_modeset_lock(&mgr->base.lock, NULL); + mst_state = to_drm_dp_mst_topology_state(mgr->base.state); + payload = drm_atomic_get_mst_payload_state(mst_state, connector->port); + if (drm_WARN_ON(mgr->dev, !payload)) + goto out; + + vcpi = payload->vcpi; + if (drm_WARN_ON(mgr->dev, vcpi < 0)) { + vcpi = 0; + goto out; + } +out: + drm_modeset_unlock(&mgr->base.lock); + return vcpi; } /* @@ -1109,8 +1132,8 @@ static void intel_hdcp_prop_work(struct work_struct *work) bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port) { - return INTEL_INFO(dev_priv)->display.has_hdcp && - (DISPLAY_VER(dev_priv) >= 12 || port < PORT_E); + return RUNTIME_INFO(dev_priv)->has_hdcp && + (DISPLAY_VER(dev_priv) >= 12 || port < PORT_E); } static int diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h new file mode 100644 index 000000000000..2a3733e8966c --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_HDCP_REGS_H__ +#define __INTEL_HDCP_REGS_H__ + +#include "i915_reg_defs.h" + +/* HDCP Key Registers */ +#define HDCP_KEY_CONF _MMIO(0x66c00) +#define HDCP_AKSV_SEND_TRIGGER REG_BIT(31) +#define HDCP_CLEAR_KEYS_TRIGGER REG_BIT(30) +#define HDCP_KEY_LOAD_TRIGGER REG_BIT(8) +#define HDCP_KEY_STATUS _MMIO(0x66c04) +#define HDCP_FUSE_IN_PROGRESS REG_BIT(7) +#define HDCP_FUSE_ERROR REG_BIT(6) +#define HDCP_FUSE_DONE REG_BIT(5) +#define HDCP_KEY_LOAD_STATUS REG_BIT(1) +#define HDCP_KEY_LOAD_DONE REG_BIT(0) +#define HDCP_AKSV_LO _MMIO(0x66c10) +#define HDCP_AKSV_HI _MMIO(0x66c14) + +/* HDCP Repeater Registers */ +#define HDCP_REP_CTL _MMIO(0x66d00) +#define HDCP_TRANSA_REP_PRESENT REG_BIT(31) +#define HDCP_TRANSB_REP_PRESENT REG_BIT(30) +#define HDCP_TRANSC_REP_PRESENT REG_BIT(29) +#define HDCP_TRANSD_REP_PRESENT REG_BIT(28) +#define HDCP_DDIB_REP_PRESENT REG_BIT(30) +#define HDCP_DDIA_REP_PRESENT REG_BIT(29) +#define HDCP_DDIC_REP_PRESENT REG_BIT(28) +#define HDCP_DDID_REP_PRESENT REG_BIT(27) +#define HDCP_DDIF_REP_PRESENT REG_BIT(26) +#define HDCP_DDIE_REP_PRESENT REG_BIT(25) +#define HDCP_TRANSA_SHA1_M0 (1 << 20) +#define HDCP_TRANSB_SHA1_M0 (2 << 20) +#define HDCP_TRANSC_SHA1_M0 (3 << 20) +#define HDCP_TRANSD_SHA1_M0 (4 << 20) +#define HDCP_DDIB_SHA1_M0 (1 << 20) +#define HDCP_DDIA_SHA1_M0 (2 << 20) +#define HDCP_DDIC_SHA1_M0 (3 << 20) +#define HDCP_DDID_SHA1_M0 (4 << 20) +#define HDCP_DDIF_SHA1_M0 (5 << 20) +#define HDCP_DDIE_SHA1_M0 (6 << 20) /* Bspec says 5? */ +#define HDCP_SHA1_BUSY REG_BIT(16) +#define HDCP_SHA1_READY REG_BIT(17) +#define HDCP_SHA1_COMPLETE REG_BIT(18) +#define HDCP_SHA1_V_MATCH REG_BIT(19) +#define HDCP_SHA1_TEXT_32 (1 << 1) +#define HDCP_SHA1_COMPLETE_HASH (2 << 1) +#define HDCP_SHA1_TEXT_24 (4 << 1) +#define HDCP_SHA1_TEXT_16 (5 << 1) +#define HDCP_SHA1_TEXT_8 (6 << 1) +#define HDCP_SHA1_TEXT_0 (7 << 1) +#define HDCP_SHA_V_PRIME_H0 _MMIO(0x66d04) +#define HDCP_SHA_V_PRIME_H1 _MMIO(0x66d08) +#define HDCP_SHA_V_PRIME_H2 _MMIO(0x66d0C) +#define HDCP_SHA_V_PRIME_H3 _MMIO(0x66d10) +#define HDCP_SHA_V_PRIME_H4 _MMIO(0x66d14) +#define HDCP_SHA_V_PRIME(h) _MMIO((0x66d04 + (h) * 4)) +#define HDCP_SHA_TEXT _MMIO(0x66d18) + +/* HDCP Auth Registers */ +#define _PORTA_HDCP_AUTHENC 0x66800 +#define _PORTB_HDCP_AUTHENC 0x66500 +#define _PORTC_HDCP_AUTHENC 0x66600 +#define _PORTD_HDCP_AUTHENC 0x66700 +#define _PORTE_HDCP_AUTHENC 0x66A00 +#define _PORTF_HDCP_AUTHENC 0x66900 +#define _PORT_HDCP_AUTHENC(port, x) _MMIO(_PICK(port, \ + _PORTA_HDCP_AUTHENC, \ + _PORTB_HDCP_AUTHENC, \ + _PORTC_HDCP_AUTHENC, \ + _PORTD_HDCP_AUTHENC, \ + _PORTE_HDCP_AUTHENC, \ + _PORTF_HDCP_AUTHENC) + (x)) +#define PORT_HDCP_CONF(port) _PORT_HDCP_AUTHENC(port, 0x0) +#define _TRANSA_HDCP_CONF 0x66400 +#define _TRANSB_HDCP_CONF 0x66500 +#define TRANS_HDCP_CONF(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_CONF, \ + _TRANSB_HDCP_CONF) +#define HDCP_CONF(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_CONF(trans) : \ + PORT_HDCP_CONF(port)) + +#define HDCP_CONF_CAPTURE_AN REG_BIT(0) +#define HDCP_CONF_AUTH_AND_ENC (REG_BIT(1) | REG_BIT(0)) +#define PORT_HDCP_ANINIT(port) _PORT_HDCP_AUTHENC(port, 0x4) +#define _TRANSA_HDCP_ANINIT 0x66404 +#define _TRANSB_HDCP_ANINIT 0x66504 +#define TRANS_HDCP_ANINIT(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_ANINIT, \ + _TRANSB_HDCP_ANINIT) +#define HDCP_ANINIT(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_ANINIT(trans) : \ + PORT_HDCP_ANINIT(port)) + +#define PORT_HDCP_ANLO(port) _PORT_HDCP_AUTHENC(port, 0x8) +#define _TRANSA_HDCP_ANLO 0x66408 +#define _TRANSB_HDCP_ANLO 0x66508 +#define TRANS_HDCP_ANLO(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANLO, \ + _TRANSB_HDCP_ANLO) +#define HDCP_ANLO(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_ANLO(trans) : \ + PORT_HDCP_ANLO(port)) + +#define PORT_HDCP_ANHI(port) _PORT_HDCP_AUTHENC(port, 0xC) +#define _TRANSA_HDCP_ANHI 0x6640C +#define _TRANSB_HDCP_ANHI 0x6650C +#define TRANS_HDCP_ANHI(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANHI, \ + _TRANSB_HDCP_ANHI) +#define HDCP_ANHI(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_ANHI(trans) : \ + PORT_HDCP_ANHI(port)) + +#define PORT_HDCP_BKSVLO(port) _PORT_HDCP_AUTHENC(port, 0x10) +#define _TRANSA_HDCP_BKSVLO 0x66410 +#define _TRANSB_HDCP_BKSVLO 0x66510 +#define TRANS_HDCP_BKSVLO(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_BKSVLO, \ + _TRANSB_HDCP_BKSVLO) +#define HDCP_BKSVLO(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_BKSVLO(trans) : \ + PORT_HDCP_BKSVLO(port)) + +#define PORT_HDCP_BKSVHI(port) _PORT_HDCP_AUTHENC(port, 0x14) +#define _TRANSA_HDCP_BKSVHI 0x66414 +#define _TRANSB_HDCP_BKSVHI 0x66514 +#define TRANS_HDCP_BKSVHI(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_BKSVHI, \ + _TRANSB_HDCP_BKSVHI) +#define HDCP_BKSVHI(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_BKSVHI(trans) : \ + PORT_HDCP_BKSVHI(port)) + +#define PORT_HDCP_RPRIME(port) _PORT_HDCP_AUTHENC(port, 0x18) +#define _TRANSA_HDCP_RPRIME 0x66418 +#define _TRANSB_HDCP_RPRIME 0x66518 +#define TRANS_HDCP_RPRIME(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_RPRIME, \ + _TRANSB_HDCP_RPRIME) +#define HDCP_RPRIME(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_RPRIME(trans) : \ + PORT_HDCP_RPRIME(port)) + +#define PORT_HDCP_STATUS(port) _PORT_HDCP_AUTHENC(port, 0x1C) +#define _TRANSA_HDCP_STATUS 0x6641C +#define _TRANSB_HDCP_STATUS 0x6651C +#define TRANS_HDCP_STATUS(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_STATUS, \ + _TRANSB_HDCP_STATUS) +#define HDCP_STATUS(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP_STATUS(trans) : \ + PORT_HDCP_STATUS(port)) + +#define HDCP_STATUS_STREAM_A_ENC REG_BIT(31) +#define HDCP_STATUS_STREAM_B_ENC REG_BIT(30) +#define HDCP_STATUS_STREAM_C_ENC REG_BIT(29) +#define HDCP_STATUS_STREAM_D_ENC REG_BIT(28) +#define HDCP_STATUS_AUTH REG_BIT(21) +#define HDCP_STATUS_ENC REG_BIT(20) +#define HDCP_STATUS_RI_MATCH REG_BIT(19) +#define HDCP_STATUS_R0_READY REG_BIT(18) +#define HDCP_STATUS_AN_READY REG_BIT(17) +#define HDCP_STATUS_CIPHER REG_BIT(16) +#define HDCP_STATUS_FRAME_CNT(x) (((x) >> 8) & 0xff) + +/* HDCP2.2 Registers */ +#define _PORTA_HDCP2_BASE 0x66800 +#define _PORTB_HDCP2_BASE 0x66500 +#define _PORTC_HDCP2_BASE 0x66600 +#define _PORTD_HDCP2_BASE 0x66700 +#define _PORTE_HDCP2_BASE 0x66A00 +#define _PORTF_HDCP2_BASE 0x66900 +#define _PORT_HDCP2_BASE(port, x) _MMIO(_PICK((port), \ + _PORTA_HDCP2_BASE, \ + _PORTB_HDCP2_BASE, \ + _PORTC_HDCP2_BASE, \ + _PORTD_HDCP2_BASE, \ + _PORTE_HDCP2_BASE, \ + _PORTF_HDCP2_BASE) + (x)) + +#define PORT_HDCP2_AUTH(port) _PORT_HDCP2_BASE(port, 0x98) +#define _TRANSA_HDCP2_AUTH 0x66498 +#define _TRANSB_HDCP2_AUTH 0x66598 +#define TRANS_HDCP2_AUTH(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_AUTH, \ + _TRANSB_HDCP2_AUTH) +#define AUTH_LINK_AUTHENTICATED REG_BIT(31) +#define AUTH_LINK_TYPE REG_BIT(30) +#define AUTH_FORCE_CLR_INPUTCTR REG_BIT(19) +#define AUTH_CLR_KEYS REG_BIT(18) +#define HDCP2_AUTH(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_AUTH(trans) : \ + PORT_HDCP2_AUTH(port)) + +#define PORT_HDCP2_CTL(port) _PORT_HDCP2_BASE(port, 0xB0) +#define _TRANSA_HDCP2_CTL 0x664B0 +#define _TRANSB_HDCP2_CTL 0x665B0 +#define TRANS_HDCP2_CTL(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_CTL, \ + _TRANSB_HDCP2_CTL) +#define CTL_LINK_ENCRYPTION_REQ REG_BIT(31) +#define HDCP2_CTL(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_CTL(trans) : \ + PORT_HDCP2_CTL(port)) + +#define PORT_HDCP2_STATUS(port) _PORT_HDCP2_BASE(port, 0xB4) +#define _TRANSA_HDCP2_STATUS 0x664B4 +#define _TRANSB_HDCP2_STATUS 0x665B4 +#define TRANS_HDCP2_STATUS(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP2_STATUS, \ + _TRANSB_HDCP2_STATUS) +#define LINK_TYPE_STATUS REG_BIT(22) +#define LINK_AUTH_STATUS REG_BIT(21) +#define LINK_ENCRYPTION_STATUS REG_BIT(20) +#define HDCP2_STATUS(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_STATUS(trans) : \ + PORT_HDCP2_STATUS(port)) + +#define _PIPEA_HDCP2_STREAM_STATUS 0x668C0 +#define _PIPEB_HDCP2_STREAM_STATUS 0x665C0 +#define _PIPEC_HDCP2_STREAM_STATUS 0x666C0 +#define _PIPED_HDCP2_STREAM_STATUS 0x667C0 +#define PIPE_HDCP2_STREAM_STATUS(pipe) _MMIO(_PICK((pipe), \ + _PIPEA_HDCP2_STREAM_STATUS, \ + _PIPEB_HDCP2_STREAM_STATUS, \ + _PIPEC_HDCP2_STREAM_STATUS, \ + _PIPED_HDCP2_STREAM_STATUS)) + +#define _TRANSA_HDCP2_STREAM_STATUS 0x664C0 +#define _TRANSB_HDCP2_STREAM_STATUS 0x665C0 +#define TRANS_HDCP2_STREAM_STATUS(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP2_STREAM_STATUS, \ + _TRANSB_HDCP2_STREAM_STATUS) +#define STREAM_ENCRYPTION_STATUS REG_BIT(31) +#define STREAM_TYPE_STATUS REG_BIT(30) +#define HDCP2_STREAM_STATUS(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_STREAM_STATUS(trans) : \ + PIPE_HDCP2_STREAM_STATUS(pipe)) + +#define _PORTA_HDCP2_AUTH_STREAM 0x66F00 +#define _PORTB_HDCP2_AUTH_STREAM 0x66F04 +#define PORT_HDCP2_AUTH_STREAM(port) _MMIO_PORT(port, \ + _PORTA_HDCP2_AUTH_STREAM, \ + _PORTB_HDCP2_AUTH_STREAM) +#define _TRANSA_HDCP2_AUTH_STREAM 0x66F00 +#define _TRANSB_HDCP2_AUTH_STREAM 0x66F04 +#define TRANS_HDCP2_AUTH_STREAM(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP2_AUTH_STREAM, \ + _TRANSB_HDCP2_AUTH_STREAM) +#define AUTH_STREAM_TYPE REG_BIT(31) +#define HDCP2_AUTH_STREAM(dev_priv, trans, port) \ + (GRAPHICS_VER(dev_priv) >= 12 ? \ + TRANS_HDCP2_AUTH_STREAM(trans) : \ + PORT_HDCP2_AUTH_STREAM(port)) + +#endif /* __INTEL_HDCP_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index a4a6f8bd2841..09f85afeb2d4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -32,11 +32,12 @@ #include <linux/slab.h> #include <linux/string_helpers.h> +#include <drm/display/drm_hdcp_helper.h> +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_scdc_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include <drm/drm_hdcp.h> -#include <drm/drm_scdc_helper.h> #include <drm/intel_lpe_audio.h> #include "i915_debugfs.h" @@ -49,6 +50,7 @@ #include "intel_dp.h" #include "intel_gmbus.h" #include "intel_hdcp.h" +#include "intel_hdcp_regs.h" #include "intel_hdmi.h" #include "intel_lspcon.h" #include "intel_panel.h" @@ -2000,6 +2002,15 @@ intel_hdmi_mode_valid(struct drm_connector *connector, clock *= 2; } + /* + * HDMI2.1 requires higher resolution modes like 8k60, 4K120 to be + * enumerated only if FRL is supported. Current platforms do not support + * FRL so prune the higher resolution modes that require doctclock more + * than 600MHz. + */ + if (clock > 600000) + return MODE_CLOCK_HIGH; + ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode); status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, ycbcr_420_only); @@ -2851,7 +2862,7 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); else if (DISPLAY_VER(dev_priv) == 9 && HAS_PCH_TGP(dev_priv)) ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port); - else if (HAS_PCH_MCC(dev_priv)) + else if (IS_JSL_EHL(dev_priv) && HAS_PCH_TGP(dev_priv)) ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) ddc_pin = icl_port_to_ddc_pin(dev_priv, port); diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 8204126d17f9..f7a2f485b177 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -119,13 +119,13 @@ intel_connector_hpd_pin(struct intel_connector *connector) * responsible for further action. * * The number of IRQs that are allowed within @HPD_STORM_DETECT_PERIOD is - * stored in @dev_priv->hotplug.hpd_storm_threshold which defaults to + * stored in @dev_priv->display.hotplug.hpd_storm_threshold which defaults to * @HPD_STORM_DEFAULT_THRESHOLD. Long IRQs count as +10 to this threshold, and * short IRQs count as +1. If this threshold is exceeded, it's considered an * IRQ storm and the IRQ state is set to @HPD_MARK_DISABLED. * * By default, most systems will only count long IRQs towards - * &dev_priv->hotplug.hpd_storm_threshold. However, some older systems also + * &dev_priv->display.hotplug.hpd_storm_threshold. However, some older systems also * suffer from short IRQ storms and must also track these. Because short IRQ * storms are naturally caused by sideband interactions with DP MST devices, * short IRQ detection is only enabled for systems without DP MST support. @@ -140,7 +140,7 @@ intel_connector_hpd_pin(struct intel_connector *connector) static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv, enum hpd_pin pin, bool long_hpd) { - struct i915_hotplug *hpd = &dev_priv->hotplug; + struct intel_hotplug *hpd = &dev_priv->display.hotplug; unsigned long start = hpd->stats[pin].last_jiffies; unsigned long end = start + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD); const int increment = long_hpd ? 10 : 1; @@ -148,7 +148,7 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv, bool storm = false; if (!threshold || - (!long_hpd && !dev_priv->hotplug.hpd_short_storm_enabled)) + (!long_hpd && !dev_priv->display.hotplug.hpd_short_storm_enabled)) return false; if (!time_in_range(jiffies, start, end)) { @@ -191,7 +191,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) pin = intel_connector_hpd_pin(connector); if (pin == HPD_NONE || - dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED) + dev_priv->display.hotplug.stats[pin].state != HPD_MARK_DISABLED) continue; drm_info(&dev_priv->drm, @@ -199,7 +199,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) "switching from hotplug detection to polling\n", connector->base.name); - dev_priv->hotplug.stats[pin].state = HPD_DISABLED; + dev_priv->display.hotplug.stats[pin].state = HPD_DISABLED; connector->base.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; hpd_disabled = true; @@ -209,7 +209,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) /* Enable polling and queue hotplug re-enabling. */ if (hpd_disabled) { drm_kms_helper_poll_enable(dev); - mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work, + mod_delayed_work(system_wq, &dev_priv->display.hotplug.reenable_work, msecs_to_jiffies(HPD_STORM_REENABLE_DELAY)); } } @@ -218,7 +218,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), - hotplug.reenable_work.work); + display.hotplug.reenable_work.work); struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; @@ -233,7 +233,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) for_each_intel_connector_iter(connector, &conn_iter) { pin = intel_connector_hpd_pin(connector); if (pin == HPD_NONE || - dev_priv->hotplug.stats[pin].state != HPD_DISABLED) + dev_priv->display.hotplug.stats[pin].state != HPD_DISABLED) continue; if (connector->base.polled != connector->polled) @@ -245,8 +245,8 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) drm_connector_list_iter_end(&conn_iter); for_each_hpd_pin(pin) { - if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) - dev_priv->hotplug.stats[pin].state = HPD_ENABLED; + if (dev_priv->display.hotplug.stats[pin].state == HPD_DISABLED) + dev_priv->display.hotplug.stats[pin].state = HPD_ENABLED; } intel_hpd_irq_setup(dev_priv); @@ -297,16 +297,16 @@ static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder) static void i915_digport_work_func(struct work_struct *work) { struct drm_i915_private *dev_priv = - container_of(work, struct drm_i915_private, hotplug.dig_port_work); + container_of(work, struct drm_i915_private, display.hotplug.dig_port_work); u32 long_port_mask, short_port_mask; struct intel_encoder *encoder; u32 old_bits = 0; spin_lock_irq(&dev_priv->irq_lock); - long_port_mask = dev_priv->hotplug.long_port_mask; - dev_priv->hotplug.long_port_mask = 0; - short_port_mask = dev_priv->hotplug.short_port_mask; - dev_priv->hotplug.short_port_mask = 0; + long_port_mask = dev_priv->display.hotplug.long_port_mask; + dev_priv->display.hotplug.long_port_mask = 0; + short_port_mask = dev_priv->display.hotplug.short_port_mask; + dev_priv->display.hotplug.short_port_mask = 0; spin_unlock_irq(&dev_priv->irq_lock); for_each_intel_encoder(&dev_priv->drm, encoder) { @@ -335,9 +335,9 @@ static void i915_digport_work_func(struct work_struct *work) if (old_bits) { spin_lock_irq(&dev_priv->irq_lock); - dev_priv->hotplug.event_bits |= old_bits; + dev_priv->display.hotplug.event_bits |= old_bits; spin_unlock_irq(&dev_priv->irq_lock); - queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0); + queue_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work, 0); } } @@ -353,10 +353,10 @@ void intel_hpd_trigger_irq(struct intel_digital_port *dig_port) struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); spin_lock_irq(&i915->irq_lock); - i915->hotplug.short_port_mask |= BIT(dig_port->base.port); + i915->display.hotplug.short_port_mask |= BIT(dig_port->base.port); spin_unlock_irq(&i915->irq_lock); - queue_work(i915->hotplug.dp_wq, &i915->hotplug.dig_port_work); + queue_work(i915->display.hotplug.dp_wq, &i915->display.hotplug.dig_port_work); } /* @@ -366,7 +366,7 @@ static void i915_hotplug_work_func(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, - hotplug.hotplug_work.work); + display.hotplug.hotplug_work.work); struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; @@ -379,10 +379,10 @@ static void i915_hotplug_work_func(struct work_struct *work) spin_lock_irq(&dev_priv->irq_lock); - hpd_event_bits = dev_priv->hotplug.event_bits; - dev_priv->hotplug.event_bits = 0; - hpd_retry_bits = dev_priv->hotplug.retry_bits; - dev_priv->hotplug.retry_bits = 0; + hpd_event_bits = dev_priv->display.hotplug.event_bits; + dev_priv->display.hotplug.event_bits = 0; + hpd_retry_bits = dev_priv->display.hotplug.retry_bits; + dev_priv->display.hotplug.retry_bits = 0; /* Enable polling for connectors which had HPD IRQ storms */ intel_hpd_irq_storm_switch_to_polling(dev_priv); @@ -435,10 +435,10 @@ static void i915_hotplug_work_func(struct work_struct *work) retry &= ~changed; if (retry) { spin_lock_irq(&dev_priv->irq_lock); - dev_priv->hotplug.retry_bits |= retry; + dev_priv->display.hotplug.retry_bits |= retry; spin_unlock_irq(&dev_priv->irq_lock); - mod_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, + mod_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work, msecs_to_jiffies(HPD_RETRY_DELAY)); } } @@ -502,10 +502,10 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (long_hpd) { long_hpd_pulse_mask |= BIT(pin); - dev_priv->hotplug.long_port_mask |= BIT(port); + dev_priv->display.hotplug.long_port_mask |= BIT(port); } else { short_hpd_pulse_mask |= BIT(pin); - dev_priv->hotplug.short_port_mask |= BIT(port); + dev_priv->display.hotplug.short_port_mask |= BIT(port); } } @@ -516,7 +516,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (!(BIT(pin) & pin_mask)) continue; - if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) { + if (dev_priv->display.hotplug.stats[pin].state == HPD_DISABLED) { /* * On GMCH platforms the interrupt mask bits only * prevent irq generation, not the setting of the @@ -529,7 +529,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, continue; } - if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED) + if (dev_priv->display.hotplug.stats[pin].state != HPD_ENABLED) continue; /* @@ -540,13 +540,13 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) { long_hpd = long_hpd_pulse_mask & BIT(pin); } else { - dev_priv->hotplug.event_bits |= BIT(pin); + dev_priv->display.hotplug.event_bits |= BIT(pin); long_hpd = true; queue_hp = true; } if (intel_hpd_irq_storm_detect(dev_priv, pin, long_hpd)) { - dev_priv->hotplug.event_bits &= ~BIT(pin); + dev_priv->display.hotplug.event_bits &= ~BIT(pin); storm_detected = true; queue_hp = true; } @@ -567,9 +567,9 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, * deadlock. */ if (queue_dig) - queue_work(dev_priv->hotplug.dp_wq, &dev_priv->hotplug.dig_port_work); + queue_work(dev_priv->display.hotplug.dp_wq, &dev_priv->display.hotplug.dig_port_work); if (queue_hp) - queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0); + queue_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work, 0); } /** @@ -594,8 +594,8 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) return; for_each_hpd_pin(i) { - dev_priv->hotplug.stats[i].count = 0; - dev_priv->hotplug.stats[i].state = HPD_ENABLED; + dev_priv->display.hotplug.stats[i].count = 0; + dev_priv->display.hotplug.stats[i].state = HPD_ENABLED; } /* @@ -611,7 +611,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, - hotplug.poll_init_work); + display.hotplug.poll_init_work); struct drm_device *dev = &dev_priv->drm; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; @@ -619,7 +619,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work) mutex_lock(&dev->mode_config.mutex); - enabled = READ_ONCE(dev_priv->hotplug.poll_enabled); + enabled = READ_ONCE(dev_priv->display.hotplug.poll_enabled); drm_connector_list_iter_begin(dev, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { @@ -668,10 +668,11 @@ static void i915_hpd_poll_init_work(struct work_struct *work) */ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv) { - if (!HAS_DISPLAY(dev_priv)) + if (!HAS_DISPLAY(dev_priv) || + !INTEL_DISPLAY_ENABLED(dev_priv)) return; - WRITE_ONCE(dev_priv->hotplug.poll_enabled, true); + WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, true); /* * We might already be holding dev->mode_config.mutex, so do this in a @@ -679,7 +680,7 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv) * As well, there's no issue if we race here since we always reschedule * this worker anyway */ - schedule_work(&dev_priv->hotplug.poll_init_work); + schedule_work(&dev_priv->display.hotplug.poll_init_work); } /** @@ -706,17 +707,17 @@ void intel_hpd_poll_disable(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - WRITE_ONCE(dev_priv->hotplug.poll_enabled, false); - schedule_work(&dev_priv->hotplug.poll_init_work); + WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, false); + schedule_work(&dev_priv->display.hotplug.poll_init_work); } void intel_hpd_init_work(struct drm_i915_private *dev_priv) { - INIT_DELAYED_WORK(&dev_priv->hotplug.hotplug_work, + INIT_DELAYED_WORK(&dev_priv->display.hotplug.hotplug_work, i915_hotplug_work_func); - INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func); - INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work); - INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work, + INIT_WORK(&dev_priv->display.hotplug.dig_port_work, i915_digport_work_func); + INIT_WORK(&dev_priv->display.hotplug.poll_init_work, i915_hpd_poll_init_work); + INIT_DELAYED_WORK(&dev_priv->display.hotplug.reenable_work, intel_hpd_irq_storm_reenable_work); } @@ -727,17 +728,17 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) spin_lock_irq(&dev_priv->irq_lock); - dev_priv->hotplug.long_port_mask = 0; - dev_priv->hotplug.short_port_mask = 0; - dev_priv->hotplug.event_bits = 0; - dev_priv->hotplug.retry_bits = 0; + dev_priv->display.hotplug.long_port_mask = 0; + dev_priv->display.hotplug.short_port_mask = 0; + dev_priv->display.hotplug.event_bits = 0; + dev_priv->display.hotplug.retry_bits = 0; spin_unlock_irq(&dev_priv->irq_lock); - cancel_work_sync(&dev_priv->hotplug.dig_port_work); - cancel_delayed_work_sync(&dev_priv->hotplug.hotplug_work); - cancel_work_sync(&dev_priv->hotplug.poll_init_work); - cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work); + cancel_work_sync(&dev_priv->display.hotplug.dig_port_work); + cancel_delayed_work_sync(&dev_priv->display.hotplug.hotplug_work); + cancel_work_sync(&dev_priv->display.hotplug.poll_init_work); + cancel_delayed_work_sync(&dev_priv->display.hotplug.reenable_work); } bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin) @@ -748,8 +749,8 @@ bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin) return false; spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->hotplug.stats[pin].state == HPD_ENABLED) { - dev_priv->hotplug.stats[pin].state = HPD_DISABLED; + if (dev_priv->display.hotplug.stats[pin].state == HPD_ENABLED) { + dev_priv->display.hotplug.stats[pin].state = HPD_DISABLED; ret = true; } spin_unlock_irq(&dev_priv->irq_lock); @@ -763,6 +764,6 @@ void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin) return; spin_lock_irq(&dev_priv->irq_lock); - dev_priv->hotplug.stats[pin].state = HPD_ENABLED; + dev_priv->display.hotplug.stats[pin].state = HPD_ENABLED; spin_unlock_irq(&dev_priv->irq_lock); } diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 4970bf146c4a..dca6003ccac8 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -73,8 +73,9 @@ #include "i915_drv.h" #include "intel_de.h" #include "intel_lpe_audio.h" +#include "intel_pci_config.h" -#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->audio.lpe.platdev != NULL) +#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->display.audio.lpe.platdev != NULL) static struct platform_device * lpe_audio_platdev_create(struct drm_i915_private *dev_priv) @@ -96,13 +97,13 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) return ERR_PTR(-ENOMEM); } - rsc[0].start = rsc[0].end = dev_priv->audio.lpe.irq; + rsc[0].start = rsc[0].end = dev_priv->display.audio.lpe.irq; rsc[0].flags = IORESOURCE_IRQ; rsc[0].name = "hdmi-lpe-audio-irq"; - rsc[1].start = pci_resource_start(pdev, 0) + + rsc[1].start = pci_resource_start(pdev, GTTMMADR_BAR) + I915_HDMI_LPE_AUDIO_BASE; - rsc[1].end = pci_resource_start(pdev, 0) + + rsc[1].end = pci_resource_start(pdev, GTTMMADR_BAR) + I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1; rsc[1].flags = IORESOURCE_MEM; rsc[1].name = "hdmi-lpe-audio-mmio"; @@ -148,7 +149,7 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) * than us fiddle with its internals. */ - platform_device_unregister(dev_priv->audio.lpe.platdev); + platform_device_unregister(dev_priv->display.audio.lpe.platdev); } static void lpe_audio_irq_unmask(struct irq_data *d) @@ -167,7 +168,7 @@ static struct irq_chip lpe_audio_irqchip = { static int lpe_audio_irq_init(struct drm_i915_private *dev_priv) { - int irq = dev_priv->audio.lpe.irq; + int irq = dev_priv->display.audio.lpe.irq; drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); irq_set_chip_and_handler_name(irq, @@ -204,15 +205,15 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) { int ret; - dev_priv->audio.lpe.irq = irq_alloc_desc(0); - if (dev_priv->audio.lpe.irq < 0) { + dev_priv->display.audio.lpe.irq = irq_alloc_desc(0); + if (dev_priv->display.audio.lpe.irq < 0) { drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n", - dev_priv->audio.lpe.irq); - ret = dev_priv->audio.lpe.irq; + dev_priv->display.audio.lpe.irq); + ret = dev_priv->display.audio.lpe.irq; goto err; } - drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->audio.lpe.irq); + drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->display.audio.lpe.irq); ret = lpe_audio_irq_init(dev_priv); @@ -223,10 +224,10 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) goto err_free_irq; } - dev_priv->audio.lpe.platdev = lpe_audio_platdev_create(dev_priv); + dev_priv->display.audio.lpe.platdev = lpe_audio_platdev_create(dev_priv); - if (IS_ERR(dev_priv->audio.lpe.platdev)) { - ret = PTR_ERR(dev_priv->audio.lpe.platdev); + if (IS_ERR(dev_priv->display.audio.lpe.platdev)) { + ret = PTR_ERR(dev_priv->display.audio.lpe.platdev); drm_err(&dev_priv->drm, "Failed to create lpe audio platform device: %d\n", ret); @@ -241,10 +242,10 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv) return 0; err_free_irq: - irq_free_desc(dev_priv->audio.lpe.irq); + irq_free_desc(dev_priv->display.audio.lpe.irq); err: - dev_priv->audio.lpe.irq = -1; - dev_priv->audio.lpe.platdev = NULL; + dev_priv->display.audio.lpe.irq = -1; + dev_priv->display.audio.lpe.platdev = NULL; return ret; } @@ -262,7 +263,7 @@ void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv) if (!HAS_LPE_AUDIO(dev_priv)) return; - ret = generic_handle_irq(dev_priv->audio.lpe.irq); + ret = generic_handle_irq(dev_priv->display.audio.lpe.irq); if (ret) drm_err_ratelimited(&dev_priv->drm, "error handling LPE audio irq: %d\n", ret); @@ -303,10 +304,10 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) lpe_audio_platdev_destroy(dev_priv); - irq_free_desc(dev_priv->audio.lpe.irq); + irq_free_desc(dev_priv->display.audio.lpe.irq); - dev_priv->audio.lpe.irq = -1; - dev_priv->audio.lpe.platdev = NULL; + dev_priv->display.audio.lpe.irq = -1; + dev_priv->display.audio.lpe.platdev = NULL; } /** @@ -333,7 +334,7 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, if (!HAS_LPE_AUDIO(dev_priv)) return; - pdata = dev_get_platdata(&dev_priv->audio.lpe.platdev->dev); + pdata = dev_get_platdata(&dev_priv->display.audio.lpe.platdev->dev); ppdata = &pdata->port[port - PORT_B]; spin_lock_irqsave(&pdata->lpe_audio_slock, irqflags); @@ -361,7 +362,7 @@ void intel_lpe_audio_notify(struct drm_i915_private *dev_priv, } if (pdata->notify_audio_lpe) - pdata->notify_audio_lpe(dev_priv->audio.lpe.platdev, port - PORT_B); + pdata->notify_audio_lpe(dev_priv->display.audio.lpe.platdev, port - PORT_B); spin_unlock_irqrestore(&pdata->lpe_audio_slock, irqflags); } diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 76357c9b76e4..15d59de8810e 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -23,8 +23,9 @@ * */ +#include <drm/display/drm_dp_dual_mode_helper.h> +#include <drm/display/drm_hdmi_helper.h> #include <drm/drm_atomic_helper.h> -#include <drm/dp/drm_dp_dual_mode_helper.h> #include <drm/drm_edid.h> #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index e8478161f8b9..730480ac3300 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -809,7 +809,7 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) else val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK); if (val == 0) - val = dev_priv->vbt.bios_lvds_val; + val = connector->panel.vbt.bios_lvds_val; return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; } @@ -967,9 +967,13 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) } intel_connector->edid = edid; + intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, + IS_ERR(edid) ? NULL : edid); + /* Try EDID first */ intel_panel_add_edid_fixed_modes(intel_connector, - dev_priv->vbt.drrs_type != DRRS_TYPE_NONE); + intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE, + false); /* Failed to get EDID, what about VBT? */ if (!intel_panel_preferred_fixed_mode(intel_connector)) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c new file mode 100644 index 000000000000..4b30e8228a5e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -0,0 +1,734 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + * + * Read out the current hardware modeset state, and sanitize it to the current + * state. + */ + +#include <drm/drm_atomic_uapi.h> +#include <drm/drm_atomic_state_helper.h> + +#include "i915_drv.h" +#include "intel_atomic.h" +#include "intel_bw.h" +#include "intel_color.h" +#include "intel_crtc.h" +#include "intel_crtc_state_dump.h" +#include "intel_ddi.h" +#include "intel_de.h" +#include "intel_display.h" +#include "intel_display_power.h" +#include "intel_display_types.h" +#include "intel_modeset_setup.h" +#include "intel_pch_display.h" +#include "intel_pm.h" + +static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx) +{ + struct intel_encoder *encoder; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_bw_state *bw_state = + to_intel_bw_state(i915->bw_obj.state); + struct intel_cdclk_state *cdclk_state = + to_intel_cdclk_state(i915->cdclk.obj.state); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(i915->dbuf.obj.state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + struct intel_plane *plane; + struct drm_atomic_state *state; + struct intel_crtc_state *temp_crtc_state; + enum pipe pipe = crtc->pipe; + int ret; + + if (!crtc_state->hw.active) + return; + + for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + + if (plane_state->uapi.visible) + intel_plane_disable_noatomic(crtc, plane); + } + + state = drm_atomic_state_alloc(&i915->drm); + if (!state) { + drm_dbg_kms(&i915->drm, + "failed to disable [CRTC:%d:%s], out of memory", + crtc->base.base.id, crtc->base.name); + return; + } + + state->acquire_ctx = ctx; + + /* Everything's already locked, -EDEADLK can't happen. */ + temp_crtc_state = intel_atomic_get_crtc_state(state, crtc); + ret = drm_atomic_add_affected_connectors(state, &crtc->base); + + drm_WARN_ON(&i915->drm, IS_ERR(temp_crtc_state) || ret); + + i915->display.funcs.display->crtc_disable(to_intel_atomic_state(state), crtc); + + drm_atomic_state_put(state); + + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", + crtc->base.base.id, crtc->base.name); + + crtc->active = false; + crtc->base.enabled = false; + + drm_WARN_ON(&i915->drm, + drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0); + crtc_state->uapi.active = false; + crtc_state->uapi.connector_mask = 0; + crtc_state->uapi.encoder_mask = 0; + intel_crtc_free_hw_state(crtc_state); + memset(&crtc_state->hw, 0, sizeof(crtc_state->hw)); + + for_each_encoder_on_crtc(&i915->drm, &crtc->base, encoder) + encoder->base.crtc = NULL; + + intel_fbc_disable(crtc); + intel_update_watermarks(i915); + intel_disable_shared_dpll(crtc_state); + + intel_display_power_put_all_in_set(i915, &crtc->enabled_power_domains); + + cdclk_state->min_cdclk[pipe] = 0; + cdclk_state->min_voltage_level[pipe] = 0; + cdclk_state->active_pipes &= ~BIT(pipe); + + dbuf_state->active_pipes &= ~BIT(pipe); + + bw_state->data_rate[pipe] = 0; + bw_state->num_active_planes[pipe] = 0; +} + +static void intel_modeset_update_connector_atomic_state(struct drm_i915_private *i915) +{ + struct intel_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(&i915->drm, &conn_iter); + for_each_intel_connector_iter(connector, &conn_iter) { + struct drm_connector_state *conn_state = connector->base.state; + struct intel_encoder *encoder = + to_intel_encoder(connector->base.encoder); + + if (conn_state->crtc) + drm_connector_put(&connector->base); + + if (encoder) { + struct intel_crtc *crtc = + to_intel_crtc(encoder->base.crtc); + const struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + conn_state->best_encoder = &encoder->base; + conn_state->crtc = &crtc->base; + conn_state->max_bpc = (crtc_state->pipe_bpp ?: 24) / 3; + + drm_connector_get(&connector->base); + } else { + conn_state->best_encoder = NULL; + conn_state->crtc = NULL; + } + } + drm_connector_list_iter_end(&conn_iter); +} + +static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) +{ + if (intel_crtc_is_bigjoiner_slave(crtc_state)) + return; + + crtc_state->uapi.enable = crtc_state->hw.enable; + crtc_state->uapi.active = crtc_state->hw.active; + drm_WARN_ON(crtc_state->uapi.crtc->dev, + drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0); + + crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; + crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; + + drm_property_replace_blob(&crtc_state->uapi.degamma_lut, + crtc_state->hw.degamma_lut); + drm_property_replace_blob(&crtc_state->uapi.gamma_lut, + crtc_state->hw.gamma_lut); + drm_property_replace_blob(&crtc_state->uapi.ctm, + crtc_state->hw.ctm); +} + +static void +intel_sanitize_plane_mapping(struct drm_i915_private *i915) +{ + struct intel_crtc *crtc; + + if (DISPLAY_VER(i915) >= 4) + return; + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_plane *plane = + to_intel_plane(crtc->base.primary); + struct intel_crtc *plane_crtc; + enum pipe pipe; + + if (!plane->get_hw_state(plane, &pipe)) + continue; + + if (pipe == crtc->pipe) + continue; + + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] attached to the wrong pipe, disabling plane\n", + plane->base.base.id, plane->base.name); + + plane_crtc = intel_crtc_for_pipe(i915, pipe); + intel_plane_disable_noatomic(plane_crtc, plane); + } +} + +static bool intel_crtc_has_encoders(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(dev, &crtc->base, encoder) + return true; + + return false; +} + +static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct intel_connector *connector; + + for_each_connector_on_encoder(dev, &encoder->base, connector) + return connector; + + return NULL; +} + +static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (!crtc_state->hw.active && !HAS_GMCH(i915)) + return; + + /* + * We start out with underrun reporting disabled to avoid races. + * For correct bookkeeping mark this on active crtcs. + * + * Also on gmch platforms we dont have any hardware bits to + * disable the underrun reporting. Which means we need to start + * out with underrun reporting disabled also on inactive pipes, + * since otherwise we'll complain about the garbage we read when + * e.g. coming up after runtime pm. + * + * No protection against concurrent access is required - at + * worst a fifo underrun happens which also sets this to false. + */ + crtc->cpu_fifo_underrun_disabled = true; + + /* + * We track the PCH trancoder underrun reporting state + * within the crtc. With crtc for pipe A housing the underrun + * reporting state for PCH transcoder A, crtc for pipe B housing + * it for PCH transcoder B, etc. LPT-H has only PCH transcoder A, + * and marking underrun reporting as disabled for the non-existing + * PCH transcoders B and C would prevent enabling the south + * error interrupt (see cpt_can_enable_serr_int()). + */ + if (intel_has_pch_trancoder(i915, crtc->pipe)) + crtc->pch_fifo_underrun_disabled = true; +} + +static void intel_sanitize_crtc(struct intel_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + + if (crtc_state->hw.active) { + struct intel_plane *plane; + + /* Disable everything but the primary plane */ + for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + + if (plane_state->uapi.visible && + plane->base.type != DRM_PLANE_TYPE_PRIMARY) + intel_plane_disable_noatomic(crtc, plane); + } + + /* Disable any background color/etc. set by the BIOS */ + intel_color_commit_noarm(crtc_state); + intel_color_commit_arm(crtc_state); + } + + /* + * Adjust the state of the output pipe according to whether we have + * active connectors/encoders. + */ + if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) && + !intel_crtc_is_bigjoiner_slave(crtc_state)) + intel_crtc_disable_noatomic(crtc, ctx); +} + +static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + /* + * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram + * the hardware when a high res displays plugged in. DPLL P + * divider is zero, and the pipe timings are bonkers. We'll + * try to disable everything in that case. + * + * FIXME would be nice to be able to sanitize this state + * without several WARNs, but for now let's take the easy + * road. + */ + return IS_SANDYBRIDGE(i915) && + crtc_state->hw.active && + crtc_state->shared_dpll && + crtc_state->port_clock == 0; +} + +static void intel_sanitize_encoder(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_connector *connector; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + struct intel_crtc_state *crtc_state = crtc ? + to_intel_crtc_state(crtc->base.state) : NULL; + + /* + * We need to check both for a crtc link (meaning that the encoder is + * active and trying to read from a pipe) and the pipe itself being + * active. + */ + bool has_active_crtc = crtc_state && + crtc_state->hw.active; + + if (crtc_state && has_bogus_dpll_config(crtc_state)) { + drm_dbg_kms(&i915->drm, + "BIOS has misprogrammed the hardware. Disabling pipe %c\n", + pipe_name(crtc->pipe)); + has_active_crtc = false; + } + + connector = intel_encoder_find_connector(encoder); + if (connector && !has_active_crtc) { + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] has active connectors but no active pipe!\n", + encoder->base.base.id, + encoder->base.name); + + /* + * Connector is active, but has no active pipe. This is fallout + * from our resume register restoring. Disable the encoder + * manually again. + */ + if (crtc_state) { + struct drm_encoder *best_encoder; + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] manually disabled\n", + encoder->base.base.id, + encoder->base.name); + + /* avoid oopsing in case the hooks consult best_encoder */ + best_encoder = connector->base.state->best_encoder; + connector->base.state->best_encoder = &encoder->base; + + /* FIXME NULL atomic state passed! */ + if (encoder->disable) + encoder->disable(NULL, encoder, crtc_state, + connector->base.state); + if (encoder->post_disable) + encoder->post_disable(NULL, encoder, crtc_state, + connector->base.state); + + connector->base.state->best_encoder = best_encoder; + } + encoder->base.crtc = NULL; + + /* + * Inconsistent output/port/pipe state happens presumably due to + * a bug in one of the get_hw_state functions. Or someplace else + * in our code, like the register restore mess on resume. Clamp + * things to off as a safer default. + */ + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; + } + + /* notify opregion of the sanitized encoder state */ + intel_opregion_notify_encoder(encoder, connector && has_active_crtc); + + if (HAS_DDI(i915)) + intel_ddi_sanitize_encoder_pll_mapping(encoder); +} + +/* FIXME read out full plane state for all planes */ +static void readout_plane_state(struct drm_i915_private *i915) +{ + struct intel_plane *plane; + struct intel_crtc *crtc; + + for_each_intel_plane(&i915->drm, plane) { + struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + struct intel_crtc_state *crtc_state; + enum pipe pipe = PIPE_A; + bool visible; + + visible = plane->get_hw_state(plane, &pipe); + + crtc = intel_crtc_for_pipe(i915, pipe); + crtc_state = to_intel_crtc_state(crtc->base.state); + + intel_set_plane_visible(crtc_state, plane_state, visible); + + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] hw state readout: %s, pipe %c\n", + plane->base.base.id, plane->base.name, + str_enabled_disabled(visible), pipe_name(pipe)); + } + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + intel_plane_fixup_bitmasks(crtc_state); + } +} + +static void intel_modeset_readout_hw_state(struct drm_i915_private *i915) +{ + struct intel_cdclk_state *cdclk_state = + to_intel_cdclk_state(i915->cdclk.obj.state); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(i915->dbuf.obj.state); + enum pipe pipe; + struct intel_crtc *crtc; + struct intel_encoder *encoder; + struct intel_connector *connector; + struct drm_connector_list_iter conn_iter; + u8 active_pipes = 0; + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); + intel_crtc_free_hw_state(crtc_state); + intel_crtc_state_reset(crtc_state, crtc); + + intel_crtc_get_pipe_config(crtc_state); + + crtc_state->hw.enable = crtc_state->hw.active; + + crtc->base.enabled = crtc_state->hw.enable; + crtc->active = crtc_state->hw.active; + + if (crtc_state->hw.active) + active_pipes |= BIT(crtc->pipe); + + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] hw state readout: %s\n", + crtc->base.base.id, crtc->base.name, + str_enabled_disabled(crtc_state->hw.active)); + } + + cdclk_state->active_pipes = active_pipes; + dbuf_state->active_pipes = active_pipes; + + readout_plane_state(i915); + + for_each_intel_encoder(&i915->drm, encoder) { + struct intel_crtc_state *crtc_state = NULL; + + pipe = 0; + + if (encoder->get_hw_state(encoder, &pipe)) { + crtc = intel_crtc_for_pipe(i915, pipe); + crtc_state = to_intel_crtc_state(crtc->base.state); + + encoder->base.crtc = &crtc->base; + intel_encoder_get_config(encoder, crtc_state); + + /* read out to slave crtc as well for bigjoiner */ + if (crtc_state->bigjoiner_pipes) { + struct intel_crtc *slave_crtc; + + /* encoder should read be linked to bigjoiner master */ + WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); + + for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(crtc_state)) { + struct intel_crtc_state *slave_crtc_state; + + slave_crtc_state = to_intel_crtc_state(slave_crtc->base.state); + intel_encoder_get_config(encoder, slave_crtc_state); + } + } + } else { + encoder->base.crtc = NULL; + } + + if (encoder->sync_state) + encoder->sync_state(encoder, crtc_state); + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", + encoder->base.base.id, encoder->base.name, + str_enabled_disabled(encoder->base.crtc), + pipe_name(pipe)); + } + + intel_dpll_readout_hw_state(i915); + + drm_connector_list_iter_begin(&i915->drm, &conn_iter); + for_each_intel_connector_iter(connector, &conn_iter) { + if (connector->get_hw_state(connector)) { + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + + connector->base.dpms = DRM_MODE_DPMS_ON; + + encoder = intel_attached_encoder(connector); + connector->base.encoder = &encoder->base; + + crtc = to_intel_crtc(encoder->base.crtc); + crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL; + + if (crtc_state && crtc_state->hw.active) { + /* + * This has to be done during hardware readout + * because anything calling .crtc_disable may + * rely on the connector_mask being accurate. + */ + crtc_state->uapi.connector_mask |= + drm_connector_mask(&connector->base); + crtc_state->uapi.encoder_mask |= + drm_encoder_mask(&encoder->base); + } + } else { + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; + } + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] hw state readout: %s\n", + connector->base.base.id, connector->base.name, + str_enabled_disabled(connector->base.encoder)); + } + drm_connector_list_iter_end(&conn_iter); + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_bw_state *bw_state = + to_intel_bw_state(i915->bw_obj.state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + struct intel_plane *plane; + int min_cdclk = 0; + + if (crtc_state->hw.active) { + /* + * The initial mode needs to be set in order to keep + * the atomic core happy. It wants a valid mode if the + * crtc's enabled, so we do the above call. + * + * But we don't set all the derived state fully, hence + * set a flag to indicate that a full recalculation is + * needed on the next commit. + */ + crtc_state->inherited = true; + + intel_crtc_update_active_timings(crtc_state); + + intel_crtc_copy_hw_to_uapi_state(crtc_state); + } + + for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + + /* + * FIXME don't have the fb yet, so can't + * use intel_plane_data_rate() :( + */ + if (plane_state->uapi.visible) + crtc_state->data_rate[plane->id] = + 4 * crtc_state->pixel_rate; + /* + * FIXME don't have the fb yet, so can't + * use plane->min_cdclk() :( + */ + if (plane_state->uapi.visible && plane->min_cdclk) { + if (crtc_state->double_wide || DISPLAY_VER(i915) >= 10) + crtc_state->min_cdclk[plane->id] = + DIV_ROUND_UP(crtc_state->pixel_rate, 2); + else + crtc_state->min_cdclk[plane->id] = + crtc_state->pixel_rate; + } + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] min_cdclk %d kHz\n", + plane->base.base.id, plane->base.name, + crtc_state->min_cdclk[plane->id]); + } + + if (crtc_state->hw.active) { + min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); + if (drm_WARN_ON(&i915->drm, min_cdclk < 0)) + min_cdclk = 0; + } + + cdclk_state->min_cdclk[crtc->pipe] = min_cdclk; + cdclk_state->min_voltage_level[crtc->pipe] = + crtc_state->min_voltage_level; + + intel_bw_crtc_update(bw_state, crtc_state); + } +} + +static void +get_encoder_power_domains(struct drm_i915_private *i915) +{ + struct intel_encoder *encoder; + + for_each_intel_encoder(&i915->drm, encoder) { + struct intel_crtc_state *crtc_state; + + if (!encoder->get_power_domains) + continue; + + /* + * MST-primary and inactive encoders don't have a crtc state + * and neither of these require any power domain references. + */ + if (!encoder->base.crtc) + continue; + + crtc_state = to_intel_crtc_state(encoder->base.crtc->state); + encoder->get_power_domains(encoder, crtc_state); + } +} + +static void intel_early_display_was(struct drm_i915_private *i915) +{ + /* + * Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl + * Also known as Wa_14010480278. + */ + if (IS_DISPLAY_VER(i915, 10, 12)) + intel_de_write(i915, GEN9_CLKGATE_DIS_0, + intel_de_read(i915, GEN9_CLKGATE_DIS_0) | DARBF_GATING_DIS); + + if (IS_HASWELL(i915)) { + /* + * WaRsPkgCStateDisplayPMReq:hsw + * System hang if this isn't done before disabling all planes! + */ + intel_de_write(i915, CHICKEN_PAR1_1, + intel_de_read(i915, CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); + } + + if (IS_KABYLAKE(i915) || IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) { + /* Display WA #1142:kbl,cfl,cml */ + intel_de_rmw(i915, CHICKEN_PAR1_1, + KBL_ARB_FILL_SPARE_22, KBL_ARB_FILL_SPARE_22); + intel_de_rmw(i915, CHICKEN_MISC_2, + KBL_ARB_FILL_SPARE_13 | KBL_ARB_FILL_SPARE_14, + KBL_ARB_FILL_SPARE_14); + } +} + +void intel_modeset_setup_hw_state(struct drm_i915_private *i915, + struct drm_modeset_acquire_ctx *ctx) +{ + struct intel_encoder *encoder; + struct intel_crtc *crtc; + intel_wakeref_t wakeref; + + wakeref = intel_display_power_get(i915, POWER_DOMAIN_INIT); + + intel_early_display_was(i915); + intel_modeset_readout_hw_state(i915); + + /* HW state is read out, now we need to sanitize this mess. */ + get_encoder_power_domains(i915); + + intel_pch_sanitize(i915); + + /* + * intel_sanitize_plane_mapping() may need to do vblank + * waits, so we need vblank interrupts restored beforehand. + */ + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + intel_sanitize_fifo_underrun_reporting(crtc_state); + + drm_crtc_vblank_reset(&crtc->base); + + if (crtc_state->hw.active) + intel_crtc_vblank_on(crtc_state); + } + + intel_fbc_sanitize(i915); + + intel_sanitize_plane_mapping(i915); + + for_each_intel_encoder(&i915->drm, encoder) + intel_sanitize_encoder(encoder); + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + intel_sanitize_crtc(crtc, ctx); + intel_crtc_state_dump(crtc_state, NULL, "setup_hw_state"); + } + + intel_modeset_update_connector_atomic_state(i915); + + intel_dpll_sanitize_state(i915); + + if (IS_G4X(i915)) { + g4x_wm_get_hw_state(i915); + g4x_wm_sanitize(i915); + } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + vlv_wm_get_hw_state(i915); + vlv_wm_sanitize(i915); + } else if (DISPLAY_VER(i915) >= 9) { + skl_wm_get_hw_state(i915); + skl_wm_sanitize(i915); + } else if (HAS_PCH_SPLIT(i915)) { + ilk_wm_get_hw_state(i915); + } + + for_each_intel_crtc(&i915->drm, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + struct intel_power_domain_mask put_domains; + + intel_modeset_get_crtc_power_domains(crtc_state, &put_domains); + if (drm_WARN_ON(&i915->drm, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM))) + intel_modeset_put_crtc_power_domains(crtc, &put_domains); + } + + intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref); + + intel_power_domains_sanitize_state(i915); +} diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.h b/drivers/gpu/drm/i915/display/intel_modeset_setup.h new file mode 100644 index 000000000000..3beff67b33d0 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_MODESET_SETUP_H__ +#define __INTEL_MODESET_SETUP_H__ + +struct drm_i915_private; +struct drm_modeset_acquire_ctx; + +void intel_modeset_setup_hw_state(struct drm_i915_private *i915, + struct drm_modeset_acquire_ctx *ctx); + +#endif /* __INTEL_MODESET_SETUP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c new file mode 100644 index 000000000000..a91586d77cb6 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + * + * High level crtc/connector/encoder modeset state verification. + */ + +#include <drm/drm_atomic_state_helper.h> + +#include "i915_drv.h" +#include "intel_atomic.h" +#include "intel_crtc.h" +#include "intel_crtc_state_dump.h" +#include "intel_display.h" +#include "intel_display_types.h" +#include "intel_fdi.h" +#include "intel_modeset_verify.h" +#include "intel_pm.h" +#include "intel_snps_phy.h" + +/* + * Cross check the actual hw state with our own modeset state tracking (and its + * internal consistency). + */ +static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", + connector->base.base.id, connector->base.name); + + if (connector->get_hw_state(connector)) { + struct intel_encoder *encoder = intel_attached_encoder(connector); + + I915_STATE_WARN(!crtc_state, + "connector enabled without attached crtc\n"); + + if (!crtc_state) + return; + + I915_STATE_WARN(!crtc_state->hw.active, + "connector is active, but attached crtc isn't\n"); + + if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST) + return; + + I915_STATE_WARN(conn_state->best_encoder != &encoder->base, + "atomic encoder doesn't match attached encoder\n"); + + I915_STATE_WARN(conn_state->crtc != encoder->base.crtc, + "attached encoder crtc differs from connector crtc\n"); + } else { + I915_STATE_WARN(crtc_state && crtc_state->hw.active, + "attached crtc is active, but connector isn't\n"); + I915_STATE_WARN(!crtc_state && conn_state->best_encoder, + "best encoder set without crtc!\n"); + } +} + +static void +verify_connector_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_connector *connector; + struct drm_connector_state *new_conn_state; + int i; + + for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) { + struct drm_encoder *encoder = connector->encoder; + struct intel_crtc_state *crtc_state = NULL; + + if (new_conn_state->crtc != &crtc->base) + continue; + + if (crtc) + crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + + intel_connector_verify_state(crtc_state, new_conn_state); + + I915_STATE_WARN(new_conn_state->best_encoder != encoder, + "connector's atomic encoder doesn't match legacy encoder\n"); + } +} + +static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv, + const struct intel_crtc_state *pipe_config) +{ + if (pipe_config->has_pch_encoder) { + int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), + &pipe_config->fdi_m_n); + int dotclock = pipe_config->hw.adjusted_mode.crtc_clock; + + /* + * FDI already provided one idea for the dotclock. + * Yell if the encoder disagrees. + */ + drm_WARN(&dev_priv->drm, + !intel_fuzzy_clock_check(fdi_dotclock, dotclock), + "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", + fdi_dotclock, dotclock); + } +} + +static void +verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_state *state) +{ + struct intel_encoder *encoder; + struct drm_connector *connector; + struct drm_connector_state *old_conn_state, *new_conn_state; + int i; + + for_each_intel_encoder(&dev_priv->drm, encoder) { + bool enabled = false, found = false; + enum pipe pipe; + + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s]\n", + encoder->base.base.id, + encoder->base.name); + + for_each_oldnew_connector_in_state(&state->base, connector, old_conn_state, + new_conn_state, i) { + if (old_conn_state->best_encoder == &encoder->base) + found = true; + + if (new_conn_state->best_encoder != &encoder->base) + continue; + + found = true; + enabled = true; + + I915_STATE_WARN(new_conn_state->crtc != + encoder->base.crtc, + "connector's crtc doesn't match encoder crtc\n"); + } + + if (!found) + continue; + + I915_STATE_WARN(!!encoder->base.crtc != enabled, + "encoder's enabled state mismatch (expected %i, found %i)\n", + !!encoder->base.crtc, enabled); + + if (!encoder->base.crtc) { + bool active; + + active = encoder->get_hw_state(encoder, &pipe); + I915_STATE_WARN(active, + "encoder detached but still enabled on pipe %c.\n", + pipe_name(pipe)); + } + } +} + +static void +verify_crtc_state(struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_encoder *encoder; + struct intel_crtc_state *pipe_config = old_crtc_state; + struct drm_atomic_state *state = old_crtc_state->uapi.state; + struct intel_crtc *master_crtc; + + __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); + intel_crtc_free_hw_state(old_crtc_state); + intel_crtc_state_reset(old_crtc_state, crtc); + old_crtc_state->uapi.state = state; + + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s]\n", crtc->base.base.id, + crtc->base.name); + + pipe_config->hw.enable = new_crtc_state->hw.enable; + + intel_crtc_get_pipe_config(pipe_config); + + /* we keep both pipes enabled on 830 */ + if (IS_I830(dev_priv) && pipe_config->hw.active) + pipe_config->hw.active = new_crtc_state->hw.active; + + I915_STATE_WARN(new_crtc_state->hw.active != pipe_config->hw.active, + "crtc active state doesn't match with hw state (expected %i, found %i)\n", + new_crtc_state->hw.active, pipe_config->hw.active); + + I915_STATE_WARN(crtc->active != new_crtc_state->hw.active, + "transitional active state does not match atomic hw state (expected %i, found %i)\n", + new_crtc_state->hw.active, crtc->active); + + master_crtc = intel_master_crtc(new_crtc_state); + + for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) { + enum pipe pipe; + bool active; + + active = encoder->get_hw_state(encoder, &pipe); + I915_STATE_WARN(active != new_crtc_state->hw.active, + "[ENCODER:%i] active %i with crtc active %i\n", + encoder->base.base.id, active, + new_crtc_state->hw.active); + + I915_STATE_WARN(active && master_crtc->pipe != pipe, + "Encoder connected to wrong pipe %c\n", + pipe_name(pipe)); + + if (active) + intel_encoder_get_config(encoder, pipe_config); + } + + if (!new_crtc_state->hw.active) + return; + + intel_pipe_config_sanity_check(dev_priv, pipe_config); + + if (!intel_pipe_config_compare(new_crtc_state, + pipe_config, false)) { + I915_STATE_WARN(1, "pipe state doesn't match!\n"); + intel_crtc_state_dump(pipe_config, NULL, "hw state"); + intel_crtc_state_dump(new_crtc_state, NULL, "sw state"); + } +} + +void intel_modeset_verify_crtc(struct intel_crtc *crtc, + struct intel_atomic_state *state, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe) + return; + + intel_wm_state_verify(crtc, new_crtc_state); + verify_connector_state(state, crtc); + verify_crtc_state(crtc, old_crtc_state, new_crtc_state); + intel_shared_dpll_state_verify(crtc, old_crtc_state, new_crtc_state); + intel_mpllb_state_verify(state, new_crtc_state); +} + +void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv, + struct intel_atomic_state *state) +{ + verify_encoder_state(dev_priv, state); + verify_connector_state(state, NULL); + intel_shared_dpll_verify_disabled(dev_priv); +} diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.h b/drivers/gpu/drm/i915/display/intel_modeset_verify.h new file mode 100644 index 000000000000..2d6fbe4f7846 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_MODESET_VERIFY_H__ +#define __INTEL_MODESET_VERIFY_H__ + +struct drm_i915_private; +struct intel_atomic_state; +struct intel_crtc; +struct intel_crtc_state; + +void intel_modeset_verify_crtc(struct intel_crtc *crtc, + struct intel_atomic_state *state, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state); +void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv, + struct intel_atomic_state *state); + +#endif /* __INTEL_MODESET_VERIFY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index f31e8c3f8ce0..1c0c745c142d 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -30,6 +30,8 @@ #include <linux/firmware.h> #include <acpi/video.h> +#include <drm/drm_edid.h> + #include "i915_drv.h" #include "intel_acpi.h" #include "intel_backlight.h" @@ -53,6 +55,8 @@ #define MBOX_ASLE_EXT BIT(4) /* Mailbox #5 */ #define MBOX_BACKLIGHT BIT(5) /* Mailbox #2 (valid from v3.x) */ +#define PCON_HEADLESS_SKU BIT(13) + struct opregion_header { u8 signature[16]; u32 size; @@ -1135,6 +1139,18 @@ struct edid *intel_opregion_get_edid(struct intel_connector *intel_connector) return new_edid; } +bool intel_opregion_headless_sku(struct drm_i915_private *i915) +{ + struct intel_opregion *opregion = &i915->opregion; + struct opregion_header *header = opregion->header; + + if (!header || header->over.major < 2 || + (header->over.major == 2 && header->over.minor < 3)) + return false; + + return opregion->header->pcon & PCON_HEADLESS_SKU; +} + void intel_opregion_register(struct drm_i915_private *i915) { struct intel_opregion *opregion = &i915->opregion; diff --git a/drivers/gpu/drm/i915/display/intel_opregion.h b/drivers/gpu/drm/i915/display/intel_opregion.h index 82cc0ba34af7..2f261f985400 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.h +++ b/drivers/gpu/drm/i915/display/intel_opregion.h @@ -76,6 +76,8 @@ int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv, int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv); struct edid *intel_opregion_get_edid(struct intel_connector *connector); +bool intel_opregion_headless_sku(struct drm_i915_private *i915); + #else /* CONFIG_ACPI*/ static inline int intel_opregion_setup(struct drm_i915_private *dev_priv) @@ -127,6 +129,11 @@ intel_opregion_get_edid(struct intel_connector *connector) return NULL; } +static inline bool intel_opregion_headless_sku(struct drm_i915_private *i915) +{ + return false; +} + #endif /* CONFIG_ACPI */ #endif diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index ee46561b5ae8..6f26f7f91925 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -487,7 +487,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) void intel_overlay_reset(struct drm_i915_private *dev_priv) { - struct intel_overlay *overlay = dev_priv->overlay; + struct intel_overlay *overlay = dev_priv->display.overlay; if (!overlay) return; @@ -1113,7 +1113,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_object *new_bo; int ret; - overlay = dev_priv->overlay; + overlay = dev_priv->display.overlay; if (!overlay) { drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n"); return -ENODEV; @@ -1273,7 +1273,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, struct intel_overlay *overlay; int ret; - overlay = dev_priv->overlay; + overlay = dev_priv->display.overlay; if (!overlay) { drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n"); return -ENODEV; @@ -1399,8 +1399,6 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv) overlay->i915 = dev_priv; overlay->context = engine->kernel_context; - GEM_BUG_ON(!overlay->context); - overlay->color_key = 0x0101fe; overlay->color_key_enabled = true; overlay->brightness = -19; @@ -1418,7 +1416,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv) update_polyphase_filter(overlay->regs); update_reg_attrs(overlay, overlay->regs); - dev_priv->overlay = overlay; + dev_priv->display.overlay = overlay; drm_info(&dev_priv->drm, "Initialized overlay support.\n"); return; @@ -1430,7 +1428,7 @@ void intel_overlay_cleanup(struct drm_i915_private *dev_priv) { struct intel_overlay *overlay; - overlay = fetch_and_zero(&dev_priv->overlay); + overlay = fetch_and_zero(&dev_priv->display.overlay); if (!overlay) return; @@ -1459,7 +1457,7 @@ struct intel_overlay_error_state { struct intel_overlay_error_state * intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) { - struct intel_overlay *overlay = dev_priv->overlay; + struct intel_overlay *overlay = dev_priv->display.overlay; struct intel_overlay_error_state *error; if (!overlay || !overlay->active) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index d1d1b59102d6..237a40623dd7 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -71,20 +71,41 @@ intel_panel_fixed_mode(struct intel_connector *connector, return best_mode; } +static bool is_alt_drrs_mode(const struct drm_display_mode *mode, + const struct drm_display_mode *preferred_mode) +{ + return drm_mode_match(mode, preferred_mode, + DRM_MODE_MATCH_TIMINGS | + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS) && + mode->clock != preferred_mode->clock; +} + +static bool is_alt_vrr_mode(const struct drm_display_mode *mode, + const struct drm_display_mode *preferred_mode) +{ + return drm_mode_match(mode, preferred_mode, + DRM_MODE_MATCH_FLAGS | + DRM_MODE_MATCH_3D_FLAGS) && + mode->hdisplay == preferred_mode->hdisplay && + mode->vdisplay == preferred_mode->vdisplay && + mode->clock != preferred_mode->clock; +} + const struct drm_display_mode * intel_panel_downclock_mode(struct intel_connector *connector, const struct drm_display_mode *adjusted_mode) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode, *best_mode = NULL; - int min_vrefresh = i915->vbt.seamless_drrs_min_refresh_rate; + int min_vrefresh = connector->panel.vbt.seamless_drrs_min_refresh_rate; int max_vrefresh = drm_mode_vrefresh(adjusted_mode); /* pick the fixed_mode with the lowest refresh rate */ list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) { int vrefresh = drm_mode_vrefresh(fixed_mode); - if (vrefresh >= min_vrefresh && vrefresh < max_vrefresh) { + if (is_alt_drrs_mode(fixed_mode, adjusted_mode) && + vrefresh >= min_vrefresh && vrefresh < max_vrefresh) { max_vrefresh = vrefresh; best_mode = fixed_mode; } @@ -113,13 +134,11 @@ int intel_panel_get_modes(struct intel_connector *connector) enum drrs_type intel_panel_drrs_type(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); - if (list_empty(&connector->panel.fixed_modes) || list_is_singular(&connector->panel.fixed_modes)) return DRRS_TYPE_NONE; - return i915->vbt.drrs_type; + return connector->panel.vbt.drrs_type; } int intel_panel_compute_config(struct intel_connector *connector, @@ -154,16 +173,18 @@ int intel_panel_compute_config(struct intel_connector *connector, } static bool is_alt_fixed_mode(const struct drm_display_mode *mode, - const struct drm_display_mode *preferred_mode) + const struct drm_display_mode *preferred_mode, + bool has_vrr) { - return drm_mode_match(mode, preferred_mode, - DRM_MODE_MATCH_TIMINGS | - DRM_MODE_MATCH_FLAGS | - DRM_MODE_MATCH_3D_FLAGS) && - mode->clock != preferred_mode->clock; + /* is_alt_drrs_mode() is a subset of is_alt_vrr_mode() */ + if (has_vrr) + return is_alt_vrr_mode(mode, preferred_mode); + else + return is_alt_drrs_mode(mode, preferred_mode); } -static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector) +static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector, + bool has_vrr) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *preferred_mode = @@ -171,7 +192,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect struct drm_display_mode *mode, *next; list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { - if (!is_alt_fixed_mode(mode, preferred_mode)) + if (!is_alt_fixed_mode(mode, preferred_mode, has_vrr)) continue; drm_dbg_kms(&dev_priv->drm, @@ -220,16 +241,21 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector) struct drm_display_mode *mode, *next; list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] not using EDID mode: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(mode)); list_del(&mode->head); drm_mode_destroy(&i915->drm, mode); } } -void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs) +void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, + bool has_drrs, bool has_vrr) { intel_panel_add_edid_preferred_mode(connector); - if (intel_panel_preferred_fixed_mode(connector) && has_drrs) - intel_panel_add_edid_alt_fixed_modes(connector); + if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr)) + intel_panel_add_edid_alt_fixed_modes(connector, has_vrr); intel_panel_destroy_probed_modes(connector); } @@ -260,7 +286,7 @@ void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *mode; - mode = i915->vbt.lfp_lvds_vbt_mode; + mode = connector->panel.vbt.lfp_lvds_vbt_mode; if (!mode) return; @@ -274,7 +300,7 @@ void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector) struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *mode; - mode = i915->vbt.sdvo_lvds_vbt_mode; + mode = connector->panel.vbt.sdvo_lvds_vbt_mode; if (!mode) return; @@ -639,6 +665,8 @@ void intel_panel_fini(struct intel_connector *connector) intel_backlight_destroy(panel); + intel_bios_fini_panel(panel); + list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) { list_del(&fixed_mode->head); drm_mode_destroy(connector->base.dev, fixed_mode); diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 2e32bb728beb..b087c0c3cc6d 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -40,7 +40,8 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); -void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs); +void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, + bool has_drrs, bool has_vrr); void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector); void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector); void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index b688fd87e3da..ee72400759a3 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -122,16 +122,29 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->sb_lock); } -/* Program iCLKIP clock to the desired frequency */ -void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) +struct iclkip_params { + u32 iclk_virtual_root_freq; + u32 iclk_pi_range; + u32 divsel, phaseinc, auxdiv, phasedir, desired_divisor; +}; + +static void iclkip_params_init(struct iclkip_params *p) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int clock = crtc_state->hw.adjusted_mode.crtc_clock; - u32 divsel, phaseinc, auxdiv, phasedir = 0; - u32 temp; + memset(p, 0, sizeof(*p)); - lpt_disable_iclkip(dev_priv); + p->iclk_virtual_root_freq = 172800 * 1000; + p->iclk_pi_range = 64; +} + +static int lpt_iclkip_freq(struct iclkip_params *p) +{ + return DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq, + p->desired_divisor << p->auxdiv); +} + +static void lpt_compute_iclkip(struct iclkip_params *p, int clock) +{ + iclkip_params_init(p); /* The iCLK virtual clock root frequency is in MHz, * but the adjusted_mode->crtc_clock in KHz. To get the @@ -139,50 +152,60 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) * convert the virtual clock precision to KHz here for higher * precision. */ - for (auxdiv = 0; auxdiv < 2; auxdiv++) { - u32 iclk_virtual_root_freq = 172800 * 1000; - u32 iclk_pi_range = 64; - u32 desired_divisor; - - desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, - clock << auxdiv); - divsel = (desired_divisor / iclk_pi_range) - 2; - phaseinc = desired_divisor % iclk_pi_range; + for (p->auxdiv = 0; p->auxdiv < 2; p->auxdiv++) { + p->desired_divisor = DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq, + clock << p->auxdiv); + p->divsel = (p->desired_divisor / p->iclk_pi_range) - 2; + p->phaseinc = p->desired_divisor % p->iclk_pi_range; /* * Near 20MHz is a corner case which is * out of range for the 7-bit divisor */ - if (divsel <= 0x7f) + if (p->divsel <= 0x7f) break; } +} + +/* Program iCLKIP clock to the desired frequency */ +void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int clock = crtc_state->hw.adjusted_mode.crtc_clock; + struct iclkip_params p; + u32 temp; + + lpt_disable_iclkip(dev_priv); + + lpt_compute_iclkip(&p, clock); /* This should not happen with any sane values */ - drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(divsel) & + drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(p.divsel) & ~SBI_SSCDIVINTPHASE_DIVSEL_MASK); - drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(phasedir) & + drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(p.phasedir) & ~SBI_SSCDIVINTPHASE_INCVAL_MASK); drm_dbg_kms(&dev_priv->drm, "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", - clock, auxdiv, divsel, phasedir, phaseinc); + clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc); mutex_lock(&dev_priv->sb_lock); /* Program SSCDIVINTPHASE6 */ temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; - temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel); + temp |= SBI_SSCDIVINTPHASE_DIVSEL(p.divsel); temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; - temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc); - temp |= SBI_SSCDIVINTPHASE_DIR(phasedir); + temp |= SBI_SSCDIVINTPHASE_INCVAL(p.phaseinc); + temp |= SBI_SSCDIVINTPHASE_DIR(p.phasedir); temp |= SBI_SSCDIVINTPHASE_PROPAGATE; intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); /* Program SSCAUXDIV */ temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); - temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv); + temp |= SBI_SSCAUXDIV_FINALDIV2SEL(p.auxdiv); intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK); /* Enable modulator and associated divider */ @@ -200,15 +223,14 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) int lpt_get_iclkip(struct drm_i915_private *dev_priv) { - u32 divsel, phaseinc, auxdiv; - u32 iclk_virtual_root_freq = 172800 * 1000; - u32 iclk_pi_range = 64; - u32 desired_divisor; + struct iclkip_params p; u32 temp; if ((intel_de_read(dev_priv, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0) return 0; + iclkip_params_init(&p); + mutex_lock(&dev_priv->sb_lock); temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); @@ -218,21 +240,20 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv) } temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); - divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> + p.divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; - phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> + p.phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> SBI_SSCDIVINTPHASE_INCVAL_SHIFT; temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); - auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> + p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; mutex_unlock(&dev_priv->sb_lock); - desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc; + p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc; - return DIV_ROUND_CLOSEST(iclk_virtual_root_freq, - desired_divisor << auxdiv); + return lpt_iclkip_freq(&p); } /* Implements 3 different sequences from BSpec chapter "Display iCLK @@ -501,7 +522,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) } /* Check if any DPLLs are using the SSC source */ - for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) { + for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { u32 temp = intel_de_read(dev_priv, PCH_DPLL(i)); if (!(temp & DPLL_VCO_ENABLE)) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d10f27d0b7b0..76be796df255 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -311,7 +311,7 @@ void intel_crtc_initial_plane_config(struct intel_crtc *crtc) * can even allow for smooth boot transitions if the BIOS * fb is large enough for the active pipe configuration. */ - dev_priv->display->get_initial_plane_config(crtc, &plane_config); + dev_priv->display.funcs.display->get_initial_plane_config(crtc, &plane_config); /* * If the fb is shared between multiple heads, we'll diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 5a598dd06039..9a66e03aa2d6 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -28,7 +28,7 @@ intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp) * See intel_pps_reset_all() why we need a power domain reference here. */ wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE); - mutex_lock(&dev_priv->pps_mutex); + mutex_lock(&dev_priv->display.pps.mutex); return wakeref; } @@ -38,7 +38,7 @@ intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + mutex_unlock(&dev_priv->display.pps.mutex); intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); return 0; @@ -163,7 +163,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); enum pipe pipe; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); /* We should never land here with regular DP ports */ drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp)); @@ -209,9 +209,10 @@ static int bxt_power_sequencer_idx(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - int backlight_controller = dev_priv->vbt.backlight.controller; + struct intel_connector *connector = intel_dp->attached_connector; + int backlight_controller = connector->panel.vbt.backlight.controller; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); /* We should never land here with regular DP ports */ drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp)); @@ -281,7 +282,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); enum port port = dig_port->base.port; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); /* try to find a pipe with this port selected */ /* first pick one where the panel is on */ @@ -406,7 +407,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_dp->pps.pps_pipe == INVALID_PIPE) @@ -419,7 +420,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_dp->pps.pps_pipe == INVALID_PIPE) @@ -462,7 +463,7 @@ static void wait_panel_status(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); i915_reg_t pp_stat_reg, pp_ctrl_reg; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); intel_pps_verify_state(intel_dp); @@ -509,7 +510,7 @@ static void wait_panel_power_cycle(struct intel_dp *intel_dp) drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n"); - /* take the difference of currrent time and panel power off time + /* take the difference of current time and panel power off time * and then make panel wait for t11_t12 if needed. */ panel_power_on_time = ktime_get_boottime(); panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->pps.panel_power_off_time); @@ -555,7 +556,7 @@ static u32 ilk_get_pp_control(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 control; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)); if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) && @@ -579,7 +580,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) i915_reg_t pp_stat_reg, pp_ctrl_reg; bool need_to_disable = !intel_dp->pps.want_panel_vdd; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if (!intel_dp_is_edp(intel_dp)) return false; @@ -656,7 +657,7 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) u32 pp; i915_reg_t pp_stat_reg, pp_ctrl_reg; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); drm_WARN_ON(&dev_priv->drm, intel_dp->pps.want_panel_vdd); @@ -723,6 +724,13 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp) unsigned long delay; /* + * We may not yet know the real power sequencing delays, + * so keep VDD enabled until we're done with init. + */ + if (intel_dp->pps.initializing) + return; + + /* * Queue the timer to fire a long time from now (relative to the power * down delay) to keep the panel power up across a sequence of * operations. @@ -740,7 +748,7 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if (!intel_dp_is_edp(intel_dp)) return; @@ -763,7 +771,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) u32 pp; i915_reg_t pp_ctrl_reg; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if (!intel_dp_is_edp(intel_dp)) return; @@ -824,7 +832,7 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp) u32 pp; i915_reg_t pp_ctrl_reg; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if (!intel_dp_is_edp(intel_dp)) return; @@ -983,7 +991,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, { struct intel_encoder *encoder; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); for_each_intel_dp(&dev_priv->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1013,7 +1021,7 @@ void vlv_pps_init(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE); @@ -1051,12 +1059,12 @@ void vlv_pps_init(struct intel_encoder *encoder, pps_init_registers(intel_dp, true); } -static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp) +static void pps_vdd_init(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); if (!edp_have_panel_vdd(intel_dp)) return; @@ -1072,8 +1080,6 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref); intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port)); - - edp_panel_vdd_schedule_off(intel_dp); } bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp) @@ -1159,53 +1165,96 @@ intel_pps_verify_state(struct intel_dp *intel_dp) } } -static void pps_init_delays(struct intel_dp *intel_dp) +static bool pps_delays_valid(struct edp_power_seq *delays) +{ + return delays->t1_t3 || delays->t8 || delays->t9 || + delays->t10 || delays->t11_t12; +} + +static void pps_init_delays_bios(struct intel_dp *intel_dp, + struct edp_power_seq *bios) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct edp_power_seq cur, vbt, spec, - *final = &intel_dp->pps.pps_delays; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); - /* already initialized? */ - if (final->t11_t12 != 0) - return; + if (!pps_delays_valid(&intel_dp->pps.bios_pps_delays)) + intel_pps_readout_hw_state(intel_dp, &intel_dp->pps.bios_pps_delays); + + *bios = intel_dp->pps.bios_pps_delays; + + intel_pps_dump_state(intel_dp, "bios", bios); +} + +static void pps_init_delays_vbt(struct intel_dp *intel_dp, + struct edp_power_seq *vbt) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_connector *connector = intel_dp->attached_connector; - intel_pps_readout_hw_state(intel_dp, &cur); + *vbt = connector->panel.vbt.edp.pps; - intel_pps_dump_state(intel_dp, "cur", &cur); + if (!pps_delays_valid(vbt)) + return; - vbt = dev_priv->vbt.edp.pps; /* On Toshiba Satellite P50-C-18C system the VBT T12 delay * of 500ms appears to be too short. Ocassionally the panel * just fails to power back on. Increasing the delay to 800ms * seems sufficient to avoid this problem. */ if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) { - vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10); + vbt->t11_t12 = max_t(u16, vbt->t11_t12, 1300 * 10); drm_dbg_kms(&dev_priv->drm, "Increasing T12 panel delay as per the quirk to %d\n", - vbt.t11_t12); + vbt->t11_t12); } + /* T11_T12 delay is special and actually in units of 100ms, but zero * based in the hw (so we need to add 100 ms). But the sw vbt * table multiplies it with 1000 to make it in units of 100usec, * too. */ - vbt.t11_t12 += 100 * 10; + vbt->t11_t12 += 100 * 10; + + intel_pps_dump_state(intel_dp, "vbt", vbt); +} + +static void pps_init_delays_spec(struct intel_dp *intel_dp, + struct edp_power_seq *spec) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + lockdep_assert_held(&dev_priv->display.pps.mutex); /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of * our hw here, which are all in 100usec. */ - spec.t1_t3 = 210 * 10; - spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */ - spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */ - spec.t10 = 500 * 10; + spec->t1_t3 = 210 * 10; + spec->t8 = 50 * 10; /* no limit for t8, use t7 instead */ + spec->t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */ + spec->t10 = 500 * 10; /* This one is special and actually in units of 100ms, but zero * based in the hw (so we need to add 100 ms). But the sw vbt * table multiplies it with 1000 to make it in units of 100usec, * too. */ - spec.t11_t12 = (510 + 100) * 10; + spec->t11_t12 = (510 + 100) * 10; + + intel_pps_dump_state(intel_dp, "spec", spec); +} + +static void pps_init_delays(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct edp_power_seq cur, vbt, spec, + *final = &intel_dp->pps.pps_delays; + + lockdep_assert_held(&dev_priv->display.pps.mutex); - intel_pps_dump_state(intel_dp, "vbt", &vbt); + /* already initialized? */ + if (pps_delays_valid(final)) + return; + + pps_init_delays_bios(intel_dp, &cur); + pps_init_delays_vbt(intel_dp, &vbt); + pps_init_delays_spec(intel_dp, &spec); /* Use the max of the register settings and vbt. If both are * unset, fall back to the spec limits. */ @@ -1263,7 +1312,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd enum port port = dp_to_dig_port(intel_dp)->base.port; const struct edp_power_seq *seq = &intel_dp->pps.pps_delays; - lockdep_assert_held(&dev_priv->pps_mutex); + lockdep_assert_held(&dev_priv->display.pps.mutex); intel_pps_get_registers(intel_dp, ®s); @@ -1367,18 +1416,48 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp) pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); + pps_vdd_init(intel_dp); - intel_pps_vdd_sanitize(intel_dp); + if (edp_have_panel_vdd(intel_dp)) + edp_panel_vdd_schedule_off(intel_dp); } } void intel_pps_init(struct intel_dp *intel_dp) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + intel_wakeref_t wakeref; + + intel_dp->pps.initializing = true; INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work); pps_init_timestamps(intel_dp); - intel_pps_encoder_reset(intel_dp); + with_intel_pps_lock(intel_dp, wakeref) { + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + vlv_initial_power_sequencer_setup(intel_dp); + + pps_init_delays(intel_dp); + pps_init_registers(intel_dp, false); + pps_vdd_init(intel_dp); + } +} + +void intel_pps_init_late(struct intel_dp *intel_dp) +{ + intel_wakeref_t wakeref; + + with_intel_pps_lock(intel_dp, wakeref) { + /* Reinit delays after per-panel info has been parsed from VBT */ + memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp->pps.pps_delays)); + pps_init_delays(intel_dp); + pps_init_registers(intel_dp, false); + + intel_dp->pps.initializing = false; + + if (edp_have_panel_vdd(intel_dp)) + edp_panel_vdd_schedule_off(intel_dp); + } } void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) @@ -1408,11 +1487,11 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) void intel_pps_setup(struct drm_i915_private *i915) { if (HAS_PCH_SPLIT(i915) || IS_GEMINILAKE(i915) || IS_BROXTON(i915)) - i915->pps_mmio_base = PCH_PPS_BASE; + i915->display.pps.mmio_base = PCH_PPS_BASE; else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - i915->pps_mmio_base = VLV_PPS_BASE; + i915->display.pps.mmio_base = VLV_PPS_BASE; else - i915->pps_mmio_base = PPS_BASE; + i915->display.pps.mmio_base = PPS_BASE; } void assert_pps_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h index e64144659d31..a3a56f903f26 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.h +++ b/drivers/gpu/drm/i915/display/intel_pps.h @@ -41,6 +41,7 @@ bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp); void intel_pps_wait_power_cycle(struct intel_dp *intel_dp); void intel_pps_init(struct intel_dp *intel_dp); +void intel_pps_init_late(struct intel_dp *intel_dp); void intel_pps_encoder_reset(struct intel_dp *intel_dp); void intel_pps_reset_all(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 36356893c7ca..079b7d3d0c53 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -86,10 +86,13 @@ static bool psr_global_enabled(struct intel_dp *intel_dp) { + struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *i915 = dp_to_i915(intel_dp); switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) { case I915_PSR_DEBUG_DEFAULT: + if (i915->params.enable_psr == -1) + return connector->panel.vbt.psr.enable; return i915->params.enable_psr; case I915_PSR_DEBUG_DISABLE: return false; @@ -399,6 +402,7 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) { + struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 val = 0; @@ -411,20 +415,20 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) goto check_tp3_sel; } - if (dev_priv->vbt.psr.tp1_wakeup_time_us == 0) + if (connector->panel.vbt.psr.tp1_wakeup_time_us == 0) val |= EDP_PSR_TP1_TIME_0us; - else if (dev_priv->vbt.psr.tp1_wakeup_time_us <= 100) + else if (connector->panel.vbt.psr.tp1_wakeup_time_us <= 100) val |= EDP_PSR_TP1_TIME_100us; - else if (dev_priv->vbt.psr.tp1_wakeup_time_us <= 500) + else if (connector->panel.vbt.psr.tp1_wakeup_time_us <= 500) val |= EDP_PSR_TP1_TIME_500us; else val |= EDP_PSR_TP1_TIME_2500us; - if (dev_priv->vbt.psr.tp2_tp3_wakeup_time_us == 0) + if (connector->panel.vbt.psr.tp2_tp3_wakeup_time_us == 0) val |= EDP_PSR_TP2_TP3_TIME_0us; - else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time_us <= 100) + else if (connector->panel.vbt.psr.tp2_tp3_wakeup_time_us <= 100) val |= EDP_PSR_TP2_TP3_TIME_100us; - else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time_us <= 500) + else if (connector->panel.vbt.psr.tp2_tp3_wakeup_time_us <= 500) val |= EDP_PSR_TP2_TP3_TIME_500us; else val |= EDP_PSR_TP2_TP3_TIME_2500us; @@ -441,13 +445,14 @@ check_tp3_sel: static u8 psr_compute_idle_frames(struct intel_dp *intel_dp) { + struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); int idle_frames; /* Let's use 6 as the minimum to cover all known cases including the * off-by-one issue that HW has in some cases. */ - idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + idle_frames = max(6, connector->panel.vbt.psr.idle_frames); idle_frames = max(idle_frames, intel_dp->psr.sink_sync_latency + 1); if (drm_WARN_ON(&dev_priv->drm, idle_frames > 0xf)) @@ -483,18 +488,19 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) { + struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 val = 0; if (dev_priv->params.psr_safest_params) return EDP_PSR2_TP2_TIME_2500us; - if (dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us >= 0 && - dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 50) + if (connector->panel.vbt.psr.psr2_tp2_tp3_wakeup_time_us >= 0 && + connector->panel.vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 50) val |= EDP_PSR2_TP2_TIME_50us; - else if (dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 100) + else if (connector->panel.vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 100) val |= EDP_PSR2_TP2_TIME_100us; - else if (dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 500) + else if (connector->panel.vbt.psr.psr2_tp2_tp3_wakeup_time_us <= 500) val |= EDP_PSR2_TP2_TIME_500us; else val |= EDP_PSR2_TP2_TIME_2500us; @@ -549,7 +555,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) /* * TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default * values from BSpec. In order to setting an optimal power - * consumption, lower than 4k resoluition mode needs to decrese + * consumption, lower than 4k resolution mode needs to decrease * IO_BUFFER_WAKE and FAST_WAKE. And higher than 4K resolution * mode needs to increase IO_BUFFER_WAKE and FAST_WAKE. */ @@ -700,7 +706,7 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp, if (crtc_state->enable_psr2_sel_fetch) return; - if (!(dev_priv->dmc.allowed_dc_mask & DC_STATE_EN_DC3CO)) + if (!(dev_priv->display.dmc.allowed_dc_mask & DC_STATE_EN_DC3CO)) return; if (!dc3co_is_pipe_port_compatible(intel_dp, crtc_state)) @@ -953,7 +959,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, int psr_setup_time; /* - * Current PSR panels dont work reliably with VRR enabled + * Current PSR panels don't work reliably with VRR enabled * So if VRR is enabled, do not enable PSR. */ if (crtc_state->vrr.enable) @@ -1658,7 +1664,7 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c * * Plane scaling and rotation is not supported by selective fetch and both * properties can change without a modeset, so need to be check at every - * atomic commmit. + * atomic commit. */ static bool psr2_sel_fetch_plane_state_supported(const struct intel_plane_state *plane_state) { @@ -1857,7 +1863,9 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_crtc_state *crtc_state = + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_encoder *encoder; @@ -1865,7 +1873,7 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, return; for_each_intel_encoder_mask_with_psr(state->base.dev, encoder, - crtc_state->uapi.encoder_mask) { + old_crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_psr *psr = &intel_dp->psr; bool needs_to_disable = false; @@ -1878,10 +1886,10 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, * - All planes will go inactive * - Changing between PSR versions */ - needs_to_disable |= intel_crtc_needs_modeset(crtc_state); - needs_to_disable |= !crtc_state->has_psr; - needs_to_disable |= !crtc_state->active_planes; - needs_to_disable |= crtc_state->has_psr2 != psr->psr2_enabled; + needs_to_disable |= intel_crtc_needs_modeset(new_crtc_state); + needs_to_disable |= !new_crtc_state->has_psr; + needs_to_disable |= !new_crtc_state->active_planes; + needs_to_disable |= new_crtc_state->has_psr2 != psr->psr2_enabled; if (psr->enabled && needs_to_disable) intel_psr_disable_locked(intel_dp); @@ -2197,7 +2205,7 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp) } /** - * intel_psr_invalidate - Invalidade PSR + * intel_psr_invalidate - Invalidate PSR * @dev_priv: i915 device * @frontbuffer_bits: frontbuffer plane tracking bits * @origin: which operation caused the invalidate @@ -2367,6 +2375,7 @@ unlock: */ void intel_psr_init(struct intel_dp *intel_dp) { + struct intel_connector *connector = intel_dp->attached_connector; struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -2390,14 +2399,10 @@ void intel_psr_init(struct intel_dp *intel_dp) intel_dp->psr.source_support = true; - if (dev_priv->params.enable_psr == -1) - if (!dev_priv->vbt.psr.enable) - dev_priv->params.enable_psr = 0; - /* Set link_standby x link_off defaults */ if (DISPLAY_VER(dev_priv) < 12) /* For new platforms up to TGL let's respect VBT back again */ - intel_dp->psr.link_standby = dev_priv->vbt.psr.full_link; + intel_dp->psr.link_standby = connector->panel.vbt.psr.full_link; INIT_WORK(&intel_dp->psr.work, intel_psr_work); INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work); diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.c b/drivers/gpu/drm/i915/display/intel_qp_tables.c index c626a24fe98f..6f8e4ec5c0fb 100644 --- a/drivers/gpu/drm/i915/display/intel_qp_tables.c +++ b/drivers/gpu/drm/i915/display/intel_qp_tables.c @@ -3,7 +3,7 @@ * Copyright © 2021 Intel Corporation */ -#include <drm/drm_dsc.h> +#include <drm/display/drm_dsc.h> #include "i915_utils.h" #include "intel_qp_tables.h" diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index c8488f5ebd04..e415cd7c0b84 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -191,6 +191,9 @@ static struct intel_quirk intel_quirks[] = { /* ASRock ITX*/ { 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time }, { 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time }, + /* ECS Liva Q2 */ + { 0x3185, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time }, + { 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time }, }; void intel_init_quirks(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index ab88d8b783e6..19122bc6d2ab 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -31,6 +31,7 @@ #include <linux/i2c.h> #include <linux/slab.h> +#include <drm/display/drm_hdmi_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> @@ -2868,6 +2869,7 @@ static bool intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) { struct drm_encoder *encoder = &intel_sdvo->base.base; + struct drm_i915_private *i915 = to_i915(encoder->dev); struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; @@ -2899,6 +2901,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; + intel_bios_init_panel(i915, &intel_connector->panel, NULL, NULL); + /* * Fetch modes from VBT. For SDVO prefer the VBT mode since some * SDVO->LVDS transcoders can't cope with the EDID mode. @@ -2907,7 +2911,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_panel_preferred_fixed_mode(intel_connector)) { intel_ddc_get_modes(connector, &intel_sdvo->ddc); - intel_panel_add_edid_fixed_modes(intel_connector, false); + intel_panel_add_edid_fixed_modes(intel_connector, false, false); } intel_panel_init(intel_connector); diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 0dd4775e8195..937cefd6f78f 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -517,6 +517,1117 @@ static const struct intel_mpllb_state dg2_hdmi_148_5 = { REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), }; +/* values in the below table are calculted using the algo */ +static const struct intel_mpllb_state dg2_hdmi_25200 = { + .clock = 25200, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 128) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 41943) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2621), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_27027 = { + .clock = 27027, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 140) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 31876) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 46555), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_28320 = { + .clock = 28320, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 148) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40894) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 30408), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_30240 = { + .clock = 30240, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 160) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 50331) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 42466), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_31500 = { + .clock = 31500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 68) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_36000 = { + .clock = 36000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 82) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_40000 = { + .clock = 40000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 96) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_49500 = { + .clock = 49500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 126) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_50000 = { + .clock = 50000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 128) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_57284 = { + .clock = 57284, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 150) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 42886) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 49701), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_58000 = { + .clock = 58000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 152) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_65000 = { + .clock = 65000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 72) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_71000 = { + .clock = 71000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 80) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_74176 = { + .clock = 74176, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22334) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 43829), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_75000 = { + .clock = 75000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 88) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_78750 = { + .clock = 78750, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_85500 = { + .clock = 85500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 104) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_88750 = { + .clock = 88750, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 110) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_106500 = { + .clock = 106500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 138) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_108000 = { + .clock = 108000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 140) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_115500 = { + .clock = 115500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 152) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_119000 = { + .clock = 119000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 158) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_135000 = { + .clock = 135000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 76) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_138500 = { + .clock = 138500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 78) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_147160 = { + .clock = 147160, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 84) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 56623) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 6815), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_148352 = { + .clock = 148352, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22334) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 43829), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_154000 = { + .clock = 154000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 13) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 90) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_162000 = { + .clock = 162000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 96) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_209800 = { + .clock = 209800, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 134) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 60293) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 7864), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_262750 = { + .clock = 262750, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 72) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36044) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_268500 = { + .clock = 268500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 45875) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_296703 = { + .clock = 296703, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22321) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36804), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_241500 = { + .clock = 241500, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 160) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_497750 = { + .clock = 497750, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 166) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36044) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_592000 = { + .clock = 592000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_593407 = { + .clock = 593407, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 0) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22328) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 7549), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + +static const struct intel_mpllb_state dg2_hdmi_297 = { + .clock = 297000, + .ref_control = + REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), + .mpllb_cp = + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), + .mpllb_div = + REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), + .mpllb_div2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), + .mpllb_fracn1 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), + .mpllb_fracn2 = + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | + REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), + .mpllb_sscen = + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; + static const struct intel_mpllb_state dg2_hdmi_594 = { .clock = 594000, .ref_control = @@ -551,7 +1662,44 @@ static const struct intel_mpllb_state * const dg2_hdmi_tables[] = { &dg2_hdmi_27_0, &dg2_hdmi_74_25, &dg2_hdmi_148_5, + &dg2_hdmi_297, &dg2_hdmi_594, + &dg2_hdmi_25200, + &dg2_hdmi_27027, + &dg2_hdmi_28320, + &dg2_hdmi_30240, + &dg2_hdmi_31500, + &dg2_hdmi_36000, + &dg2_hdmi_40000, + &dg2_hdmi_49500, + &dg2_hdmi_50000, + &dg2_hdmi_57284, + &dg2_hdmi_58000, + &dg2_hdmi_65000, + &dg2_hdmi_71000, + &dg2_hdmi_74176, + &dg2_hdmi_75000, + &dg2_hdmi_78750, + &dg2_hdmi_85500, + &dg2_hdmi_88750, + &dg2_hdmi_106500, + &dg2_hdmi_108000, + &dg2_hdmi_115500, + &dg2_hdmi_119000, + &dg2_hdmi_135000, + &dg2_hdmi_138500, + &dg2_hdmi_147160, + &dg2_hdmi_148352, + &dg2_hdmi_154000, + &dg2_hdmi_162000, + &dg2_hdmi_209800, + &dg2_hdmi_241500, + &dg2_hdmi_262750, + &dg2_hdmi_268500, + &dg2_hdmi_296703, + &dg2_hdmi_497750, + &dg2_hdmi_592000, + &dg2_hdmi_593407, NULL, }; @@ -597,7 +1745,7 @@ int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state, return -EINVAL; for (i = 0; tables[i]; i++) { - if (crtc_state->port_clock <= tables[i]->clock) { + if (crtc_state->port_clock == tables[i]->clock) { crtc_state->mpllb_state = *tables[i]; return 0; } @@ -781,3 +1929,46 @@ int intel_snps_phy_check_hdmi_link_rate(int clock) return MODE_CLOCK_RANGE; } + +void intel_mpllb_state_verify(struct intel_atomic_state *state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_mpllb_state mpllb_hw_state = { 0 }; + struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state; + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + struct intel_encoder *encoder; + + if (!IS_DG2(i915)) + return; + + if (!new_crtc_state->hw.active) + return; + + encoder = intel_get_crtc_new_encoder(state, new_crtc_state); + intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state); + +#define MPLLB_CHECK(__name) \ + I915_STATE_WARN(mpllb_sw_state->__name != mpllb_hw_state.__name, \ + "[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \ + crtc->base.base.id, crtc->base.name, \ + __stringify(__name), \ + mpllb_sw_state->__name, mpllb_hw_state.__name) + + MPLLB_CHECK(mpllb_cp); + MPLLB_CHECK(mpllb_div); + MPLLB_CHECK(mpllb_div2); + MPLLB_CHECK(mpllb_fracn1); + MPLLB_CHECK(mpllb_fracn2); + MPLLB_CHECK(mpllb_sscen); + MPLLB_CHECK(mpllb_sscstep); + + /* + * ref_control is handled by the hardware/firemware and never + * programmed by the software, but the proper values are supplied + * in the bspec for verification purposes. + */ + MPLLB_CHECK(ref_control); + +#undef MPLLB_CHECK +} diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h index 11dcd6deb070..557ef820bc0b 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.h +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h @@ -9,8 +9,9 @@ #include <linux/types.h> struct drm_i915_private; -struct intel_encoder; +struct intel_atomic_state; struct intel_crtc_state; +struct intel_encoder; struct intel_mpllb_state; enum phy; @@ -31,5 +32,7 @@ int intel_mpllb_calc_port_clock(struct intel_encoder *encoder, int intel_snps_phy_check_hdmi_link_rate(int clock); void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); +void intel_mpllb_state_verify(struct intel_atomic_state *state, + struct intel_crtc_state *new_crtc_state); #endif /* __INTEL_SNPS_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 7c0df80612d0..7649c50b5445 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -34,11 +34,11 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_color_mgmt.h> #include <drm/drm_crtc.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> #include "i915_drv.h" @@ -1354,8 +1354,8 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; + int min_scale = DRM_PLANE_NO_SCALING; + int max_scale = DRM_PLANE_NO_SCALING; int ret; if (g4x_fb_scalable(plane_state->hw.fb)) { @@ -1425,8 +1425,8 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, return ret; ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index b8b822ea3755..e5af955b5600 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -246,7 +246,7 @@ static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_uncore *uncore = &i915->uncore; - u32 isr_bit = i915->hotplug.pch_hpd[dig_port->base.hpd_pin]; + u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; u32 mask = 0; u32 val; @@ -279,7 +279,7 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); - u32 isr_bit = i915->hotplug.pch_hpd[dig_port->base.hpd_pin]; + u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; struct intel_uncore *uncore = &i915->uncore; u32 val, mask = 0; @@ -494,7 +494,8 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port, } live_status_mask = tc_port_live_status_mask(dig_port); - if (!(live_status_mask & (BIT(TC_PORT_DP_ALT) | BIT(TC_PORT_LEGACY)))) { + if (!(live_status_mask & (BIT(TC_PORT_DP_ALT) | BIT(TC_PORT_LEGACY))) && + !dig_port->tc_legacy_port) { drm_dbg_kms(&i915->drm, "Port %s: PHY ownership not required (live status %02x)\n", dig_port->tc_port_name, live_status_mask); goto out_set_tbt_alt_mode; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index 4b98bab3b890..509b0a419c20 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -182,6 +182,10 @@ struct bdb_general_features { #define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */ #define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */ +/* Device handle */ +#define DEVICE_HANDLE_LFP1 0x0008 +#define DEVICE_HANDLE_LFP2 0x0080 + /* Pre 915 */ #define DEVICE_TYPE_NONE 0x00 #define DEVICE_TYPE_CRT 0x01 @@ -564,7 +568,9 @@ struct bdb_driver_features { u16 tbt_enabled:1; u16 psr_enabled:1; u16 ips_enabled:1; - u16 reserved3:4; + u16 reserved3:1; + u16 dmrrs_enabled:1; + u16 reserved4:2; u16 pc_feature_valid:1; } __packed; @@ -636,6 +642,7 @@ struct bdb_sdvo_panel_dtds { #define EDP_30BPP 2 #define EDP_RATE_1_62 0 #define EDP_RATE_2_7 1 +#define EDP_RATE_5_4 2 #define EDP_LANE_1 0 #define EDP_LANE_2 1 #define EDP_LANE_4 3 @@ -666,6 +673,16 @@ struct edp_full_link_params { u8 vswing:4; } __packed; +struct edp_apical_params { + u32 panel_oui; + u32 dpcd_base_address; + u32 dpcd_idridix_control_0; + u32 dpcd_option_select; + u32 dpcd_backlight; + u32 ambient_light; + u32 backlight_scale; +} __packed; + struct bdb_edp { struct edp_power_seq power_seqs[16]; u32 color_depth; @@ -681,15 +698,16 @@ struct bdb_edp { struct edp_pwm_delays pwm_delays[16]; /* 186 */ u16 full_link_params_provided; /* 199 */ struct edp_full_link_params full_link_params[16]; /* 199 */ + u16 apical_enable; /* 203 */ + struct edp_apical_params apical_params[16]; /* 203 */ + u16 edp_fast_link_training_rate[16]; /* 224 */ + u16 edp_max_port_link_rate[16]; /* 244 */ } __packed; /* * Block 40 - LFP Data Block */ -/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */ -#define MODE_MASK 0x3 - struct bdb_lvds_options { u8 panel_type; u8 panel_type2; /* 212 */ @@ -717,6 +735,7 @@ struct bdb_lvds_options { u16 lcdvcc_s0_enable; /* 200 */ u32 rotation; /* 228 */ + u32 position; /* 240 */ } __packed; /* @@ -843,28 +862,43 @@ struct bdb_lfp_backlight_data { u8 level[16]; /* Obsolete from 234+ */ struct lfp_backlight_control_method backlight_control[16]; struct lfp_brightness_level brightness_level[16]; /* 234+ */ - struct lfp_brightness_level brightness_min_level[16]; /* 234+ */ - u8 brightness_precision_bits[16]; /* 236+ */ + struct lfp_brightness_level brightness_min_level[16]; /* 234+ */ + u8 brightness_precision_bits[16]; /* 236+ */ + u16 hdr_dpcd_refresh_timeout[16]; /* 239+ */ } __packed; /* * Block 44 - LFP Power Conservation Features Block */ +struct lfp_power_features { + u8 reserved1:1; + u8 power_conservation_pref:3; + u8 reserved2:1; + u8 lace_enabled_status:1; + u8 lace_support:1; + u8 als_enable:1; +} __packed; struct als_data_entry { u16 backlight_adjust; u16 lux; } __packed; -struct agressiveness_profile_entry { - u8 dpst_agressiveness : 4; - u8 lace_agressiveness : 4; +struct aggressiveness_profile_entry { + u8 dpst_aggressiveness : 4; + u8 lace_aggressiveness : 4; +} __packed; + +struct aggressiveness_profile2_entry { + u8 opst_aggressiveness : 4; + u8 elp_aggressiveness : 4; } __packed; struct bdb_lfp_power { - u8 lfp_feature_bits; + struct lfp_power_features features; struct als_data_entry als[5]; - u8 lace_aggressiveness_profile; + u8 lace_aggressiveness_profile:3; + u8 reserved1:5; u16 dpst; u16 psr; u16 drrs; @@ -873,9 +907,12 @@ struct bdb_lfp_power { u16 dmrrs; u16 adb; u16 lace_enabled_status; - struct agressiveness_profile_entry aggressivenes[16]; + struct aggressiveness_profile_entry aggressiveness[16]; u16 hobl; /* 232+ */ u16 vrr_feature_enabled; /* 233+ */ + u16 elp; /* 247+ */ + u16 opst; /* 247+ */ + struct aggressiveness_profile2_entry aggressiveness2[16]; /* 247+ */ } __packed; /* @@ -885,8 +922,10 @@ struct bdb_lfp_power { #define MAX_MIPI_CONFIGURATIONS 6 struct bdb_mipi_config { - struct mipi_config config[MAX_MIPI_CONFIGURATIONS]; - struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS]; + struct mipi_config config[MAX_MIPI_CONFIGURATIONS]; /* 175 */ + struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS]; /* 177 */ + struct edp_pwm_delays pwm_delays[MAX_MIPI_CONFIGURATIONS]; /* 186 */ + u8 pmic_i2c_bus_number[MAX_MIPI_CONFIGURATIONS]; /* 190 */ } __packed; /* diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index e59c29ab1300..d7eb1af328e7 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -7,6 +7,8 @@ */ #include <linux/limits.h> +#include <drm/display/drm_dsc_helper.h> + #include "i915_drv.h" #include "intel_crtc.h" #include "intel_de.h" @@ -342,7 +344,7 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - if (!INTEL_INFO(i915)->display.has_dsc) + if (!RUNTIME_INFO(i915)->has_dsc) return false; if (DISPLAY_VER(i915) >= 12) @@ -595,6 +597,8 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) DSC_VER_MIN_SHIFT | vdsc_cfg->bits_per_component << DSC_BPC_SHIFT | vdsc_cfg->line_buf_depth << DSC_LINE_BUF_DEPTH_SHIFT; + if (vdsc_cfg->dsc_version_minor == 2) + pps_val |= DSC_ALT_ICH_SEL; if (vdsc_cfg->block_pred_enable) pps_val |= DSC_BLOCK_PREDICTION; if (vdsc_cfg->convert_rgb) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 396f2f994fa0..5eac99021875 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -9,25 +9,35 @@ #include "intel_display_types.h" #include "intel_vrr.h" -bool intel_vrr_is_capable(struct drm_connector *connector) +bool intel_vrr_is_capable(struct intel_connector *connector) { + const struct drm_display_info *info = &connector->base.display_info; + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_dp *intel_dp; - const struct drm_display_info *info = &connector->display_info; - struct drm_i915_private *i915 = to_i915(connector->dev); - - if (connector->connector_type != DRM_MODE_CONNECTOR_eDP && - connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) - return false; - intel_dp = intel_attached_dp(to_intel_connector(connector)); /* * DP Sink is capable of VRR video timings if * Ignore MSA bit is set in DPCD. * EDID monitor range also should be atleast 10 for reasonable * Adaptive Sync or Variable Refresh Rate end user experience. */ + switch (connector->base.connector_type) { + case DRM_MODE_CONNECTOR_eDP: + if (!connector->panel.vbt.vrr) + return false; + fallthrough; + case DRM_MODE_CONNECTOR_DisplayPort: + intel_dp = intel_attached_dp(connector); + + if (!drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd)) + return false; + + break; + default: + return false; + } + return HAS_VRR(i915) && - drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd) && info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; } @@ -97,7 +107,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, const struct drm_display_info *info = &connector->base.display_info; int vmin, vmax; - if (!intel_vrr_is_capable(&connector->base)) + if (!intel_vrr_is_capable(connector)) return; if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -132,11 +142,16 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, * For XE_LPD+, we use guardband and pipeline override * is deprecated. */ - if (DISPLAY_VER(i915) >= 13) + if (DISPLAY_VER(i915) >= 13) { + /* + * FIXME: Subtract Window2 delay from below value. + * + * Window2 specifies time required to program DSB (Window2) in + * number of scan lines. Assuming 0 for no DSB. + */ crtc_state->vrr.guardband = - crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - - i915->window2_delay; - else + crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay; + } else { /* * FIXME: s/4/framestart_delay/ to get consistent * earliest/latest points for register latching regardless @@ -149,6 +164,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, */ crtc_state->vrr.pipeline_full = min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); + } crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h index 1c2da572693d..9fda1135b0dd 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.h +++ b/drivers/gpu/drm/i915/display/intel_vrr.h @@ -8,15 +8,15 @@ #include <linux/types.h> -struct drm_connector; struct drm_connector_state; struct intel_atomic_state; +struct intel_connector; struct intel_crtc; struct intel_crtc_state; struct intel_dp; struct intel_encoder; -bool intel_vrr_is_capable(struct drm_connector *connector); +bool intel_vrr_is_capable(struct intel_connector *connector); void intel_vrr_check_modeset(struct intel_atomic_state *state); void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index caa03324a733..bcfde81e4d08 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -4,9 +4,9 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "i915_drv.h" #include "intel_atomic_plane.h" @@ -1855,8 +1855,8 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; + int min_scale = DRM_PLANE_NO_SCALING; + int max_scale = DRM_PLANE_NO_SCALING; int ret; ret = skl_plane_check_fb(crtc_state, plane_state); @@ -1928,7 +1928,7 @@ static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv, enum intel_fbc_id fbc_id, enum plane_id plane_id) { - if ((INTEL_INFO(dev_priv)->display.fbc_mask & BIT(fbc_id)) == 0) + if ((RUNTIME_INFO(dev_priv)->fbc_mask & BIT(fbc_id)) == 0) return false; return plane_id == PLANE_PRIMARY; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 1954f07f0d3e..784ae52059d1 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -782,6 +782,7 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; enum port port; @@ -838,7 +839,7 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, * the delay in that case. If there is no deassert-seq, then an * unconditional msleep is used to give the panel time to power-on. */ - if (dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) { + if (connector->panel.vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) { intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET); } else { @@ -1690,7 +1691,8 @@ static void vlv_dphy_param_init(struct intel_dsi *intel_dsi) { struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; + struct intel_connector *connector = intel_dsi->attached_connector; + struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; u32 tlpx_ns, extra_byte_count, tlpx_ui; u32 ui_num, ui_den; u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt; @@ -1924,13 +1926,18 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_dsi->panel_power_off_time = ktime_get_boottime(); - if (dev_priv->vbt.dsi.config->dual_link) + intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + + if (intel_connector->panel.vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); else intel_dsi->ports = BIT(port); - intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports; - intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports; + if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; + + if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index b7b2c14fd9e1..cd75b0ca2555 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -6,7 +6,6 @@ #include <linux/dma-resv.h> #include <linux/highmem.h> -#include <linux/intel-iommu.h> #include <linux/sync_file.h> #include <linux/uaccess.h> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 8357dbdcab5c..4df50b049cea 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -20,7 +20,7 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, unsigned int sg_page_sizes) { struct drm_i915_private *i915 = to_i915(obj->base.dev); - unsigned long supported = INTEL_INFO(i915)->page_sizes; + unsigned long supported = RUNTIME_INFO(i915)->page_sizes; bool shrinkable; int i; @@ -66,7 +66,7 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, shrinkable = i915_gem_object_is_shrinkable(obj); if (i915_gem_object_is_tiled(obj) && - i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) { + i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) { GEM_BUG_ON(i915_gem_object_has_tiling_quirk(obj)); i915_gem_object_set_tiling_quirk(obj); GEM_BUG_ON(!list_empty(&obj->mm.link)); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 6a80ad8097bb..f42ca1179f37 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -409,6 +409,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj, const struct drm_i915_gem_pwrite *arg) { struct address_space *mapping = obj->base.filp->f_mapping; + const struct address_space_operations *aops = mapping->a_ops; char __user *user_data = u64_to_user_ptr(arg->data_ptr); u64 remain, offset; unsigned int pg; @@ -466,9 +467,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj, if (err) return err; - err = pagecache_write_begin(obj->base.filp, mapping, - offset, len, 0, - &page, &data); + err = aops->write_begin(obj->base.filp, mapping, offset, len, + &page, &data); if (err < 0) return err; @@ -478,9 +478,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj, len); kunmap_atomic(vaddr); - err = pagecache_write_end(obj->base.filp, mapping, - offset, len, len - unwritten, - page, data); + err = aops->write_end(obj->base.filp, mapping, offset, len, + len - unwritten, page, data); if (err < 0) return err; @@ -624,6 +623,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv, { struct drm_i915_gem_object *obj; struct file *file; + const struct address_space_operations *aops; resource_size_t offset; int err; @@ -635,15 +635,15 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv, GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); file = obj->base.filp; + aops = file->f_mapping->a_ops; offset = 0; do { unsigned int len = min_t(typeof(size), size, PAGE_SIZE); struct page *page; void *pgdata, *vaddr; - err = pagecache_write_begin(file, file->f_mapping, - offset, len, 0, - &page, &pgdata); + err = aops->write_begin(file, file->f_mapping, offset, len, + &page, &pgdata); if (err < 0) goto fail; @@ -651,9 +651,8 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv, memcpy(vaddr, data, len); kunmap(page); - err = pagecache_write_end(file, file->f_mapping, - offset, len, len, - page, pgdata); + err = aops->write_end(file, file->f_mapping, offset, len, len, + page, pgdata); if (err < 0) goto fail; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index 1030053571a2..8dc5c8874d8a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -426,7 +426,8 @@ void i915_gem_driver_register__shrinker(struct drm_i915_private *i915) i915->mm.shrinker.count_objects = i915_gem_shrinker_count; i915->mm.shrinker.seeks = DEFAULT_SEEKS; i915->mm.shrinker.batch = 4096; - drm_WARN_ON(&i915->drm, register_shrinker(&i915->mm.shrinker)); + drm_WARN_ON(&i915->drm, register_shrinker(&i915->mm.shrinker, + "drm-i915_gem")); i915->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; drm_WARN_ON(&i915->drm, register_oom_notifier(&i915->mm.oom_notifier)); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index ed4a67ddab19..acc561c0f0aa 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -18,10 +18,12 @@ #include "gt/intel_region_lmem.h" #include "i915_drv.h" #include "i915_gem_stolen.h" +#include "i915_pci.h" #include "i915_reg.h" #include "i915_utils.h" #include "i915_vgpu.h" #include "intel_mchbar_regs.h" +#include "intel_pci_config.h" /* * The BIOS typically reserves some of the system's memory for the exclusive @@ -808,10 +810,13 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, if (WARN_ON_ONCE(instance)) return ERR_PTR(-ENODEV); + if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR)) + return ERR_PTR(-ENXIO); + /* Use DSM base address instead for stolen memory */ dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE); if (IS_DG1(uncore->i915)) { - lmem_size = pci_resource_len(pdev, 2); + lmem_size = pci_resource_len(pdev, GEN12_LMEM_BAR); if (WARN_ON(lmem_size < dsm_base)) return ERR_PTR(-ENODEV); } else { @@ -823,11 +828,11 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, } dsm_size = lmem_size - dsm_base; - if (pci_resource_len(pdev, 2) < lmem_size) { + if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) { io_start = 0; io_size = 0; } else { - io_start = pci_resource_start(pdev, 2) + dsm_base; + io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base; io_size = dsm_size; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index 85518b28cd72..fd42b89b7162 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, */ if (i915_gem_object_has_pages(obj) && obj->mm.madv == I915_MADV_WILLNEED && - i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) { + i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) { if (tiling == I915_TILING_NONE) { GEM_BUG_ON(!i915_gem_object_has_tiling_quirk(obj)); i915_gem_object_clear_tiling_quirk(obj); @@ -458,7 +458,7 @@ i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data, } /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ - if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) + if (dev_priv->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN; else args->phys_swizzle_mode = args->swizzle_mode; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index dea6e378946f..0544b0a4a43a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -361,7 +361,6 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); - struct ttm_resource *res = bo->resource; if (!obj) return false; @@ -378,45 +377,7 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo, if (!i915_gem_object_evictable(obj)) return false; - switch (res->mem_type) { - case I915_PL_LMEM0: { - struct ttm_resource_manager *man = - ttm_manager_type(bo->bdev, res->mem_type); - struct i915_ttm_buddy_resource *bman_res = - to_ttm_buddy_resource(res); - struct drm_buddy *mm = bman_res->mm; - struct drm_buddy_block *block; - - if (!place->fpfn && !place->lpfn) - return true; - - GEM_BUG_ON(!place->lpfn); - - /* - * If we just want something mappable then we can quickly check - * if the current victim resource is using any of the CPU - * visible portion. - */ - if (!place->fpfn && - place->lpfn == i915_ttm_buddy_man_visible_size(man)) - return bman_res->used_visible_size > 0; - - /* Real range allocation */ - list_for_each_entry(block, &bman_res->blocks, link) { - unsigned long fpfn = - drm_buddy_block_offset(block) >> PAGE_SHIFT; - unsigned long lpfn = fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); - - if (place->fpfn < lpfn && place->lpfn > fpfn) - return true; - } - return false; - } default: - break; - } - - return true; + return ttm_bo_eviction_valuable(bo, place); } static void i915_ttm_evict_flags(struct ttm_buffer_object *bo, @@ -1274,9 +1235,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem, * Similarly, in delayed_destroy, we can't call ttm_bo_put() * until successful initialization. */ - ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), size, - bo_type, &i915_sys_placement, - page_size >> PAGE_SHIFT, + ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), bo_type, + &i915_sys_placement, page_size >> PAGE_SHIFT, &ctx, NULL, NULL, i915_ttm_bo_destroy); if (ret) return i915_ttm_err_to_gem(ret); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 094f06b4ce33..8423df021b71 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -216,8 +216,8 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj, * However...! * * The mmu-notifier can be invalidated for a - * migrate_page, that is alreadying holding the lock - * on the page. Such a try_to_unmap() will result + * migrate_folio, that is alreadying holding the lock + * on the folio. Such a try_to_unmap() will result * in us calling put_pages() and so recursively try * to lock the page. We avoid that deadlock with * a trylock_page() and in exchange we risk missing diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 72ce2c9f42fd..c570cf780079 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -358,7 +358,7 @@ fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single) static int igt_check_page_sizes(struct i915_vma *vma) { struct drm_i915_private *i915 = vma->vm->i915; - unsigned int supported = INTEL_INFO(i915)->page_sizes; + unsigned int supported = RUNTIME_INFO(i915)->page_sizes; struct drm_i915_gem_object *obj = vma->obj; int err; @@ -419,7 +419,7 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) { struct i915_ppgtt *ppgtt = arg; struct drm_i915_private *i915 = ppgtt->vm.i915; - unsigned int saved_mask = INTEL_INFO(i915)->page_sizes; + unsigned int saved_mask = RUNTIME_INFO(i915)->page_sizes; struct drm_i915_gem_object *obj; struct i915_vma *vma; int i, j, single; @@ -438,7 +438,7 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) combination |= page_sizes[j]; } - mkwrite_device_info(i915)->page_sizes = combination; + RUNTIME_INFO(i915)->page_sizes = combination; for (single = 0; single <= 1; ++single) { obj = fake_huge_pages_object(i915, combination, !!single); @@ -485,7 +485,7 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) out_put: i915_gem_object_put(obj); out_device: - mkwrite_device_info(i915)->page_sizes = saved_mask; + RUNTIME_INFO(i915)->page_sizes = saved_mask; return err; } @@ -495,7 +495,7 @@ static int igt_mock_memory_region_huge_pages(void *arg) const unsigned int flags[] = { 0, I915_BO_ALLOC_CONTIGUOUS }; struct i915_ppgtt *ppgtt = arg; struct drm_i915_private *i915 = ppgtt->vm.i915; - unsigned long supported = INTEL_INFO(i915)->page_sizes; + unsigned long supported = RUNTIME_INFO(i915)->page_sizes; struct intel_memory_region *mem; struct drm_i915_gem_object *obj; struct i915_vma *vma; @@ -573,7 +573,7 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg) { struct i915_ppgtt *ppgtt = arg; struct drm_i915_private *i915 = ppgtt->vm.i915; - unsigned long supported = INTEL_INFO(i915)->page_sizes; + unsigned long supported = RUNTIME_INFO(i915)->page_sizes; struct drm_i915_gem_object *obj; int bit; int err; @@ -1390,7 +1390,7 @@ out_put: static int igt_ppgtt_sanity_check(void *arg) { struct drm_i915_private *i915 = arg; - unsigned int supported = INTEL_INFO(i915)->page_sizes; + unsigned int supported = RUNTIME_INFO(i915)->page_sizes; struct { igt_create_fn fn; unsigned int flags; @@ -1764,8 +1764,8 @@ int i915_gem_huge_page_mock_selftests(void) return -ENOMEM; /* Pretend to be a device which supports the 48b PPGTT */ - mkwrite_device_info(dev_priv)->ppgtt_type = INTEL_PPGTT_FULL; - mkwrite_device_info(dev_priv)->ppgtt_size = 48; + RUNTIME_INFO(dev_priv)->ppgtt_type = INTEL_PPGTT_FULL; + RUNTIME_INFO(dev_priv)->ppgtt_size = 48; ppgtt = i915_ppgtt_create(to_gt(dev_priv), 0); if (IS_ERR(ppgtt)) { diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index 3cfc621ef363..9a6a6b5b722b 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -711,7 +711,7 @@ static bool bad_swizzling(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; - if (i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) + if (i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) return true; if (has_bit17_swizzle(ggtt->bit_6_swizzle_x) || diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 55bf23dc0e54..b73c91aa5450 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -367,7 +367,7 @@ static int igt_partial_tiling(void *arg) unsigned int pitch; struct tile tile; - if (i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) + if (i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) /* * The swizzling pattern is actually unknown as it * varies based on physical address of each page. @@ -464,7 +464,7 @@ static int igt_smoke_tiling(void *arg) * Remember to look at the st_seed if we see a flip-flop in BAT! */ - if (i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) + if (i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) return 0; obj = huge_gem_object(i915, diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index aab240ea1d25..4b909cb88cdf 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -1360,7 +1360,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * submission. If we don't cancel the timer now, * we will see that the timer has expired and * reschedule the tasklet; continually until the - * next context switch or other preeemption event. + * next context switch or other preemption event. * * Since we have decided to reschedule based on * consumption of this timeslice, if we submit the diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 15a915bb4088..30cf5c3369d9 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -16,7 +16,9 @@ #include "intel_ggtt_gmch.h" #include "intel_gt.h" #include "intel_gt_regs.h" +#include "intel_pci_config.h" #include "i915_drv.h" +#include "i915_pci.h" #include "i915_scatterlist.h" #include "i915_utils.h" #include "i915_vgpu.h" @@ -869,8 +871,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) u32 pte_flags; int ret; - GEM_WARN_ON(pci_resource_len(pdev, 0) != gen6_gttmmadr_size(i915)); - phys_addr = pci_resource_start(pdev, 0) + gen6_gttadr_offset(i915); + GEM_WARN_ON(pci_resource_len(pdev, GTTMMADR_BAR) != gen6_gttmmadr_size(i915)); + phys_addr = pci_resource_start(pdev, GTTMMADR_BAR) + gen6_gttadr_offset(i915); /* * On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range @@ -930,7 +932,10 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) u16 snb_gmch_ctl; if (!HAS_LMEM(i915)) { - ggtt->gmadr = pci_resource(pdev, 2); + if (!i915_pci_resource_valid(pdev, GTT_APERTURE_BAR)) + return -ENXIO; + + ggtt->gmadr = pci_resource(pdev, GTT_APERTURE_BAR); ggtt->mappable_end = resource_size(&ggtt->gmadr); } @@ -1084,7 +1089,10 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) unsigned int size; u16 snb_gmch_ctl; - ggtt->gmadr = pci_resource(pdev, 2); + if (!i915_pci_resource_valid(pdev, GTT_APERTURE_BAR)) + return -ENXIO; + + ggtt->gmadr = pci_resource(pdev, GTT_APERTURE_BAR); ggtt->mappable_end = resource_size(&ggtt->gmadr); /* diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index f920d5484132..ea775e601686 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -727,7 +727,7 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt) * bit17 dependent, and so we need to also prevent the pages * from being moved. */ - i915->quirks |= QUIRK_PIN_SWIZZLED_PAGES; + i915->gem_quirks |= GEM_QUIRK_PIN_SWIZZLED_PAGES; swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 926a1515cd3b..d0b03a928b9a 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -26,6 +26,7 @@ #include "intel_gt_requests.h" #include "intel_migrate.h" #include "intel_mocs.h" +#include "intel_pci_config.h" #include "intel_pm.h" #include "intel_rc6.h" #include "intel_renderstate.h" @@ -827,7 +828,7 @@ int intel_gt_probe_all(struct drm_i915_private *i915) unsigned int i; int ret; - mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0; + mmio_bar = GRAPHICS_VER(i915) == 2 ? GEN2_GTTMMADR_BAR : GTTMMADR_BAR; phys_addr = pci_resource_start(pdev, mmio_bar); /* @@ -837,7 +838,7 @@ int intel_gt_probe_all(struct drm_i915_private *i915) */ gt->i915 = i915; gt->name = "Primary GT"; - gt->info.engine_mask = INTEL_INFO(i915)->platform_engine_mask; + gt->info.engine_mask = RUNTIME_INFO(i915)->platform_engine_mask; drm_dbg(&i915->drm, "Setting up %s\n", gt->name); ret = intel_gt_tile_setup(gt, phys_addr); diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index 6ee8d1127016..7ecfa672f738 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -312,7 +312,7 @@ void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt, ppgtt->vm.gt = gt; ppgtt->vm.i915 = i915; ppgtt->vm.dma = i915->drm.dev; - ppgtt->vm.total = BIT_ULL(INTEL_INFO(i915)->ppgtt_size); + ppgtt->vm.total = BIT_ULL(RUNTIME_INFO(i915)->ppgtt_size); ppgtt->vm.lmem_pt_obj_flags = lmem_pt_obj_flags; dma_resv_init(&ppgtt->vm._resv); diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index aa6aed837194..f3ad93db0b21 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -4,8 +4,10 @@ */ #include "i915_drv.h" +#include "i915_pci.h" #include "i915_reg.h" #include "intel_memory_region.h" +#include "intel_pci_config.h" #include "intel_region_lmem.h" #include "intel_region_ttm.h" #include "gem/i915_gem_lmem.h" @@ -45,7 +47,6 @@ _resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size) drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size); } -#define LMEM_BAR_NUM 2 static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) { struct pci_dev *pdev = to_pci_dev(i915->drm.dev); @@ -56,15 +57,14 @@ static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t u32 pci_cmd; int i; - current_size = roundup_pow_of_two(pci_resource_len(pdev, LMEM_BAR_NUM)); + current_size = roundup_pow_of_two(pci_resource_len(pdev, GEN12_LMEM_BAR)); if (i915->params.lmem_bar_size) { u32 bar_sizes; rebar_size = i915->params.lmem_bar_size * (resource_size_t)SZ_1M; - bar_sizes = pci_rebar_get_possible_sizes(pdev, - LMEM_BAR_NUM); + bar_sizes = pci_rebar_get_possible_sizes(pdev, GEN12_LMEM_BAR); if (rebar_size == current_size) return; @@ -107,7 +107,7 @@ static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd & ~PCI_COMMAND_MEMORY); - _resize_bar(i915, LMEM_BAR_NUM, rebar_size); + _resize_bar(i915, GEN12_LMEM_BAR, rebar_size); pci_assign_unassigned_bus_resources(pdev->bus); pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); @@ -202,6 +202,9 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) if (!IS_DGFX(i915)) return ERR_PTR(-ENODEV); + if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR)) + return ERR_PTR(-ENXIO); + if (HAS_FLAT_CCS(i915)) { resource_size_t lmem_range; u64 tile_stolen, flat_ccs_base; @@ -236,8 +239,8 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) mul_u32_u32(i915->params.lmem_size, SZ_1M)); } - io_start = pci_resource_start(pdev, 2); - io_size = min(pci_resource_len(pdev, 2), lmem_size); + io_start = pci_resource_start(pdev, GEN12_LMEM_BAR); + io_size = min(pci_resource_len(pdev, GEN12_LMEM_BAR), lmem_size); if (!io_size) return ERR_PTR(-EIO); diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index c6d3050604c8..66f21c735d54 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -382,7 +382,6 @@ static void cherryview_sseu_info_init(struct intel_gt *gt) static void gen9_sseu_info_init(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; - struct intel_device_info *info = mkwrite_device_info(i915); struct sseu_dev_info *sseu = >->info.sseu; struct intel_uncore *uncore = gt->uncore; u32 fuse2, eu_disable, subslice_mask; @@ -471,10 +470,10 @@ static void gen9_sseu_info_init(struct intel_gt *gt) if (IS_GEN9_LP(i915)) { #define IS_SS_DISABLED(ss) (!(sseu->subslice_mask.hsw[0] & BIT(ss))) - info->has_pooled_eu = hweight8(sseu->subslice_mask.hsw[0]) == 3; + RUNTIME_INFO(i915)->has_pooled_eu = hweight8(sseu->subslice_mask.hsw[0]) == 3; sseu->min_eu_in_pool = 0; - if (info->has_pooled_eu) { + if (HAS_POOLED_EU(i915)) { if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) sseu->min_eu_in_pool = 3; else if (IS_SS_DISABLED(1)) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 55d4b8f8e33e..b071973ac41c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -744,7 +744,7 @@ int intel_guc_log_relay_open(struct intel_guc_log *log) /* * We require SSE 4.1 for fast reads from the GuC log buffer and * it should be present on the chipsets supporting GuC based - * submisssions. + * submissions. */ if (!i915_has_memcpy_from_wc()) { ret = -ENXIO; diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index dad3a6054335..eef3bba8a41b 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -33,6 +33,7 @@ #include "i915_drv.h" #include "gvt.h" +#include "intel_pci_config.h" enum { INTEL_GVT_PCI_BAR_GTTMMIO = 0, @@ -353,9 +354,9 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4); vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size = - pci_resource_len(pdev, 0); + pci_resource_len(pdev, GTTMMADR_BAR); vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = - pci_resource_len(pdev, 2); + pci_resource_len(pdev, GTT_APERTURE_BAR); memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0ba2a3455d99..de13f102d4fd 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -3117,9 +3117,9 @@ void intel_gvt_update_reg_whitelist(struct intel_vgpu *vgpu) continue; vaddr = shmem_pin_map(engine->default_state); - if (IS_ERR(vaddr)) { - gvt_err("failed to map %s->default state, err:%zd\n", - engine->name, PTR_ERR(vaddr)); + if (!vaddr) { + gvt_err("failed to map %s->default state\n", + engine->name); return; } diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 9c5cc2800975..b4f69364f9a1 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -51,7 +51,7 @@ static int preallocated_oos_pages = 8192; static bool intel_gvt_is_valid_gfn(struct intel_vgpu *vgpu, unsigned long gfn) { - struct kvm *kvm = vgpu->kvm; + struct kvm *kvm = vgpu->vfio_device.kvm; int idx; bool ret; @@ -1185,7 +1185,7 @@ static int is_2MB_gtt_possible(struct intel_vgpu *vgpu, if (!vgpu->attached) return -EINVAL; - pfn = gfn_to_pfn(vgpu->kvm, ops->get_pfn(entry)); + pfn = gfn_to_pfn(vgpu->vfio_device.kvm, ops->get_pfn(entry)); if (is_error_noslot_pfn(pfn)) return -EINVAL; return PageTransHuge(pfn_to_page(pfn)); diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 03ecffc2ba56..705689e64011 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -226,12 +226,7 @@ struct intel_vgpu { unsigned long nr_cache_entries; struct mutex cache_lock; - struct notifier_block iommu_notifier; - struct notifier_block group_notifier; - struct kvm *kvm; - struct work_struct release_work; atomic_t released; - struct vfio_group *vfio_group; struct kvm_page_track_notifier_node track_node; #define NR_BKT (1 << 18) @@ -732,7 +727,7 @@ static inline int intel_gvt_read_gpa(struct intel_vgpu *vgpu, unsigned long gpa, { if (!vgpu->attached) return -ESRCH; - return vfio_dma_rw(vgpu->vfio_group, gpa, buf, len, false); + return vfio_dma_rw(&vgpu->vfio_device, gpa, buf, len, false); } /** @@ -750,7 +745,7 @@ static inline int intel_gvt_write_gpa(struct intel_vgpu *vgpu, { if (!vgpu->attached) return -ESRCH; - return vfio_dma_rw(vgpu->vfio_group, gpa, buf, len, true); + return vfio_dma_rw(&vgpu->vfio_device, gpa, buf, len, true); } void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index beea5895e499..e7e33f95cc51 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -498,7 +498,7 @@ static u32 bdw_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) switch (wrpll_ctl & WRPLL_REF_MASK) { case WRPLL_REF_PCH_SSC: - refclk = vgpu->gvt->gt->i915->dpll.ref_clks.ssc; + refclk = vgpu->gvt->gt->i915->display.dpll.ref_clks.ssc; break; case WRPLL_REF_LCPLL: refclk = 2700000; @@ -529,7 +529,7 @@ out: static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) { u32 dp_br = 0; - int refclk = vgpu->gvt->gt->i915->dpll.ref_clks.nssc; + int refclk = vgpu->gvt->gt->i915->display.dpll.ref_clks.nssc; enum dpio_phy phy = DPIO_PHY0; enum dpio_channel ch = DPIO_CH0; struct dpll clock = {0}; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 0787ba5c301f..e3cd58946477 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -228,62 +228,41 @@ static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt) } } -static void intel_vgpu_release_work(struct work_struct *work); - static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, unsigned long size) { - struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - int total_pages; - int npage; - int ret; - - total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE; - - for (npage = 0; npage < total_pages; npage++) { - unsigned long cur_gfn = gfn + npage; - - ret = vfio_group_unpin_pages(vgpu->vfio_group, &cur_gfn, 1); - drm_WARN_ON(&i915->drm, ret != 1); - } + vfio_unpin_pages(&vgpu->vfio_device, gfn << PAGE_SHIFT, + DIV_ROUND_UP(size, PAGE_SIZE)); } /* Pin a normal or compound guest page for dma. */ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, unsigned long size, struct page **page) { - unsigned long base_pfn = 0; - int total_pages; + int total_pages = DIV_ROUND_UP(size, PAGE_SIZE); + struct page *base_page = NULL; int npage; int ret; - total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE; /* * We pin the pages one-by-one to avoid allocating a big arrary * on stack to hold pfns. */ for (npage = 0; npage < total_pages; npage++) { - unsigned long cur_gfn = gfn + npage; - unsigned long pfn; + dma_addr_t cur_iova = (gfn + npage) << PAGE_SHIFT; + struct page *cur_page; - ret = vfio_group_pin_pages(vgpu->vfio_group, &cur_gfn, 1, - IOMMU_READ | IOMMU_WRITE, &pfn); + ret = vfio_pin_pages(&vgpu->vfio_device, cur_iova, 1, + IOMMU_READ | IOMMU_WRITE, &cur_page); if (ret != 1) { - gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n", - cur_gfn, ret); - goto err; - } - - if (!pfn_valid(pfn)) { - gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn); - npage++; - ret = -EFAULT; + gvt_vgpu_err("vfio_pin_pages failed for iova %pad, ret %d\n", + &cur_iova, ret); goto err; } if (npage == 0) - base_pfn = pfn; - else if (base_pfn + npage != pfn) { + base_page = cur_page; + else if (base_page + npage != cur_page) { gvt_vgpu_err("The pages are not continuous\n"); ret = -EINVAL; npage++; @@ -291,7 +270,7 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, } } - *page = pfn_to_page(base_pfn); + *page = base_page; return 0; err: gvt_unpin_guest_page(vgpu, gfn, npage * PAGE_SIZE); @@ -731,51 +710,25 @@ int intel_gvt_set_edid(struct intel_vgpu *vgpu, int port_num) return ret; } -static int intel_vgpu_iommu_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct intel_vgpu *vgpu = - container_of(nb, struct intel_vgpu, iommu_notifier); - - if (action == VFIO_IOMMU_NOTIFY_DMA_UNMAP) { - struct vfio_iommu_type1_dma_unmap *unmap = data; - struct gvt_dma *entry; - unsigned long iov_pfn, end_iov_pfn; - - iov_pfn = unmap->iova >> PAGE_SHIFT; - end_iov_pfn = iov_pfn + unmap->size / PAGE_SIZE; - - mutex_lock(&vgpu->cache_lock); - for (; iov_pfn < end_iov_pfn; iov_pfn++) { - entry = __gvt_cache_find_gfn(vgpu, iov_pfn); - if (!entry) - continue; - - gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr, - entry->size); - __gvt_cache_remove_entry(vgpu, entry); - } - mutex_unlock(&vgpu->cache_lock); - } - - return NOTIFY_OK; -} - -static int intel_vgpu_group_notifier(struct notifier_block *nb, - unsigned long action, void *data) +static void intel_vgpu_dma_unmap(struct vfio_device *vfio_dev, u64 iova, + u64 length) { - struct intel_vgpu *vgpu = - container_of(nb, struct intel_vgpu, group_notifier); + struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); + struct gvt_dma *entry; + u64 iov_pfn = iova >> PAGE_SHIFT; + u64 end_iov_pfn = iov_pfn + length / PAGE_SIZE; - /* the only action we care about */ - if (action == VFIO_GROUP_NOTIFY_SET_KVM) { - vgpu->kvm = data; + mutex_lock(&vgpu->cache_lock); + for (; iov_pfn < end_iov_pfn; iov_pfn++) { + entry = __gvt_cache_find_gfn(vgpu, iov_pfn); + if (!entry) + continue; - if (!data) - schedule_work(&vgpu->release_work); + gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr, + entry->size); + __gvt_cache_remove_entry(vgpu, entry); } - - return NOTIFY_OK; + mutex_unlock(&vgpu->cache_lock); } static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu) @@ -789,7 +742,7 @@ static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu) if (!itr->attached) continue; - if (vgpu->kvm == itr->kvm) { + if (vgpu->vfio_device.kvm == itr->vfio_device.kvm) { ret = true; goto out; } @@ -802,63 +755,30 @@ out: static int intel_vgpu_open_device(struct vfio_device *vfio_dev) { struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); - unsigned long events; - int ret; - struct vfio_group *vfio_group; - - vgpu->iommu_notifier.notifier_call = intel_vgpu_iommu_notifier; - vgpu->group_notifier.notifier_call = intel_vgpu_group_notifier; - - events = VFIO_IOMMU_NOTIFY_DMA_UNMAP; - ret = vfio_register_notifier(vfio_dev->dev, VFIO_IOMMU_NOTIFY, &events, - &vgpu->iommu_notifier); - if (ret != 0) { - gvt_vgpu_err("vfio_register_notifier for iommu failed: %d\n", - ret); - goto out; - } - - events = VFIO_GROUP_NOTIFY_SET_KVM; - ret = vfio_register_notifier(vfio_dev->dev, VFIO_GROUP_NOTIFY, &events, - &vgpu->group_notifier); - if (ret != 0) { - gvt_vgpu_err("vfio_register_notifier for group failed: %d\n", - ret); - goto undo_iommu; - } - vfio_group = - vfio_group_get_external_user_from_dev(vgpu->vfio_device.dev); - if (IS_ERR_OR_NULL(vfio_group)) { - ret = !vfio_group ? -EFAULT : PTR_ERR(vfio_group); - gvt_vgpu_err("vfio_group_get_external_user_from_dev failed\n"); - goto undo_register; - } - vgpu->vfio_group = vfio_group; - - ret = -EEXIST; if (vgpu->attached) - goto undo_group; + return -EEXIST; - ret = -ESRCH; - if (!vgpu->kvm || vgpu->kvm->mm != current->mm) { + if (!vgpu->vfio_device.kvm || + vgpu->vfio_device.kvm->mm != current->mm) { gvt_vgpu_err("KVM is required to use Intel vGPU\n"); - goto undo_group; + return -ESRCH; } - ret = -EEXIST; + kvm_get_kvm(vgpu->vfio_device.kvm); + if (__kvmgt_vgpu_exist(vgpu)) - goto undo_group; + return -EEXIST; vgpu->attached = true; - kvm_get_kvm(vgpu->kvm); kvmgt_protect_table_init(vgpu); gvt_cache_init(vgpu); vgpu->track_node.track_write = kvmgt_page_track_write; vgpu->track_node.track_flush_slot = kvmgt_page_track_flush_slot; - kvm_page_track_register_notifier(vgpu->kvm, &vgpu->track_node); + kvm_page_track_register_notifier(vgpu->vfio_device.kvm, + &vgpu->track_node); debugfs_create_ulong(KVMGT_DEBUGFS_FILENAME, 0444, vgpu->debugfs, &vgpu->nr_cache_entries); @@ -867,20 +787,6 @@ static int intel_vgpu_open_device(struct vfio_device *vfio_dev) atomic_set(&vgpu->released, 0); return 0; - -undo_group: - vfio_group_put_external_user(vgpu->vfio_group); - vgpu->vfio_group = NULL; - -undo_register: - vfio_unregister_notifier(vfio_dev->dev, VFIO_GROUP_NOTIFY, - &vgpu->group_notifier); - -undo_iommu: - vfio_unregister_notifier(vfio_dev->dev, VFIO_IOMMU_NOTIFY, - &vgpu->iommu_notifier); -out: - return ret; } static void intel_vgpu_release_msi_eventfd_ctx(struct intel_vgpu *vgpu) @@ -894,10 +800,9 @@ static void intel_vgpu_release_msi_eventfd_ctx(struct intel_vgpu *vgpu) } } -static void __intel_vgpu_release(struct intel_vgpu *vgpu) +static void intel_vgpu_close_device(struct vfio_device *vfio_dev) { - struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - int ret; + struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); if (!vgpu->attached) return; @@ -907,41 +812,19 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu) intel_gvt_release_vgpu(vgpu); - ret = vfio_unregister_notifier(vgpu->vfio_device.dev, VFIO_IOMMU_NOTIFY, - &vgpu->iommu_notifier); - drm_WARN(&i915->drm, ret, - "vfio_unregister_notifier for iommu failed: %d\n", ret); - - ret = vfio_unregister_notifier(vgpu->vfio_device.dev, VFIO_GROUP_NOTIFY, - &vgpu->group_notifier); - drm_WARN(&i915->drm, ret, - "vfio_unregister_notifier for group failed: %d\n", ret); - debugfs_remove(debugfs_lookup(KVMGT_DEBUGFS_FILENAME, vgpu->debugfs)); - kvm_page_track_unregister_notifier(vgpu->kvm, &vgpu->track_node); - kvm_put_kvm(vgpu->kvm); + kvm_page_track_unregister_notifier(vgpu->vfio_device.kvm, + &vgpu->track_node); kvmgt_protect_table_destroy(vgpu); gvt_cache_destroy(vgpu); intel_vgpu_release_msi_eventfd_ctx(vgpu); - vfio_group_put_external_user(vgpu->vfio_group); - vgpu->kvm = NULL; vgpu->attached = false; -} - -static void intel_vgpu_close_device(struct vfio_device *vfio_dev) -{ - __intel_vgpu_release(vfio_dev_to_vgpu(vfio_dev)); -} - -static void intel_vgpu_release_work(struct work_struct *work) -{ - struct intel_vgpu *vgpu = - container_of(work, struct intel_vgpu, release_work); - __intel_vgpu_release(vgpu); + if (vgpu->vfio_device.kvm) + kvm_put_kvm(vgpu->vfio_device.kvm); } static u64 intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar) @@ -1670,6 +1553,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = { .write = intel_vgpu_write, .mmap = intel_vgpu_mmap, .ioctl = intel_vgpu_ioctl, + .dma_unmap = intel_vgpu_dma_unmap, }; static int intel_vgpu_probe(struct mdev_device *mdev) @@ -1690,7 +1574,6 @@ static int intel_vgpu_probe(struct mdev_device *mdev) return PTR_ERR(vgpu); } - INIT_WORK(&vgpu->release_work, intel_vgpu_release_work); vfio_init_group_dev(&vgpu->vfio_device, &mdev->dev, &intel_vgpu_dev_ops); @@ -1728,7 +1611,7 @@ static struct mdev_driver intel_vgpu_mdev_driver = { int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn) { - struct kvm *kvm = info->kvm; + struct kvm *kvm = info->vfio_device.kvm; struct kvm_memory_slot *slot; int idx; @@ -1758,7 +1641,7 @@ out: int intel_gvt_page_track_remove(struct intel_vgpu *info, u64 gfn) { - struct kvm *kvm = info->kvm; + struct kvm *kvm = info->vfio_device.kvm; struct kvm_memory_slot *slot; int idx; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3a8450058548..b527f2bf7dfa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -66,8 +66,7 @@ static int i915_capabilities(struct seq_file *m, void *data) seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(i915)); - intel_device_info_print_static(INTEL_INFO(i915), &p); - intel_device_info_print_runtime(RUNTIME_INFO(i915), &p); + intel_device_info_print(INTEL_INFO(i915), RUNTIME_INFO(i915), &p); i915_print_iommu_status(i915, &p); intel_gt_info_print(&to_gt(i915)->info, &p); intel_driver_caps_print(&i915->caps, &p); @@ -411,7 +410,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) seq_printf(m, "bit6 swizzle for Y-tiling = %s\n", swizzle_string(to_gt(dev_priv)->ggtt->bit_6_swizzle_y)); - if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) + if (dev_priv->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) seq_puts(m, "L-shaped memory detected\n"); /* On BDW+, swizzling is not used. See detect_bit_6_swizzle() */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 01f42777b6e3..d94e183d716a 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -260,8 +260,8 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) if (dev_priv->wq == NULL) goto out_err; - dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (dev_priv->hotplug.dp_wq == NULL) + dev_priv->display.hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); + if (dev_priv->display.hotplug.dp_wq == NULL) goto out_free_wq; return 0; @@ -276,7 +276,7 @@ out_err: static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { - destroy_workqueue(dev_priv->hotplug.dp_wq); + destroy_workqueue(dev_priv->display.hotplug.dp_wq); destroy_workqueue(dev_priv->wq); } @@ -348,9 +348,9 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->sb_lock); cpu_latency_qos_add_request(&dev_priv->sb_qos, PM_QOS_DEFAULT_VALUE); - mutex_init(&dev_priv->audio.mutex); - mutex_init(&dev_priv->wm.wm_mutex); - mutex_init(&dev_priv->pps_mutex); + mutex_init(&dev_priv->display.audio.mutex); + mutex_init(&dev_priv->display.wm.wm_mutex); + mutex_init(&dev_priv->display.pps.mutex); mutex_init(&dev_priv->hdcp_comp_mutex); i915_memcpy_init_early(dev_priv); @@ -572,6 +572,7 @@ static int i915_pcode_init(struct drm_i915_private *i915) static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; int ret; if (i915_inject_probe_failure(dev_priv)) @@ -683,6 +684,15 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) intel_bw_init_hw(dev_priv); + /* + * FIXME: Temporary hammer to avoid freezing the machine on our DGFX + * This should be totally removed when we handle the pci states properly + * on runtime PM and on s2idle cases. + */ + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_disable(root_pdev); + return 0; err_msi: @@ -706,11 +716,16 @@ err_perf: static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; i915_perf_fini(dev_priv); if (pdev->msi_enabled) pci_disable_msi(pdev); + + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_enable(root_pdev); } /** @@ -810,8 +825,8 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) INTEL_INFO(dev_priv)->platform), GRAPHICS_VER(dev_priv)); - intel_device_info_print_static(INTEL_INFO(dev_priv), &p); - intel_device_info_print_runtime(RUNTIME_INFO(dev_priv), &p); + intel_device_info_print(INTEL_INFO(dev_priv), + RUNTIME_INFO(dev_priv), &p); i915_print_iommu_status(dev_priv, &p); for_each_gt(gt, dev_priv, i) intel_gt_info_print(>->info, &p); @@ -832,6 +847,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) const struct intel_device_info *match_info = (struct intel_device_info *)ent->driver_data; struct intel_device_info *device_info; + struct intel_runtime_info *runtime; struct drm_i915_private *i915; i915 = devm_drm_dev_alloc(&pdev->dev, &i915_drm_driver, @@ -847,7 +863,11 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) /* Setup the write-once "constant" device info */ device_info = mkwrite_device_info(i915); memcpy(device_info, match_info, sizeof(*device_info)); - RUNTIME_INFO(i915)->device_id = pdev->device; + + /* Initialize initial runtime info from static const data and pdev. */ + runtime = RUNTIME_INFO(i915); + memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime)); + runtime->device_id = pdev->device; return i915; } @@ -865,8 +885,6 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) */ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct intel_device_info *match_info = - (struct intel_device_info *)ent->driver_data; struct drm_i915_private *i915; int ret; @@ -875,7 +893,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return PTR_ERR(i915); /* Disable nuclear pageflip by default on pre-ILK */ - if (!i915->params.nuclear_pageflip && match_info->graphics.ver < 5) + if (!i915->params.nuclear_pageflip && DISPLAY_VER(i915) < 5) i915->drm.driver_features &= ~DRIVER_ATOMIC; ret = pci_enable_device(pdev); @@ -1103,8 +1121,6 @@ void i915_driver_shutdown(struct drm_i915_private *i915) intel_runtime_pm_disable(&i915->runtime_pm); intel_power_domains_disable(i915); - i915_gem_suspend(i915); - if (HAS_DISPLAY(i915)) { drm_kms_helper_poll_disable(&i915->drm); @@ -1121,6 +1137,8 @@ void i915_driver_shutdown(struct drm_i915_private *i915) intel_dmc_ucode_suspend(i915); + i915_gem_suspend(i915); + /* * The only requirement is to reboot with display DC states disabled, * for now leaving all display power wells in the INIT power domain @@ -1204,6 +1222,8 @@ static int i915_drm_suspend(struct drm_device *dev) enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); + i915_gem_drain_freed_objects(dev_priv); + return 0; } @@ -1247,14 +1267,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) goto out; } - /* - * FIXME: Temporary hammer to avoid freezing the machine on our DGFX - * This should be totally removed when we handle the pci states properly - * on runtime PM and on s2idle cases. - */ - if (suspend_to_idle(dev_priv)) - pci_d3cold_disable(pdev); - pci_disable_device(pdev); /* * During hibernation on some platforms the BIOS may try to access @@ -1420,8 +1432,6 @@ static int i915_drm_resume_early(struct drm_device *dev) pci_set_master(pdev); - pci_d3cold_enable(pdev); - disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); ret = vlv_resume_prepare(dev_priv, false); @@ -1612,7 +1622,6 @@ static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_gt *gt; int ret, i; @@ -1661,12 +1670,6 @@ static int intel_runtime_suspend(struct device *kdev) drm_err(&dev_priv->drm, "Unclaimed access detected prior to suspending\n"); - /* - * FIXME: Temporary hammer to avoid freezing the machine on our DGFX - * This should be totally removed when we handle the pci states properly - * on runtime PM and on s2idle cases. - */ - pci_d3cold_disable(pdev); rpm->suspended = true; /* @@ -1705,7 +1708,6 @@ static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_gt *gt; int ret, i; @@ -1719,7 +1721,6 @@ static int intel_runtime_resume(struct device *kdev) intel_opregion_notify_adapter(dev_priv, PCI_D0); rpm->suspended = false; - pci_d3cold_enable(pdev); if (intel_uncore_unclaimed_mmio(&dev_priv->uncore)) drm_dbg(&dev_priv->drm, "Unclaimed access during suspend, bios?\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b11c212f1b0d..4828f9d2460d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -37,17 +37,14 @@ #include <drm/drm_connector.h> #include <drm/ttm/ttm_device.h> -#include "display/intel_bios.h" #include "display/intel_cdclk.h" #include "display/intel_display.h" +#include "display/intel_display_core.h" #include "display/intel_display_power.h" -#include "display/intel_dmc.h" -#include "display/intel_dpll_mgr.h" #include "display/intel_dsb.h" #include "display/intel_fbc.h" #include "display/intel_frontbuffer.h" #include "display/intel_global_state.h" -#include "display/intel_gmbus.h" #include "display/intel_opregion.h" #include "gem/i915_gem_context_types.h" @@ -71,80 +68,27 @@ #include "intel_device_info.h" #include "intel_memory_region.h" #include "intel_pch.h" -#include "intel_pm_types.h" #include "intel_runtime_pm.h" #include "intel_step.h" #include "intel_uncore.h" #include "intel_wopcm.h" -struct dpll; struct drm_i915_clock_gating_funcs; struct drm_i915_gem_object; struct drm_i915_private; -struct intel_atomic_state; -struct intel_audio_funcs; struct intel_cdclk_config; -struct intel_cdclk_funcs; struct intel_cdclk_state; struct intel_cdclk_vals; -struct intel_color_funcs; struct intel_connector; -struct intel_crtc; struct intel_dp; -struct intel_dpll_funcs; struct intel_encoder; -struct intel_fbdev; -struct intel_fdi_funcs; -struct intel_gmbus; -struct intel_hotplug_funcs; -struct intel_initial_plane_config; struct intel_limit; -struct intel_overlay; struct intel_overlay_error_state; struct vlv_s0ix_state; /* Threshold == 5 for long IRQs, 50 for short */ #define HPD_STORM_DEFAULT_THRESHOLD 50 -struct i915_hotplug { - struct delayed_work hotplug_work; - - const u32 *hpd, *pch_hpd; - - struct { - unsigned long last_jiffies; - int count; - enum { - HPD_ENABLED = 0, - HPD_DISABLED = 1, - HPD_MARK_DISABLED = 2 - } state; - } stats[HPD_NUM_PINS]; - u32 event_bits; - u32 retry_bits; - struct delayed_work reenable_work; - - u32 long_port_mask; - u32 short_port_mask; - struct work_struct dig_port_work; - - struct work_struct poll_init_work; - bool poll_enabled; - - unsigned int hpd_storm_threshold; - /* Whether or not to count short HPD IRQs in HPD storms */ - u8 hpd_short_storm_enabled; - - /* - * if we get a HPD irq from DP and a HPD irq from non-DP - * the non-DP HPD could block the workqueue on a mode config - * mutex getting, that userspace may have taken. However - * userspace is waiting on the DP workqueue to run which is - * blocked behind the non-DP one. - */ - struct workqueue_struct *dp_wq; -}; - #define I915_GEM_GPU_DOMAINS \ (I915_GEM_DOMAIN_RENDER | \ I915_GEM_DOMAIN_SAMPLER | \ @@ -161,49 +105,13 @@ struct sdvo_device_mapping { u8 ddc_pin; }; -/* functions used for watermark calcs for display. */ -struct drm_i915_wm_disp_funcs { - /* update_wm is for legacy wm management */ - void (*update_wm)(struct drm_i915_private *dev_priv); - int (*compute_pipe_wm)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - int (*compute_intermediate_wm)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - void (*initial_watermarks)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - void (*atomic_update_watermarks)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - void (*optimize_watermarks)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - int (*compute_global_watermarks)(struct intel_atomic_state *state); -}; - -struct drm_i915_display_funcs { - /* Returns the active state of the crtc, and if the crtc is active, - * fills out the pipe-config with the hw state. */ - bool (*get_pipe_config)(struct intel_crtc *, - struct intel_crtc_state *); - void (*get_initial_plane_config)(struct intel_crtc *, - struct intel_initial_plane_config *); - void (*crtc_enable)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - void (*crtc_disable)(struct intel_atomic_state *state, - struct intel_crtc *crtc); - void (*commit_modeset_enables)(struct intel_atomic_state *state); -}; - #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ -enum drrs_type { - DRRS_TYPE_NONE, - DRRS_TYPE_STATIC, - DRRS_TYPE_SEAMLESS, -}; +#define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) #define QUIRK_BACKLIGHT_PRESENT (1<<3) -#define QUIRK_PIN_SWIZZLED_PAGES (1<<5) #define QUIRK_INCREASE_T12_DELAY (1<<6) #define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7) #define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8) @@ -308,76 +216,19 @@ struct intel_vbt_data { /* bdb version */ u16 version; - struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ - struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ - /* Feature bits */ unsigned int int_tv_support:1; - unsigned int lvds_dither:1; unsigned int int_crt_support:1; unsigned int lvds_use_ssc:1; unsigned int int_lvds_support:1; unsigned int display_clock_mode:1; unsigned int fdi_rx_polarity_inverted:1; - unsigned int panel_type:4; int lvds_ssc_freq; - unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ enum drm_panel_orientation orientation; bool override_afc_startup; u8 override_afc_startup_val; - u8 seamless_drrs_min_refresh_rate; - enum drrs_type drrs_type; - - struct { - int rate; - int lanes; - int preemphasis; - int vswing; - int bpp; - struct edp_power_seq pps; - u8 drrs_msa_timing_delay; - bool low_vswing; - bool initialized; - bool hobl; - } edp; - - struct { - bool enable; - bool full_link; - bool require_aux_wakeup; - int idle_frames; - int tp1_wakeup_time_us; - int tp2_tp3_wakeup_time_us; - int psr2_tp2_tp3_wakeup_time_us; - } psr; - - struct { - u16 pwm_freq_hz; - u16 brightness_precision_bits; - bool present; - bool active_low_pwm; - u8 min_brightness; /* min_brightness/255 of max */ - u8 controller; /* brightness controller number */ - enum intel_backlight_type type; - } backlight; - - /* MIPI DSI */ - struct { - u16 panel_id; - struct mipi_config *config; - struct mipi_pps_data *pps; - u16 bl_ports; - u16 cabc_ports; - u8 seq_version; - u32 size; - u8 *data; - const u8 *sequence[MIPI_SEQ_MAX]; - u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ - enum drm_panel_orientation orientation; - } dsi; - int crt_ddc_pin; struct list_head display_devices; @@ -412,32 +263,11 @@ struct i915_selftest_stash { struct ida mock_region_instances; }; -/* intel_audio.c private */ -struct intel_audio_private { - /* Display internal audio functions */ - const struct intel_audio_funcs *funcs; - - /* hda/i915 audio component */ - struct i915_audio_component *component; - bool component_registered; - /* mutex for audio/video sync */ - struct mutex mutex; - int power_refcount; - u32 freq_cntrl; - - /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *encoder_map[I915_MAX_PIPES]; - - /* necessary resource sharing with HDMI LPE audio driver. */ - struct { - struct platform_device *platdev; - int irq; - } lpe; -}; - struct drm_i915_private { struct drm_device drm; + struct intel_display display; + /* FIXME: Device release actions should all be moved to drmm_ */ bool do_release; @@ -481,27 +311,9 @@ struct drm_i915_private { struct intel_wopcm wopcm; - struct intel_dmc dmc; - - struct intel_gmbus *gmbus[GMBUS_NUM_PINS]; - - /** gmbus_mutex protects against concurrent usage of the single hw gmbus - * controller on different i2c buses. */ - struct mutex gmbus_mutex; - - /** - * Base address of where the gmbus and gpio blocks are located (either - * on PCH or on SoC for platforms without PCH). - */ - u32 gpio_mmio_base; - /* MMIO base address for MIPI regs */ u32 mipi_mmio_base; - u32 pps_mmio_base; - - wait_queue_head_t gmbus_wait_queue; - struct pci_dev *bridge_dev; struct rb_root uabi_engines; @@ -525,22 +337,15 @@ struct drm_i915_private { }; u32 pipestat_irq_mask[I915_MAX_PIPES]; - struct i915_hotplug hotplug; struct intel_fbc *fbc[I915_MAX_FBCS]; struct intel_opregion opregion; struct intel_vbt_data vbt; bool preserve_bios_swizzle; - /* overlay */ - struct intel_overlay *overlay; - /* backlight registers and fields in struct intel_panel */ struct mutex backlight_lock; - /* protects panel power sequencer state */ - struct mutex pps_mutex; - unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int skl_preferred_vco_freq; unsigned int max_cdclk_freq; @@ -584,31 +389,11 @@ struct drm_i915_private { /* pm private clock gating functions */ const struct drm_i915_clock_gating_funcs *clock_gating_funcs; - /* pm display functions */ - const struct drm_i915_wm_disp_funcs *wm_disp; - - /* irq display functions */ - const struct intel_hotplug_funcs *hotplug_funcs; - - /* fdi display functions */ - const struct intel_fdi_funcs *fdi_funcs; - - /* display pll funcs */ - const struct intel_dpll_funcs *dpll_funcs; - - /* Display functions */ - const struct drm_i915_display_funcs *display; - - /* Display internal color functions */ - const struct intel_color_funcs *color_funcs; - - /* Display CDCLK functions */ - const struct intel_cdclk_funcs *cdclk_funcs; - /* PCH chipset type */ enum intel_pch pch_type; unsigned short pch_id; + unsigned long gem_quirks; unsigned long quirks; struct drm_atomic_state *modeset_restore_state; @@ -618,25 +403,6 @@ struct drm_i915_private { /* Kernel Modesetting */ - /** - * dpll and cdclk state is protected by connection_mutex - * dpll.lock serializes intel_{prepare,enable,disable}_shared_dpll. - * Must be global rather than per dpll, because on some platforms plls - * share registers. - */ - struct { - struct mutex lock; - - int num_shared_dpll; - struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; - const struct intel_dpll_mgr *mgr; - - struct { - int nssc; - int ssc; - } ref_clks; - } dpll; - struct list_head global_obj_list; struct i915_frontbuffer_tracking fb_tracking; @@ -668,10 +434,6 @@ struct drm_i915_private { struct i915_gpu_error gpu_error; - /* list of fbdev register on this device */ - struct intel_fbdev *fbdev; - struct work_struct fbdev_suspend_work; - struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; @@ -691,51 +453,6 @@ struct drm_i915_private { struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state *vlv_s0ix_state; - enum { - I915_SAGV_UNKNOWN = 0, - I915_SAGV_DISABLED, - I915_SAGV_ENABLED, - I915_SAGV_NOT_CONTROLLED - } sagv_status; - - u32 sagv_block_time_us; - - struct { - /* - * Raw watermark latency values: - * in 0.1us units for WM0, - * in 0.5us units for WM1+. - */ - /* primary */ - u16 pri_latency[5]; - /* sprite */ - u16 spr_latency[5]; - /* cursor */ - u16 cur_latency[5]; - /* - * Raw watermark memory latency values - * for SKL for all 8 levels - * in 1us units. - */ - u16 skl_latency[8]; - - /* current hardware state */ - union { - struct ilk_wm_values hw; - struct vlv_wm_values vlv; - struct g4x_wm_values g4x; - }; - - u8 max_level; - - /* - * Should be held around atomic WM register writing; also - * protects * intel_crtc->wm.active and - * crtc_state->wm.need_postvbl_update. - */ - struct mutex wm_mutex; - } wm; - struct dram_info { bool wm_lv_0_adjust_needed; u8 num_channels; @@ -800,9 +517,6 @@ struct drm_i915_private { struct file *mmap_singleton; } gem; - /* Window2 specifies time required to program DSB (Window2) in number of scan lines */ - u8 window2_delay; - u8 pch_ssc_use; /* For i915gm/i945gm vblank irq workaround */ @@ -823,8 +537,6 @@ struct drm_i915_private { bool ipc_enabled; - struct intel_audio_private audio; - struct i915_pmu pmu; struct i915_drm_clients clients; @@ -895,26 +607,6 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define I915_GTT_OFFSET_NONE ((u32)-1) -/* - * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is - * considered to be the frontbuffer for the given plane interface-wise. This - * doesn't mean that the hw necessarily already scans it out, but that any - * rendering (by the cpu or gpu) will land in the frontbuffer eventually. - * - * We have one bit per pipe and per scanout plane type. - */ -#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 -#define INTEL_FRONTBUFFER(pipe, plane_id) ({ \ - BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 32); \ - BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); \ - BIT((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)); \ -}) -#define INTEL_FRONTBUFFER_OVERLAY(pipe) \ - BIT(INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) -#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ - GENMASK(INTEL_FRONTBUFFER_BITS_PER_PIPE * ((pipe) + 1) - 1, \ - INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) - #define INTEL_INFO(dev_priv) (&(dev_priv)->__info) #define RUNTIME_INFO(dev_priv) (&(dev_priv)->__runtime) #define DRIVER_CAPS(dev_priv) (&(dev_priv)->caps) @@ -923,9 +615,9 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define IP_VER(ver, rel) ((ver) << 8 | (rel)) -#define GRAPHICS_VER(i915) (INTEL_INFO(i915)->graphics.ver) -#define GRAPHICS_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->graphics.ver, \ - INTEL_INFO(i915)->graphics.rel) +#define GRAPHICS_VER(i915) (RUNTIME_INFO(i915)->graphics.ver) +#define GRAPHICS_VER_FULL(i915) IP_VER(RUNTIME_INFO(i915)->graphics.ver, \ + RUNTIME_INFO(i915)->graphics.rel) #define IS_GRAPHICS_VER(i915, from, until) \ (GRAPHICS_VER(i915) >= (from) && GRAPHICS_VER(i915) <= (until)) @@ -1277,7 +969,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv) -#define INTEL_PPGTT(dev_priv) (INTEL_INFO(dev_priv)->ppgtt_type) +#define INTEL_PPGTT(dev_priv) (RUNTIME_INFO(dev_priv)->ppgtt_type) #define HAS_PPGTT(dev_priv) \ (INTEL_PPGTT(dev_priv) != INTEL_PPGTT_NONE) #define HAS_FULL_PPGTT(dev_priv) \ @@ -1285,7 +977,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_PAGE_SIZES(dev_priv, sizes) ({ \ GEM_BUG_ON((sizes) == 0); \ - ((sizes) & ~INTEL_INFO(dev_priv)->page_sizes) == 0; \ + ((sizes) & ~RUNTIME_INFO(dev_priv)->page_sizes) == 0; \ }) #define HAS_OVERLAY(dev_priv) (INTEL_INFO(dev_priv)->display.has_overlay) @@ -1316,13 +1008,13 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define I915_HAS_HOTPLUG(dev_priv) (INTEL_INFO(dev_priv)->display.has_hotplug) #define HAS_FW_BLC(dev_priv) (DISPLAY_VER(dev_priv) > 2) -#define HAS_FBC(dev_priv) (INTEL_INFO(dev_priv)->display.fbc_mask != 0) +#define HAS_FBC(dev_priv) (RUNTIME_INFO(dev_priv)->fbc_mask != 0) #define HAS_CUR_FBC(dev_priv) (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) >= 7) #define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) #define HAS_DP_MST(dev_priv) (INTEL_INFO(dev_priv)->display.has_dp_mst) -#define HAS_DP20(dev_priv) (IS_DG2(dev_priv)) +#define HAS_DP20(dev_priv) (IS_DG2(dev_priv) || DISPLAY_VER(dev_priv) >= 14) #define HAS_CDCLK_CRAWL(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_crawl) #define HAS_DDI(dev_priv) (INTEL_INFO(dev_priv)->display.has_ddi) @@ -1331,7 +1023,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_PSR_HW_TRACKING(dev_priv) \ (INTEL_INFO(dev_priv)->display.has_psr_hw_tracking) #define HAS_PSR2_SEL_FETCH(dev_priv) (DISPLAY_VER(dev_priv) >= 12) -#define HAS_TRANSCODER(dev_priv, trans) ((INTEL_INFO(dev_priv)->display.cpu_transcoder_mask & BIT(trans)) != 0) +#define HAS_TRANSCODER(dev_priv, trans) ((RUNTIME_INFO(dev_priv)->cpu_transcoder_mask & BIT(trans)) != 0) #define HAS_RC6(dev_priv) (INTEL_INFO(dev_priv)->has_rc6) #define HAS_RC6p(dev_priv) (INTEL_INFO(dev_priv)->has_rc6p) @@ -1339,7 +1031,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_RPS(dev_priv) (INTEL_INFO(dev_priv)->has_rps) -#define HAS_DMC(dev_priv) (INTEL_INFO(dev_priv)->display.has_dmc) +#define HAS_DMC(dev_priv) (RUNTIME_INFO(dev_priv)->has_dmc) #define HAS_HECI_PXP(dev_priv) \ (INTEL_INFO(dev_priv)->has_heci_pxp) @@ -1369,7 +1061,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_IPC(dev_priv) (INTEL_INFO(dev_priv)->display.has_ipc) -#define HAS_REGION(i915, i) (INTEL_INFO(i915)->memory_regions & (i)) +#define HAS_REGION(i915, i) (RUNTIME_INFO(i915)->memory_regions & (i)) #define HAS_LMEM(i915) HAS_REGION(i915, REGION_LMEM) #define HAS_EXTRA_GT_LIST(dev_priv) (INTEL_INFO(dev_priv)->extra_gt_list) @@ -1382,7 +1074,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_GT_UC(dev_priv) (INTEL_INFO(dev_priv)->has_gt_uc) -#define HAS_POOLED_EU(dev_priv) (INTEL_INFO(dev_priv)->has_pooled_eu) +#define HAS_POOLED_EU(dev_priv) (RUNTIME_INFO(dev_priv)->has_pooled_eu) #define HAS_GLOBAL_MOCS_REGISTERS(dev_priv) (INTEL_INFO(dev_priv)->has_global_mocs) @@ -1404,9 +1096,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define GT_FREQUENCY_MULTIPLIER 50 #define GEN9_FREQ_SCALER 3 -#define INTEL_NUM_PIPES(dev_priv) (hweight8(INTEL_INFO(dev_priv)->display.pipe_mask)) +#define INTEL_NUM_PIPES(dev_priv) (hweight8(RUNTIME_INFO(dev_priv)->pipe_mask)) -#define HAS_DISPLAY(dev_priv) (INTEL_INFO(dev_priv)->display.pipe_mask != 0) +#define HAS_DISPLAY(dev_priv) (RUNTIME_INFO(dev_priv)->pipe_mask != 0) #define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11) @@ -1414,7 +1106,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, /* Only valid when HAS_DISPLAY() is true */ #define INTEL_DISPLAY_ENABLED(dev_priv) \ - (drm_WARN_ON(&(dev_priv)->drm, !HAS_DISPLAY(dev_priv)), !(dev_priv)->params.disable_display) + (drm_WARN_ON(&(dev_priv)->drm, !HAS_DISPLAY(dev_priv)), \ + !(dev_priv)->params.disable_display && \ + !intel_opregion_headless_sku(dev_priv)) #define HAS_GUC_DEPRIVILEGE(dev_priv) \ (INTEL_INFO(dev_priv)->has_guc_deprivilege) @@ -1422,7 +1116,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_D12_PLANE_MINIMIZATION(dev_priv) (IS_ROCKETLAKE(dev_priv) || \ IS_ALDERLAKE_S(dev_priv)) -#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915)) +#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) #define HAS_3D_PIPELINE(i915) (INTEL_INFO(i915)->has_3d_pipeline) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8e14ed9c2a9..53b63540c3c7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1039,7 +1039,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, if (i915_gem_object_has_pages(obj) && i915_gem_object_is_tiled(obj) && - i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) { + i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) { if (obj->mm.madv == I915_MADV_WILLNEED) { GEM_BUG_ON(!i915_gem_object_has_tiling_quirk(obj)); i915_gem_object_clear_tiling_quirk(obj); @@ -1095,8 +1095,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) /* We need to fallback to 4K pages if host doesn't support huge gtt. */ if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv)) - mkwrite_device_info(dev_priv)->page_sizes = - I915_GTT_PAGE_SIZE_4K; + RUNTIME_INFO(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K; ret = i915_gem_init_userptr(dev_priv); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index a2be323a4be5..68d8d52bd541 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -26,7 +26,6 @@ #define __I915_GEM_H__ #include <linux/bug.h> -#include <linux/interrupt.h> #include <drm/drm_drv.h> @@ -85,36 +84,4 @@ struct drm_i915_private; #define I915_GEM_IDLE_TIMEOUT (HZ / 5) -static inline void tasklet_lock(struct tasklet_struct *t) -{ - while (!tasklet_trylock(t)) - cpu_relax(); -} - -static inline bool tasklet_is_locked(const struct tasklet_struct *t) -{ - return test_bit(TASKLET_STATE_RUN, &t->state); -} - -static inline void __tasklet_disable_sync_once(struct tasklet_struct *t) -{ - if (!atomic_fetch_inc(&t->count)) - tasklet_unlock_spin_wait(t); -} - -static inline bool __tasklet_is_enabled(const struct tasklet_struct *t) -{ - return !atomic_read(&t->count); -} - -static inline bool __tasklet_enable(struct tasklet_struct *t) -{ - return atomic_dec_and_test(&t->count); -} - -static inline bool __tasklet_is_scheduled(struct tasklet_struct *t) -{ - return test_bit(TASKLET_STATE_SCHED, &t->state); -} - #endif /* __I915_GEM_H__ */ diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index 6fd15b39570c..342c8ca6414e 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -36,7 +36,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, value = to_gt(i915)->ggtt->num_fences; break; case I915_PARAM_HAS_OVERLAY: - value = !!i915->overlay; + value = !!i915->display.overlay; break; case I915_PARAM_HAS_BSD: value = !!intel_engine_lookup_user(i915, diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 16d8b7ba65dc..9ea2fe34e7d3 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -646,8 +646,7 @@ static void err_print_capabilities(struct drm_i915_error_state_buf *m, { struct drm_printer p = i915_error_printer(m); - intel_device_info_print_static(&error->device_info, &p); - intel_device_info_print_runtime(&error->runtime_info, &p); + intel_device_info_print(&error->device_info, &error->runtime_info, &p); intel_driver_caps_print(&error->driver_caps, &p); } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5652acdcf910..14efd58e37d7 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -65,7 +65,7 @@ /* * Interrupt statistic for PMU. Increments the counter only if the - * interrupt originated from the the GPU so interrupts from a device which + * interrupt originated from the GPU so interrupts from a device which * shares the interrupt line are not accounted. */ static inline void pmu_irq_stats(struct drm_i915_private *i915, @@ -185,7 +185,7 @@ static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) { - struct i915_hotplug *hpd = &dev_priv->hotplug; + struct intel_hotplug *hpd = &dev_priv->display.hotplug; if (HAS_GMCH(dev_priv)) { if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || @@ -1272,7 +1272,7 @@ static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, u32 enabled_irqs = 0; for_each_intel_encoder(&dev_priv->drm, encoder) - if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) + if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) enabled_irqs |= hpd[encoder->hpd_pin]; return enabled_irqs; @@ -1304,12 +1304,12 @@ static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, static void gmbus_irq_handler(struct drm_i915_private *dev_priv) { - wake_up_all(&dev_priv->gmbus_wait_queue); + wake_up_all(&dev_priv->display.gmbus.wait_queue); } static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) { - wake_up_all(&dev_priv->gmbus_wait_queue); + wake_up_all(&dev_priv->display.gmbus.wait_queue); } #if defined(CONFIG_DEBUG_FS) @@ -1637,7 +1637,7 @@ static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, if (hotplug_trigger) { intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, hotplug_trigger, - dev_priv->hotplug.hpd, + dev_priv->display.hotplug.hpd, i9xx_port_hotplug_long_detect); intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); @@ -1841,7 +1841,7 @@ static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.pch_hpd, + dev_priv->display.hotplug.pch_hpd, pch_port_hotplug_long_detect); intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); @@ -1986,7 +1986,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, ddi_hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.pch_hpd, + dev_priv->display.hotplug.pch_hpd, icp_ddi_port_hotplug_long_detect); } @@ -1998,7 +1998,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, tc_hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.pch_hpd, + dev_priv->display.hotplug.pch_hpd, icp_tc_port_hotplug_long_detect); } @@ -2024,7 +2024,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.pch_hpd, + dev_priv->display.hotplug.pch_hpd, spt_port_hotplug_long_detect); } @@ -2036,7 +2036,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug2_trigger, dig_hotplug_reg, - dev_priv->hotplug.pch_hpd, + dev_priv->display.hotplug.pch_hpd, spt_port_hotplug2_long_detect); } @@ -2057,7 +2057,7 @@ static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.hpd, + dev_priv->display.hotplug.hpd, ilk_port_hotplug_long_detect); intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); @@ -2237,7 +2237,7 @@ static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, - dev_priv->hotplug.hpd, + dev_priv->display.hotplug.hpd, bxt_port_hotplug_long_detect); intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); @@ -2257,7 +2257,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, dig_hotplug_reg, - dev_priv->hotplug.hpd, + dev_priv->display.hotplug.hpd, gen11_port_hotplug_long_detect); } @@ -2269,7 +2269,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, dig_hotplug_reg, - dev_priv->hotplug.hpd, + dev_priv->display.hotplug.hpd, gen11_port_hotplug_long_detect); } @@ -2653,9 +2653,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } static u32 -gen11_gu_misc_irq_ack(struct intel_gt *gt, const u32 master_ctl) +gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) { - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = i915->uncore.regs; u32 iir; if (!(master_ctl & GEN11_GU_MISC_IRQ)) @@ -2669,10 +2669,10 @@ gen11_gu_misc_irq_ack(struct intel_gt *gt, const u32 master_ctl) } static void -gen11_gu_misc_irq_handler(struct intel_gt *gt, const u32 iir) +gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) { if (iir & GEN11_GU_MISC_GSE) - intel_opregion_asle_intr(gt->i915); + intel_opregion_asle_intr(i915); } static inline u32 gen11_master_intr_disable(void __iomem * const regs) @@ -2736,11 +2736,11 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) if (master_ctl & GEN11_DISPLAY_IRQ) gen11_display_irq_handler(i915); - gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); + gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); gen11_master_intr_enable(regs); - gen11_gu_misc_irq_handler(gt, gu_misc_iir); + gen11_gu_misc_irq_handler(i915, gu_misc_iir); pmu_irq_stats(i915, IRQ_HANDLED); @@ -2801,11 +2801,11 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) if (master_ctl & GEN11_DISPLAY_IRQ) gen11_display_irq_handler(i915); - gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); + gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); dg1_master_intr_enable(regs); - gen11_gu_misc_irq_handler(gt, gu_misc_iir); + gen11_gu_misc_irq_handler(i915, gu_misc_iir); pmu_irq_stats(i915, IRQ_HANDLED); @@ -3313,8 +3313,8 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -3383,8 +3383,8 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); @@ -3460,8 +3460,8 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) u32 hotplug_irqs, enabled_irqs; u32 val; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); val = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); val &= ~hotplug_irqs; @@ -3538,8 +3538,8 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -3578,8 +3578,8 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); if (DISPLAY_VER(dev_priv) >= 8) bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); @@ -3636,8 +3636,8 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); @@ -4370,8 +4370,8 @@ HPD_FUNCS(ilk); void intel_hpd_irq_setup(struct drm_i915_private *i915) { - if (i915->display_irqs_enabled && i915->hotplug_funcs) - i915->hotplug_funcs->hpd_irq_setup(i915); + if (i915->display_irqs_enabled && i915->display.funcs.hotplug) + i915->display.funcs.hotplug->hpd_irq_setup(i915); } /** @@ -4413,33 +4413,33 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) dev_priv->display_irqs_enabled = false; - dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; + dev_priv->display.hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; /* If we have MST support, we want to avoid doing short HPD IRQ storm * detection, as short HPD storms will occur as a natural part of * sideband messaging with MST. * On older platforms however, IRQ storms can occur with both long and * short pulses, as seen on some G4x systems. */ - dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); + dev_priv->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); if (HAS_GMCH(dev_priv)) { if (I915_HAS_HOTPLUG(dev_priv)) - dev_priv->hotplug_funcs = &i915_hpd_funcs; + dev_priv->display.funcs.hotplug = &i915_hpd_funcs; } else { if (HAS_PCH_DG2(dev_priv)) - dev_priv->hotplug_funcs = &icp_hpd_funcs; + dev_priv->display.funcs.hotplug = &icp_hpd_funcs; else if (HAS_PCH_DG1(dev_priv)) - dev_priv->hotplug_funcs = &dg1_hpd_funcs; + dev_priv->display.funcs.hotplug = &dg1_hpd_funcs; else if (DISPLAY_VER(dev_priv) >= 11) - dev_priv->hotplug_funcs = &gen11_hpd_funcs; + dev_priv->display.funcs.hotplug = &gen11_hpd_funcs; else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - dev_priv->hotplug_funcs = &bxt_hpd_funcs; + dev_priv->display.funcs.hotplug = &bxt_hpd_funcs; else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - dev_priv->hotplug_funcs = &icp_hpd_funcs; + dev_priv->display.funcs.hotplug = &icp_hpd_funcs; else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) - dev_priv->hotplug_funcs = &spt_hpd_funcs; + dev_priv->display.funcs.hotplug = &spt_hpd_funcs; else - dev_priv->hotplug_funcs = &ilk_hpd_funcs; + dev_priv->display.funcs.hotplug = &ilk_hpd_funcs; } } diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 2899c7cbdfb5..19fc00bcd7b9 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -33,51 +33,52 @@ #include "i915_drv.h" #include "i915_pci.h" #include "i915_reg.h" +#include "intel_pci_config.h" #define PLATFORM(x) .platform = (x) #define GEN(x) \ - .graphics.ver = (x), \ + .__runtime.graphics.ver = (x), \ .media.ver = (x), \ .display.ver = (x) #define I845_PIPE_OFFSETS \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ } #define I9XX_PIPE_OFFSETS \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ } #define IVB_PIPE_OFFSETS \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ } #define HSW_PIPE_OFFSETS \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ [TRANSCODER_EDP] = PIPE_EDP_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ @@ -85,44 +86,44 @@ } #define CHV_PIPE_OFFSETS \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = CHV_PIPE_C_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = CHV_TRANSCODER_C_OFFSET, \ } #define I845_CURSOR_OFFSETS \ - .cursor_offsets = { \ + .display.cursor_offsets = { \ [PIPE_A] = CURSOR_A_OFFSET, \ } #define I9XX_CURSOR_OFFSETS \ - .cursor_offsets = { \ + .display.cursor_offsets = { \ [PIPE_A] = CURSOR_A_OFFSET, \ [PIPE_B] = CURSOR_B_OFFSET, \ } #define CHV_CURSOR_OFFSETS \ - .cursor_offsets = { \ + .display.cursor_offsets = { \ [PIPE_A] = CURSOR_A_OFFSET, \ [PIPE_B] = CURSOR_B_OFFSET, \ [PIPE_C] = CHV_CURSOR_C_OFFSET, \ } #define IVB_CURSOR_OFFSETS \ - .cursor_offsets = { \ + .display.cursor_offsets = { \ [PIPE_A] = CURSOR_A_OFFSET, \ [PIPE_B] = IVB_CURSOR_B_OFFSET, \ [PIPE_C] = IVB_CURSOR_C_OFFSET, \ } #define TGL_CURSOR_OFFSETS \ - .cursor_offsets = { \ + .display.cursor_offsets = { \ [PIPE_A] = CURSOR_A_OFFSET, \ [PIPE_B] = IVB_CURSOR_B_OFFSET, \ [PIPE_C] = IVB_CURSOR_C_OFFSET, \ @@ -130,45 +131,48 @@ } #define I9XX_COLORS \ - .color = { .gamma_lut_size = 256 } + .display.color = { .gamma_lut_size = 256 } #define I965_COLORS \ - .color = { .gamma_lut_size = 129, \ + .display.color = { .gamma_lut_size = 129, \ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ } #define ILK_COLORS \ - .color = { .gamma_lut_size = 1024 } + .display.color = { .gamma_lut_size = 1024 } #define IVB_COLORS \ - .color = { .degamma_lut_size = 1024, .gamma_lut_size = 1024 } + .display.color = { .degamma_lut_size = 1024, .gamma_lut_size = 1024 } #define CHV_COLORS \ - .color = { .degamma_lut_size = 65, .gamma_lut_size = 257, \ - .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ - .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ + .display.color = { \ + .degamma_lut_size = 65, .gamma_lut_size = 257, \ + .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ + .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ } #define GLK_COLORS \ - .color = { .degamma_lut_size = 33, .gamma_lut_size = 1024, \ - .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ - DRM_COLOR_LUT_EQUAL_CHANNELS, \ + .display.color = { \ + .degamma_lut_size = 33, .gamma_lut_size = 1024, \ + .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ + DRM_COLOR_LUT_EQUAL_CHANNELS, \ } #define ICL_COLORS \ - .color = { .degamma_lut_size = 33, .gamma_lut_size = 262145, \ - .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ - DRM_COLOR_LUT_EQUAL_CHANNELS, \ - .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ + .display.color = { \ + .degamma_lut_size = 33, .gamma_lut_size = 262145, \ + .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ + DRM_COLOR_LUT_EQUAL_CHANNELS, \ + .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ } /* Keep in gen based order, and chronological order within a gen */ #define GEN_DEFAULT_PAGE_SIZES \ - .page_sizes = I915_GTT_PAGE_SIZE_4K + .__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K #define GEN_DEFAULT_REGIONS \ - .memory_regions = REGION_SMEM | REGION_STOLEN_SMEM + .__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_SMEM #define I830_FEATURES \ GEN(2), \ .is_mobile = 1, \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .display.has_overlay = 1, \ .display.cursor_needs_physical = 1, \ .display.overlay_needs_physical = 1, \ @@ -177,7 +181,7 @@ .has_3d_pipeline = 1, \ .hws_needs_physical = 1, \ .unfenced_needs_alignment = 1, \ - .platform_engine_mask = BIT(RCS0), \ + .__runtime.platform_engine_mask = BIT(RCS0), \ .has_snoop = true, \ .has_coherent_ggtt = false, \ .dma_mask_size = 32, \ @@ -189,8 +193,8 @@ #define I845_FEATURES \ GEN(2), \ - .display.pipe_mask = BIT(PIPE_A), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A), \ + .__runtime.pipe_mask = BIT(PIPE_A), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A), \ .display.has_overlay = 1, \ .display.overlay_needs_physical = 1, \ .display.has_gmch = 1, \ @@ -198,7 +202,7 @@ .gpu_reset_clobbers_display = true, \ .hws_needs_physical = 1, \ .unfenced_needs_alignment = 1, \ - .platform_engine_mask = BIT(RCS0), \ + .__runtime.platform_engine_mask = BIT(RCS0), \ .has_snoop = true, \ .has_coherent_ggtt = false, \ .dma_mask_size = 32, \ @@ -221,22 +225,22 @@ static const struct intel_device_info i845g_info = { static const struct intel_device_info i85x_info = { I830_FEATURES, PLATFORM(INTEL_I85X), - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), }; static const struct intel_device_info i865g_info = { I845_FEATURES, PLATFORM(INTEL_I865G), - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), }; #define GEN3_FEATURES \ GEN(3), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .display.has_gmch = 1, \ .gpu_reset_clobbers_display = true, \ - .platform_engine_mask = BIT(RCS0), \ + .__runtime.platform_engine_mask = BIT(RCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -266,7 +270,7 @@ static const struct intel_device_info i915gm_info = { .display.has_overlay = 1, .display.overlay_needs_physical = 1, .display.supports_tv = 1, - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), .hws_needs_physical = 1, .unfenced_needs_alignment = 1, }; @@ -291,7 +295,7 @@ static const struct intel_device_info i945gm_info = { .display.has_overlay = 1, .display.overlay_needs_physical = 1, .display.supports_tv = 1, - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), .hws_needs_physical = 1, .unfenced_needs_alignment = 1, }; @@ -323,12 +327,12 @@ static const struct intel_device_info pnv_m_info = { #define GEN4_FEATURES \ GEN(4), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .display.has_hotplug = 1, \ .display.has_gmch = 1, \ .gpu_reset_clobbers_display = true, \ - .platform_engine_mask = BIT(RCS0), \ + .__runtime.platform_engine_mask = BIT(RCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -351,7 +355,7 @@ static const struct intel_device_info i965gm_info = { GEN4_FEATURES, PLATFORM(INTEL_I965GM), .is_mobile = 1, - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), .display.has_overlay = 1, .display.supports_tv = 1, .hws_needs_physical = 1, @@ -361,7 +365,7 @@ static const struct intel_device_info i965gm_info = { static const struct intel_device_info g45_info = { GEN4_FEATURES, PLATFORM(INTEL_G45), - .platform_engine_mask = BIT(RCS0) | BIT(VCS0), + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), .gpu_reset_clobbers_display = false, }; @@ -369,18 +373,18 @@ static const struct intel_device_info gm45_info = { GEN4_FEATURES, PLATFORM(INTEL_GM45), .is_mobile = 1, - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), .display.supports_tv = 1, - .platform_engine_mask = BIT(RCS0) | BIT(VCS0), + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), .gpu_reset_clobbers_display = false, }; #define GEN5_FEATURES \ GEN(5), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .display.has_hotplug = 1, \ - .platform_engine_mask = BIT(RCS0) | BIT(VCS0), \ + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -403,16 +407,16 @@ static const struct intel_device_info ilk_m_info = { PLATFORM(INTEL_IRONLAKE), .is_mobile = 1, .has_rps = true, - .display.fbc_mask = BIT(INTEL_FBC_A), + .__runtime.fbc_mask = BIT(INTEL_FBC_A), }; #define GEN6_FEATURES \ GEN(6), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .display.has_hotplug = 1, \ - .display.fbc_mask = BIT(INTEL_FBC_A), \ - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ + .__runtime.fbc_mask = BIT(INTEL_FBC_A), \ + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ .has_3d_pipeline = 1, \ .has_coherent_ggtt = true, \ .has_llc = 1, \ @@ -420,8 +424,8 @@ static const struct intel_device_info ilk_m_info = { .has_rc6p = 1, \ .has_rps = true, \ .dma_mask_size = 40, \ - .ppgtt_type = INTEL_PPGTT_ALIASING, \ - .ppgtt_size = 31, \ + .__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, \ + .__runtime.ppgtt_size = 31, \ I9XX_PIPE_OFFSETS, \ I9XX_CURSOR_OFFSETS, \ ILK_COLORS, \ @@ -460,11 +464,11 @@ static const struct intel_device_info snb_m_gt2_info = { #define GEN7_FEATURES \ GEN(7), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), \ .display.has_hotplug = 1, \ - .display.fbc_mask = BIT(INTEL_FBC_A), \ - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ + .__runtime.fbc_mask = BIT(INTEL_FBC_A), \ + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ .has_3d_pipeline = 1, \ .has_coherent_ggtt = true, \ .has_llc = 1, \ @@ -473,8 +477,8 @@ static const struct intel_device_info snb_m_gt2_info = { .has_reset_engine = true, \ .has_rps = true, \ .dma_mask_size = 40, \ - .ppgtt_type = INTEL_PPGTT_ALIASING, \ - .ppgtt_size = 31, \ + .__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, \ + .__runtime.ppgtt_size = 31, \ IVB_PIPE_OFFSETS, \ IVB_CURSOR_OFFSETS, \ IVB_COLORS, \ @@ -516,8 +520,8 @@ static const struct intel_device_info ivb_q_info = { GEN7_FEATURES, PLATFORM(INTEL_IVYBRIDGE), .gt = 2, - .display.pipe_mask = 0, /* legal, last one wins */ - .display.cpu_transcoder_mask = 0, + .__runtime.pipe_mask = 0, /* legal, last one wins */ + .__runtime.cpu_transcoder_mask = 0, .has_l3_dpf = 1, }; @@ -525,8 +529,8 @@ static const struct intel_device_info vlv_info = { PLATFORM(INTEL_VALLEYVIEW), GEN(7), .is_lp = 1, - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), .has_runtime_pm = 1, .has_rc6 = 1, .has_reset_engine = true, @@ -534,12 +538,12 @@ static const struct intel_device_info vlv_info = { .display.has_gmch = 1, .display.has_hotplug = 1, .dma_mask_size = 40, - .ppgtt_type = INTEL_PPGTT_ALIASING, - .ppgtt_size = 31, + .__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, + .__runtime.ppgtt_size = 31, .has_snoop = true, .has_coherent_ggtt = false, - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), - .display_mmio_offset = VLV_DISPLAY_BASE, + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), + .display.mmio_offset = VLV_DISPLAY_BASE, I9XX_PIPE_OFFSETS, I9XX_CURSOR_OFFSETS, I965_COLORS, @@ -549,8 +553,8 @@ static const struct intel_device_info vlv_info = { #define G75_FEATURES \ GEN7_FEATURES, \ - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), \ .display.has_ddi = 1, \ .display.has_fpga_dbg = 1, \ @@ -584,8 +588,8 @@ static const struct intel_device_info hsw_gt3_info = { GEN(8), \ .has_logical_ring_contexts = 1, \ .dma_mask_size = 39, \ - .ppgtt_type = INTEL_PPGTT_FULL, \ - .ppgtt_size = 48, \ + .__runtime.ppgtt_type = INTEL_PPGTT_FULL, \ + .__runtime.ppgtt_size = 48, \ .has_64bit_reloc = 1 #define BDW_PLATFORM \ @@ -613,18 +617,18 @@ static const struct intel_device_info bdw_rsvd_info = { static const struct intel_device_info bdw_gt3_info = { BDW_PLATFORM, .gt = 3, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; static const struct intel_device_info chv_info = { PLATFORM(INTEL_CHERRYVIEW), GEN(8), - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), .display.has_hotplug = 1, .is_lp = 1, - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), .has_64bit_reloc = 1, .has_runtime_pm = 1, .has_rc6 = 1, @@ -632,12 +636,12 @@ static const struct intel_device_info chv_info = { .has_logical_ring_contexts = 1, .display.has_gmch = 1, .dma_mask_size = 39, - .ppgtt_type = INTEL_PPGTT_FULL, - .ppgtt_size = 32, + .__runtime.ppgtt_type = INTEL_PPGTT_FULL, + .__runtime.ppgtt_size = 32, .has_reset_engine = 1, .has_snoop = true, .has_coherent_ggtt = false, - .display_mmio_offset = VLV_DISPLAY_BASE, + .display.mmio_offset = VLV_DISPLAY_BASE, CHV_PIPE_OFFSETS, CHV_CURSOR_OFFSETS, CHV_COLORS, @@ -646,21 +650,21 @@ static const struct intel_device_info chv_info = { }; #define GEN9_DEFAULT_PAGE_SIZES \ - .page_sizes = I915_GTT_PAGE_SIZE_4K | \ - I915_GTT_PAGE_SIZE_64K + .__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K | \ + I915_GTT_PAGE_SIZE_64K #define GEN9_FEATURES \ GEN8_FEATURES, \ GEN(9), \ GEN9_DEFAULT_PAGE_SIZES, \ - .display.has_dmc = 1, \ + .__runtime.has_dmc = 1, \ .has_gt_uc = 1, \ - .display.has_hdcp = 1, \ + .__runtime.has_hdcp = 1, \ .display.has_ipc = 1, \ .display.has_psr = 1, \ .display.has_psr_hw_tracking = 1, \ - .dbuf.size = 896 - 4, /* 4 blocks for bypass path allocation */ \ - .dbuf.slice_mask = BIT(DBUF_S1) + .display.dbuf.size = 896 - 4, /* 4 blocks for bypass path allocation */ \ + .display.dbuf.slice_mask = BIT(DBUF_S1) #define SKL_PLATFORM \ GEN9_FEATURES, \ @@ -678,7 +682,7 @@ static const struct intel_device_info skl_gt2_info = { #define SKL_GT3_PLUS_PLATFORM \ SKL_PLATFORM, \ - .platform_engine_mask = \ + .__runtime.platform_engine_mask = \ BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1) @@ -695,31 +699,31 @@ static const struct intel_device_info skl_gt4_info = { #define GEN9_LP_FEATURES \ GEN(9), \ .is_lp = 1, \ - .dbuf.slice_mask = BIT(DBUF_S1), \ + .display.dbuf.slice_mask = BIT(DBUF_S1), \ .display.has_hotplug = 1, \ - .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \ BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C), \ .has_3d_pipeline = 1, \ .has_64bit_reloc = 1, \ .display.has_ddi = 1, \ .display.has_fpga_dbg = 1, \ - .display.fbc_mask = BIT(INTEL_FBC_A), \ - .display.has_hdcp = 1, \ + .__runtime.fbc_mask = BIT(INTEL_FBC_A), \ + .__runtime.has_hdcp = 1, \ .display.has_psr = 1, \ .display.has_psr_hw_tracking = 1, \ .has_runtime_pm = 1, \ - .display.has_dmc = 1, \ + .__runtime.has_dmc = 1, \ .has_rc6 = 1, \ .has_rps = true, \ .display.has_dp_mst = 1, \ .has_logical_ring_contexts = 1, \ .has_gt_uc = 1, \ .dma_mask_size = 39, \ - .ppgtt_type = INTEL_PPGTT_FULL, \ - .ppgtt_size = 48, \ + .__runtime.ppgtt_type = INTEL_PPGTT_FULL, \ + .__runtime.ppgtt_size = 48, \ .has_reset_engine = 1, \ .has_snoop = true, \ .has_coherent_ggtt = false, \ @@ -733,14 +737,14 @@ static const struct intel_device_info skl_gt4_info = { static const struct intel_device_info bxt_info = { GEN9_LP_FEATURES, PLATFORM(INTEL_BROXTON), - .dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */ + .display.dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */ }; static const struct intel_device_info glk_info = { GEN9_LP_FEATURES, PLATFORM(INTEL_GEMINILAKE), .display.ver = 10, - .dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */ + .display.dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */ GLK_COLORS, }; @@ -761,7 +765,7 @@ static const struct intel_device_info kbl_gt2_info = { static const struct intel_device_info kbl_gt3_info = { KBL_PLATFORM, .gt = 3, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; @@ -782,7 +786,7 @@ static const struct intel_device_info cfl_gt2_info = { static const struct intel_device_info cfl_gt3_info = { CFL_PLATFORM, .gt = 3, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; @@ -801,18 +805,18 @@ static const struct intel_device_info cml_gt2_info = { }; #define GEN11_DEFAULT_PAGE_SIZES \ - .page_sizes = I915_GTT_PAGE_SIZE_4K | \ - I915_GTT_PAGE_SIZE_64K | \ - I915_GTT_PAGE_SIZE_2M + .__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K | \ + I915_GTT_PAGE_SIZE_64K | \ + I915_GTT_PAGE_SIZE_2M #define GEN11_FEATURES \ GEN9_FEATURES, \ GEN11_DEFAULT_PAGE_SIZES, \ .display.abox_mask = BIT(0), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \ BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ @@ -820,7 +824,7 @@ static const struct intel_device_info cml_gt2_info = { [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ @@ -830,42 +834,42 @@ static const struct intel_device_info cml_gt2_info = { }, \ GEN(11), \ ICL_COLORS, \ - .dbuf.size = 2048, \ - .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \ - .display.has_dsc = 1, \ + .display.dbuf.size = 2048, \ + .display.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \ + .__runtime.has_dsc = 1, \ .has_coherent_ggtt = false, \ .has_logical_ring_elsq = 1 static const struct intel_device_info icl_info = { GEN11_FEATURES, PLATFORM(INTEL_ICELAKE), - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), }; static const struct intel_device_info ehl_info = { GEN11_FEATURES, PLATFORM(INTEL_ELKHARTLAKE), - .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), - .ppgtt_size = 36, + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), + .__runtime.ppgtt_size = 36, }; static const struct intel_device_info jsl_info = { GEN11_FEATURES, PLATFORM(INTEL_JASPERLAKE), - .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), - .ppgtt_size = 36, + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), + .__runtime.ppgtt_size = 36, }; #define GEN12_FEATURES \ GEN11_FEATURES, \ GEN(12), \ .display.abox_mask = GENMASK(2, 1), \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \ - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \ + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \ BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \ - .pipe_offsets = { \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ @@ -873,7 +877,7 @@ static const struct intel_device_info jsl_info = { [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ @@ -890,7 +894,7 @@ static const struct intel_device_info tgl_info = { GEN12_FEATURES, PLATFORM(INTEL_TIGERLAKE), .display.has_modular_fia = 1, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), }; @@ -898,17 +902,17 @@ static const struct intel_device_info rkl_info = { GEN12_FEATURES, PLATFORM(INTEL_ROCKETLAKE), .display.abox_mask = BIT(0), - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), .display.has_hti = 1, .display.has_psr_hw_tracking = 0, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0), }; #define DGFX_FEATURES \ - .memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \ + .__runtime.memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \ .has_llc = 0, \ .has_pxp = 0, \ .has_snoop = 1, \ @@ -918,59 +922,52 @@ static const struct intel_device_info rkl_info = { static const struct intel_device_info dg1_info = { GEN12_FEATURES, DGFX_FEATURES, - .graphics.rel = 10, + .__runtime.graphics.rel = 10, PLATFORM(INTEL_DG1), - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), .require_force_probe = 1, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), /* Wa_16011227922 */ - .ppgtt_size = 47, + .__runtime.ppgtt_size = 47, }; static const struct intel_device_info adl_s_info = { GEN12_FEATURES, PLATFORM(INTEL_ALDERLAKE_S), - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), .display.has_hti = 1, .display.has_psr_hw_tracking = 0, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), .dma_mask_size = 39, }; -#define XE_LPD_CURSOR_OFFSETS \ - .cursor_offsets = { \ - [PIPE_A] = CURSOR_A_OFFSET, \ - [PIPE_B] = IVB_CURSOR_B_OFFSET, \ - [PIPE_C] = IVB_CURSOR_C_OFFSET, \ - [PIPE_D] = TGL_CURSOR_D_OFFSET, \ - } - #define XE_LPD_FEATURES \ .display.abox_mask = GENMASK(1, 0), \ - .color = { .degamma_lut_size = 128, .gamma_lut_size = 1024, \ - .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ - DRM_COLOR_LUT_EQUAL_CHANNELS, \ + .display.color = { \ + .degamma_lut_size = 128, .gamma_lut_size = 1024, \ + .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ + DRM_COLOR_LUT_EQUAL_CHANNELS, \ }, \ - .dbuf.size = 4096, \ - .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \ + .display.dbuf.size = 4096, \ + .display.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \ BIT(DBUF_S4), \ .display.has_ddi = 1, \ - .display.has_dmc = 1, \ + .__runtime.has_dmc = 1, \ .display.has_dp_mst = 1, \ .display.has_dsb = 1, \ - .display.has_dsc = 1, \ - .display.fbc_mask = BIT(INTEL_FBC_A), \ + .__runtime.has_dsc = 1, \ + .__runtime.fbc_mask = BIT(INTEL_FBC_A), \ .display.has_fpga_dbg = 1, \ - .display.has_hdcp = 1, \ + .__runtime.has_hdcp = 1, \ .display.has_hotplug = 1, \ .display.has_ipc = 1, \ .display.has_psr = 1, \ .display.ver = 13, \ - .display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \ - .pipe_offsets = { \ + .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \ + .display.pipe_offsets = { \ [TRANSCODER_A] = PIPE_A_OFFSET, \ [TRANSCODER_B] = PIPE_B_OFFSET, \ [TRANSCODER_C] = PIPE_C_OFFSET, \ @@ -978,7 +975,7 @@ static const struct intel_device_info adl_s_info = { [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \ }, \ - .trans_offsets = { \ + .display.trans_offsets = { \ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ @@ -986,34 +983,34 @@ static const struct intel_device_info adl_s_info = { [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \ [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \ }, \ - XE_LPD_CURSOR_OFFSETS + TGL_CURSOR_OFFSETS static const struct intel_device_info adl_p_info = { GEN12_FEATURES, XE_LPD_FEATURES, PLATFORM(INTEL_ALDERLAKE_P), - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), .display.has_cdclk_crawl = 1, .display.has_modular_fia = 1, .display.has_psr_hw_tracking = 0, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), - .ppgtt_size = 48, + .__runtime.ppgtt_size = 48, .dma_mask_size = 39, }; #undef GEN #define XE_HP_PAGE_SIZES \ - .page_sizes = I915_GTT_PAGE_SIZE_4K | \ - I915_GTT_PAGE_SIZE_64K | \ - I915_GTT_PAGE_SIZE_2M + .__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K | \ + I915_GTT_PAGE_SIZE_64K | \ + I915_GTT_PAGE_SIZE_2M #define XE_HP_FEATURES \ - .graphics.ver = 12, \ - .graphics.rel = 50, \ + .__runtime.graphics.ver = 12, \ + .__runtime.graphics.rel = 50, \ XE_HP_PAGE_SIZES, \ .dma_mask_size = 46, \ .has_3d_pipeline = 1, \ @@ -1029,8 +1026,8 @@ static const struct intel_device_info adl_p_info = { .has_reset_engine = 1, \ .has_rps = 1, \ .has_runtime_pm = 1, \ - .ppgtt_size = 48, \ - .ppgtt_type = INTEL_PPGTT_FULL + .__runtime.ppgtt_size = 48, \ + .__runtime.ppgtt_type = INTEL_PPGTT_FULL #define XE_HPM_FEATURES \ .media.ver = 12, \ @@ -1046,7 +1043,7 @@ static const struct intel_device_info xehpsdv_info = { .has_64k_pages = 1, .needs_compact_pt = 1, .has_media_ratio_mode = 1, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VECS1) | BIT(VECS2) | BIT(VECS3) | BIT(VCS0) | BIT(VCS1) | BIT(VCS2) | BIT(VCS3) | @@ -1059,7 +1056,7 @@ static const struct intel_device_info xehpsdv_info = { XE_HP_FEATURES, \ XE_HPM_FEATURES, \ DGFX_FEATURES, \ - .graphics.rel = 55, \ + .__runtime.graphics.rel = 55, \ .media.rel = 55, \ PLATFORM(INTEL_DG2), \ .has_4tile = 1, \ @@ -1068,7 +1065,7 @@ static const struct intel_device_info xehpsdv_info = { .has_heci_pxp = 1, \ .needs_compact_pt = 1, \ .has_media_ratio_mode = 1, \ - .platform_engine_mask = \ + .__runtime.platform_engine_mask = \ BIT(RCS0) | BIT(BCS0) | \ BIT(VECS0) | BIT(VECS1) | \ BIT(VCS0) | BIT(VCS2) | \ @@ -1077,7 +1074,7 @@ static const struct intel_device_info xehpsdv_info = { static const struct intel_device_info dg2_info = { DG2_FEATURES, XE_LPD_FEATURES, - .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D), .require_force_probe = 1, }; @@ -1103,12 +1100,12 @@ static const struct intel_device_info pvc_info = { XE_HPC_FEATURES, XE_HPM_FEATURES, DGFX_FEATURES, - .graphics.rel = 60, + .__runtime.graphics.rel = 60, .media.rel = 60, PLATFORM(INTEL_PONTEVECCHIO), .display = { 0 }, .has_flat_ccs = 0, - .platform_engine_mask = + .__runtime.platform_engine_mask = BIT(BCS0) | BIT(VCS0) | BIT(CCS0) | BIT(CCS1) | BIT(CCS2) | BIT(CCS3), @@ -1118,7 +1115,8 @@ static const struct intel_device_info pvc_info = { #define XE_LPDP_FEATURES \ XE_LPD_FEATURES, \ .display.ver = 14, \ - .display.has_cdclk_crawl = 1 + .display.has_cdclk_crawl = 1, \ + .__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) static const struct intel_gt_definition xelpmp_extra_gt[] = { { @@ -1138,16 +1136,16 @@ static const struct intel_device_info mtl_info = { * Real graphics IP version will be obtained from hardware GMD_ID * register. Value provided here is just for sanity checking. */ - .graphics.ver = 12, - .graphics.rel = 70, + .__runtime.graphics.ver = 12, + .__runtime.graphics.rel = 70, .media.ver = 13, PLATFORM(INTEL_METEORLAKE), .display.has_modular_fia = 1, .extra_gt_list = xelpmp_extra_gt, .has_flat_ccs = 0, .has_snoop = 1, - .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, - .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), + .__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, + .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), .require_force_probe = 1, }; @@ -1281,6 +1279,27 @@ static bool force_probe(u16 device_id, const char *devices) return ret; } +bool i915_pci_resource_valid(struct pci_dev *pdev, int bar) +{ + if (!pci_resource_flags(pdev, bar)) + return false; + + if (pci_resource_flags(pdev, bar) & IORESOURCE_UNSET) + return false; + + if (!pci_resource_len(pdev, bar)) + return false; + + return true; +} + +static bool intel_mmio_bar_valid(struct pci_dev *pdev, struct intel_device_info *intel_info) +{ + int gttmmaddr_bar = intel_info->__runtime.graphics.ver == 2 ? GEN2_GTTMMADR_BAR : GTTMMADR_BAR; + + return i915_pci_resource_valid(pdev, gttmmaddr_bar); +} + static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_device_info *intel_info = @@ -1306,6 +1325,9 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (PCI_FUNC(pdev->devfn)) return -ENODEV; + if (!intel_mmio_bar_valid(pdev, intel_info)) + return -ENXIO; + /* Detect if we need to wait for other drivers early on */ if (intel_modeset_probe_defer(pdev)) return -EPROBE_DEFER; diff --git a/drivers/gpu/drm/i915/i915_pci.h b/drivers/gpu/drm/i915/i915_pci.h index ee048c238174..8dfe19f9a775 100644 --- a/drivers/gpu/drm/i915/i915_pci.h +++ b/drivers/gpu/drm/i915/i915_pci.h @@ -6,7 +6,13 @@ #ifndef __I915_PCI_H__ #define __I915_PCI_H__ +#include <linux/types.h> + +struct pci_dev; + int i915_pci_register_driver(void); void i915_pci_unregister_driver(void); +bool i915_pci_resource_valid(struct pci_dev *pdev, int bar); + #endif /* __I915_PCI_H__ */ diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 3e3b09588fd3..958b37123bf1 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -1047,7 +1047,7 @@ static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) GEM_BUG_ON(!pmu->base.event_init); /* Select the first online CPU as a designated reader. */ - if (!cpumask_weight(&i915_pmu_cpumask)) + if (cpumask_empty(&i915_pmu_cpumask)) cpumask_set_cpu(cpu, &i915_pmu_cpumask); return 0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f44eec7f7a9c..8b1c1b527e9b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -115,7 +115,7 @@ * #define GEN8_BAR _MMIO(0xb888) */ -#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display_mmio_offset) +#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset) /* * Given the first two numbers __a and __b of arbitrarily many evenly spaced @@ -161,16 +161,15 @@ * Device info offset array based helpers for groups of registers with unevenly * spaced base offsets. */ -#define _MMIO_PIPE2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->pipe_offsets[pipe] - \ - INTEL_INFO(dev_priv)->pipe_offsets[PIPE_A] + (reg) + \ - DISPLAY_MMIO_BASE(dev_priv)) -#define _TRANS2(tran, reg) (INTEL_INFO(dev_priv)->trans_offsets[(tran)] - \ - INTEL_INFO(dev_priv)->trans_offsets[TRANSCODER_A] + (reg) + \ - DISPLAY_MMIO_BASE(dev_priv)) -#define _MMIO_TRANS2(tran, reg) _MMIO(_TRANS2(tran, reg)) -#define _CURSOR2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->cursor_offsets[(pipe)] - \ - INTEL_INFO(dev_priv)->cursor_offsets[PIPE_A] + (reg) + \ - DISPLAY_MMIO_BASE(dev_priv)) +#define _MMIO_PIPE2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.pipe_offsets[(pipe)] - \ + INTEL_INFO(dev_priv)->display.pipe_offsets[PIPE_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) +#define _MMIO_TRANS2(tran, reg) _MMIO(INTEL_INFO(dev_priv)->display.trans_offsets[(tran)] - \ + INTEL_INFO(dev_priv)->display.trans_offsets[TRANSCODER_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) +#define _MMIO_CURSOR2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.cursor_offsets[(pipe)] - \ + INTEL_INFO(dev_priv)->display.cursor_offsets[PIPE_A] + \ + DISPLAY_MMIO_BASE(dev_priv) + (reg)) #define __MASKED_FIELD(mask, value) ((mask) << 16 | (value)) #define _MASKED_FIELD(mask, value) ({ \ @@ -1465,7 +1464,7 @@ /* * GPIO regs */ -#define GPIO(gpio) _MMIO(dev_priv->gpio_mmio_base + 0x5010 + \ +#define GPIO(gpio) _MMIO(dev_priv->display.gmbus.mmio_base + 0x5010 + \ 4 * (gpio)) # define GPIO_CLOCK_DIR_MASK (1 << 0) @@ -1483,7 +1482,7 @@ # define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_PULLUP_DISABLE (1 << 13) -#define GMBUS0 _MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */ +#define GMBUS0 _MMIO(dev_priv->display.gmbus.mmio_base + 0x5100) /* clock/port select */ #define GMBUS_AKSV_SELECT (1 << 11) #define GMBUS_RATE_100KHZ (0 << 8) #define GMBUS_RATE_50KHZ (1 << 8) @@ -1492,7 +1491,7 @@ #define GMBUS_HOLD_EXT (1 << 7) /* 300ns hold time, rsvd on Pineview */ #define GMBUS_BYTE_CNT_OVERRIDE (1 << 6) -#define GMBUS1 _MMIO(dev_priv->gpio_mmio_base + 0x5104) /* command/status */ +#define GMBUS1 _MMIO(dev_priv->display.gmbus.mmio_base + 0x5104) /* command/status */ #define GMBUS_SW_CLR_INT (1 << 31) #define GMBUS_SW_RDY (1 << 30) #define GMBUS_ENT (1 << 29) /* enable timeout */ @@ -1507,7 +1506,7 @@ #define GMBUS_SLAVE_ADDR_SHIFT 1 #define GMBUS_SLAVE_READ (1 << 0) #define GMBUS_SLAVE_WRITE (0 << 0) -#define GMBUS2 _MMIO(dev_priv->gpio_mmio_base + 0x5108) /* status */ +#define GMBUS2 _MMIO(dev_priv->display.gmbus.mmio_base + 0x5108) /* status */ #define GMBUS_INUSE (1 << 15) #define GMBUS_HW_WAIT_PHASE (1 << 14) #define GMBUS_STALL_TIMEOUT (1 << 13) @@ -1515,14 +1514,14 @@ #define GMBUS_HW_RDY (1 << 11) #define GMBUS_SATOER (1 << 10) #define GMBUS_ACTIVE (1 << 9) -#define GMBUS3 _MMIO(dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */ -#define GMBUS4 _MMIO(dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */ +#define GMBUS3 _MMIO(dev_priv->display.gmbus.mmio_base + 0x510c) /* data buffer bytes 3-0 */ +#define GMBUS4 _MMIO(dev_priv->display.gmbus.mmio_base + 0x5110) /* interrupt mask (Pineview+) */ #define GMBUS_SLAVE_TIMEOUT_EN (1 << 4) #define GMBUS_NAK_EN (1 << 3) #define GMBUS_IDLE_EN (1 << 2) #define GMBUS_HW_WAIT_EN (1 << 1) #define GMBUS_HW_RDY_EN (1 << 0) -#define GMBUS5 _MMIO(dev_priv->gpio_mmio_base + 0x5120) /* byte index */ +#define GMBUS5 _MMIO(dev_priv->display.gmbus.mmio_base + 0x5120) /* byte index */ #define GMBUS_2BYTE_INDEX_EN (1 << 31) /* @@ -1917,6 +1916,13 @@ #define CLKGATE_DIS_PSL(pipe) \ _MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_A, _CLKGATE_DIS_PSL_B) +#define _CLKGATE_DIS_PSL_EXT_A 0x4654C +#define _CLKGATE_DIS_PSL_EXT_B 0x46550 +#define PIPEDMC_GATING_DIS REG_BIT(12) + +#define CLKGATE_DIS_PSL_EXT(pipe) \ + _MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_EXT_A, _CLKGATE_DIS_PSL_EXT_B) + /* * Display engine regs */ @@ -2171,7 +2177,7 @@ */ #define _SRD_CTL_A 0x60800 #define _SRD_CTL_EDP 0x6f800 -#define EDP_PSR_CTL(tran) _MMIO(_TRANS2(tran, _SRD_CTL_A)) +#define EDP_PSR_CTL(tran) _MMIO_TRANS2(tran, _SRD_CTL_A) #define EDP_PSR_ENABLE (1 << 31) #define BDW_PSR_SINGLE_FRAME (1 << 30) #define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK (1 << 29) /* SW can't modify */ @@ -2217,11 +2223,11 @@ #define _SRD_AUX_DATA_A 0x60814 #define _SRD_AUX_DATA_EDP 0x6f814 -#define EDP_PSR_AUX_DATA(tran, i) _MMIO(_TRANS2(tran, _SRD_AUX_DATA_A) + (i) + 4) /* 5 registers */ +#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) + 4) /* 5 registers */ #define _SRD_STATUS_A 0x60840 #define _SRD_STATUS_EDP 0x6f840 -#define EDP_PSR_STATUS(tran) _MMIO(_TRANS2(tran, _SRD_STATUS_A)) +#define EDP_PSR_STATUS(tran) _MMIO_TRANS2(tran, _SRD_STATUS_A) #define EDP_PSR_STATUS_STATE_MASK (7 << 29) #define EDP_PSR_STATUS_STATE_SHIFT 29 #define EDP_PSR_STATUS_STATE_IDLE (0 << 29) @@ -2248,13 +2254,13 @@ #define _SRD_PERF_CNT_A 0x60844 #define _SRD_PERF_CNT_EDP 0x6f844 -#define EDP_PSR_PERF_CNT(tran) _MMIO(_TRANS2(tran, _SRD_PERF_CNT_A)) +#define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(tran, _SRD_PERF_CNT_A) #define EDP_PSR_PERF_CNT_MASK 0xffffff /* PSR_MASK on SKL+ */ #define _SRD_DEBUG_A 0x60860 #define _SRD_DEBUG_EDP 0x6f860 -#define EDP_PSR_DEBUG(tran) _MMIO(_TRANS2(tran, _SRD_DEBUG_A)) +#define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(tran, _SRD_DEBUG_A) #define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1 << 28) #define EDP_PSR_DEBUG_MASK_LPSP (1 << 27) #define EDP_PSR_DEBUG_MASK_MEMUP (1 << 26) @@ -2329,7 +2335,7 @@ #define _PSR2_SU_STATUS_A 0x60914 #define _PSR2_SU_STATUS_EDP 0x6f914 -#define _PSR2_SU_STATUS(tran, index) _MMIO(_TRANS2(tran, _PSR2_SU_STATUS_A) + (index) * 4) +#define _PSR2_SU_STATUS(tran, index) _MMIO_TRANS2(tran, _PSR2_SU_STATUS_A + (index) * 4) #define PSR2_SU_STATUS(tran, frame) (_PSR2_SU_STATUS(tran, (frame) / 3)) #define PSR2_SU_STATUS_SHIFT(frame) (((frame) % 3) * 10) #define PSR2_SU_STATUS_MASK(frame) (0x3ff << PSR2_SU_STATUS_SHIFT(frame)) @@ -2823,7 +2829,7 @@ #define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) #define PCH_PPS_BASE 0xC7200 -#define _MMIO_PPS(pps_idx, reg) _MMIO(dev_priv->pps_mmio_base - \ +#define _MMIO_PPS(pps_idx, reg) _MMIO(dev_priv->display.pps.mmio_base - \ PPS_BASE + (reg) + \ (pps_idx) * 0x100) @@ -2919,118 +2925,6 @@ #define PFIT_AUTO_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61238) -#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250) -#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350) -#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ - _VLV_BLC_PWM_CTL2_B) - -#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254) -#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354) -#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ - _VLV_BLC_PWM_CTL_B) - -#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260) -#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360) -#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ - _VLV_BLC_HIST_CTL_B) - -/* Backlight control */ -#define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */ -#define BLM_PWM_ENABLE (1 << 31) -#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ -#define BLM_PIPE_SELECT (1 << 29) -#define BLM_PIPE_SELECT_IVB (3 << 29) -#define BLM_PIPE_A (0 << 29) -#define BLM_PIPE_B (1 << 29) -#define BLM_PIPE_C (2 << 29) /* ivb + */ -#define BLM_TRANSCODER_A BLM_PIPE_A /* hsw */ -#define BLM_TRANSCODER_B BLM_PIPE_B -#define BLM_TRANSCODER_C BLM_PIPE_C -#define BLM_TRANSCODER_EDP (3 << 29) -#define BLM_PIPE(pipe) ((pipe) << 29) -#define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ -#define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) -#define BLM_PHASE_IN_ENABLE (1 << 25) -#define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) -#define BLM_PHASE_IN_TIME_BASE_SHIFT (16) -#define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) -#define BLM_PHASE_IN_COUNT_SHIFT (8) -#define BLM_PHASE_IN_COUNT_MASK (0xff << 8) -#define BLM_PHASE_IN_INCR_SHIFT (0) -#define BLM_PHASE_IN_INCR_MASK (0xff << 0) -#define BLC_PWM_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254) -/* - * This is the most significant 15 bits of the number of backlight cycles in a - * complete cycle of the modulated backlight control. - * - * The actual value is this field multiplied by two. - */ -#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) -#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) -#define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ -/* - * This is the number of cycles out of the backlight modulation cycle for which - * the backlight is on. - * - * This field must be no greater than the number of cycles in the complete - * backlight modulation cycle. - */ -#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) -#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) -#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) -#define BLM_POLARITY_PNV (1 << 0) /* pnv only */ - -#define BLC_HIST_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260) -#define BLM_HISTOGRAM_ENABLE (1 << 31) - -/* New registers for PCH-split platforms. Safe where new bits show up, the - * register layout machtes with gen4 BLC_PWM_CTL[12]. */ -#define BLC_PWM_CPU_CTL2 _MMIO(0x48250) -#define BLC_PWM_CPU_CTL _MMIO(0x48254) - -#define HSW_BLC_PWM2_CTL _MMIO(0x48350) - -/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is - * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ -#define BLC_PWM_PCH_CTL1 _MMIO(0xc8250) -#define BLM_PCH_PWM_ENABLE (1 << 31) -#define BLM_PCH_OVERRIDE_ENABLE (1 << 30) -#define BLM_PCH_POLARITY (1 << 29) -#define BLC_PWM_PCH_CTL2 _MMIO(0xc8254) - -#define UTIL_PIN_CTL _MMIO(0x48400) -#define UTIL_PIN_ENABLE (1 << 31) -#define UTIL_PIN_PIPE_MASK (3 << 29) -#define UTIL_PIN_PIPE(x) ((x) << 29) -#define UTIL_PIN_MODE_MASK (0xf << 24) -#define UTIL_PIN_MODE_DATA (0 << 24) -#define UTIL_PIN_MODE_PWM (1 << 24) -#define UTIL_PIN_MODE_VBLANK (4 << 24) -#define UTIL_PIN_MODE_VSYNC (5 << 24) -#define UTIL_PIN_MODE_EYE_LEVEL (8 << 24) -#define UTIL_PIN_OUTPUT_DATA (1 << 23) -#define UTIL_PIN_POLARITY (1 << 22) -#define UTIL_PIN_DIRECTION_INPUT (1 << 19) -#define UTIL_PIN_INPUT_DATA (1 << 16) - -/* BXT backlight register definition. */ -#define _BXT_BLC_PWM_CTL1 0xC8250 -#define BXT_BLC_PWM_ENABLE (1 << 31) -#define BXT_BLC_PWM_POLARITY (1 << 29) -#define _BXT_BLC_PWM_FREQ1 0xC8254 -#define _BXT_BLC_PWM_DUTY1 0xC8258 - -#define _BXT_BLC_PWM_CTL2 0xC8350 -#define _BXT_BLC_PWM_FREQ2 0xC8354 -#define _BXT_BLC_PWM_DUTY2 0xC8358 - -#define BXT_BLC_PWM_CTL(controller) _MMIO_PIPE(controller, \ - _BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2) -#define BXT_BLC_PWM_FREQ(controller) _MMIO_PIPE(controller, \ - _BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2) -#define BXT_BLC_PWM_DUTY(controller) _MMIO_PIPE(controller, \ - _BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2) - #define PCH_GTC_CTL _MMIO(0xe7000) #define PCH_GTC_ENABLE (1 << 31) @@ -4328,12 +4222,12 @@ #define _CURBBASE_IVB 0x71084 #define _CURBPOS_IVB 0x71088 -#define CURCNTR(pipe) _CURSOR2(pipe, _CURACNTR) -#define CURBASE(pipe) _CURSOR2(pipe, _CURABASE) -#define CURPOS(pipe) _CURSOR2(pipe, _CURAPOS) -#define CURSIZE(pipe) _CURSOR2(pipe, _CURASIZE) -#define CUR_FBC_CTL(pipe) _CURSOR2(pipe, _CUR_FBC_CTL_A) -#define CURSURFLIVE(pipe) _CURSOR2(pipe, _CURASURFLIVE) +#define CURCNTR(pipe) _MMIO_CURSOR2(pipe, _CURACNTR) +#define CURBASE(pipe) _MMIO_CURSOR2(pipe, _CURABASE) +#define CURPOS(pipe) _MMIO_CURSOR2(pipe, _CURAPOS) +#define CURSIZE(pipe) _MMIO_CURSOR2(pipe, _CURASIZE) +#define CUR_FBC_CTL(pipe) _MMIO_CURSOR2(pipe, _CUR_FBC_CTL_A) +#define CURSURFLIVE(pipe) _MMIO_CURSOR2(pipe, _CURASURFLIVE) #define CURSOR_A_OFFSET 0x70080 #define CURSOR_B_OFFSET 0x700c0 @@ -4408,7 +4302,7 @@ #define DSPLINOFF(plane) DSPADDR(plane) #define DSPOFFSET(plane) _MMIO_PIPE2(plane, _DSPAOFFSET) #define DSPSURFLIVE(plane) _MMIO_PIPE2(plane, _DSPASURFLIVE) -#define DSPGAMC(plane, i) _MMIO(_PIPE2(plane, _DSPAGAMC) + (5 - (i)) * 4) /* plane C only, 6 x u0.8 */ +#define DSPGAMC(plane, i) _MMIO_PIPE2(plane, _DSPAGAMC + (5 - (i)) * 4) /* plane C only, 6 x u0.8 */ /* CHV pipe B blender and primary plane */ #define _CHV_BLEND_A 0x60a00 @@ -5927,7 +5821,8 @@ _BW_BUDDY1_PAGE_MASK)) #define HSW_NDE_RSTWRN_OPT _MMIO(0x46408) -#define RESET_PCH_HANDSHAKE_ENABLE (1 << 4) +#define MTL_RESET_PICA_HANDSHAKE_EN REG_BIT(6) +#define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) #define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30) @@ -6794,163 +6689,12 @@ (((reg) & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) #define GEN7_L3CDERRST1_ENABLE (1 << 7) -/* Audio */ -#define G4X_AUD_VID_DID _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x62020) -#define INTEL_AUDIO_DEVCL 0x808629FB -#define INTEL_AUDIO_DEVBLC 0x80862801 -#define INTEL_AUDIO_DEVCTG 0x80862802 - -#define G4X_AUD_CNTL_ST _MMIO(0x620B4) -#define G4X_ELDV_DEVCL_DEVBLC (1 << 13) -#define G4X_ELDV_DEVCTG (1 << 14) -#define G4X_ELD_ADDR_MASK (0xf << 5) -#define G4X_ELD_ACK (1 << 4) -#define G4X_HDMIW_HDMIEDID _MMIO(0x6210C) - -#define _IBX_HDMIW_HDMIEDID_A 0xE2050 -#define _IBX_HDMIW_HDMIEDID_B 0xE2150 -#define IBX_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _IBX_HDMIW_HDMIEDID_A, \ - _IBX_HDMIW_HDMIEDID_B) -#define _IBX_AUD_CNTL_ST_A 0xE20B4 -#define _IBX_AUD_CNTL_ST_B 0xE21B4 -#define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \ - _IBX_AUD_CNTL_ST_B) -#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10) -#define IBX_ELD_ADDRESS_MASK (0x1f << 5) -#define IBX_ELD_ACK (1 << 4) -#define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0) -#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4)) -#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4)) - -#define _CPT_HDMIW_HDMIEDID_A 0xE5050 -#define _CPT_HDMIW_HDMIEDID_B 0xE5150 -#define CPT_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _CPT_HDMIW_HDMIEDID_A, _CPT_HDMIW_HDMIEDID_B) -#define _CPT_AUD_CNTL_ST_A 0xE50B4 -#define _CPT_AUD_CNTL_ST_B 0xE51B4 -#define CPT_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CNTL_ST_A, _CPT_AUD_CNTL_ST_B) -#define CPT_AUD_CNTRL_ST2 _MMIO(0xE50C0) - -#define _VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050) -#define _VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150) -#define VLV_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _VLV_HDMIW_HDMIEDID_A, _VLV_HDMIW_HDMIEDID_B) -#define _VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4) -#define _VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4) -#define VLV_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CNTL_ST_A, _VLV_AUD_CNTL_ST_B) -#define VLV_AUD_CNTL_ST2 _MMIO(VLV_DISPLAY_BASE + 0x620C0) - /* These are the 4 32-bit write offset registers for each stream * output buffer. It determines the offset from the * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. */ #define GEN7_SO_WRITE_OFFSET(n) _MMIO(0x5280 + (n) * 4) -#define _IBX_AUD_CONFIG_A 0xe2000 -#define _IBX_AUD_CONFIG_B 0xe2100 -#define IBX_AUD_CFG(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CONFIG_A, _IBX_AUD_CONFIG_B) -#define _CPT_AUD_CONFIG_A 0xe5000 -#define _CPT_AUD_CONFIG_B 0xe5100 -#define CPT_AUD_CFG(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CONFIG_A, _CPT_AUD_CONFIG_B) -#define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000) -#define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100) -#define VLV_AUD_CFG(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CONFIG_A, _VLV_AUD_CONFIG_B) - -#define AUD_CONFIG_N_VALUE_INDEX (1 << 29) -#define AUD_CONFIG_N_PROG_ENABLE (1 << 28) -#define AUD_CONFIG_UPPER_N_SHIFT 20 -#define AUD_CONFIG_UPPER_N_MASK (0xff << 20) -#define AUD_CONFIG_LOWER_N_SHIFT 4 -#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) -#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK) -#define AUD_CONFIG_N(n) \ - (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \ - (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT)) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 (10 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 (11 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 (12 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 (13 << 16) -#define AUD_CONFIG_DISABLE_NCTS (1 << 3) - -/* HSW Audio */ -#define _HSW_AUD_CONFIG_A 0x65000 -#define _HSW_AUD_CONFIG_B 0x65100 -#define HSW_AUD_CFG(trans) _MMIO_TRANS(trans, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B) - -#define _HSW_AUD_MISC_CTRL_A 0x65010 -#define _HSW_AUD_MISC_CTRL_B 0x65110 -#define HSW_AUD_MISC_CTRL(trans) _MMIO_TRANS(trans, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B) - -#define _HSW_AUD_M_CTS_ENABLE_A 0x65028 -#define _HSW_AUD_M_CTS_ENABLE_B 0x65128 -#define HSW_AUD_M_CTS_ENABLE(trans) _MMIO_TRANS(trans, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B) -#define AUD_M_CTS_M_VALUE_INDEX (1 << 21) -#define AUD_M_CTS_M_PROG_ENABLE (1 << 20) -#define AUD_CONFIG_M_MASK 0xfffff - -#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 -#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 -#define HSW_AUD_DIP_ELD_CTRL(trans) _MMIO_TRANS(trans, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B) - -/* Audio Digital Converter */ -#define _HSW_AUD_DIG_CNVT_1 0x65080 -#define _HSW_AUD_DIG_CNVT_2 0x65180 -#define AUD_DIG_CNVT(trans) _MMIO_TRANS(trans, _HSW_AUD_DIG_CNVT_1, _HSW_AUD_DIG_CNVT_2) -#define DIP_PORT_SEL_MASK 0x3 - -#define _HSW_AUD_EDID_DATA_A 0x65050 -#define _HSW_AUD_EDID_DATA_B 0x65150 -#define HSW_AUD_EDID_DATA(trans) _MMIO_TRANS(trans, _HSW_AUD_EDID_DATA_A, _HSW_AUD_EDID_DATA_B) - -#define HSW_AUD_PIPE_CONV_CFG _MMIO(0x6507c) -#define HSW_AUD_PIN_ELD_CP_VLD _MMIO(0x650c0) -#define AUDIO_INACTIVE(trans) ((1 << 3) << ((trans) * 4)) -#define AUDIO_OUTPUT_ENABLE(trans) ((1 << 2) << ((trans) * 4)) -#define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4)) -#define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4)) - -#define _AUD_TCA_DP_2DOT0_CTRL 0x650bc -#define _AUD_TCB_DP_2DOT0_CTRL 0x651bc -#define AUD_DP_2DOT0_CTRL(trans) _MMIO_TRANS(trans, _AUD_TCA_DP_2DOT0_CTRL, _AUD_TCB_DP_2DOT0_CTRL) -#define AUD_ENABLE_SDP_SPLIT REG_BIT(31) - -#define HSW_AUD_CHICKENBIT _MMIO(0x65f10) -#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) - -#define AUD_FREQ_CNTRL _MMIO(0x65900) -#define AUD_PIN_BUF_CTL _MMIO(0x48414) -#define AUD_PIN_BUF_ENABLE REG_BIT(31) - -#define AUD_TS_CDCLK_M _MMIO(0x65ea0) -#define AUD_TS_CDCLK_M_EN REG_BIT(31) -#define AUD_TS_CDCLK_N _MMIO(0x65ea4) - -/* Display Audio Config Reg */ -#define AUD_CONFIG_BE _MMIO(0x65ef0) -#define HBLANK_EARLY_ENABLE_ICL(pipe) (0x1 << (20 - (pipe))) -#define HBLANK_EARLY_ENABLE_TGL(pipe) (0x1 << (24 + (pipe))) -#define HBLANK_START_COUNT_MASK(pipe) (0x7 << (3 + ((pipe) * 6))) -#define HBLANK_START_COUNT(pipe, val) (((val) & 0x7) << (3 + ((pipe)) * 6)) -#define NUMBER_SAMPLES_PER_LINE_MASK(pipe) (0x3 << ((pipe) * 6)) -#define NUMBER_SAMPLES_PER_LINE(pipe, val) (((val) & 0x3) << ((pipe) * 6)) - -#define HBLANK_START_COUNT_8 0 -#define HBLANK_START_COUNT_16 1 -#define HBLANK_START_COUNT_32 2 -#define HBLANK_START_COUNT_64 3 -#define HBLANK_START_COUNT_96 4 -#define HBLANK_START_COUNT_128 5 - /* * HSW - ICL power wells * @@ -7089,265 +6833,6 @@ enum skl_power_gate { #define ICL_AUX_ANAOVRD1_LDO_BYPASS (1 << 7) #define ICL_AUX_ANAOVRD1_ENABLE (1 << 0) -/* HDCP Key Registers */ -#define HDCP_KEY_CONF _MMIO(0x66c00) -#define HDCP_AKSV_SEND_TRIGGER BIT(31) -#define HDCP_CLEAR_KEYS_TRIGGER BIT(30) -#define HDCP_KEY_LOAD_TRIGGER BIT(8) -#define HDCP_KEY_STATUS _MMIO(0x66c04) -#define HDCP_FUSE_IN_PROGRESS BIT(7) -#define HDCP_FUSE_ERROR BIT(6) -#define HDCP_FUSE_DONE BIT(5) -#define HDCP_KEY_LOAD_STATUS BIT(1) -#define HDCP_KEY_LOAD_DONE BIT(0) -#define HDCP_AKSV_LO _MMIO(0x66c10) -#define HDCP_AKSV_HI _MMIO(0x66c14) - -/* HDCP Repeater Registers */ -#define HDCP_REP_CTL _MMIO(0x66d00) -#define HDCP_TRANSA_REP_PRESENT BIT(31) -#define HDCP_TRANSB_REP_PRESENT BIT(30) -#define HDCP_TRANSC_REP_PRESENT BIT(29) -#define HDCP_TRANSD_REP_PRESENT BIT(28) -#define HDCP_DDIB_REP_PRESENT BIT(30) -#define HDCP_DDIA_REP_PRESENT BIT(29) -#define HDCP_DDIC_REP_PRESENT BIT(28) -#define HDCP_DDID_REP_PRESENT BIT(27) -#define HDCP_DDIF_REP_PRESENT BIT(26) -#define HDCP_DDIE_REP_PRESENT BIT(25) -#define HDCP_TRANSA_SHA1_M0 (1 << 20) -#define HDCP_TRANSB_SHA1_M0 (2 << 20) -#define HDCP_TRANSC_SHA1_M0 (3 << 20) -#define HDCP_TRANSD_SHA1_M0 (4 << 20) -#define HDCP_DDIB_SHA1_M0 (1 << 20) -#define HDCP_DDIA_SHA1_M0 (2 << 20) -#define HDCP_DDIC_SHA1_M0 (3 << 20) -#define HDCP_DDID_SHA1_M0 (4 << 20) -#define HDCP_DDIF_SHA1_M0 (5 << 20) -#define HDCP_DDIE_SHA1_M0 (6 << 20) /* Bspec says 5? */ -#define HDCP_SHA1_BUSY BIT(16) -#define HDCP_SHA1_READY BIT(17) -#define HDCP_SHA1_COMPLETE BIT(18) -#define HDCP_SHA1_V_MATCH BIT(19) -#define HDCP_SHA1_TEXT_32 (1 << 1) -#define HDCP_SHA1_COMPLETE_HASH (2 << 1) -#define HDCP_SHA1_TEXT_24 (4 << 1) -#define HDCP_SHA1_TEXT_16 (5 << 1) -#define HDCP_SHA1_TEXT_8 (6 << 1) -#define HDCP_SHA1_TEXT_0 (7 << 1) -#define HDCP_SHA_V_PRIME_H0 _MMIO(0x66d04) -#define HDCP_SHA_V_PRIME_H1 _MMIO(0x66d08) -#define HDCP_SHA_V_PRIME_H2 _MMIO(0x66d0C) -#define HDCP_SHA_V_PRIME_H3 _MMIO(0x66d10) -#define HDCP_SHA_V_PRIME_H4 _MMIO(0x66d14) -#define HDCP_SHA_V_PRIME(h) _MMIO((0x66d04 + (h) * 4)) -#define HDCP_SHA_TEXT _MMIO(0x66d18) - -/* HDCP Auth Registers */ -#define _PORTA_HDCP_AUTHENC 0x66800 -#define _PORTB_HDCP_AUTHENC 0x66500 -#define _PORTC_HDCP_AUTHENC 0x66600 -#define _PORTD_HDCP_AUTHENC 0x66700 -#define _PORTE_HDCP_AUTHENC 0x66A00 -#define _PORTF_HDCP_AUTHENC 0x66900 -#define _PORT_HDCP_AUTHENC(port, x) _MMIO(_PICK(port, \ - _PORTA_HDCP_AUTHENC, \ - _PORTB_HDCP_AUTHENC, \ - _PORTC_HDCP_AUTHENC, \ - _PORTD_HDCP_AUTHENC, \ - _PORTE_HDCP_AUTHENC, \ - _PORTF_HDCP_AUTHENC) + (x)) -#define PORT_HDCP_CONF(port) _PORT_HDCP_AUTHENC(port, 0x0) -#define _TRANSA_HDCP_CONF 0x66400 -#define _TRANSB_HDCP_CONF 0x66500 -#define TRANS_HDCP_CONF(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_CONF, \ - _TRANSB_HDCP_CONF) -#define HDCP_CONF(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_CONF(trans) : \ - PORT_HDCP_CONF(port)) - -#define HDCP_CONF_CAPTURE_AN BIT(0) -#define HDCP_CONF_AUTH_AND_ENC (BIT(1) | BIT(0)) -#define PORT_HDCP_ANINIT(port) _PORT_HDCP_AUTHENC(port, 0x4) -#define _TRANSA_HDCP_ANINIT 0x66404 -#define _TRANSB_HDCP_ANINIT 0x66504 -#define TRANS_HDCP_ANINIT(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP_ANINIT, \ - _TRANSB_HDCP_ANINIT) -#define HDCP_ANINIT(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_ANINIT(trans) : \ - PORT_HDCP_ANINIT(port)) - -#define PORT_HDCP_ANLO(port) _PORT_HDCP_AUTHENC(port, 0x8) -#define _TRANSA_HDCP_ANLO 0x66408 -#define _TRANSB_HDCP_ANLO 0x66508 -#define TRANS_HDCP_ANLO(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANLO, \ - _TRANSB_HDCP_ANLO) -#define HDCP_ANLO(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_ANLO(trans) : \ - PORT_HDCP_ANLO(port)) - -#define PORT_HDCP_ANHI(port) _PORT_HDCP_AUTHENC(port, 0xC) -#define _TRANSA_HDCP_ANHI 0x6640C -#define _TRANSB_HDCP_ANHI 0x6650C -#define TRANS_HDCP_ANHI(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANHI, \ - _TRANSB_HDCP_ANHI) -#define HDCP_ANHI(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_ANHI(trans) : \ - PORT_HDCP_ANHI(port)) - -#define PORT_HDCP_BKSVLO(port) _PORT_HDCP_AUTHENC(port, 0x10) -#define _TRANSA_HDCP_BKSVLO 0x66410 -#define _TRANSB_HDCP_BKSVLO 0x66510 -#define TRANS_HDCP_BKSVLO(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP_BKSVLO, \ - _TRANSB_HDCP_BKSVLO) -#define HDCP_BKSVLO(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_BKSVLO(trans) : \ - PORT_HDCP_BKSVLO(port)) - -#define PORT_HDCP_BKSVHI(port) _PORT_HDCP_AUTHENC(port, 0x14) -#define _TRANSA_HDCP_BKSVHI 0x66414 -#define _TRANSB_HDCP_BKSVHI 0x66514 -#define TRANS_HDCP_BKSVHI(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP_BKSVHI, \ - _TRANSB_HDCP_BKSVHI) -#define HDCP_BKSVHI(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_BKSVHI(trans) : \ - PORT_HDCP_BKSVHI(port)) - -#define PORT_HDCP_RPRIME(port) _PORT_HDCP_AUTHENC(port, 0x18) -#define _TRANSA_HDCP_RPRIME 0x66418 -#define _TRANSB_HDCP_RPRIME 0x66518 -#define TRANS_HDCP_RPRIME(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP_RPRIME, \ - _TRANSB_HDCP_RPRIME) -#define HDCP_RPRIME(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_RPRIME(trans) : \ - PORT_HDCP_RPRIME(port)) - -#define PORT_HDCP_STATUS(port) _PORT_HDCP_AUTHENC(port, 0x1C) -#define _TRANSA_HDCP_STATUS 0x6641C -#define _TRANSB_HDCP_STATUS 0x6651C -#define TRANS_HDCP_STATUS(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP_STATUS, \ - _TRANSB_HDCP_STATUS) -#define HDCP_STATUS(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP_STATUS(trans) : \ - PORT_HDCP_STATUS(port)) - -#define HDCP_STATUS_STREAM_A_ENC BIT(31) -#define HDCP_STATUS_STREAM_B_ENC BIT(30) -#define HDCP_STATUS_STREAM_C_ENC BIT(29) -#define HDCP_STATUS_STREAM_D_ENC BIT(28) -#define HDCP_STATUS_AUTH BIT(21) -#define HDCP_STATUS_ENC BIT(20) -#define HDCP_STATUS_RI_MATCH BIT(19) -#define HDCP_STATUS_R0_READY BIT(18) -#define HDCP_STATUS_AN_READY BIT(17) -#define HDCP_STATUS_CIPHER BIT(16) -#define HDCP_STATUS_FRAME_CNT(x) (((x) >> 8) & 0xff) - -/* HDCP2.2 Registers */ -#define _PORTA_HDCP2_BASE 0x66800 -#define _PORTB_HDCP2_BASE 0x66500 -#define _PORTC_HDCP2_BASE 0x66600 -#define _PORTD_HDCP2_BASE 0x66700 -#define _PORTE_HDCP2_BASE 0x66A00 -#define _PORTF_HDCP2_BASE 0x66900 -#define _PORT_HDCP2_BASE(port, x) _MMIO(_PICK((port), \ - _PORTA_HDCP2_BASE, \ - _PORTB_HDCP2_BASE, \ - _PORTC_HDCP2_BASE, \ - _PORTD_HDCP2_BASE, \ - _PORTE_HDCP2_BASE, \ - _PORTF_HDCP2_BASE) + (x)) - -#define PORT_HDCP2_AUTH(port) _PORT_HDCP2_BASE(port, 0x98) -#define _TRANSA_HDCP2_AUTH 0x66498 -#define _TRANSB_HDCP2_AUTH 0x66598 -#define TRANS_HDCP2_AUTH(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_AUTH, \ - _TRANSB_HDCP2_AUTH) -#define AUTH_LINK_AUTHENTICATED BIT(31) -#define AUTH_LINK_TYPE BIT(30) -#define AUTH_FORCE_CLR_INPUTCTR BIT(19) -#define AUTH_CLR_KEYS BIT(18) -#define HDCP2_AUTH(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP2_AUTH(trans) : \ - PORT_HDCP2_AUTH(port)) - -#define PORT_HDCP2_CTL(port) _PORT_HDCP2_BASE(port, 0xB0) -#define _TRANSA_HDCP2_CTL 0x664B0 -#define _TRANSB_HDCP2_CTL 0x665B0 -#define TRANS_HDCP2_CTL(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_CTL, \ - _TRANSB_HDCP2_CTL) -#define CTL_LINK_ENCRYPTION_REQ BIT(31) -#define HDCP2_CTL(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP2_CTL(trans) : \ - PORT_HDCP2_CTL(port)) - -#define PORT_HDCP2_STATUS(port) _PORT_HDCP2_BASE(port, 0xB4) -#define _TRANSA_HDCP2_STATUS 0x664B4 -#define _TRANSB_HDCP2_STATUS 0x665B4 -#define TRANS_HDCP2_STATUS(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP2_STATUS, \ - _TRANSB_HDCP2_STATUS) -#define LINK_TYPE_STATUS BIT(22) -#define LINK_AUTH_STATUS BIT(21) -#define LINK_ENCRYPTION_STATUS BIT(20) -#define HDCP2_STATUS(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP2_STATUS(trans) : \ - PORT_HDCP2_STATUS(port)) - -#define _PIPEA_HDCP2_STREAM_STATUS 0x668C0 -#define _PIPEB_HDCP2_STREAM_STATUS 0x665C0 -#define _PIPEC_HDCP2_STREAM_STATUS 0x666C0 -#define _PIPED_HDCP2_STREAM_STATUS 0x667C0 -#define PIPE_HDCP2_STREAM_STATUS(pipe) _MMIO(_PICK((pipe), \ - _PIPEA_HDCP2_STREAM_STATUS, \ - _PIPEB_HDCP2_STREAM_STATUS, \ - _PIPEC_HDCP2_STREAM_STATUS, \ - _PIPED_HDCP2_STREAM_STATUS)) - -#define _TRANSA_HDCP2_STREAM_STATUS 0x664C0 -#define _TRANSB_HDCP2_STREAM_STATUS 0x665C0 -#define TRANS_HDCP2_STREAM_STATUS(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP2_STREAM_STATUS, \ - _TRANSB_HDCP2_STREAM_STATUS) -#define STREAM_ENCRYPTION_STATUS BIT(31) -#define STREAM_TYPE_STATUS BIT(30) -#define HDCP2_STREAM_STATUS(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP2_STREAM_STATUS(trans) : \ - PIPE_HDCP2_STREAM_STATUS(pipe)) - -#define _PORTA_HDCP2_AUTH_STREAM 0x66F00 -#define _PORTB_HDCP2_AUTH_STREAM 0x66F04 -#define PORT_HDCP2_AUTH_STREAM(port) _MMIO_PORT(port, \ - _PORTA_HDCP2_AUTH_STREAM, \ - _PORTB_HDCP2_AUTH_STREAM) -#define _TRANSA_HDCP2_AUTH_STREAM 0x66F00 -#define _TRANSB_HDCP2_AUTH_STREAM 0x66F04 -#define TRANS_HDCP2_AUTH_STREAM(trans) _MMIO_TRANS(trans, \ - _TRANSA_HDCP2_AUTH_STREAM, \ - _TRANSB_HDCP2_AUTH_STREAM) -#define AUTH_STREAM_TYPE BIT(31) -#define HDCP2_AUTH_STREAM(dev_priv, trans, port) \ - (GRAPHICS_VER(dev_priv) >= 12 ? \ - TRANS_HDCP2_AUTH_STREAM(trans) : \ - PORT_HDCP2_AUTH_STREAM(port)) - /* Per-pipe DDI Function Control */ #define _TRANS_DDI_FUNC_CTL_A 0x60400 #define _TRANS_DDI_FUNC_CTL_B 0x61400 @@ -8519,6 +8004,7 @@ enum skl_power_gate { #define ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PC) +#define DSC_ALT_ICH_SEL (1 << 20) #define DSC_VBR_ENABLE (1 << 19) #define DSC_422_ENABLE (1 << 18) #define DSC_COLOR_SPACE_CONVERSION (1 << 17) @@ -8869,4 +8355,10 @@ enum skl_power_gate { #define GEN12_CULLBIT2 _MMIO(0x7030) #define GEN12_STATE_ACK_DEBUG _MMIO(0x20BC) +#define MTL_LATENCY_LP0_LP1 _MMIO(0x45780) +#define MTL_LATENCY_LP2_LP3 _MMIO(0x45784) +#define MTL_LATENCY_LP4_LP5 _MMIO(0x45788) +#define MTL_LATENCY_LEVEL_EVEN_MASK REG_GENMASK(12, 0) +#define MTL_LATENCY_LEVEL_ODD_MASK REG_GENMASK(28, 16) + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h index 0b9b86af6c7f..c229c91071d7 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.h +++ b/drivers/gpu/drm/i915/i915_scheduler.h @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include "i915_scheduler_types.h" +#include "i915_tasklet.h" struct drm_printer; diff --git a/drivers/gpu/drm/i915/i915_tasklet.h b/drivers/gpu/drm/i915/i915_tasklet.h new file mode 100644 index 000000000000..5d7069bdf2c0 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_tasklet.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __I915_TASKLET_H__ +#define __I915_TASKLET_H__ + +#include <linux/interrupt.h> + +static inline void tasklet_lock(struct tasklet_struct *t) +{ + while (!tasklet_trylock(t)) + cpu_relax(); +} + +static inline bool tasklet_is_locked(const struct tasklet_struct *t) +{ + return test_bit(TASKLET_STATE_RUN, &t->state); +} + +static inline void __tasklet_disable_sync_once(struct tasklet_struct *t) +{ + if (!atomic_fetch_inc(&t->count)) + tasklet_unlock_spin_wait(t); +} + +static inline bool __tasklet_is_enabled(const struct tasklet_struct *t) +{ + return !atomic_read(&t->count); +} + +static inline bool __tasklet_enable(struct tasklet_struct *t) +{ + return atomic_dec_and_test(&t->count); +} + +static inline bool __tasklet_is_scheduled(struct tasklet_struct *t) +{ + return test_bit(TASKLET_STATE_SCHED, &t->state); +} + +#endif /* __I915_TASKLET_H__ */ diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index 427de1aaab36..e19452f0e100 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -173,6 +173,77 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, kfree(bman_res); } +static bool i915_ttm_buddy_man_intersects(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct drm_buddy *mm = &bman->mm; + struct drm_buddy_block *block; + + if (!place->fpfn && !place->lpfn) + return true; + + GEM_BUG_ON(!place->lpfn); + + /* + * If we just want something mappable then we can quickly check + * if the current victim resource is using any of the CPU + * visible portion. + */ + if (!place->fpfn && + place->lpfn == i915_ttm_buddy_man_visible_size(man)) + return bman_res->used_visible_size > 0; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &bman_res->blocks, link) { + unsigned long fpfn = + drm_buddy_block_offset(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + + if (place->fpfn < lpfn && place->lpfn > fpfn) + return true; + } + + return false; +} + +static bool i915_ttm_buddy_man_compatible(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct drm_buddy *mm = &bman->mm; + struct drm_buddy_block *block; + + if (!place->fpfn && !place->lpfn) + return true; + + GEM_BUG_ON(!place->lpfn); + + if (!place->fpfn && + place->lpfn == i915_ttm_buddy_man_visible_size(man)) + return bman_res->used_visible_size == res->num_pages; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, &bman_res->blocks, link) { + unsigned long fpfn = + drm_buddy_block_offset(block) >> PAGE_SHIFT; + unsigned long lpfn = fpfn + + (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + + if (fpfn < place->fpfn || lpfn > place->lpfn) + return false; + } + + return true; +} + static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { @@ -200,6 +271,8 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { .alloc = i915_ttm_buddy_man_alloc, .free = i915_ttm_buddy_man_free, + .intersects = i915_ttm_buddy_man_intersects, + .compatible = i915_ttm_buddy_man_compatible, .debug = i915_ttm_buddy_man_debug, }; diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index ea7648e3aa0e..6c14d13364bf 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -115,39 +115,6 @@ bool i915_error_injected(void); #define overflows_type(x, T) \ (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) -static inline bool -__check_struct_size(size_t base, size_t arr, size_t count, size_t *size) -{ - size_t sz; - - if (check_mul_overflow(count, arr, &sz)) - return false; - - if (check_add_overflow(sz, base, &sz)) - return false; - - *size = sz; - return true; -} - -/** - * check_struct_size() - Calculate size of structure with trailing array. - * @p: Pointer to the structure. - * @member: Name of the array member. - * @n: Number of elements in the array. - * @sz: Total size of structure and array - * - * Calculates size of memory needed for structure @p followed by an - * array of @n @member elements, like struct_size() but reports - * whether it overflowed, and the resultant size in @sz - * - * Return: false if the calculation overflowed. - */ -#define check_struct_size(p, member, n, sz) \ - likely(__check_struct_size(sizeof(*(p)), \ - sizeof(*(p)->member) + __must_be_array((p)->member), \ - n, sz)) - #define ptr_mask_bits(ptr, n) ({ \ unsigned long __v = (unsigned long)(ptr); \ (typeof(ptr))(__v & -BIT(n)); \ @@ -184,8 +151,6 @@ __check_struct_size(size_t base, size_t arr, size_t count, size_t *size) #define struct_member(T, member) (((T *)0)->member) -#define ptr_offset(ptr, member) offsetof(typeof(*(ptr)), member) - #define fetch_and_zero(ptr) ({ \ typeof(*ptr) __T = *(ptr); \ *(ptr) = (typeof(*ptr))0; \ @@ -228,11 +193,6 @@ static __always_inline ptrdiff_t ptrdiff(const void *a, const void *b) get_user(mbz__, (U)) ? -EFAULT : mbz__ ? -EINVAL : 0; \ }) -static inline u64 ptr_to_u64(const void *ptr) -{ - return (uintptr_t)ptr; -} - #define u64_to_ptr(T, x) ({ \ typecheck(u64, x); \ (T *)(uintptr_t)(x); \ @@ -400,10 +360,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) #define KHz(x) (1000 * (x)) #define MHz(x) KHz(1000 * (x)) -#define KBps(x) (1000 * (x)) -#define MBps(x) KBps(1000 * (x)) -#define GBps(x) ((u64)1000 * MBps((x))) - void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint); static inline void __add_taint_for_CI(unsigned int taint) { diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index d98fbbd589aa..0a1f97b35f2b 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -88,14 +88,15 @@ const char *intel_platform_name(enum intel_platform platform) return platform_names[platform]; } -void intel_device_info_print_static(const struct intel_device_info *info, - struct drm_printer *p) +void intel_device_info_print(const struct intel_device_info *info, + const struct intel_runtime_info *runtime, + struct drm_printer *p) { - if (info->graphics.rel) - drm_printf(p, "graphics version: %u.%02u\n", info->graphics.ver, - info->graphics.rel); + if (runtime->graphics.rel) + drm_printf(p, "graphics version: %u.%02u\n", runtime->graphics.ver, + runtime->graphics.rel); else - drm_printf(p, "graphics version: %u\n", info->graphics.ver); + drm_printf(p, "graphics version: %u\n", runtime->graphics.ver); if (info->media.rel) drm_printf(p, "media version: %u.%02u\n", info->media.ver, info->media.rel); @@ -108,26 +109,28 @@ void intel_device_info_print_static(const struct intel_device_info *info, drm_printf(p, "display version: %u\n", info->display.ver); drm_printf(p, "gt: %d\n", info->gt); - drm_printf(p, "memory-regions: %x\n", info->memory_regions); - drm_printf(p, "page-sizes: %x\n", info->page_sizes); + drm_printf(p, "memory-regions: %x\n", runtime->memory_regions); + drm_printf(p, "page-sizes: %x\n", runtime->page_sizes); drm_printf(p, "platform: %s\n", intel_platform_name(info->platform)); - drm_printf(p, "ppgtt-size: %d\n", info->ppgtt_size); - drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type); + drm_printf(p, "ppgtt-size: %d\n", runtime->ppgtt_size); + drm_printf(p, "ppgtt-type: %d\n", runtime->ppgtt_type); drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size); #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name)) DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG + drm_printf(p, "has_pooled_eu: %s\n", str_yes_no(runtime->has_pooled_eu)); + #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display.name)) DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG -} -void intel_device_info_print_runtime(const struct intel_runtime_info *info, - struct drm_printer *p) -{ - drm_printf(p, "rawclk rate: %u kHz\n", info->rawclk_freq); + drm_printf(p, "has_hdcp: %s\n", str_yes_no(runtime->has_hdcp)); + drm_printf(p, "has_dmc: %s\n", str_yes_no(runtime->has_dmc)); + drm_printf(p, "has_dsc: %s\n", str_yes_no(runtime->has_dsc)); + + drm_printf(p, "rawclk rate: %u kHz\n", runtime->rawclk_freq); } #undef INTEL_VGA_DEVICE @@ -364,55 +367,55 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { drm_info(&dev_priv->drm, "Display fused off, disabling\n"); - info->display.pipe_mask = 0; - info->display.cpu_transcoder_mask = 0; - info->display.fbc_mask = 0; + runtime->pipe_mask = 0; + runtime->cpu_transcoder_mask = 0; + runtime->fbc_mask = 0; } else if (fuse_strap & IVB_PIPE_C_DISABLE) { drm_info(&dev_priv->drm, "PipeC fused off\n"); - info->display.pipe_mask &= ~BIT(PIPE_C); - info->display.cpu_transcoder_mask &= ~BIT(TRANSCODER_C); + runtime->pipe_mask &= ~BIT(PIPE_C); + runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); } } else if (HAS_DISPLAY(dev_priv) && DISPLAY_VER(dev_priv) >= 9) { u32 dfsm = intel_de_read(dev_priv, SKL_DFSM); if (dfsm & SKL_DFSM_PIPE_A_DISABLE) { - info->display.pipe_mask &= ~BIT(PIPE_A); - info->display.cpu_transcoder_mask &= ~BIT(TRANSCODER_A); - info->display.fbc_mask &= ~BIT(INTEL_FBC_A); + runtime->pipe_mask &= ~BIT(PIPE_A); + runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_A); + runtime->fbc_mask &= ~BIT(INTEL_FBC_A); } if (dfsm & SKL_DFSM_PIPE_B_DISABLE) { - info->display.pipe_mask &= ~BIT(PIPE_B); - info->display.cpu_transcoder_mask &= ~BIT(TRANSCODER_B); + runtime->pipe_mask &= ~BIT(PIPE_B); + runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_B); } if (dfsm & SKL_DFSM_PIPE_C_DISABLE) { - info->display.pipe_mask &= ~BIT(PIPE_C); - info->display.cpu_transcoder_mask &= ~BIT(TRANSCODER_C); + runtime->pipe_mask &= ~BIT(PIPE_C); + runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); } if (DISPLAY_VER(dev_priv) >= 12 && (dfsm & TGL_DFSM_PIPE_D_DISABLE)) { - info->display.pipe_mask &= ~BIT(PIPE_D); - info->display.cpu_transcoder_mask &= ~BIT(TRANSCODER_D); + runtime->pipe_mask &= ~BIT(PIPE_D); + runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D); } if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE) - info->display.has_hdcp = 0; + runtime->has_hdcp = 0; if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE) - info->display.fbc_mask = 0; + runtime->fbc_mask = 0; if (DISPLAY_VER(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE)) - info->display.has_dmc = 0; + runtime->has_dmc = 0; if (DISPLAY_VER(dev_priv) >= 10 && (dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE)) - info->display.has_dsc = 0; + runtime->has_dsc = 0; } if (GRAPHICS_VER(dev_priv) == 6 && i915_vtd_active(dev_priv)) { drm_info(&dev_priv->drm, "Disabling ppGTT for VT-d support\n"); - info->ppgtt_type = INTEL_PPGTT_NONE; + runtime->ppgtt_type = INTEL_PPGTT_NONE; } runtime->rawclk_freq = intel_read_rawclk(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 80ff83f96b88..deaa07d8df2c 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -165,7 +165,6 @@ enum intel_ppgtt_type { func(has_media_ratio_mode); \ func(has_mslice_steering); \ func(has_one_eu_per_fuse_bit); \ - func(has_pooled_eu); \ func(has_pxp); \ func(has_rc6); \ func(has_rc6p); \ @@ -181,14 +180,11 @@ enum intel_ppgtt_type { /* Keep in alphabetical order */ \ func(cursor_needs_physical); \ func(has_cdclk_crawl); \ - func(has_dmc); \ func(has_ddi); \ func(has_dp_mst); \ func(has_dsb); \ - func(has_dsc); \ func(has_fpga_dbg); \ func(has_gmch); \ - func(has_hdcp); \ func(has_hotplug); \ func(has_hti); \ func(has_ipc); \ @@ -204,24 +200,58 @@ struct ip_version { u8 rel; }; -struct intel_device_info { +struct intel_runtime_info { struct ip_version graphics; - struct ip_version media; + + /* + * Platform mask is used for optimizing or-ed IS_PLATFORM calls into + * single runtime conditionals, and also to provide groundwork for + * future per platform, or per SKU build optimizations. + * + * Array can be extended when necessary if the corresponding + * BUILD_BUG_ON is hit. + */ + u32 platform_mask[2]; + + u16 device_id; intel_engine_mask_t platform_engine_mask; /* Engines supported by the HW */ - enum intel_platform platform; + u32 rawclk_freq; - unsigned int dma_mask_size; /* available DMA address bits */ + struct intel_step_info step; + + unsigned int page_sizes; /* page sizes supported by the HW */ enum intel_ppgtt_type ppgtt_type; unsigned int ppgtt_size; /* log2, e.g. 31/32/48 bits */ - unsigned int page_sizes; /* page sizes supported by the HW */ - u32 memory_regions; /* regions supported by the HW */ - u32 display_mmio_offset; + bool has_pooled_eu; + + /* display */ + struct { + u8 pipe_mask; + u8 cpu_transcoder_mask; + + u8 num_sprites[I915_MAX_PIPES]; + u8 num_scalers[I915_MAX_PIPES]; + + u8 fbc_mask; + + bool has_hdcp; + bool has_dmc; + bool has_dsc; + }; +}; + +struct intel_device_info { + struct ip_version media; + + enum intel_platform platform; + + unsigned int dma_mask_size; /* available DMA address bits */ const struct intel_gt_definition *extra_gt_list; @@ -235,53 +265,37 @@ struct intel_device_info { u8 ver; u8 rel; - u8 pipe_mask; - u8 cpu_transcoder_mask; - u8 fbc_mask; u8 abox_mask; + struct { + u16 size; /* in blocks */ + u8 slice_mask; + } dbuf; + #define DEFINE_FLAG(name) u8 name:1 DEV_INFO_DISPLAY_FOR_EACH_FLAG(DEFINE_FLAG); #undef DEFINE_FLAG - } display; - - struct { - u16 size; /* in blocks */ - u8 slice_mask; - } dbuf; - - /* Register offsets for the various display pipes and transcoders */ - int pipe_offsets[I915_MAX_TRANSCODERS]; - int trans_offsets[I915_MAX_TRANSCODERS]; - int cursor_offsets[I915_MAX_PIPES]; - - struct color_luts { - u32 degamma_lut_size; - u32 gamma_lut_size; - u32 degamma_lut_tests; - u32 gamma_lut_tests; - } color; -}; - -struct intel_runtime_info { - /* - * Platform mask is used for optimizing or-ed IS_PLATFORM calls into - * into single runtime conditionals, and also to provide groundwork - * for future per platform, or per SKU build optimizations. - * - * Array can be extended when necessary if the corresponding - * BUILD_BUG_ON is hit. - */ - u32 platform_mask[2]; - u16 device_id; + /* Global register offset for the display engine */ + u32 mmio_offset; - u8 num_sprites[I915_MAX_PIPES]; - u8 num_scalers[I915_MAX_PIPES]; + /* Register offsets for the various display pipes and transcoders */ + u32 pipe_offsets[I915_MAX_TRANSCODERS]; + u32 trans_offsets[I915_MAX_TRANSCODERS]; + u32 cursor_offsets[I915_MAX_PIPES]; - u32 rawclk_freq; + struct { + u32 degamma_lut_size; + u32 gamma_lut_size; + u32 degamma_lut_tests; + u32 gamma_lut_tests; + } color; + } display; - struct intel_step_info step; + /* + * Initial runtime info. Do not access outside of i915_driver_create(). + */ + const struct intel_runtime_info __runtime; }; struct intel_driver_caps { @@ -294,10 +308,9 @@ const char *intel_platform_name(enum intel_platform platform); void intel_device_info_subplatform_init(struct drm_i915_private *dev_priv); void intel_device_info_runtime_init(struct drm_i915_private *dev_priv); -void intel_device_info_print_static(const struct intel_device_info *info, - struct drm_printer *p); -void intel_device_info_print_runtime(const struct intel_runtime_info *info, - struct drm_printer *p); +void intel_device_info_print(const struct intel_device_info *info, + const struct intel_runtime_info *runtime, + struct drm_printer *p); void intel_driver_caps_print(const struct intel_driver_caps *caps, struct drm_printer *p); diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index 72dac1718f3e..e015bc91a26f 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -3,10 +3,13 @@ * Copyright © 2020 Intel Corporation */ +#include "display/intel_audio_regs.h" +#include "display/intel_backlight_regs.h" #include "display/intel_dmc_regs.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" #include "gvt/gvt.h" + #include "i915_drv.h" #include "i915_pvinfo.h" #include "i915_reg.h" diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index e2b2bbdc0714..ba9843cb1b13 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -25,7 +25,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n"); drm_WARN_ON(&dev_priv->drm, GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv)); - /* PantherPoint is CPT compatible */ + /* PPT is CPT compatible */ return PCH_CPT; case INTEL_PCH_LPT_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n"); @@ -47,7 +47,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); - /* WildcatPoint is LPT compatible */ + /* WPT is LPT compatible */ return PCH_LPT; case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n"); @@ -55,7 +55,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); - /* WildcatPoint is LPT compatible */ + /* WPT is LPT compatible */ return PCH_LPT; case INTEL_PCH_SPT_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n"); @@ -99,14 +99,14 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_COFFEELAKE(dev_priv) && !IS_COMETLAKE(dev_priv) && !IS_ROCKETLAKE(dev_priv)); - /* CometPoint is CNP Compatible */ + /* CMP is CNP compatible */ return PCH_CNP; case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n"); drm_WARN_ON(&dev_priv->drm, !IS_COFFEELAKE(dev_priv) && !IS_COMETLAKE(dev_priv)); - /* Comet Lake V PCH is based on KBP, which is SPT compatible */ + /* CMP-V is based on KBP, which is SPT compatible */ return PCH_SPT; case INTEL_PCH_ICP_DEVICE_ID_TYPE: case INTEL_PCH_ICP2_DEVICE_ID_TYPE: @@ -116,7 +116,8 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) case INTEL_PCH_MCC_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); - return PCH_MCC; + /* MCC is TGP compatible */ + return PCH_TGP; case INTEL_PCH_TGP_DEVICE_ID_TYPE: case INTEL_PCH_TGP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n"); @@ -127,7 +128,8 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) case INTEL_PCH_JSP_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); - return PCH_JSP; + /* JSP is ICP compatible */ + return PCH_ICP; case INTEL_PCH_ADP_DEVICE_ID_TYPE: case INTEL_PCH_ADP2_DEVICE_ID_TYPE: case INTEL_PCH_ADP3_DEVICE_ID_TYPE: @@ -136,6 +138,11 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) && !IS_ALDERLAKE_P(dev_priv)); return PCH_ADP; + case INTEL_PCH_MTP_DEVICE_ID_TYPE: + case INTEL_PCH_MTP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Meteor Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_METEORLAKE(dev_priv)); + return PCH_MTP; default: return PCH_NONE; } @@ -164,7 +171,9 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv, * make an educated guess as to which PCH is really there. */ - if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) + if (IS_METEORLAKE(dev_priv)) + id = INTEL_PCH_MTP_DEVICE_ID_TYPE; + else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) id = INTEL_PCH_ADP_DEVICE_ID_TYPE; else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) id = INTEL_PCH_TGP_DEVICE_ID_TYPE; diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index b7a8cf409d48..32aff5a70d04 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -22,11 +22,10 @@ enum intel_pch { PCH_LPT, /* Lynxpoint/Wildcatpoint PCH */ PCH_SPT, /* Sunrisepoint/Kaby Lake PCH */ PCH_CNP, /* Cannon/Comet Lake PCH */ - PCH_ICP, /* Ice Lake PCH */ - PCH_JSP, /* Jasper Lake PCH */ - PCH_MCC, /* Mule Creek Canyon PCH */ - PCH_TGP, /* Tiger Lake PCH */ + PCH_ICP, /* Ice Lake/Jasper Lake PCH */ + PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */ PCH_ADP, /* Alder Lake PCH */ + PCH_MTP, /* Meteor Lake PCH */ /* Fake PCHs, functionality handled on the same PCI dev */ PCH_DG1 = 1024, @@ -59,17 +58,18 @@ enum intel_pch { #define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 #define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 #define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480 +#define INTEL_PCH_MTP_DEVICE_ID_TYPE 0x7E00 +#define INTEL_PCH_MTP2_DEVICE_ID_TYPE 0xAE00 #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 #define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ #define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) #define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id) +#define HAS_PCH_MTP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_MTP) #define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2) #define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP) #define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1) -#define HAS_PCH_JSP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_JSP) -#define HAS_PCH_MCC(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_MCC) #define HAS_PCH_TGP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_TGP) #define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP) #define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP) diff --git a/drivers/gpu/drm/i915/intel_pci_config.h b/drivers/gpu/drm/i915/intel_pci_config.h index 12cd9d4f23de..4977a524ce6f 100644 --- a/drivers/gpu/drm/i915/intel_pci_config.h +++ b/drivers/gpu/drm/i915/intel_pci_config.h @@ -6,6 +6,13 @@ #ifndef __INTEL_PCI_CONFIG_H__ #define __INTEL_PCI_CONFIG_H__ +/* PCI BARs */ +#define GTTMMADR_BAR 0 +#define GEN2_GTTMMADR_BAR 1 +#define GFXMEM_BAR 2 +#define GTT_APERTURE_BAR GFXMEM_BAR +#define GEN12_LMEM_BAR GFXMEM_BAR + /* BSM in include/drm/i915_drm.h */ #define MCHBAR_I915 0x44 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d309cc031e93..efc040cccc24 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -30,8 +30,8 @@ #include <linux/pm_runtime.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h> #include "display/intel_atomic.h" #include "display/intel_atomic_plane.h" @@ -468,13 +468,13 @@ bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) { bool ret; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); ret = _intel_set_memory_cxsr(dev_priv, enable); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - dev_priv->wm.vlv.cxsr = enable; + dev_priv->display.wm.vlv.cxsr = enable; else if (IS_G4X(dev_priv)) - dev_priv->wm.g4x.cxsr = enable; - mutex_unlock(&dev_priv->wm.wm_mutex); + dev_priv->display.wm.g4x.cxsr = enable; + mutex_unlock(&dev_priv->display.wm.wm_mutex); return ret; } @@ -834,7 +834,7 @@ static bool is_enabling(int old, int new, int threshold) static int intel_wm_num_levels(struct drm_i915_private *dev_priv) { - return dev_priv->wm.max_level + 1; + return dev_priv->display.wm.max_level + 1; } static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, @@ -1093,11 +1093,11 @@ static void vlv_write_wm_values(struct drm_i915_private *dev_priv, static void g4x_setup_wm_latency(struct drm_i915_private *dev_priv) { /* all latencies in usec */ - dev_priv->wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 5; - dev_priv->wm.pri_latency[G4X_WM_LEVEL_SR] = 12; - dev_priv->wm.pri_latency[G4X_WM_LEVEL_HPLL] = 35; + dev_priv->display.wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 5; + dev_priv->display.wm.pri_latency[G4X_WM_LEVEL_SR] = 12; + dev_priv->display.wm.pri_latency[G4X_WM_LEVEL_HPLL] = 35; - dev_priv->wm.max_level = G4X_WM_LEVEL_HPLL; + dev_priv->display.wm.max_level = G4X_WM_LEVEL_HPLL; } static int g4x_plane_fifo_size(enum plane_id plane_id, int level) @@ -1150,7 +1150,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; - unsigned int latency = dev_priv->wm.pri_latency[level] * 10; + unsigned int latency = dev_priv->display.wm.pri_latency[level] * 10; unsigned int pixel_rate, htotal, cpp, width, wm; if (latency == 0) @@ -1324,7 +1324,7 @@ static bool g4x_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - if (level > dev_priv->wm.max_level) + if (level > dev_priv->display.wm.max_level) return false; return g4x_raw_plane_wm_is_valid(crtc_state, PLANE_PRIMARY, level) && @@ -1583,7 +1583,7 @@ static void g4x_merge_wm(struct drm_i915_private *dev_priv, static void g4x_program_watermarks(struct drm_i915_private *dev_priv) { - struct g4x_wm_values *old_wm = &dev_priv->wm.g4x; + struct g4x_wm_values *old_wm = &dev_priv->display.wm.g4x; struct g4x_wm_values new_wm = {}; g4x_merge_wm(dev_priv, &new_wm); @@ -1609,10 +1609,10 @@ static void g4x_initial_watermarks(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.g4x = crtc_state->wm.g4x.intermediate; g4x_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } static void g4x_optimize_watermarks(struct intel_atomic_state *state, @@ -1625,10 +1625,10 @@ static void g4x_optimize_watermarks(struct intel_atomic_state *state, if (!crtc_state->wm.need_postvbl_update) return; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.g4x = crtc_state->wm.g4x.optimal; g4x_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } /* latency must be in 0.1us units. */ @@ -1650,15 +1650,15 @@ static unsigned int vlv_wm_method2(unsigned int pixel_rate, static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv) { /* all latencies in usec */ - dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3; + dev_priv->display.wm.pri_latency[VLV_WM_LEVEL_PM2] = 3; - dev_priv->wm.max_level = VLV_WM_LEVEL_PM2; + dev_priv->display.wm.max_level = VLV_WM_LEVEL_PM2; if (IS_CHERRYVIEW(dev_priv)) { - dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 12; - dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33; + dev_priv->display.wm.pri_latency[VLV_WM_LEVEL_PM5] = 12; + dev_priv->display.wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33; - dev_priv->wm.max_level = VLV_WM_LEVEL_DDR_DVFS; + dev_priv->display.wm.max_level = VLV_WM_LEVEL_DDR_DVFS; } } @@ -1672,7 +1672,7 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, &crtc_state->hw.pipe_mode; unsigned int pixel_rate, htotal, cpp, width, wm; - if (dev_priv->wm.pri_latency[level] == 0) + if (dev_priv->display.wm.pri_latency[level] == 0) return USHRT_MAX; if (!intel_wm_plane_visible(crtc_state, plane_state)) @@ -1693,7 +1693,7 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, wm = 63; } else { wm = vlv_wm_method2(pixel_rate, htotal, width, cpp, - dev_priv->wm.pri_latency[level] * 10); + dev_priv->display.wm.pri_latency[level] * 10); } return min_t(unsigned int, wm, USHRT_MAX); @@ -2158,7 +2158,7 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv, struct intel_crtc *crtc; int num_active_pipes = 0; - wm->level = dev_priv->wm.max_level; + wm->level = dev_priv->display.wm.max_level; wm->cxsr = true; for_each_intel_crtc(&dev_priv->drm, crtc) { @@ -2197,7 +2197,7 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv, static void vlv_program_watermarks(struct drm_i915_private *dev_priv) { - struct vlv_wm_values *old_wm = &dev_priv->wm.vlv; + struct vlv_wm_values *old_wm = &dev_priv->display.wm.vlv; struct vlv_wm_values new_wm = {}; vlv_merge_wm(dev_priv, &new_wm); @@ -2235,10 +2235,10 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate; vlv_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } static void vlv_optimize_watermarks(struct intel_atomic_state *state, @@ -2251,10 +2251,10 @@ static void vlv_optimize_watermarks(struct intel_atomic_state *state, if (!crtc_state->wm.need_postvbl_update) return; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.vlv = crtc_state->wm.vlv.optimal; vlv_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } static void i965_update_wm(struct drm_i915_private *dev_priv) @@ -2835,9 +2835,9 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, const struct intel_plane_state *curstate, struct intel_wm_level *result) { - u16 pri_latency = dev_priv->wm.pri_latency[level]; - u16 spr_latency = dev_priv->wm.spr_latency[level]; - u16 cur_latency = dev_priv->wm.cur_latency[level]; + u16 pri_latency = dev_priv->display.wm.pri_latency[level]; + u16 spr_latency = dev_priv->display.wm.spr_latency[level]; + u16 cur_latency = dev_priv->display.wm.cur_latency[level]; /* WM1+ latency values stored in 0.5us units */ if (level > 0) { @@ -2861,16 +2861,75 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, result->enable = true; } +static void +adjust_wm_latency(struct drm_i915_private *i915, + u16 wm[], int max_level, int read_latency) +{ + bool wm_lv_0_adjust_needed = i915->dram_info.wm_lv_0_adjust_needed; + int i, level; + + /* + * If a level n (n > 1) has a 0us latency, all levels m (m >= n) + * need to be disabled. We make sure to sanitize the values out + * of the punit to satisfy this requirement. + */ + for (level = 1; level <= max_level; level++) { + if (wm[level] == 0) { + for (i = level + 1; i <= max_level; i++) + wm[i] = 0; + + max_level = level - 1; + break; + } + } + + /* + * WaWmMemoryReadLatency + * + * punit doesn't take into account the read latency so we need + * to add proper adjustement to each valid level we retrieve + * from the punit when level 0 response data is 0us. + */ + if (wm[0] == 0) { + for (level = 0; level <= max_level; level++) + wm[level] += read_latency; + } + + /* + * WA Level-0 adjustment for 16GB DIMMs: SKL+ + * If we could not get dimm info enable this WA to prevent from + * any underrun. If not able to get Dimm info assume 16GB dimm + * to avoid any underrun. + */ + if (wm_lv_0_adjust_needed) + wm[0] += 1; +} + static void intel_read_wm_latency(struct drm_i915_private *dev_priv, - u16 wm[8]) + u16 wm[]) { struct intel_uncore *uncore = &dev_priv->uncore; + int max_level = ilk_wm_max_level(dev_priv); - if (DISPLAY_VER(dev_priv) >= 9) { + if (DISPLAY_VER(dev_priv) >= 14) { u32 val; - int ret, i; - int level, max_level = ilk_wm_max_level(dev_priv); + + val = intel_uncore_read(uncore, MTL_LATENCY_LP0_LP1); + wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); + wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); + val = intel_uncore_read(uncore, MTL_LATENCY_LP2_LP3); + wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); + wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); + val = intel_uncore_read(uncore, MTL_LATENCY_LP4_LP5); + wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); + wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); + + adjust_wm_latency(dev_priv, wm, max_level, 6); + } else if (DISPLAY_VER(dev_priv) >= 9) { + int read_latency = DISPLAY_VER(dev_priv) >= 12 ? 3 : 2; int mult = IS_DG2(dev_priv) ? 2 : 1; + u32 val; + int ret; /* read the first set of memory latencies[0:3] */ val = 0; /* data0 to be programmed to 0 for first set */ @@ -2909,44 +2968,7 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, wm[7] = ((val >> GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT) & GEN9_MEM_LATENCY_LEVEL_MASK) * mult; - /* - * If a level n (n > 1) has a 0us latency, all levels m (m >= n) - * need to be disabled. We make sure to sanitize the values out - * of the punit to satisfy this requirement. - */ - for (level = 1; level <= max_level; level++) { - if (wm[level] == 0) { - for (i = level + 1; i <= max_level; i++) - wm[i] = 0; - - max_level = level - 1; - - break; - } - } - - /* - * WaWmMemoryReadLatency - * - * punit doesn't take into account the read latency so we need - * to add proper adjustement to each valid level we retrieve - * from the punit when level 0 response data is 0us. - */ - if (wm[0] == 0) { - u8 adjust = DISPLAY_VER(dev_priv) >= 12 ? 3 : 2; - - for (level = 0; level <= max_level; level++) - wm[level] += adjust; - } - - /* - * WA Level-0 adjustment for 16GB DIMMs: SKL+ - * If we could not get dimm info enable this WA to prevent from - * any underrun. If not able to get Dimm info assume 16GB dimm - * to avoid any underrun. - */ - if (dev_priv->dram_info.wm_lv_0_adjust_needed) - wm[0] += 1; + adjust_wm_latency(dev_priv, wm, max_level, read_latency); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { u64 sskpd = intel_uncore_read64(uncore, MCH_SSKPD); @@ -3061,18 +3083,18 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) * The BIOS provided WM memory latency values are often * inadequate for high resolution displays. Adjust them. */ - changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12); - changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12); - changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); + changed = ilk_increase_wm_latency(dev_priv, dev_priv->display.wm.pri_latency, 12); + changed |= ilk_increase_wm_latency(dev_priv, dev_priv->display.wm.spr_latency, 12); + changed |= ilk_increase_wm_latency(dev_priv, dev_priv->display.wm.cur_latency, 12); if (!changed) return; drm_dbg_kms(&dev_priv->drm, "WM latency values increased to avoid potential underruns\n"); - intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->display.wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->display.wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->display.wm.cur_latency); } static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) @@ -3088,37 +3110,37 @@ static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) * interrupts only. To play it safe we disable LP3 * watermarks entirely. */ - if (dev_priv->wm.pri_latency[3] == 0 && - dev_priv->wm.spr_latency[3] == 0 && - dev_priv->wm.cur_latency[3] == 0) + if (dev_priv->display.wm.pri_latency[3] == 0 && + dev_priv->display.wm.spr_latency[3] == 0 && + dev_priv->display.wm.cur_latency[3] == 0) return; - dev_priv->wm.pri_latency[3] = 0; - dev_priv->wm.spr_latency[3] = 0; - dev_priv->wm.cur_latency[3] = 0; + dev_priv->display.wm.pri_latency[3] = 0; + dev_priv->display.wm.spr_latency[3] = 0; + dev_priv->display.wm.cur_latency[3] = 0; drm_dbg_kms(&dev_priv->drm, "LP3 watermarks disabled due to potential for lost interrupts\n"); - intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->display.wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->display.wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->display.wm.cur_latency); } static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) { - intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); + intel_read_wm_latency(dev_priv, dev_priv->display.wm.pri_latency); - memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency, - sizeof(dev_priv->wm.pri_latency)); - memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency, - sizeof(dev_priv->wm.pri_latency)); + memcpy(dev_priv->display.wm.spr_latency, dev_priv->display.wm.pri_latency, + sizeof(dev_priv->display.wm.pri_latency)); + memcpy(dev_priv->display.wm.cur_latency, dev_priv->display.wm.pri_latency, + sizeof(dev_priv->display.wm.pri_latency)); - intel_fixup_spr_wm_latency(dev_priv, dev_priv->wm.spr_latency); - intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency); + intel_fixup_spr_wm_latency(dev_priv, dev_priv->display.wm.spr_latency); + intel_fixup_cur_wm_latency(dev_priv, dev_priv->display.wm.cur_latency); - intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->display.wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->display.wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->display.wm.cur_latency); if (DISPLAY_VER(dev_priv) == 6) { snb_wm_latency_quirk(dev_priv); @@ -3128,8 +3150,8 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) { - intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency); - intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency); + intel_read_wm_latency(dev_priv, dev_priv->display.wm.skl_latency); + intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->display.wm.skl_latency); } static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv, @@ -3386,7 +3408,7 @@ static unsigned int ilk_wm_lp_latency(struct drm_i915_private *dev_priv, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) return 2 * level; else - return dev_priv->wm.pri_latency[level]; + return dev_priv->display.wm.pri_latency[level]; } static void ilk_compute_wm_results(struct drm_i915_private *dev_priv, @@ -3538,7 +3560,7 @@ static unsigned int ilk_compute_wm_dirty(struct drm_i915_private *dev_priv, static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv, unsigned int dirty) { - struct ilk_wm_values *previous = &dev_priv->wm.hw; + struct ilk_wm_values *previous = &dev_priv->display.wm.hw; bool changed = false; if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM_LP_ENABLE) { @@ -3572,7 +3594,7 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv, static void ilk_write_wm_values(struct drm_i915_private *dev_priv, struct ilk_wm_values *results) { - struct ilk_wm_values *previous = &dev_priv->wm.hw; + struct ilk_wm_values *previous = &dev_priv->display.wm.hw; unsigned int dirty; u32 val; @@ -3634,7 +3656,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2]) intel_uncore_write(&dev_priv->uncore, WM3_LP_ILK, results->wm_lp[2]); - dev_priv->wm.hw = *results; + dev_priv->display.wm.hw = *results; } bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv) @@ -3669,7 +3691,7 @@ static bool intel_has_sagv(struct drm_i915_private *dev_priv) { return DISPLAY_VER(dev_priv) >= 9 && !IS_LP(dev_priv) && - dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED; + dev_priv->display.sagv.status != I915_SAGV_NOT_CONTROLLED; } static u32 @@ -3700,7 +3722,7 @@ intel_sagv_block_time(struct drm_i915_private *dev_priv) static void intel_sagv_init(struct drm_i915_private *i915) { if (!intel_has_sagv(i915)) - i915->sagv_status = I915_SAGV_NOT_CONTROLLED; + i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; /* * Probe to see if we have working SAGV control. @@ -3709,21 +3731,21 @@ static void intel_sagv_init(struct drm_i915_private *i915) if (DISPLAY_VER(i915) < 11) skl_sagv_disable(i915); - drm_WARN_ON(&i915->drm, i915->sagv_status == I915_SAGV_UNKNOWN); + drm_WARN_ON(&i915->drm, i915->display.sagv.status == I915_SAGV_UNKNOWN); - i915->sagv_block_time_us = intel_sagv_block_time(i915); + i915->display.sagv.block_time_us = intel_sagv_block_time(i915); drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n", - str_yes_no(intel_has_sagv(i915)), i915->sagv_block_time_us); + str_yes_no(intel_has_sagv(i915)), i915->display.sagv.block_time_us); /* avoid overflow when adding with wm0 latency/etc. */ - if (drm_WARN(&i915->drm, i915->sagv_block_time_us > U16_MAX, + if (drm_WARN(&i915->drm, i915->display.sagv.block_time_us > U16_MAX, "Excessive SAGV block time %u, ignoring\n", - i915->sagv_block_time_us)) - i915->sagv_block_time_us = 0; + i915->display.sagv.block_time_us)) + i915->display.sagv.block_time_us = 0; if (!intel_has_sagv(i915)) - i915->sagv_block_time_us = 0; + i915->display.sagv.block_time_us = 0; } /* @@ -3744,7 +3766,7 @@ static void skl_sagv_enable(struct drm_i915_private *dev_priv) if (!intel_has_sagv(dev_priv)) return; - if (dev_priv->sagv_status == I915_SAGV_ENABLED) + if (dev_priv->display.sagv.status == I915_SAGV_ENABLED) return; drm_dbg_kms(&dev_priv->drm, "Enabling SAGV\n"); @@ -3759,14 +3781,14 @@ static void skl_sagv_enable(struct drm_i915_private *dev_priv) */ if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n"); - dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; + dev_priv->display.sagv.status = I915_SAGV_NOT_CONTROLLED; return; } else if (ret < 0) { drm_err(&dev_priv->drm, "Failed to enable SAGV\n"); return; } - dev_priv->sagv_status = I915_SAGV_ENABLED; + dev_priv->display.sagv.status = I915_SAGV_ENABLED; } static void skl_sagv_disable(struct drm_i915_private *dev_priv) @@ -3776,7 +3798,7 @@ static void skl_sagv_disable(struct drm_i915_private *dev_priv) if (!intel_has_sagv(dev_priv)) return; - if (dev_priv->sagv_status == I915_SAGV_DISABLED) + if (dev_priv->display.sagv.status == I915_SAGV_DISABLED) return; drm_dbg_kms(&dev_priv->drm, "Disabling SAGV\n"); @@ -3791,14 +3813,14 @@ static void skl_sagv_disable(struct drm_i915_private *dev_priv) */ if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n"); - dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; + dev_priv->display.sagv.status = I915_SAGV_NOT_CONTROLLED; return; } else if (ret < 0) { drm_err(&dev_priv->drm, "Failed to disable SAGV (%d)\n", ret); return; } - dev_priv->sagv_status = I915_SAGV_DISABLED; + dev_priv->display.sagv.status = I915_SAGV_DISABLED; } static void skl_sagv_pre_plane_update(struct intel_atomic_state *state) @@ -4100,8 +4122,8 @@ static u16 skl_ddb_entry_init(struct skl_ddb_entry *entry, static int intel_dbuf_slice_size(struct drm_i915_private *dev_priv) { - return INTEL_INFO(dev_priv)->dbuf.size / - hweight8(INTEL_INFO(dev_priv)->dbuf.slice_mask); + return INTEL_INFO(dev_priv)->display.dbuf.size / + hweight8(INTEL_INFO(dev_priv)->display.dbuf.slice_mask); } static void @@ -4120,7 +4142,7 @@ skl_ddb_entry_for_slices(struct drm_i915_private *dev_priv, u8 slice_mask, ddb->end = fls(slice_mask) * slice_size; WARN_ON(ddb->start >= ddb->end); - WARN_ON(ddb->end > INTEL_INFO(dev_priv)->dbuf.size); + WARN_ON(ddb->end > INTEL_INFO(dev_priv)->display.dbuf.size); } static unsigned int mbus_ddb_offset(struct drm_i915_private *i915, u8 slice_mask) @@ -4321,7 +4343,7 @@ skl_cursor_allocation(const struct intel_crtc_state *crtc_state, drm_WARN_ON(&dev_priv->drm, ret); for (level = 0; level <= max_level; level++) { - unsigned int latency = dev_priv->wm.skl_latency[level]; + unsigned int latency = dev_priv->display.wm.skl_latency[level]; skl_compute_plane_wm(crtc_state, plane, level, latency, &wp, &wm, &wm); if (wm.min_ddb_alloc == U16_MAX) @@ -4368,9 +4390,9 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, skl_ddb_entry_init_from_hw(ddb_y, val); } -void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, - struct skl_ddb_entry *ddb, - struct skl_ddb_entry *ddb_y) +static void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, + struct skl_ddb_entry *ddb, + struct skl_ddb_entry *ddb_y) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum intel_display_power_domain power_domain; @@ -4905,7 +4927,7 @@ static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool if (IS_DG2(dev_priv)) return dg2_compute_dbuf_slices(pipe, active_pipes, join_mbus); - else if (IS_ALDERLAKE_P(dev_priv)) + else if (DISPLAY_VER(dev_priv) >= 13) return adlp_compute_dbuf_slices(pipe, active_pipes, join_mbus); else if (DISPLAY_VER(dev_priv) == 12) return tgl_compute_dbuf_slices(pipe, active_pipes, join_mbus); @@ -4950,7 +4972,7 @@ skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state) return data_rate; } -const struct skl_wm_level * +static const struct skl_wm_level * skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, enum plane_id plane_id, int level) @@ -4963,7 +4985,7 @@ skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, return &wm->wm[level]; } -const struct skl_wm_level * +static const struct skl_wm_level * skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, enum plane_id plane_id) { @@ -5560,8 +5582,8 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; result->enable = true; - if (DISPLAY_VER(dev_priv) < 12 && dev_priv->sagv_block_time_us) - result->can_sagv = latency >= dev_priv->sagv_block_time_us; + if (DISPLAY_VER(dev_priv) < 12 && dev_priv->display.sagv.block_time_us) + result->can_sagv = latency >= dev_priv->display.sagv.block_time_us; } static void @@ -5576,7 +5598,7 @@ skl_compute_wm_levels(const struct intel_crtc_state *crtc_state, for (level = 0; level <= max_level; level++) { struct skl_wm_level *result = &levels[level]; - unsigned int latency = dev_priv->wm.skl_latency[level]; + unsigned int latency = dev_priv->display.wm.skl_latency[level]; skl_compute_plane_wm(crtc_state, plane, level, latency, wm_params, result_prev, result); @@ -5595,8 +5617,8 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state, struct skl_wm_level *levels = plane_wm->wm; unsigned int latency = 0; - if (dev_priv->sagv_block_time_us) - latency = dev_priv->sagv_block_time_us + dev_priv->wm.skl_latency[0]; + if (dev_priv->display.sagv.block_time_us) + latency = dev_priv->display.sagv.block_time_us + dev_priv->display.wm.skl_latency[0]; skl_compute_plane_wm(crtc_state, plane, 0, latency, wm_params, &levels[0], @@ -5915,8 +5937,8 @@ void skl_write_cursor_wm(struct intel_plane *plane, skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), ddb); } -bool skl_wm_level_equals(const struct skl_wm_level *l1, - const struct skl_wm_level *l2) +static bool skl_wm_level_equals(const struct skl_wm_level *l1, + const struct skl_wm_level *l2) { return l1->enable == l2->enable && l1->ignore_lines == l2->ignore_lines && @@ -6095,7 +6117,7 @@ skl_compute_ddb(struct intel_atomic_state *state) "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", old_dbuf_state->enabled_slices, new_dbuf_state->enabled_slices, - INTEL_INFO(dev_priv)->dbuf.slice_mask, + INTEL_INFO(dev_priv)->display.dbuf.slice_mask, str_yes_no(old_dbuf_state->joined_mbus), str_yes_no(new_dbuf_state->joined_mbus)); } @@ -6458,10 +6480,10 @@ static void ilk_initial_watermarks(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.ilk = crtc_state->wm.ilk.intermediate; ilk_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } static void ilk_optimize_watermarks(struct intel_atomic_state *state, @@ -6474,10 +6496,10 @@ static void ilk_optimize_watermarks(struct intel_atomic_state *state, if (!crtc_state->wm.need_postvbl_update) return; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); crtc->wm.active.ilk = crtc_state->wm.ilk.optimal; ilk_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) @@ -6488,8 +6510,8 @@ static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); } -void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, - struct skl_pipe_wm *out) +static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, + struct skl_pipe_wm *out) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -6560,7 +6582,10 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) enum plane_id plane_id; u8 slices; - skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); + memset(&crtc_state->wm.skl.optimal, 0, + sizeof(crtc_state->wm.skl.optimal)); + if (crtc_state->hw.active) + skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal; memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe])); @@ -6571,6 +6596,9 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) struct skl_ddb_entry *ddb_y = &crtc_state->wm.skl.plane_ddb_y[plane_id]; + if (!crtc_state->hw.active) + continue; + skl_ddb_get_hw_plane_state(dev_priv, crtc->pipe, plane_id, ddb, ddb_y); @@ -6677,7 +6705,7 @@ static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct ilk_wm_values *hw = &dev_priv->wm.hw; + struct ilk_wm_values *hw = &dev_priv->display.wm.hw; struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_pipe_wm *active = &crtc_state->wm.ilk.optimal; enum pipe pipe = crtc->pipe; @@ -6825,7 +6853,7 @@ static void vlv_read_wm_values(struct drm_i915_private *dev_priv, void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv) { - struct g4x_wm_values *wm = &dev_priv->wm.g4x; + struct g4x_wm_values *wm = &dev_priv->display.wm.g4x; struct intel_crtc *crtc; g4x_read_wm_values(dev_priv, wm); @@ -6919,7 +6947,7 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv) struct intel_plane *plane; struct intel_crtc *crtc; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); for_each_intel_plane(&dev_priv->drm, plane) { struct intel_crtc *crtc = @@ -6967,12 +6995,12 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv) g4x_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv) { - struct vlv_wm_values *wm = &dev_priv->wm.vlv; + struct vlv_wm_values *wm = &dev_priv->display.wm.vlv; struct intel_crtc *crtc; u32 val; @@ -7006,7 +7034,7 @@ void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "Punit not acking DDR DVFS request, " "assuming DDR DVFS is disabled\n"); - dev_priv->wm.max_level = VLV_WM_LEVEL_PM5; + dev_priv->display.wm.max_level = VLV_WM_LEVEL_PM5; } else { val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); if ((val & FORCE_DDR_HIGH_FREQ) == 0) @@ -7075,7 +7103,7 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) struct intel_plane *plane; struct intel_crtc *crtc; - mutex_lock(&dev_priv->wm.wm_mutex); + mutex_lock(&dev_priv->display.wm.wm_mutex); for_each_intel_plane(&dev_priv->drm, plane) { struct intel_crtc *crtc = @@ -7116,7 +7144,7 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) vlv_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); + mutex_unlock(&dev_priv->display.wm.wm_mutex); } /* @@ -7137,7 +7165,7 @@ static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv) { - struct ilk_wm_values *hw = &dev_priv->wm.hw; + struct ilk_wm_values *hw = &dev_priv->display.wm.hw; struct intel_crtc *crtc; ilk_init_lp_watermarks(dev_priv); @@ -7166,6 +7194,126 @@ void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv) !(intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) & DISP_FBC_WM_DIS); } +void intel_wm_state_verify(struct intel_crtc *crtc, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct skl_hw_state { + struct skl_ddb_entry ddb[I915_MAX_PLANES]; + struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; + struct skl_pipe_wm wm; + } *hw; + const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; + int level, max_level = ilk_wm_max_level(dev_priv); + struct intel_plane *plane; + u8 hw_enabled_slices; + + if (DISPLAY_VER(dev_priv) < 9 || !new_crtc_state->hw.active) + return; + + hw = kzalloc(sizeof(*hw), GFP_KERNEL); + if (!hw) + return; + + skl_pipe_wm_get_hw_state(crtc, &hw->wm); + + skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); + + hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv); + + if (DISPLAY_VER(dev_priv) >= 11 && + hw_enabled_slices != dev_priv->dbuf.enabled_slices) + drm_err(&dev_priv->drm, + "mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n", + dev_priv->dbuf.enabled_slices, + hw_enabled_slices); + + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { + const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; + const struct skl_wm_level *hw_wm_level, *sw_wm_level; + + /* Watermarks */ + for (level = 0; level <= max_level; level++) { + hw_wm_level = &hw->wm.planes[plane->id].wm[level]; + sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level); + + if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) + continue; + + drm_err(&dev_priv->drm, + "[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + plane->base.base.id, plane->base.name, level, + sw_wm_level->enable, + sw_wm_level->blocks, + sw_wm_level->lines, + hw_wm_level->enable, + hw_wm_level->blocks, + hw_wm_level->lines); + } + + hw_wm_level = &hw->wm.planes[plane->id].trans_wm; + sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id); + + if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) { + drm_err(&dev_priv->drm, + "[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + plane->base.base.id, plane->base.name, + sw_wm_level->enable, + sw_wm_level->blocks, + sw_wm_level->lines, + hw_wm_level->enable, + hw_wm_level->blocks, + hw_wm_level->lines); + } + + hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0; + sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0; + + if (HAS_HW_SAGV_WM(dev_priv) && + !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { + drm_err(&dev_priv->drm, + "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + plane->base.base.id, plane->base.name, + sw_wm_level->enable, + sw_wm_level->blocks, + sw_wm_level->lines, + hw_wm_level->enable, + hw_wm_level->blocks, + hw_wm_level->lines); + } + + hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm; + sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm; + + if (HAS_HW_SAGV_WM(dev_priv) && + !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { + drm_err(&dev_priv->drm, + "[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + plane->base.base.id, plane->base.name, + sw_wm_level->enable, + sw_wm_level->blocks, + sw_wm_level->lines, + hw_wm_level->enable, + hw_wm_level->blocks, + hw_wm_level->lines); + } + + /* DDB */ + hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; + sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; + + if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { + drm_err(&dev_priv->drm, + "[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n", + plane->base.base.id, plane->base.name, + sw_ddb_entry->start, sw_ddb_entry->end, + hw_ddb_entry->start, hw_ddb_entry->end); + } + } + + kfree(hw); +} + void intel_enable_ipc(struct drm_i915_private *dev_priv) { u32 val; @@ -8047,18 +8195,18 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) } } -static const struct drm_i915_wm_disp_funcs skl_wm_funcs = { +static const struct intel_wm_funcs skl_wm_funcs = { .compute_global_watermarks = skl_compute_wm, }; -static const struct drm_i915_wm_disp_funcs ilk_wm_funcs = { +static const struct intel_wm_funcs ilk_wm_funcs = { .compute_pipe_wm = ilk_compute_pipe_wm, .compute_intermediate_wm = ilk_compute_intermediate_wm, .initial_watermarks = ilk_initial_watermarks, .optimize_watermarks = ilk_optimize_watermarks, }; -static const struct drm_i915_wm_disp_funcs vlv_wm_funcs = { +static const struct intel_wm_funcs vlv_wm_funcs = { .compute_pipe_wm = vlv_compute_pipe_wm, .compute_intermediate_wm = vlv_compute_intermediate_wm, .initial_watermarks = vlv_initial_watermarks, @@ -8066,30 +8214,30 @@ static const struct drm_i915_wm_disp_funcs vlv_wm_funcs = { .atomic_update_watermarks = vlv_atomic_update_fifo, }; -static const struct drm_i915_wm_disp_funcs g4x_wm_funcs = { +static const struct intel_wm_funcs g4x_wm_funcs = { .compute_pipe_wm = g4x_compute_pipe_wm, .compute_intermediate_wm = g4x_compute_intermediate_wm, .initial_watermarks = g4x_initial_watermarks, .optimize_watermarks = g4x_optimize_watermarks, }; -static const struct drm_i915_wm_disp_funcs pnv_wm_funcs = { +static const struct intel_wm_funcs pnv_wm_funcs = { .update_wm = pnv_update_wm, }; -static const struct drm_i915_wm_disp_funcs i965_wm_funcs = { +static const struct intel_wm_funcs i965_wm_funcs = { .update_wm = i965_update_wm, }; -static const struct drm_i915_wm_disp_funcs i9xx_wm_funcs = { +static const struct intel_wm_funcs i9xx_wm_funcs = { .update_wm = i9xx_update_wm, }; -static const struct drm_i915_wm_disp_funcs i845_wm_funcs = { +static const struct intel_wm_funcs i845_wm_funcs = { .update_wm = i845_update_wm, }; -static const struct drm_i915_wm_disp_funcs nop_funcs = { +static const struct intel_wm_funcs nop_funcs = { }; /* Set up chip specific power management-related functions */ @@ -8106,27 +8254,27 @@ void intel_init_pm(struct drm_i915_private *dev_priv) /* For FIFO watermark updates */ if (DISPLAY_VER(dev_priv) >= 9) { skl_setup_wm_latency(dev_priv); - dev_priv->wm_disp = &skl_wm_funcs; + dev_priv->display.funcs.wm = &skl_wm_funcs; } else if (HAS_PCH_SPLIT(dev_priv)) { ilk_setup_wm_latency(dev_priv); - if ((DISPLAY_VER(dev_priv) == 5 && dev_priv->wm.pri_latency[1] && - dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || - (DISPLAY_VER(dev_priv) != 5 && dev_priv->wm.pri_latency[0] && - dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { - dev_priv->wm_disp = &ilk_wm_funcs; + if ((DISPLAY_VER(dev_priv) == 5 && dev_priv->display.wm.pri_latency[1] && + dev_priv->display.wm.spr_latency[1] && dev_priv->display.wm.cur_latency[1]) || + (DISPLAY_VER(dev_priv) != 5 && dev_priv->display.wm.pri_latency[0] && + dev_priv->display.wm.spr_latency[0] && dev_priv->display.wm.cur_latency[0])) { + dev_priv->display.funcs.wm = &ilk_wm_funcs; } else { drm_dbg_kms(&dev_priv->drm, "Failed to read display plane latency. " "Disable CxSR\n"); - dev_priv->wm_disp = &nop_funcs; + dev_priv->display.funcs.wm = &nop_funcs; } } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { vlv_setup_wm_latency(dev_priv); - dev_priv->wm_disp = &vlv_wm_funcs; + dev_priv->display.funcs.wm = &vlv_wm_funcs; } else if (IS_G4X(dev_priv)) { g4x_setup_wm_latency(dev_priv); - dev_priv->wm_disp = &g4x_wm_funcs; + dev_priv->display.funcs.wm = &g4x_wm_funcs; } else if (IS_PINEVIEW(dev_priv)) { if (!intel_get_cxsr_latency(!IS_MOBILE(dev_priv), dev_priv->is_ddr3, @@ -8140,22 +8288,22 @@ void intel_init_pm(struct drm_i915_private *dev_priv) dev_priv->fsb_freq, dev_priv->mem_freq); /* Disable CxSR and never update its watermark again */ intel_set_memory_cxsr(dev_priv, false); - dev_priv->wm_disp = &nop_funcs; + dev_priv->display.funcs.wm = &nop_funcs; } else - dev_priv->wm_disp = &pnv_wm_funcs; + dev_priv->display.funcs.wm = &pnv_wm_funcs; } else if (DISPLAY_VER(dev_priv) == 4) { - dev_priv->wm_disp = &i965_wm_funcs; + dev_priv->display.funcs.wm = &i965_wm_funcs; } else if (DISPLAY_VER(dev_priv) == 3) { - dev_priv->wm_disp = &i9xx_wm_funcs; + dev_priv->display.funcs.wm = &i9xx_wm_funcs; } else if (DISPLAY_VER(dev_priv) == 2) { if (INTEL_NUM_PIPES(dev_priv) == 1) - dev_priv->wm_disp = &i845_wm_funcs; + dev_priv->display.funcs.wm = &i845_wm_funcs; else - dev_priv->wm_disp = &i9xx_wm_funcs; + dev_priv->display.funcs.wm = &i9xx_wm_funcs; } else { drm_err(&dev_priv->drm, "unexpected fall-through in %s\n", __func__); - dev_priv->wm_disp = &nop_funcs; + dev_priv->display.funcs.wm = &nop_funcs; } } diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h index 50604cf7398c..945503ae493e 100644 --- a/drivers/gpu/drm/i915/intel_pm.h +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -35,15 +35,12 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv); void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv); void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv); void skl_wm_get_hw_state(struct drm_i915_private *dev_priv); +void intel_wm_state_verify(struct intel_crtc *crtc, + struct intel_crtc_state *new_crtc_state); u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv); -void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, - struct skl_ddb_entry *ddb_y, - struct skl_ddb_entry *ddb_uv); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv); u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *dev_priv, const struct skl_ddb_entry *entry); -void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, - struct skl_pipe_wm *out); void g4x_wm_sanitize(struct drm_i915_private *dev_priv); void vlv_wm_sanitize(struct drm_i915_private *dev_priv); void skl_wm_sanitize(struct drm_i915_private *dev_priv); @@ -51,13 +48,6 @@ bool intel_can_enable_sagv(struct drm_i915_private *dev_priv, const struct intel_bw_state *bw_state); void intel_sagv_pre_plane_update(struct intel_atomic_state *state); void intel_sagv_post_plane_update(struct intel_atomic_state *state); -const struct skl_wm_level *skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, - enum plane_id plane_id, - int level); -const struct skl_wm_level *skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, - enum plane_id plane_id); -bool skl_wm_level_equals(const struct skl_wm_level *l1, - const struct skl_wm_level *l2); bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, const struct skl_ddb_entry *entries, int num_entries, int ignore_idx); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 5d3405cb5930..5cd423c7b646 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2086,7 +2086,7 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore) if (GRAPHICS_VER(i915) >= 11) { /* we'll prune the domains of missing engines later */ - intel_engine_mask_t emask = INTEL_INFO(i915)->platform_engine_mask; + intel_engine_mask_t emask = RUNTIME_INFO(i915)->platform_engine_mask; int i; uncore->fw_get_funcs = &uncore_get_fallback; diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c index b2d1a0f9e7af..4359e8be4101 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c @@ -9,9 +9,10 @@ #include <drm/drm_print.h> #include "gt/intel_gt_debugfs.h" -#include "pxp/intel_pxp.h" -#include "pxp/intel_pxp_irq.h" #include "i915_drv.h" +#include "intel_pxp.h" +#include "intel_pxp_debugfs.h" +#include "intel_pxp_irq.h" static int pxp_info_show(struct seq_file *m, void *data) { diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 8cd51cea77f0..915d58ba383e 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -173,14 +173,14 @@ struct drm_i915_private *mock_gem_device(void) /* Using the global GTT may ask questions about KMS users, so prepare */ drm_mode_config_init(&i915->drm); - mkwrite_device_info(i915)->graphics.ver = -1; + RUNTIME_INFO(i915)->graphics.ver = -1; - mkwrite_device_info(i915)->page_sizes = + RUNTIME_INFO(i915)->page_sizes = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M; - mkwrite_device_info(i915)->memory_regions = REGION_SMEM; + RUNTIME_INFO(i915)->memory_regions = REGION_SMEM; intel_memory_regions_hw_probe(i915); spin_lock_init(&i915->gpu_error.lock); @@ -210,7 +210,7 @@ struct drm_i915_private *mock_gem_device(void) mock_init_ggtt(to_gt(i915)); to_gt(i915)->vm = i915_vm_get(&to_gt(i915)->ggtt->vm); - mkwrite_device_info(i915)->platform_engine_mask = BIT(0); + RUNTIME_INFO(i915)->platform_engine_mask = BIT(0); to_gt(i915)->info.engine_mask = BIT(0); to_gt(i915)->engine[RCS0] = mock_engine(i915, "mock", RCS0); |