diff options
51 files changed, 959 insertions, 859 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index f47f00b162a4..2184bc5b2be7 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -266,6 +266,7 @@ i915-y += \ display/intel_quirks.o \ display/intel_sprite.o \ display/intel_tc.o \ + display/intel_vblank.o \ display/intel_vga.o \ display/i9xx_plane.o \ display/skl_scaler.o \ diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 10e1fc9d0698..1409bcfb6fd3 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -36,6 +36,7 @@ #include "gt/intel_rps.h" +#include "i915_config.h" #include "intel_atomic_plane.h" #include "intel_cdclk.h" #include "intel_display_trace.h" diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 55544d484318..78abe34c7a42 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,16 +25,15 @@ * */ -#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" -#include "display/intel_gmbus.h" +#include <drm/drm_edid.h> #include "i915_drv.h" #include "i915_reg.h" +#include "intel_display.h" +#include "intel_display_types.h" +#include "intel_gmbus.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d57631b0bb9a..8d97c299e657 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -847,17 +847,6 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state, intel_de_write_fw(i915, reg, val); } -static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, - i915_reg_t reg, u32 val) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - - if (crtc_state->dsb) - intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val); - else - intel_de_write_fw(i915, reg, val); -} - static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { @@ -962,8 +951,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state, prec_index); for (i = 0; i < lut_size; i++) - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be @@ -1093,13 +1082,13 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < glk_degamma_lut_size(i915)) - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } @@ -1165,10 +1154,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), @@ -1204,10 +1193,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } /* @@ -1225,10 +1214,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), @@ -1391,7 +1380,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) /* FIXME DSB has issues loading LUTs, disable it for now */ return; - crtc_state->dsb = intel_dsb_prepare(crtc); + crtc_state->dsb = intel_dsb_prepare(crtc, 1024); } void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 037fc140b585..82be0fbe9934 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -28,6 +28,7 @@ #include "intel_pipe_crc.h" #include "intel_psr.h" #include "intel_sprite.h" +#include "intel_vblank.h" #include "intel_vrr.h" #include "skl_universal_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1f5a471a0adf..0034a43f56e5 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4323,7 +4323,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) } if (intel_phy_is_snps(dev_priv, phy) && - dev_priv->snps_phy_failed_calibration & BIT(phy)) { + dev_priv->display.snps.phy_failed_calibration & BIT(phy)) { drm_dbg_kms(&dev_priv->drm, "SNPS PHY %c failed to calibrate, proceeding anyway\n", phy_name(phy)); diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 3dbd76fdabd6..42552d8c151e 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -22,6 +22,13 @@ intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) return intel_uncore_read8(&i915->uncore, reg); } +static inline u64 +intel_de_read64_2x32(struct drm_i915_private *i915, + i915_reg_t lower_reg, i915_reg_t upper_reg) +{ + return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg); +} + static inline void intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e75b9b2a0e01..e37cca6b18c6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -24,15 +24,15 @@ * Eric Anholt <[email protected]> */ -#include <acpi/video.h> +#include <linux/dma-resv.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/dma-resv.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/vga_switcheroo.h> +#include <acpi/video.h> #include <drm/display/drm_dp_helper.h> #include <drm/drm_atomic.h> @@ -45,28 +45,6 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> -#include "display/intel_audio.h" -#include "display/intel_crt.h" -#include "display/intel_ddi.h" -#include "display/intel_display_debugfs.h" -#include "display/intel_display_power.h" -#include "display/intel_dp.h" -#include "display/intel_dp_mst.h" -#include "display/intel_dpll.h" -#include "display/intel_dpll_mgr.h" -#include "display/intel_drrs.h" -#include "display/intel_dsi.h" -#include "display/intel_dvo.h" -#include "display/intel_fb.h" -#include "display/intel_gmbus.h" -#include "display/intel_hdmi.h" -#include "display/intel_lvds.h" -#include "display/intel_sdvo.h" -#include "display/intel_snps_phy.h" -#include "display/intel_tv.h" -#include "display/intel_vdsc.h" -#include "display/intel_vrr.h" - #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" @@ -76,31 +54,48 @@ #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" +#include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" +#include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_debugfs.h" +#include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dmc.h" +#include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_dpll.h" +#include "intel_dpll_mgr.h" #include "intel_dpt.h" +#include "intel_drrs.h" +#include "intel_dsi.h" +#include "intel_dvo.h" +#include "intel_fb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_frontbuffer.h" +#include "intel_gmbus.h" #include "intel_hdcp.h" +#include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_hti.h" -#include "intel_modeset_verify.h" +#include "intel_lvds.h" #include "intel_modeset_setup.h" +#include "intel_modeset_verify.h" #include "intel_overlay.h" #include "intel_panel.h" #include "intel_pch_display.h" @@ -112,10 +107,15 @@ #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" +#include "intel_sdvo.h" +#include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" +#include "intel_tv.h" +#include "intel_vblank.h" +#include "intel_vdsc.h" #include "intel_vga.h" -#include "i9xx_plane.h" +#include "intel_vrr.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_watermark.h" @@ -385,41 +385,6 @@ struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) return to_intel_crtc(crtc_state->uapi.crtc); } -static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t reg = PIPEDSL(pipe); - u32 line1, line2; - - line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - msleep(5); - line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - - return line1 != line2; -} - -static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - /* Wait for the display line to settle/start moving */ - if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) - drm_err(&dev_priv->drm, - "pipe %c scanline %s wait timed out\n", - pipe_name(pipe), str_on_off(state)); -} - -static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, false); -} - -static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, true); -} - static void intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { @@ -1095,22 +1060,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, return encoder; } -static void cpt_verify_modeset(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t dslreg = PIPEDSL(pipe); - u32 temp; - - temp = intel_de_read(dev_priv, dslreg); - udelay(500); - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) { - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) - drm_err(&dev_priv->drm, - "mode set failed: pipe %c stuck\n", - pipe_name(pipe)); - } -} - static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1805,7 +1754,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); if (HAS_PCH_CPT(dev_priv)) - cpt_verify_modeset(dev_priv, pipe); + intel_wait_for_pipe_scanline_moving(crtc); /* * Must wait for vblank to avoid spurious PCH FIFO underruns. @@ -1918,6 +1867,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; + intel_dmc_enable_pipe(dev_priv, crtc->pipe); + if (!new_crtc_state->bigjoiner_pipes) { intel_encoders_pre_pll_enable(state, crtc); @@ -2053,6 +2004,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, { const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* * FIXME collapse everything to one hook. @@ -2062,6 +2014,8 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); } + + intel_dmc_disable_pipe(i915, crtc->pipe); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -3292,7 +3246,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 4) { /* No way to read it out on pipes B and C */ if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) - tmp = dev_priv->chv_dpll_md[crtc->pipe]; + tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; else tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 57ddce3ba02b..24c792d44b8f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -122,6 +122,11 @@ struct intel_dpll { int nssc; int ssc; } ref_clks; + + /* + * Bitmask of PLLs using the PCH SSC, indexed using enum intel_dpll_id. + */ + u8 pch_ssc_use; }; struct intel_frontbuffer_tracking { @@ -429,6 +434,24 @@ struct intel_display { } sagv; struct { + /* + * DG2: Mask of PHYs that were not calibrated by the firmware + * and should not be used. + */ + u8 phy_failed_calibration; + } snps; + + struct { + /* + * Shadows for CHV DPLL_MD regs to keep the state + * checker somewhat working in the presence hardware + * crappiness (can't read out DPLL_MD for pipes B & C). + */ + u32 chv_dpll_md[I915_MAX_PIPES]; + u32 bxt_phy_grc; + } state; + + struct { /* ordered wq for modesets */ struct workqueue_struct *modeset; diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 725aba3fa531..651ea8564e1b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -17,6 +17,7 @@ #include "i915_irq.h" #include "intel_crtc.h" #include "intel_display_types.h" +#include "intel_vblank.h" #define __dev_name_i915(i915) dev_name((i915)->drm.dev) #define __dev_name_kms(obj) dev_name((obj)->base.dev->dev) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 4124b3d37110..257aa2b7cf20 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -42,51 +42,61 @@ #define DMC_VERSION_MAJOR(version) ((version) >> 16) #define DMC_VERSION_MINOR(version) ((version) & 0xffff) -#define DMC_PATH(platform, major, minor) \ - "i915/" \ - __stringify(platform) "_dmc_ver" \ - __stringify(major) "_" \ +#define DMC_PATH(platform) \ + "i915/" __stringify(platform) "_dmc.bin" + +/* + * New DMC additions should not use this. This is used solely to remain + * compatible with systems that have not yet updated DMC blobs to use + * unversioned file names. + */ +#define DMC_LEGACY_PATH(platform, major, minor) \ + "i915/" \ + __stringify(platform) "_dmc_ver" \ + __stringify(major) "_" \ __stringify(minor) ".bin" #define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000 #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) +#define DG2_DMC_PATH DMC_LEGACY_PATH(dg2, 2, 08) MODULE_FIRMWARE(DG2_DMC_PATH); -#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) +#define ADLP_DMC_PATH DMC_PATH(adlp) +#define ADLP_DMC_FALLBACK_PATH DMC_LEGACY_PATH(adlp, 2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); +MODULE_FIRMWARE(ADLP_DMC_FALLBACK_PATH); -#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) +#define ADLS_DMC_PATH DMC_LEGACY_PATH(adls, 2, 01) MODULE_FIRMWARE(ADLS_DMC_PATH); -#define DG1_DMC_PATH DMC_PATH(dg1, 2, 02) +#define DG1_DMC_PATH DMC_LEGACY_PATH(dg1, 2, 02) MODULE_FIRMWARE(DG1_DMC_PATH); -#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03) +#define RKL_DMC_PATH DMC_LEGACY_PATH(rkl, 2, 03) MODULE_FIRMWARE(RKL_DMC_PATH); -#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12) +#define TGL_DMC_PATH DMC_LEGACY_PATH(tgl, 2, 12) MODULE_FIRMWARE(TGL_DMC_PATH); -#define ICL_DMC_PATH DMC_PATH(icl, 1, 09) +#define ICL_DMC_PATH DMC_LEGACY_PATH(icl, 1, 09) #define ICL_DMC_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(ICL_DMC_PATH); -#define GLK_DMC_PATH DMC_PATH(glk, 1, 04) +#define GLK_DMC_PATH DMC_LEGACY_PATH(glk, 1, 04) #define GLK_DMC_MAX_FW_SIZE 0x4000 MODULE_FIRMWARE(GLK_DMC_PATH); -#define KBL_DMC_PATH DMC_PATH(kbl, 1, 04) +#define KBL_DMC_PATH DMC_LEGACY_PATH(kbl, 1, 04) #define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(KBL_DMC_PATH); -#define SKL_DMC_PATH DMC_PATH(skl, 1, 27) +#define SKL_DMC_PATH DMC_LEGACY_PATH(skl, 1, 27) #define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(SKL_DMC_PATH); -#define BXT_DMC_PATH DMC_PATH(bxt, 1, 07) +#define BXT_DMC_PATH DMC_LEGACY_PATH(bxt, 1, 07) #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); @@ -97,6 +107,8 @@ MODULE_FIRMWARE(BXT_DMC_PATH); #define DMC_V3_MAX_MMIO_COUNT 20 #define DMC_V1_MMIO_START_RANGE 0x80000 +#define PIPE_TO_DMC_ID(pipe) (DMC_FW_PIPEA + ((pipe) - PIPE_A)) + struct intel_css_header { /* 0x09 for DMC */ u32 module_type; @@ -396,6 +408,28 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) PIPEDMC_GATING_DIS, 0); } +void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe)); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE); +} + +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0); +} + /** * intel_dmc_load_program() - write the firmware from memory to register. * @dev_priv: i915 drm device. @@ -821,16 +855,40 @@ static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); } +static const char *dmc_fallback_path(struct drm_i915_private *i915) +{ + if (IS_ALDERLAKE_P(i915)) + return ADLP_DMC_FALLBACK_PATH; + + return NULL; +} + static void dmc_load_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv; struct intel_dmc *dmc; const struct firmware *fw = NULL; + const char *fallback_path; + int err; dev_priv = container_of(work, typeof(*dev_priv), display.dmc.work); dmc = &dev_priv->display.dmc; - request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + err = request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + + if (err == -ENOENT && !dev_priv->params.dmc_firmware_path) { + fallback_path = dmc_fallback_path(dev_priv); + if (fallback_path) { + drm_dbg_kms(&dev_priv->drm, + "%s not found, falling back to %s\n", + dmc->fw_path, + fallback_path); + err = request_firmware(&fw, fallback_path, dev_priv->drm.dev); + if (err == 0) + dev_priv->display.dmc.fw_path = fallback_path; + } + } + parse_dmc_fw(dev_priv, fw); if (intel_dmc_has_payload(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 435eab9b016b..fd1725de4289 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -13,6 +13,8 @@ struct drm_i915_error_state_buf; struct drm_i915_private; +enum pipe; + enum { DMC_FW_MAIN = 0, DMC_FW_PIPEA, @@ -47,6 +49,8 @@ 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_enable_pipe(struct drm_i915_private *i915, enum pipe pipe); +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe); 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 5e5e41644ddf..cf10094acae3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -11,6 +11,16 @@ #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 +#define _PIPEDMC_CONTROL_A 0x45250 +#define _PIPEDMC_CONTROL_B 0x45254 +#define PIPEDMC_CONTROL(pipe) _MMIO_PIPE(pipe, \ + _PIPEDMC_CONTROL_A, \ + _PIPEDMC_CONTROL_B) +#define PIPEDMC_ENABLE REG_BIT(0) + +#define MTL_PIPEDMC_CONTROL _MMIO(0x45250) +#define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4) + #define _ADLP_PIPEDMC_REG_MMIO_BASE_A 0x5f000 #define _TGL_PIPEDMC_REG_MMIO_BASE_A 0x92000 diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 7eb7440b3180..565c06de2432 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -376,7 +376,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { /* Still read out the GRC value for state verification */ if (phy_info->rcomp_phy != -1) - dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); + dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy); if (bxt_ddi_phy_verify_state(dev_priv, phy)) { drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, " @@ -442,8 +442,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, * the corresponding calibrated value from PHY1, and disable * the automatic calibration on PHY0. */ - val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, - phy_info->rcomp_phy); + val = bxt_get_grc(dev_priv, phy_info->rcomp_phy); + dev_priv->display.state.bxt_phy_grc = val; + grc_code = val << GRC_CODE_FAST_SHIFT | val << GRC_CODE_SLOW_SHIFT | val; @@ -568,7 +569,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, "BXT_PORT_CL2CM_DW6(%d)", phy); if (phy_info->rcomp_phy != -1) { - u32 grc_code = dev_priv->bxt_phy_grc; + u32 grc_code = dev_priv->display.state.bxt_phy_grc; grc_code = grc_code << GRC_CODE_FAST_SHIFT | grc_code << GRC_CODE_SLOW_SHIFT | diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c236aafe9be0..4e9c18be7e1f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1910,7 +1910,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, DPLL_MD(PIPE_B), crtc_state->dpll_hw_state.dpll_md); intel_de_write(dev_priv, CBR4_VLV, 0); - dev_priv->chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; + dev_priv->display.state.chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; /* * DPLLB VGA mode also seems to cause problems. diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1974eb580ed1..380368eff31a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -618,7 +618,7 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } @@ -636,7 +636,7 @@ static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 5b9e44443814..29c6421cd666 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -374,16 +374,16 @@ out: return ret; } -DEFINE_SIMPLE_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, - NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, + NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc) { debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry, crtc, &intel_drrs_debugfs_status_fops); - debugfs_create_file("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, - crtc, &intel_drrs_debugfs_ctl_fops); + debugfs_create_file_unsafe("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_ctl_fops); } static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 3d63c1bf1e4f..96bc117fd6a0 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -30,21 +30,24 @@ struct intel_dsb { struct intel_crtc *crtc; /* - * free_pos will point the first free entry position - * and help in calculating tail of command buffer. + * maximum number of dwords the buffer will hold. */ - int free_pos; + unsigned int size; /* - * ins_start_offset will help to store start address of the dsb + * free_pos will point the first free dword and + * help in calculating tail of command buffer. + */ + unsigned int free_pos; + + /* + * ins_start_offset will help to store start dword of the dsb * instuction and help in identifying the batch of auto-increment * register. */ - u32 ins_start_offset; + unsigned int ins_start_offset; }; -#define DSB_BUF_SIZE (2 * PAGE_SIZE) - /** * DOC: DSB * @@ -64,80 +67,86 @@ struct intel_dsb { /* DSB opcodes. */ #define DSB_OPCODE_SHIFT 24 +#define DSB_OPCODE_NOOP 0x0 #define DSB_OPCODE_MMIO_WRITE 0x1 +#define DSB_OPCODE_WAIT_USEC 0x2 +#define DSB_OPCODE_WAIT_LINES 0x3 +#define DSB_OPCODE_WAIT_VBLANKS 0x4 +#define DSB_OPCODE_WAIT_DSL_IN 0x5 +#define DSB_OPCODE_WAIT_DSL_OUT 0x6 +#define DSB_OPCODE_INTERRUPT 0x7 #define DSB_OPCODE_INDEXED_WRITE 0x9 +#define DSB_OPCODE_POLL 0xA #define DSB_BYTE_EN 0xF #define DSB_BYTE_EN_SHIFT 20 #define DSB_REG_VALUE_MASK 0xfffff +static bool assert_dsb_has_room(struct intel_dsb *dsb) +{ + struct intel_crtc *crtc = dsb->crtc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + /* each instruction is 2 dwords */ + return !drm_WARN(&i915->drm, dsb->free_pos > dsb->size - 2, + "DSB buffer overflow\n"); +} + static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { - return DSB_STATUS & intel_de_read(i915, DSB_CTRL(pipe, id)); + return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; } -static bool intel_dsb_enable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) +static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) { - u32 dsb_ctrl; + u32 *buf = dsb->cmd_buf; - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } + if (!assert_dsb_has_room(dsb)) + return; - dsb_ctrl |= DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); + /* Every instruction should be 8 byte aligned. */ + dsb->free_pos = ALIGN(dsb->free_pos, 2); + + dsb->ins_start_offset = dsb->free_pos; - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - return true; + buf[dsb->free_pos++] = ldw; + buf[dsb->free_pos++] = udw; } -static bool intel_dsb_disable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) +static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, + u32 opcode, i915_reg_t reg) { - u32 dsb_ctrl; + const u32 *buf = dsb->cmd_buf; + u32 prev_opcode, prev_reg; - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } + prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT; + prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; + + return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); +} - dsb_ctrl &= ~DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); +static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg); +} - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - return true; +static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg); } /** - * intel_dsb_indexed_reg_write() -Write to the DSB context for auto - * increment register. + * intel_dsb_reg_write() - Emit register wriite to the DSB context * @dsb: DSB context * @reg: register address. * @val: value. * * This function is used for writing register-value pair in command - * buffer of DSB for auto-increment register. During command buffer overflow, - * a warning is thrown and rest all erroneous condition register programming - * is done through mmio write. + * buffer of DSB. */ - -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) +void intel_dsb_reg_write(struct intel_dsb *dsb, + i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; - u32 reg_val; - - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); - return; - } - /* * For example the buffer will look like below for 3 dwords for auto * increment register: @@ -154,65 +163,55 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, * we are writing odd no of dwords, Zeros will be added in the end for * padding. */ - reg_val = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; - if (reg_val != i915_mmio_reg_offset(reg)) { - /* Every instruction should be 8 byte aligned. */ - dsb->free_pos = ALIGN(dsb->free_pos, 2); + if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) && + !intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { + intel_dsb_emit(dsb, val, + (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | + (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | + i915_mmio_reg_offset(reg)); + } else { + u32 *buf = dsb->cmd_buf; - dsb->ins_start_offset = dsb->free_pos; + if (!assert_dsb_has_room(dsb)) + return; - /* Update the size. */ - buf[dsb->free_pos++] = 1; + /* convert to indexed write? */ + if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { + u32 prev_val = buf[dsb->ins_start_offset + 0]; - /* Update the opcode and reg. */ - buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE << - DSB_OPCODE_SHIFT) | - i915_mmio_reg_offset(reg); + buf[dsb->ins_start_offset + 0] = 1; /* count */ + buf[dsb->ins_start_offset + 1] = + (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | + i915_mmio_reg_offset(reg); + buf[dsb->ins_start_offset + 2] = prev_val; - /* Update the value. */ - buf[dsb->free_pos++] = val; - } else { - /* Update the new value. */ - buf[dsb->free_pos++] = val; + dsb->free_pos++; + } - /* Update the size. */ + buf[dsb->free_pos++] = val; + /* Update the count */ buf[dsb->ins_start_offset]++; - } - /* if number of data words is odd, then the last dword should be 0.*/ - if (dsb->free_pos & 0x1) - buf[dsb->free_pos] = 0; + /* if number of data words is odd, then the last dword should be 0.*/ + if (dsb->free_pos & 0x1) + buf[dsb->free_pos] = 0; + } } -/** - * intel_dsb_reg_write() -Write to the DSB context for normal - * register. - * @crtc_state: intel_crtc_state structure - * @reg: register address. - * @val: value. - * - * This function is used for writing register-value pair in command - * buffer of DSB. During command buffer overflow, a warning is thrown - * and rest all erroneous condition register programming is done - * through mmio write. - */ -void intel_dsb_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) +static u32 intel_dsb_align_tail(struct intel_dsb *dsb) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf = dsb->cmd_buf; + u32 aligned_tail, tail; - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); - return; - } + tail = dsb->free_pos * 4; + aligned_tail = ALIGN(tail, CACHELINE_BYTES); - dsb->ins_start_offset = dsb->free_pos; - buf[dsb->free_pos++] = val; - buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | - (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | - i915_mmio_reg_offset(reg); + if (aligned_tail > tail) + memset(&dsb->cmd_buf[dsb->free_pos], 0, + aligned_tail - tail); + + dsb->free_pos = aligned_tail / 4; + + return aligned_tail; } /** @@ -228,50 +227,41 @@ void intel_dsb_commit(struct intel_dsb *dsb) enum pipe pipe = crtc->pipe; u32 tail; - if (!(dsb && dsb->free_pos)) + tail = intel_dsb_align_tail(dsb); + if (tail == 0) return; - if (!intel_dsb_enable_engine(dev_priv, pipe, dsb->id)) - goto reset; - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "HEAD_PTR write failed - dsb engine is busy.\n"); + drm_err(&dev_priv->drm, "DSB engine is busy.\n"); goto reset; } + + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), + DSB_ENABLE); intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id), i915_ggtt_offset(dsb->vma)); + intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), + i915_ggtt_offset(dsb->vma) + tail); - tail = ALIGN(dsb->free_pos * 4, CACHELINE_BYTES); - if (tail > dsb->free_pos * 4) - memset(&dsb->cmd_buf[dsb->free_pos], 0, - (tail - dsb->free_pos * 4)); - - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "TAIL_PTR write failed - dsb engine is busy.\n"); - goto reset; - } drm_dbg_kms(&dev_priv->drm, "DSB execution started - head 0x%x, tail 0x%x\n", - i915_ggtt_offset(dsb->vma), tail); - intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), - i915_ggtt_offset(dsb->vma) + tail); - if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) { + i915_ggtt_offset(dsb->vma), + i915_ggtt_offset(dsb->vma) + tail); + + if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) drm_err(&dev_priv->drm, "Timed out waiting for DSB workload completion.\n"); - goto reset; - } reset: dsb->free_pos = 0; dsb->ins_start_offset = 0; - intel_dsb_disable_engine(dev_priv, pipe, dsb->id); + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0); } /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. * @crtc: the CRTC + * @max_cmds: number of commands we need to fit into command buffer * * This function prepare the command buffer which is used to store dsb * instructions with data. @@ -279,25 +269,30 @@ reset: * Returns: * DSB context, NULL on failure */ -struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc, + unsigned int max_cmds) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_dsb *dsb; struct drm_i915_gem_object *obj; + intel_wakeref_t wakeref; + struct intel_dsb *dsb; struct i915_vma *vma; + unsigned int size; u32 *buf; - intel_wakeref_t wakeref; if (!HAS_DSB(i915)) return NULL; - dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); + dsb = kzalloc(sizeof(*dsb), GFP_KERNEL); if (!dsb) goto out; wakeref = intel_runtime_pm_get(&i915->runtime_pm); - obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); + /* ~1 qword per instruction, full cachelines */ + size = ALIGN(max_cmds * 8, CACHELINE_BYTES); + + obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size)); if (IS_ERR(obj)) goto out_put_rpm; @@ -319,6 +314,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) dsb->vma = vma; dsb->crtc = crtc; dsb->cmd_buf = buf; + dsb->size = size / 4; /* in dwords */ dsb->free_pos = 0; dsb->ins_start_offset = 0; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 25f13c4d5389..05c221b6d0a4 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -13,12 +13,11 @@ struct intel_crtc; struct intel_dsb; -struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc, + unsigned int max_cmds); void intel_dsb_cleanup(struct intel_dsb *dsb); void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val); void intel_dsb_commit(struct intel_dsb *dsb); #endif diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 5e69d3c11d21..b507ff944864 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -331,15 +331,15 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_fb.start, U32_MAX)); - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_llb.start, U32_MAX)); intel_de_write(i915, FBC_CFB_BASE, - i915->dsm.start + fbc->compressed_fb.start); + i915->dsm.stolen.start + fbc->compressed_fb.start); intel_de_write(i915, FBC_LL_BASE, - i915->dsm.start + fbc->compressed_llb.start); + i915->dsm.stolen.start + fbc->compressed_llb.start); } static const struct intel_fbc_funcs i8xx_fbc_funcs = { @@ -712,7 +712,7 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(i915) || (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) - end = resource_size(&i915->dsm) - 8 * 1024 * 1024; + end = resource_size(&i915->dsm.stolen) - 8 * 1024 * 1024; else end = U64_MAX; @@ -1807,10 +1807,10 @@ static int intel_fbc_debugfs_false_color_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, - intel_fbc_debugfs_false_color_get, - intel_fbc_debugfs_false_color_set, - "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, + intel_fbc_debugfs_false_color_get, + intel_fbc_debugfs_false_color_set, + "%llu\n"); static void intel_fbc_debugfs_add(struct intel_fbc *fbc, struct dentry *parent) @@ -1819,8 +1819,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc, fbc, &intel_fbc_debugfs_status_fops); if (fbc->funcs->set_false_color) - debugfs_create_file("i915_fbc_false_color", 0644, parent, - fbc, &intel_fbc_debugfs_false_color_fops); + debugfs_create_file_unsafe("i915_fbc_false_color", 0644, parent, + fbc, &intel_fbc_debugfs_false_color_fops); } void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index bbdb98d7c96e..19f3b5d92a55 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -170,7 +170,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, * important and we should probably use that space with FBC or other * features. */ - if (size * 2 < dev_priv->stolen_usable_size) + if (size * 2 < dev_priv->dsm.usable_size) obj = i915_gem_object_create_stolen(dev_priv, size); if (IS_ERR(obj)) obj = i915_gem_object_create_shmem(dev_priv, size); diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 96395bfbd41d..52cdbd4fc2fa 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -698,8 +698,10 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, drm_crtc_vblank_reset(&crtc->base); - if (crtc_state->hw.active) + if (crtc_state->hw.active) { + intel_dmc_enable_pipe(i915, crtc->pipe); intel_crtc_vblank_on(crtc_state); + } } intel_fbc_sanitize(i915); diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 08a94365b7d1..3657b2940702 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -467,24 +467,24 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) * clock hierarchy. That would also allow us to do * clock bending finally. */ - dev_priv->pch_ssc_use = 0; + dev_priv->display.dpll.pch_ssc_use = 0; if (spll_uses_pch_ssc(dev_priv)) { drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_SPLL); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL1); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL2); } - if (dev_priv->pch_ssc_use) + if (dev_priv->display.dpll.pch_ssc_use) return; if (has_fdi) { diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index e9774670e3f6..8d3ea8d7b737 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -72,14 +72,13 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, - enum pipe pipe, - enum intel_pipe_crc_source *source) +static void i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, + enum pipe pipe, + enum intel_pipe_crc_source *source) { struct intel_encoder *encoder; struct intel_crtc *crtc; struct intel_digital_port *dig_port; - int ret = 0; *source = INTEL_PIPE_CRC_SOURCE_PIPE; @@ -121,8 +120,6 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, } } drm_modeset_unlock_all(&dev_priv->drm); - - return ret; } static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, @@ -132,11 +129,8 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, { bool need_stable_symbols = false; - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: @@ -200,11 +194,8 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum intel_pipe_crc_source *source, u32 *val) { - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 76be796df255..bb6ea7de5c61 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -107,7 +107,7 @@ initial_plane_vma(struct drm_i915_private *i915, */ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && mem == i915->mm.stolen_region && - size * 2 > i915->stolen_usable_size) + size * 2 > i915->dsm.usable_size) return NULL; obj = i915_gem_object_create_region_at(mem, phys_base, size, 0); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d0d774219cc5..7d4a15a283a0 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -24,14 +24,13 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> -#include "display/intel_dp.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" @@ -1112,6 +1111,8 @@ static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp) return LATENCY_REPORTING_REMOVED_PIPE_B; case PIPE_C: return LATENCY_REPORTING_REMOVED_PIPE_C; + case PIPE_D: + return LATENCY_REPORTING_REMOVED_PIPE_D; default: MISSING_CASE(intel_dp->psr.pipe); return 0; @@ -1163,6 +1164,23 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, intel_dp->psr.psr2_sel_fetch_enabled ? IGNORE_PSR2_HW_TRACKING : 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) { + u16 vtotal, vblank; + + vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - + crtc_state->uapi.adjusted_mode.crtc_vdisplay; + vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - + crtc_state->uapi.adjusted_mode.crtc_vblank_start; + if (vblank > vtotal) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, + wa_16013835468_bit_get(intel_dp)); + } + if (intel_dp->psr.psr2_enabled) { if (DISPLAY_VER(dev_priv) == 9) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, @@ -1196,20 +1214,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, CLKGATE_DIS_MISC_DMASC_GATING_DIS); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) { - u16 vtotal, vblank; - - vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - - crtc_state->uapi.adjusted_mode.crtc_vdisplay; - vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - - crtc_state->uapi.adjusted_mode.crtc_vblank_start; - if (vblank > vtotal) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, - wa_16013835468_bit_get(intel_dp)); - } } } @@ -1362,6 +1366,15 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + wa_16013835468_bit_get(intel_dp), 0); + if (intel_dp->psr.psr2_enabled) { /* Wa_16011168373:adl-p */ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) @@ -1377,12 +1390,6 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, - wa_16013835468_bit_get(intel_dp), 0); } intel_snps_phy_update_psr_power_state(dev_priv, phy, false); diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 9494cfd45519..c65c771f5c46 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -40,7 +40,7 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) */ if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy), DG2_PHY_DP_TX_ACK_MASK, 25)) - i915->snps_phy_failed_calibration |= BIT(phy); + i915->display.snps.phy_failed_calibration |= BIT(phy); } } diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c new file mode 100644 index 000000000000..4c83e2320bca --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_vblank.h" + +/* + * This timing diagram depicts the video signal in and + * around the vertical blanking period. + * + * Assumptions about the fictitious mode used in this example: + * vblank_start >= 3 + * vsync_start = vblank_start + 1 + * vsync_end = vblank_start + 2 + * vtotal = vblank_start + 3 + * + * start of vblank: + * latch double buffered registers + * increment frame counter (ctg+) + * generate start of vblank interrupt (gen4+) + * | + * | frame start: + * | generate frame start interrupt (aka. vblank interrupt) (gmch) + * | may be shifted forward 1-3 extra lines via PIPECONF + * | | + * | | start of vsync: + * | | generate vsync interrupt + * | | | + * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx + * . \hs/ . \hs/ \hs/ \hs/ . \hs/ + * ----va---> <-----------------vb--------------------> <--------va------------- + * | | <----vs-----> | + * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) + * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) + * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) + * | | | + * last visible pixel first visible pixel + * | increment frame counter (gen3/4) + * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) + * + * x = horizontal active + * _ = horizontal blanking + * hs = horizontal sync + * va = vertical active + * vb = vertical blanking + * vs = vertical sync + * vbs = vblank_start (number) + * + * Summary: + * - most events happen at the start of horizontal sync + * - frame start happens at the start of horizontal blank, 1-4 lines + * (depending on PIPECONF settings) after the start of vblank + * - gen3/4 pixel and frame counter are synchronized with the start + * of horizontal active on the first line of vertical active + */ + +/* + * Called from drm generic code, passed a 'crtc', which we use as a pipe index. + */ +u32 i915_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + const struct drm_display_mode *mode = &vblank->hwmode; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + u32 pixel, vbl_start, hsync_start, htotal; + u64 frame; + + /* + * On i965gm TV output the frame counter only works up to + * the point when we enable the TV encoder. After that the + * frame counter ceases to work and reads zero. We need a + * vblank wait before enabling the TV encoder and so we + * have to enable vblank interrupts while the frame counter + * is still in a working state. However the core vblank code + * does not like us returning non-zero frame counter values + * when we've told it that we don't have a working frame + * counter. Thus we must stop non-zero values leaking out. + */ + if (!vblank->max_vblank_count) + return 0; + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vbl_start = mode->crtc_vblank_start; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vbl_start = DIV_ROUND_UP(vbl_start, 2); + + /* Convert to pixel count */ + vbl_start *= htotal; + + /* Start of vblank event occurs at start of hsync */ + vbl_start -= htotal - hsync_start; + + /* + * High & low register fields aren't synchronized, so make sure + * we get a low value that's stable across two reads of the high + * register. + */ + frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe)); + + pixel = frame & PIPE_PIXEL_MASK; + frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; + + /* + * The frame counter increments at beginning of active. + * Cook up a vblank counter by also checking the pixel + * counter against vblank start. + */ + return (frame + (pixel >= vbl_start)) & 0xffffff; +} + +u32 g4x_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + + if (!vblank->max_vblank_count) + return 0; + + return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(pipe)); +} + +static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 htotal = mode->crtc_htotal; + u32 clock = mode->crtc_clock; + u32 scan_prev_time, scan_curr_time, scan_post_time; + + /* + * To avoid the race condition where we might cross into the + * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR + * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR + * during the same frame. + */ + do { + /* + * This field provides read back of the display + * pipe frame time stamp. The time stamp value + * is sampled at every start of vertical blank. + */ + scan_prev_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + + /* + * The TIMESTAMP_CTR register has the current + * time stamp value. + */ + scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); + + scan_post_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + } while (scan_post_time != scan_prev_time); + + return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, + clock), 1000 * htotal); +} + +/* + * On certain encoders on certain platforms, pipe + * scanline register will not work to get the scanline, + * since the timings are driven from the PORT or issues + * with scanline register updates. + * This function will use Framestamp and current + * timestamp registers to calculate the scanline. + */ +static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) +{ + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 vblank_start = mode->crtc_vblank_start; + u32 vtotal = mode->crtc_vtotal; + u32 scanline; + + scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); + scanline = min(scanline, vtotal - 1); + scanline = (scanline + vblank_start) % vtotal; + + return scanline; +} + +/* + * intel_de_read_fw(), only for fast reads of display block, no need for + * forcewake etc. + */ +static int __intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + const struct drm_display_mode *mode; + struct drm_vblank_crtc *vblank; + enum pipe pipe = crtc->pipe; + int position, vtotal; + + if (!crtc->active) + return 0; + + vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + mode = &vblank->hwmode; + + if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) + return __intel_get_crtc_scanline_from_timestamp(crtc); + + vtotal = mode->crtc_vtotal; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + + /* + * On HSW, the DSL reg (0x70000) appears to return 0 if we + * read it just before the start of vblank. So try it again + * so we don't accidentally end up spanning a vblank frame + * increment, causing the pipe_update_end() code to squak at us. + * + * The nature of this problem means we can't simply check the ISR + * bit and return the vblank start value; nor can we use the scanline + * debug register in the transcoder as it appears to have the same + * problem. We may need to extend this to include other platforms, + * but so far testing only shows the problem on HSW. + */ + if (HAS_DDI(dev_priv) && !position) { + int i, temp; + + for (i = 0; i < 100; i++) { + udelay(1); + temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + if (temp != position) { + position = temp; + break; + } + } + } + + /* + * See update_scanline_offset() for the details on the + * scanline_offset adjustment. + */ + return (position + crtc->scanline_offset) % vtotal; +} + +static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, + bool in_vblank_irq, + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) +{ + struct drm_device *dev = _crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(_crtc); + enum pipe pipe = crtc->pipe; + int position; + int vbl_start, vbl_end, hsync_start, htotal, vtotal; + unsigned long irqflags; + bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || + IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || + crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; + + if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { + drm_dbg(&dev_priv->drm, + "trying to get scanoutpos for disabled pipe %c\n", + pipe_name(pipe)); + return false; + } + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vtotal = mode->crtc_vtotal; + vbl_start = mode->crtc_vblank_start; + vbl_end = mode->crtc_vblank_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_end /= 2; + vtotal /= 2; + } + + /* + * Lock uncore.lock, as we will do multiple timing critical raw + * register reads, potentially with preemption disabled, so the + * following code must not block on uncore.lock. + */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Get optional system timestamp before query. */ + if (stime) + *stime = ktime_get(); + + if (crtc->mode_flags & I915_MODE_FLAG_VRR) { + int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); + + position = __intel_get_crtc_scanline(crtc); + + /* + * Already exiting vblank? If so, shift our position + * so it looks like we're already apporaching the full + * vblank end. This should make the generated timestamp + * more or less match when the active portion will start. + */ + if (position >= vbl_start && scanlines < position) + position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); + } else if (use_scanline_counter) { + /* No obvious pixelcount register. Only query vertical + * scanout position from Display scan line register. + */ + position = __intel_get_crtc_scanline(crtc); + } else { + /* + * Have access to pixelcount since start of frame. + * We can split this into vertical and horizontal + * scanout position. + */ + position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + + /* convert to pixel counts */ + vbl_start *= htotal; + vbl_end *= htotal; + vtotal *= htotal; + + /* + * In interlaced modes, the pixel counter counts all pixels, + * so one field will have htotal more pixels. In order to avoid + * the reported position from jumping backwards when the pixel + * counter is beyond the length of the shorter field, just + * clamp the position the length of the shorter field. This + * matches how the scanline counter based position works since + * the scanline counter doesn't count the two half lines. + */ + if (position >= vtotal) + position = vtotal - 1; + + /* + * Start of vblank interrupt is triggered at start of hsync, + * just prior to the first active line of vblank. However we + * consider lines to start at the leading edge of horizontal + * active. So, should we get here before we've crossed into + * the horizontal active of the first line in vblank, we would + * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, + * always add htotal-hsync_start to the current pixel position. + */ + position = (position + htotal - hsync_start) % vtotal; + } + + /* Get optional system timestamp after query. */ + if (etime) + *etime = ktime_get(); + + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + /* + * While in vblank, position will be negative + * counting up towards 0 at vbl_end. And outside + * vblank, position will be positive counting + * up since vbl_end. + */ + if (position >= vbl_start) + position -= vbl_end; + else + position += vtotal - vbl_end; + + if (use_scanline_counter) { + *vpos = position; + *hpos = 0; + } else { + *vpos = position / htotal; + *hpos = position - (*vpos * htotal); + } + + return true; +} + +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq) +{ + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( + crtc, max_error, vblank_time, in_vblank_irq, + i915_get_crtc_scanoutpos); +} + +int intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + unsigned long irqflags; + int position; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + position = __intel_get_crtc_scanline(crtc); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + return position; +} + +static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + i915_reg_t reg = PIPEDSL(pipe); + u32 line1, line2; + + line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + msleep(5); + line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + + return line1 != line2; +} + +static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + /* Wait for the display line to settle/start moving */ + if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) + drm_err(&dev_priv->drm, + "pipe %c scanline %s wait timed out\n", + pipe_name(pipe), str_on_off(state)); +} + +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, false); +} + +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, true); +} diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h new file mode 100644 index 000000000000..c9fea2c2a990 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#ifndef __INTEL_VBLANK_H__ +#define __INTEL_VBLANK_H__ + +#include <linux/ktime.h> +#include <linux/types.h> + +struct drm_crtc; +struct intel_crtc; + +u32 i915_get_vblank_counter(struct drm_crtc *crtc); +u32 g4x_get_vblank_counter(struct drm_crtc *crtc); +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq); +int intel_get_crtc_scanline(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc); + +#endif /* __INTEL_VBLANK_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 01e881293612..473d53610b92 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 +#define TGL_MAX_SRC_W 5120 +#define TGL_MAX_SRC_H 8192 +#define TGL_MAX_DST_W 8192 +#define TGL_MAX_DST_H 8192 #define MTL_MAX_SRC_W 4096 #define MTL_MAX_SRC_H 8192 #define MTL_MAX_DST_W 8192 @@ -173,11 +177,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, max_src_h = SKL_MAX_SRC_H; max_dst_w = SKL_MAX_DST_W; max_dst_h = SKL_MAX_DST_H; - } else if (DISPLAY_VER(dev_priv) < 14) { + } else if (DISPLAY_VER(dev_priv) < 12) { max_src_w = ICL_MAX_SRC_W; max_src_h = ICL_MAX_SRC_H; max_dst_w = ICL_MAX_DST_W; max_dst_h = ICL_MAX_DST_H; + } else if (DISPLAY_VER(dev_priv) < 14) { + max_src_w = TGL_MAX_SRC_W; + max_src_h = TGL_MAX_SRC_H; + max_dst_w = TGL_MAX_DST_W; + max_dst_h = TGL_MAX_DST_H; } else { max_src_w = MTL_MAX_SRC_W; max_src_h = MTL_MAX_SRC_H; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4b79c2d2d617..9b172a1e90de 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1627,7 +1627,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) u32 offset; int ret; - if (w > max_width || w < min_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height || h < 1) { drm_dbg_kms(&dev_priv->drm, "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", w, h, min_width, max_width, max_height); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index b3b398fe689c..385ffc575b48 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -8,6 +8,7 @@ #include "display/intel_frontbuffer.h" +#include "i915_config.h" #include "i915_drv.h" #include "i915_gem_clflush.h" #include "i915_sw_fence_work.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index bc9521078807..90a967374b1a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -110,9 +110,7 @@ static int adjust_stolen(struct drm_i915_private *i915, else ggtt_start &= PGTBL_ADDRESS_LO_MASK; - ggtt_res = - (struct resource) DEFINE_RES_MEM(ggtt_start, - ggtt_total_entries(ggtt) * 4); + ggtt_res = DEFINE_RES_MEM(ggtt_start, ggtt_total_entries(ggtt) * 4); if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end) stolen[0].end = ggtt_res.start; @@ -211,7 +209,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *i915, IS_GM45(i915) ? CTG_STOLEN_RESERVED : ELK_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "%s_STOLEN_RESERVED = %08x\n", IS_GM45(i915) ? "CTG" : "ELK", reg_val); @@ -276,7 +274,7 @@ static void vlv_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -365,7 +363,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -414,7 +412,7 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915, } /* - * Initialize i915->dsm_reserved to contain the reserved space within the Data + * Initialize i915->dsm.reserved to contain the reserved space within the Data * Stolen Memory. This is a range on the top of DSM that is reserved, not to * be used by driver, so must be excluded from the region passed to the * allocator later. In the spec this is also called as WOPCM. @@ -430,7 +428,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) resource_size_t reserved_size; int ret = 0; - stolen_top = i915->dsm.end + 1; + stolen_top = i915->dsm.stolen.end + 1; reserved_base = stolen_top; reserved_size = 0; @@ -471,13 +469,12 @@ static int init_reserved_stolen(struct drm_i915_private *i915) goto bail_out; } - i915->dsm_reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, reserved_size); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, reserved_size); - if (!resource_contains(&i915->dsm, &i915->dsm_reserved)) { + if (!resource_contains(&i915->dsm.stolen, &i915->dsm.reserved)) { drm_err(&i915->drm, "Stolen reserved area %pR outside stolen memory %pR\n", - &i915->dsm_reserved, &i915->dsm); + &i915->dsm.reserved, &i915->dsm.stolen); ret = -EINVAL; goto bail_out; } @@ -485,8 +482,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) return 0; bail_out: - i915->dsm_reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, 0); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, 0); return ret; } @@ -517,27 +513,27 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem) if (request_smem_stolen(i915, &mem->region)) return -ENOSPC; - i915->dsm = mem->region; + i915->dsm.stolen = mem->region; if (init_reserved_stolen(i915)) return -ENOSPC; /* Exclude the reserved region from driver use */ - mem->region.end = i915->dsm_reserved.start - 1; + mem->region.end = i915->dsm.reserved.start - 1; mem->io_size = min(mem->io_size, resource_size(&mem->region)); - i915->stolen_usable_size = resource_size(&mem->region); + i915->dsm.usable_size = resource_size(&mem->region); drm_dbg(&i915->drm, "Memory reserved for graphics device: %lluK, usable: %lluK\n", - (u64)resource_size(&i915->dsm) >> 10, - (u64)i915->stolen_usable_size >> 10); + (u64)resource_size(&i915->dsm.stolen) >> 10, + (u64)i915->dsm.usable_size >> 10); - if (i915->stolen_usable_size == 0) + if (i915->dsm.usable_size == 0) return -ENOSPC; /* Basic memrange allocator for stolen space. */ - drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size); + drm_mm_init(&i915->mm.stolen, 0, i915->dsm.usable_size); return 0; } @@ -587,7 +583,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, struct sg_table *st; struct scatterlist *sg; - GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm))); + GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm.stolen))); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -607,7 +603,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, sg->offset = 0; sg->length = size; - sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset; + sg_dma_address(sg) = (dma_addr_t)i915->dsm.stolen.start + offset; sg_dma_len(sg) = size; return st; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 0c7fe360f873..fe64c13fd3b4 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -885,8 +885,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm) static struct resource pci_resource(struct pci_dev *pdev, int bar) { - return (struct resource)DEFINE_RES_MEM(pci_resource_start(pdev, bar), - pci_resource_len(pdev, bar)); + return DEFINE_RES_MEM(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); } static int gen8_gmch_probe(struct i915_ggtt *ggtt) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 0e3630103693..1c492eaee7d9 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -88,8 +88,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) intel_gmch_gtt_get(&ggtt->vm.total, &gmadr_base, &ggtt->mappable_end); - ggtt->gmadr = - (struct resource)DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); + ggtt->gmadr = DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); ggtt->vm.alloc_pt_dma = alloc_pt_dma; ggtt->vm.alloc_scratch_dma = alloc_pt_dma; diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 2ee4051e4d96..5c91622dfca4 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -301,7 +301,7 @@ static int chv_rc6_init(struct intel_rc6 *rc6) pcbr = intel_uncore_read(uncore, VLV_PCBR); if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { drm_dbg(&i915->drm, "BIOS didn't set up PCBR, fixing up\n"); - paddr = i915->dsm.end + 1 - pctx_size; + paddr = i915->dsm.stolen.end + 1 - pctx_size; GEM_BUG_ON(paddr > U32_MAX); pctx_paddr = (paddr & ~4095); @@ -325,7 +325,7 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) /* BIOS set it up already, grab the pre-alloc'd space */ resource_size_t pcbr_offset; - pcbr_offset = (pcbr & ~4095) - i915->dsm.start; + pcbr_offset = (pcbr & ~4095) - i915->dsm.stolen.start; pctx = i915_gem_object_create_region_at(i915->mm.stolen_region, pcbr_offset, pctx_size, @@ -354,10 +354,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) } GEM_BUG_ON(range_overflows_end_t(u64, - i915->dsm.start, + i915->dsm.stolen.start, pctx->stolen->start, U32_MAX)); - pctx_paddr = i915->dsm.start + pctx->stolen->start; + pctx_paddr = i915->dsm.stolen.start + pctx->stolen->start; intel_uncore_write(uncore, VLV_PCBR, pctx_paddr); out: @@ -448,8 +448,8 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6) */ rc6_ctx_base = intel_uncore_read(uncore, RC6_CTX_BASE) & RC6_CTX_BASE_MASK; - if (!(rc6_ctx_base >= i915->dsm_reserved.start && - rc6_ctx_base + PAGE_SIZE < i915->dsm_reserved.end)) { + if (!(rc6_ctx_base >= i915->dsm.reserved.start && + rc6_ctx_base + PAGE_SIZE < i915->dsm.reserved.end)) { drm_dbg(&i915->drm, "RC6 Base address not as expected.\n"); enable_rc6 = false; } diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 9e1cad9ba0e9..c622962c6bef 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -12,6 +12,9 @@ struct i915_request; struct drm_printer; +#define GT_FREQUENCY_MULTIPLIER 50 +#define GEN9_FREQ_SCALER 3 + void intel_rps_init_early(struct intel_rps *rps); void intel_rps_init(struct intel_rps *rps); void intel_rps_sanitize(struct intel_rps *rps); diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c index 37c38bdd5f47..a9e0a91bc0e0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_reset.c +++ b/drivers/gpu/drm/i915/gt/selftest_reset.c @@ -20,7 +20,7 @@ __igt_reset_stolen(struct intel_gt *gt, const char *msg) { struct i915_ggtt *ggtt = gt->ggtt; - const struct resource *dsm = >->i915->dsm; + const struct resource *dsm = >->i915->dsm.stolen; resource_size_t num_pages, page; struct intel_engine_cs *engine; intel_wakeref_t wakeref; diff --git a/drivers/gpu/drm/i915/i915_config.c b/drivers/gpu/drm/i915/i915_config.c index afb828dab53b..24e5bb8a670e 100644 --- a/drivers/gpu/drm/i915/i915_config.c +++ b/drivers/gpu/drm/i915/i915_config.c @@ -3,7 +3,10 @@ * Copyright © 2020 Intel Corporation */ -#include "i915_drv.h" +#include <linux/kernel.h> + +#include "i915_config.h" +#include "i915_utils.h" unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context) diff --git a/drivers/gpu/drm/i915/i915_config.h b/drivers/gpu/drm/i915/i915_config.h new file mode 100644 index 000000000000..10e18b036489 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_config.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __I915_CONFIG_H__ +#define __I915_CONFIG_H__ + +#include <linux/types.h> +#include <linux/limits.h> + +struct drm_i915_private; + +unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, + u64 context); + +static inline unsigned long +i915_fence_timeout(const struct drm_i915_private *i915) +{ + return i915_fence_context_timeout(i915, U64_MAX); +} + +#endif /* __I915_CONFIG_H__ */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a356ca490159..45773ce1deac 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -648,13 +648,14 @@ i915_drop_caches_get(void *data, u64 *val) return 0; } + static int gt_drop_caches(struct intel_gt *gt, u64 val) { int ret; if (val & DROP_RESET_ACTIVE && - wait_for(intel_engines_are_idle(gt), I915_IDLE_ENGINES_TIMEOUT)) + wait_for(intel_engines_are_idle(gt), 200)) intel_gt_set_wedged(gt); if (val & DROP_RETIRE) @@ -762,7 +763,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_sseu_status", i915_sseu_status, 0}, {"i915_rps_boost_info", i915_rps_boost_info, 0}, }; -#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) static const struct i915_debugfs_files { const char *name; @@ -795,6 +795,6 @@ void i915_debugfs_register(struct drm_i915_private *dev_priv) } drm_debugfs_create_files(i915_debugfs_list, - I915_DEBUGFS_ENTRIES, + ARRAY_SIZE(i915_debugfs_list), minor->debugfs_root, minor); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 48fd82722f12..2a6e212f8824 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -65,26 +65,41 @@ #include "intel_uncore.h" struct drm_i915_clock_gating_funcs; -struct drm_i915_gem_object; -struct drm_i915_private; -struct intel_connector; -struct intel_dp; -struct intel_encoder; -struct intel_limit; -struct intel_overlay_error_state; struct vlv_s0ix_state; struct intel_pxp; -#define I915_GEM_GPU_DOMAINS \ - (I915_GEM_DOMAIN_RENDER | \ - I915_GEM_DOMAIN_SAMPLER | \ - I915_GEM_DOMAIN_COMMAND | \ - I915_GEM_DOMAIN_INSTRUCTION | \ - I915_GEM_DOMAIN_VERTEX) +#define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) -#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ +/* Data Stolen Memory (DSM) aka "i915 stolen memory" */ +struct i915_dsm { + /* + * The start and end of DSM which we can optionally use to create GEM + * objects backed by stolen memory. + * + * Note that usable_size tells us exactly how much of this we are + * actually allowed to use, given that some portion of it is in fact + * reserved for use by hardware functions. + */ + struct resource stolen; -#define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) + /* + * Reserved portion of DSM. + */ + struct resource reserved; + + /* + * Total size minus reserved ranges. + * + * DSM is segmented in hardware with different portions offlimits to + * certain functions. + * + * The drm_mm is initialised to the total accessible range, as found + * from the PCI config. On Broadwell+, this is further restricted to + * avoid the first page! The upper end of DSM is reserved for hardware + * functions and similarly removed from the accessible range. + */ + resource_size_t usable_size; +}; struct i915_suspend_saved_registers { u32 saveDSPARB; @@ -163,19 +178,6 @@ struct i915_gem_mm { u32 shrink_count; }; -#define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ - -unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, - u64 context); - -static inline unsigned long -i915_fence_timeout(const struct drm_i915_private *i915) -{ - return i915_fence_context_timeout(i915, U64_MAX); -} - -#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) - struct i915_virtual_gpu { struct mutex lock; /* serialises sending of g2v_notify command pkts */ bool active; @@ -205,29 +207,7 @@ struct drm_i915_private { struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */ struct intel_driver_caps caps; - /** - * Data Stolen Memory - aka "i915 stolen memory" gives us the start and - * end of stolen which we can optionally use to create GEM objects - * backed by stolen memory. Note that stolen_usable_size tells us - * exactly how much of this we are actually allowed to use, given that - * some portion of it is in fact reserved for use by hardware functions. - */ - struct resource dsm; - /** - * Reseved portion of Data Stolen Memory - */ - struct resource dsm_reserved; - - /* - * Stolen memory is segmented in hardware with different portions - * offlimits to certain functions. - * - * The drm_mm is initialised to the total accessible range, as found - * from the PCI config. On Broadwell+, this is further restricted to - * avoid the first page! The upper end of stolen memory is reserved for - * hardware functions and similarly removed from the accessible range. - */ - resource_size_t stolen_usable_size; /* Total size minus reserved ranges */ + struct i915_dsm dsm; struct intel_uncore uncore; struct intel_uncore_mmio_debug mmio_debug; @@ -300,14 +280,6 @@ struct drm_i915_private { struct i915_gpu_error gpu_error; - /* - * Shadows for CHV DPLL_MD regs to keep the state - * checker somewhat working in the presence hardware - * crappiness (can't read out DPLL_MD for pipes B & C). - */ - u32 chv_dpll_md[I915_MAX_PIPES]; - u32 bxt_phy_grc; - u32 suspend_count; struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state *vlv_s0ix_state; @@ -368,19 +340,11 @@ struct drm_i915_private { struct intel_pxp *pxp; - u8 pch_ssc_use; - /* For i915gm/i945gm vblank irq workaround */ u8 vblank_enabled; bool irq_enabled; - /* - * DG2: Mask of PHYs that were not calibrated by the firmware - * and should not be used. - */ - u8 snps_phy_failed_calibration; - struct i915_pmu pmu; struct i915_drm_clients clients; @@ -469,9 +433,6 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision) -#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) -#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) - #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step) #define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step) #define INTEL_MEDIA_STEP(__i915) (RUNTIME_INFO(__i915)->step.media_step) @@ -883,6 +844,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_RPS(dev_priv) (INTEL_INFO(dev_priv)->has_rps) #define HAS_DMC(dev_priv) (RUNTIME_INFO(dev_priv)->has_dmc) +#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) +#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) +#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) #define HAS_HECI_PXP(dev_priv) \ (INTEL_INFO(dev_priv)->has_heci_pxp) @@ -940,9 +904,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ 2 : HAS_L3_DPF(dev_priv)) -#define GT_FREQUENCY_MULTIPLIER 50 -#define GEN9_FREQ_SCALER 3 - #define INTEL_NUM_PIPES(dev_priv) (hweight8(RUNTIME_INFO(dev_priv)->pipe_mask)) #define HAS_DISPLAY(dev_priv) (RUNTIME_INFO(dev_priv)->pipe_mask != 0) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index a5cdf6662d01..82e9d289398c 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -39,6 +39,13 @@ struct i915_gem_ww_ctx; struct i915_gtt_view; struct i915_vma; +#define I915_GEM_GPU_DOMAINS \ + (I915_GEM_DOMAIN_RENDER | \ + I915_GEM_DOMAIN_SAMPLER | \ + I915_GEM_DOMAIN_COMMAND | \ + I915_GEM_DOMAIN_INSTRUCTION | \ + I915_GEM_DOMAIN_VERTEX) + void i915_gem_init_early(struct drm_i915_private *i915); void i915_gem_cleanup_early(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 243419783052..3d77679bf211 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -18,6 +18,8 @@ struct drm_i915_gem_object; struct i915_address_space; struct i915_gem_ww_ctx; +#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ + int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj, struct sg_table *pages); void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 54ea28cf8a1a..240d5e198904 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -614,414 +614,6 @@ static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->irq_lock); } -/* - * This timing diagram depicts the video signal in and - * around the vertical blanking period. - * - * Assumptions about the fictitious mode used in this example: - * vblank_start >= 3 - * vsync_start = vblank_start + 1 - * vsync_end = vblank_start + 2 - * vtotal = vblank_start + 3 - * - * start of vblank: - * latch double buffered registers - * increment frame counter (ctg+) - * generate start of vblank interrupt (gen4+) - * | - * | frame start: - * | generate frame start interrupt (aka. vblank interrupt) (gmch) - * | may be shifted forward 1-3 extra lines via PIPECONF - * | | - * | | start of vsync: - * | | generate vsync interrupt - * | | | - * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx - * . \hs/ . \hs/ \hs/ \hs/ . \hs/ - * ----va---> <-----------------vb--------------------> <--------va------------- - * | | <----vs-----> | - * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) - * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) - * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) - * | | | - * last visible pixel first visible pixel - * | increment frame counter (gen3/4) - * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) - * - * x = horizontal active - * _ = horizontal blanking - * hs = horizontal sync - * va = vertical active - * vb = vertical blanking - * vs = vertical sync - * vbs = vblank_start (number) - * - * Summary: - * - most events happen at the start of horizontal sync - * - frame start happens at the start of horizontal blank, 1-4 lines - * (depending on PIPECONF settings) after the start of vblank - * - gen3/4 pixel and frame counter are synchronized with the start - * of horizontal active on the first line of vertical active - */ - -/* Called from drm generic code, passed a 'crtc', which - * we use as a pipe index - */ -u32 i915_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - const struct drm_display_mode *mode = &vblank->hwmode; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - i915_reg_t high_frame, low_frame; - u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - unsigned long irqflags; - - /* - * On i965gm TV output the frame counter only works up to - * the point when we enable the TV encoder. After that the - * frame counter ceases to work and reads zero. We need a - * vblank wait before enabling the TV encoder and so we - * have to enable vblank interrupts while the frame counter - * is still in a working state. However the core vblank code - * does not like us returning non-zero frame counter values - * when we've told it that we don't have a working frame - * counter. Thus we must stop non-zero values leaking out. - */ - if (!vblank->max_vblank_count) - return 0; - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vbl_start = mode->crtc_vblank_start; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vbl_start = DIV_ROUND_UP(vbl_start, 2); - - /* Convert to pixel count */ - vbl_start *= htotal; - - /* Start of vblank event occurs at start of hsync */ - vbl_start -= htotal - hsync_start; - - high_frame = PIPEFRAME(pipe); - low_frame = PIPEFRAMEPIXEL(pipe); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* - * High & low register fields aren't synchronized, so make sure - * we get a low value that's stable across two reads of the high - * register. - */ - do { - high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - low = intel_de_read_fw(dev_priv, low_frame); - high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - } while (high1 != high2); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - high1 >>= PIPE_FRAME_HIGH_SHIFT; - pixel = low & PIPE_PIXEL_MASK; - low >>= PIPE_FRAME_LOW_SHIFT; - - /* - * The frame counter increments at beginning of active. - * Cook up a vblank counter by also checking the pixel - * counter against vblank start. - */ - return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; -} - -u32 g4x_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - - if (!vblank->max_vblank_count) - return 0; - - return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); -} - -static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 htotal = mode->crtc_htotal; - u32 clock = mode->crtc_clock; - u32 scan_prev_time, scan_curr_time, scan_post_time; - - /* - * To avoid the race condition where we might cross into the - * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR - * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR - * during the same frame. - */ - do { - /* - * This field provides read back of the display - * pipe frame time stamp. The time stamp value - * is sampled at every start of vertical blank. - */ - scan_prev_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - - /* - * The TIMESTAMP_CTR register has the current - * time stamp value. - */ - scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); - - scan_post_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - } while (scan_post_time != scan_prev_time); - - return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, - clock), 1000 * htotal); -} - -/* - * On certain encoders on certain platforms, pipe - * scanline register will not work to get the scanline, - * since the timings are driven from the PORT or issues - * with scanline register updates. - * This function will use Framestamp and current - * timestamp registers to calculate the scanline. - */ -static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) -{ - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 vblank_start = mode->crtc_vblank_start; - u32 vtotal = mode->crtc_vtotal; - u32 scanline; - - scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); - scanline = min(scanline, vtotal - 1); - scanline = (scanline + vblank_start) % vtotal; - - return scanline; -} - -/* - * intel_de_read_fw(), only for fast reads of display block, no need for - * forcewake etc. - */ -static int __intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank; - enum pipe pipe = crtc->pipe; - int position, vtotal; - - if (!crtc->active) - return 0; - - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->hwmode; - - if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) - return __intel_get_crtc_scanline_from_timestamp(crtc); - - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; - - position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - - /* - * On HSW, the DSL reg (0x70000) appears to return 0 if we - * read it just before the start of vblank. So try it again - * so we don't accidentally end up spanning a vblank frame - * increment, causing the pipe_update_end() code to squak at us. - * - * The nature of this problem means we can't simply check the ISR - * bit and return the vblank start value; nor can we use the scanline - * debug register in the transcoder as it appears to have the same - * problem. We may need to extend this to include other platforms, - * but so far testing only shows the problem on HSW. - */ - if (HAS_DDI(dev_priv) && !position) { - int i, temp; - - for (i = 0; i < 100; i++) { - udelay(1); - temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - if (temp != position) { - position = temp; - break; - } - } - } - - /* - * See update_scanline_offset() for the details on the - * scanline_offset adjustment. - */ - return (position + crtc->scanline_offset) % vtotal; -} - -static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, - bool in_vblank_irq, - int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = _crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(_crtc); - enum pipe pipe = crtc->pipe; - int position; - int vbl_start, vbl_end, hsync_start, htotal, vtotal; - unsigned long irqflags; - bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || - IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || - crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; - - if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { - drm_dbg(&dev_priv->drm, - "trying to get scanoutpos for disabled " - "pipe %c\n", pipe_name(pipe)); - return false; - } - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vbl_start = DIV_ROUND_UP(vbl_start, 2); - vbl_end /= 2; - vtotal /= 2; - } - - /* - * Lock uncore.lock, as we will do multiple timing critical raw - * register reads, potentially with preemption disabled, so the - * following code must not block on uncore.lock. - */ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ - if (stime) - *stime = ktime_get(); - - if (crtc->mode_flags & I915_MODE_FLAG_VRR) { - int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); - - position = __intel_get_crtc_scanline(crtc); - - /* - * Already exiting vblank? If so, shift our position - * so it looks like we're already apporaching the full - * vblank end. This should make the generated timestamp - * more or less match when the active portion will start. - */ - if (position >= vbl_start && scanlines < position) - position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); - } else if (use_scanline_counter) { - /* No obvious pixelcount register. Only query vertical - * scanout position from Display scan line register. - */ - position = __intel_get_crtc_scanline(crtc); - } else { - /* Have access to pixelcount since start of frame. - * We can split this into vertical and horizontal - * scanout position. - */ - position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; - - /* convert to pixel counts */ - vbl_start *= htotal; - vbl_end *= htotal; - vtotal *= htotal; - - /* - * In interlaced modes, the pixel counter counts all pixels, - * so one field will have htotal more pixels. In order to avoid - * the reported position from jumping backwards when the pixel - * counter is beyond the length of the shorter field, just - * clamp the position the length of the shorter field. This - * matches how the scanline counter based position works since - * the scanline counter doesn't count the two half lines. - */ - if (position >= vtotal) - position = vtotal - 1; - - /* - * Start of vblank interrupt is triggered at start of hsync, - * just prior to the first active line of vblank. However we - * consider lines to start at the leading edge of horizontal - * active. So, should we get here before we've crossed into - * the horizontal active of the first line in vblank, we would - * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, - * always add htotal-hsync_start to the current pixel position. - */ - position = (position + htotal - hsync_start) % vtotal; - } - - /* Get optional system timestamp after query. */ - if (etime) - *etime = ktime_get(); - - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - /* - * While in vblank, position will be negative - * counting up towards 0 at vbl_end. And outside - * vblank, position will be positive counting - * up since vbl_end. - */ - if (position >= vbl_start) - position -= vbl_end; - else - position += vtotal - vbl_end; - - if (use_scanline_counter) { - *vpos = position; - *hpos = 0; - } else { - *vpos = position / htotal; - *hpos = position - (*vpos * htotal); - } - - return true; -} - -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq) -{ - return drm_crtc_vblank_helper_get_vblank_timestamp_internal( - crtc, max_error, vblank_time, in_vblank_irq, - i915_get_crtc_scanoutpos); -} - -int intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - unsigned long irqflags; - int position; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - position = __intel_get_crtc_scanline(crtc); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - return position; -} - /** * ivb_parity_work - Workqueue called when a parity error interrupt * occurred. diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 9b004fc3444e..03ee4c8b1ed3 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -66,18 +66,12 @@ bool intel_irqs_enabled(struct drm_i915_private *dev_priv); void intel_synchronize_irq(struct drm_i915_private *i915); void intel_synchronize_hardirq(struct drm_i915_private *i915); -int intel_get_crtc_scanline(struct intel_crtc *crtc); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask); void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask); u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv); -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq); - -u32 i915_get_vblank_counter(struct drm_crtc *crtc); -u32 g4x_get_vblank_counter(struct drm_crtc *crtc); int i8xx_enable_vblank(struct drm_crtc *crtc); int i915gm_enable_vblank(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8b2cf980f323..bad36a67d873 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5737,6 +5737,7 @@ #define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) +#define LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31) #define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30) #define LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25) #define LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24) @@ -8105,7 +8106,7 @@ enum skl_power_gate { #define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) #define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) #define DSB_ENABLE (1 << 31) -#define DSB_STATUS (1 << 0) +#define DSB_STATUS_BUSY (1 << 0) #define CLKREQ_POLICY _MMIO(0x101038) #define CLKREQ_POLICY_MEM_UP_OVRD REG_BIT(1) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index f949a9495758..7503dcb9043b 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -43,6 +43,7 @@ #include "gt/intel_rps.h" #include "i915_active.h" +#include "i915_config.h" #include "i915_deps.h" #include "i915_driver.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index b9a164efd6ae..3d1fdea9811d 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -235,7 +235,7 @@ intel_memory_region_create(struct drm_i915_private *i915, return ERR_PTR(-ENOMEM); mem->i915 = i915; - mem->region = (struct resource)DEFINE_RES_MEM(start, size); + mem->region = DEFINE_RES_MEM(start, size); mem->io_start = io_start; mem->io_size = io_size; mem->min_page_size = min_page_size; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 2535b9684bd1..d91d0ade8abd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -44,7 +44,7 @@ static void trash_stolen(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; const u64 slot = ggtt->error_capture.start; - const resource_size_t size = resource_size(&i915->dsm); + const resource_size_t size = resource_size(&i915->dsm.stolen); unsigned long page; u32 prng = 0x12345678; @@ -53,7 +53,7 @@ static void trash_stolen(struct drm_i915_private *i915) return; for (page = 0; page < size; page += PAGE_SIZE) { - const dma_addr_t dma = i915->dsm.start + page; + const dma_addr_t dma = i915->dsm.stolen.start + page; u32 __iomem *s; int x; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 568840e7ca66..ece97e4faacb 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -112,7 +112,7 @@ void mock_init_ggtt(struct intel_gt *gt) ggtt->vm.i915 = gt->i915; ggtt->vm.is_ggtt = true; - ggtt->gmadr = (struct resource) DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); + ggtt->gmadr = DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); ggtt->mappable_end = resource_size(&ggtt->gmadr); ggtt->vm.total = 4096 * PAGE_SIZE; |