From patchwork Fri Aug 30 17:44:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,1/7] drm/i915/tgl: Add DC3CO required register and bits From: Anshuman Gupta X-Patchwork-Id: 328337 Message-Id: <20190830174433.22227-2-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:27 +0530 Adding following definition to i915_reg.h 1. DC_STATE_EN register DC3CO bit fields and masks. 2. Transcoder EXITLINE register and its bit fields and mask. Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Signed-off-by: Anshuman Gupta --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 02e1ef10c47e..d6b6181c1ffd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4135,6 +4135,7 @@ enum { #define _VTOTAL_A 0x6000c #define _VBLANK_A 0x60010 #define _VSYNC_A 0x60014 +#define _EXITLINE_A 0x60018 #define _PIPEASRC 0x6001c #define _BCLRPAT_A 0x60020 #define _VSYNCSHIFT_A 0x60028 @@ -4181,11 +4182,16 @@ enum { #define VTOTAL(trans) _MMIO_TRANS2(trans, _VTOTAL_A) #define VBLANK(trans) _MMIO_TRANS2(trans, _VBLANK_A) #define VSYNC(trans) _MMIO_TRANS2(trans, _VSYNC_A) +#define EXITLINE(trans) _MMIO_TRANS2(trans, _EXITLINE_A) #define BCLRPAT(trans) _MMIO_TRANS2(trans, _BCLRPAT_A) #define VSYNCSHIFT(trans) _MMIO_TRANS2(trans, _VSYNCSHIFT_A) #define PIPESRC(trans) _MMIO_TRANS2(trans, _PIPEASRC) #define PIPE_MULT(trans) _MMIO_TRANS2(trans, _PIPE_MULT_A) +#define EXITLINE_ENABLE (1 << 31) +#define EXITLINE_MASK (0x1fff) +#define EXITLINE_SHIFT 0 + /* * HSW+ eDP PSR registers * @@ -10005,6 +10011,8 @@ enum skl_power_gate { /* GEN9 DC */ #define DC_STATE_EN _MMIO(0x45504) #define DC_STATE_DISABLE 0 +#define DC_STATE_EN_DC3CO (1 << 30) +#define DC_STATE_DC3CO_STATUS (1 << 29) #define DC_STATE_EN_UPTO_DC5 (1 << 0) #define DC_STATE_EN_DC9 (1 << 3) #define DC_STATE_EN_UPTO_DC6 (2 << 0) From patchwork Fri Aug 30 17:44:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,2/7] drm/i915/tgl: Add DC3CO mask to allowed_dc_mask and gen9_dc_mask From: Anshuman Gupta X-Patchwork-Id: 328338 Message-Id: <20190830174433.22227-3-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:28 +0530 Enable dc3co state in enable_dc module param and add dc3co enable mask to allowed_dc_mask and gen9_dc_mask. v1: Adding enable_dc=3,4 options to enable DC3CO with DC5 and DC6 independently. Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Signed-off-by: Anshuman Gupta --- .../drm/i915/display/intel_display_power.c | 29 ++++++++++++++----- drivers/gpu/drm/i915/i915_params.c | 3 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index ce88a27229ef..496fa1b53ffb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -698,7 +698,11 @@ static u32 gen9_dc_mask(struct drm_i915_private *dev_priv) u32 mask; mask = DC_STATE_EN_UPTO_DC5; - if (INTEL_GEN(dev_priv) >= 11) + + if (INTEL_GEN(dev_priv) >= 12) + mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6 + | DC_STATE_EN_DC9; + else if (IS_GEN(dev_priv, 11)) mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9; else if (IS_GEN9_LP(dev_priv)) mask |= DC_STATE_EN_DC9; @@ -3927,14 +3931,17 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, int requested_dc; int max_dc; - if (INTEL_GEN(dev_priv) >= 11) { - max_dc = 2; + if (INTEL_GEN(dev_priv) >= 12) { + max_dc = 4; /* * DC9 has a separate HW flow from the rest of the DC states, * not depending on the DMC firmware. It's needed by system * suspend/resume, so allow it unconditionally. */ mask = DC_STATE_EN_DC9; + } else if (IS_GEN(dev_priv, 11)) { + max_dc = 2; + mask = DC_STATE_EN_DC9; } else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv)) { max_dc = 2; mask = 0; @@ -3953,7 +3960,7 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, requested_dc = enable_dc; } else if (enable_dc == -1) { requested_dc = max_dc; - } else if (enable_dc > max_dc && enable_dc <= 2) { + } else if (enable_dc > max_dc && enable_dc <= 4) { DRM_DEBUG_KMS("Adjusting requested max DC state (%d->%d)\n", enable_dc, max_dc); requested_dc = max_dc; @@ -3962,10 +3969,16 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, requested_dc = max_dc; } - if (requested_dc > 1) - mask |= DC_STATE_EN_UPTO_DC6; - if (requested_dc > 0) - mask |= DC_STATE_EN_UPTO_DC5; + if (requested_dc == 4) { + mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6; + } else if (requested_dc == 3) { + mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC5; + } else { + if (requested_dc > 1) + mask |= DC_STATE_EN_UPTO_DC6; + if (requested_dc > 0) + mask |= DC_STATE_EN_UPTO_DC5; + } DRM_DEBUG_KMS("Allowed DC state mask %02x\n", mask); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 296452f9efe4..4f1806f65040 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,7 +46,8 @@ i915_param_named(modeset, int, 0400, i915_param_named_unsafe(enable_dc, int, 0400, "Enable power-saving display C-states. " - "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); + "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6; " + "3=up to DC5 with DC3CO; 4=up to DC6 with DC3CO)"); i915_param_named_unsafe(enable_fbc, int, 0600, "Enable frame buffer compression for power savings " From patchwork Fri Aug 30 17:44:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,3/7] drm/i915/tgl: Enable DC3CO state in "DC Off" power well From: Anshuman Gupta X-Patchwork-Id: 328340 Message-Id: <20190830174433.22227-4-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:29 +0530 Add max_dc_state and tgl_set_target_dc_state() API in order to enable DC3CO state with existing DC states. max_dc_state will enable/disable the desired DC state in DC_STATE_EN reg when "DC Off" power well gets disable/enable. v2: commit log improvement. v3: Used intel_wait_for_register to wait for DC3CO exit. [Imre] Used gen9_set_dc_state() to allow/disallow DC3CO. [Imre] Moved transcoder psr2 exit line enablement from tgl_allow_dc3co() to a appropriate place haswell_crtc_enable(). [Imre] Changed the DC3CO power well enabled call back logic as recommended in review comments. [Imre] v4: Used wait_for_us() instead of intel_wait_for_reg(). [Imre (IRC)] v5: using udelay() instead of waiting for DC3CO exit status. v6: Fixed minor unwanted change. v7: Removed DC3CO powerwell and POWER_DOMAIN_VIDEO. Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Cc: Rodrigo Vivi Signed-off-by: Anshuman Gupta --- .../drm/i915/display/intel_display_power.c | 106 ++++++++++++++---- .../drm/i915/display/intel_display_power.h | 2 + drivers/gpu/drm/i915/i915_drv.h | 1 + 3 files changed, 89 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 496fa1b53ffb..868197bb4860 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -772,6 +772,29 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state) dev_priv->csr.dc_state = val & mask; } +static void tgl_allow_dc3co(struct drm_i915_private *dev_priv) +{ + if (!dev_priv->psr.sink_psr2_support) + return; + + if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO) + gen9_set_dc_state(dev_priv, DC_STATE_EN_DC3CO); +} + +static void tgl_disallow_dc3co(struct drm_i915_private *dev_priv) +{ + u32 val; + + val = I915_READ(DC_STATE_EN); + val &= ~DC_STATE_DC3CO_STATUS; + I915_WRITE(DC_STATE_EN, val); + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + /* + * Delay of 200us DC3CO Exit time B.Spec 49196 + */ + udelay(200); +} + static void bxt_enable_dc9(struct drm_i915_private *dev_priv) { assert_can_enable_dc9(dev_priv); @@ -939,7 +962,8 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0; + return ((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 && + (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0); } static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv) @@ -955,24 +979,32 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state = {}; - gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + if (dev_priv->csr.max_dc_state & DC_STATE_EN_DC3CO) { + tgl_disallow_dc3co(dev_priv); + } else { + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); - dev_priv->display.get_cdclk(dev_priv, &cdclk_state); - /* Can't read out voltage_level so can't use intel_cdclk_changed() */ - WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state)); + dev_priv->display.get_cdclk(dev_priv, &cdclk_state); + /* + * Can't read out voltage_level so can't use + * intel_cdclk_changed() + */ + WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, + &cdclk_state)); - gen9_assert_dbuf_enabled(dev_priv); + gen9_assert_dbuf_enabled(dev_priv); - if (IS_GEN9_LP(dev_priv)) - bxt_verify_ddi_phy_power_wells(dev_priv); + if (IS_GEN9_LP(dev_priv)) + bxt_verify_ddi_phy_power_wells(dev_priv); - if (INTEL_GEN(dev_priv) >= 11) - /* - * DMC retains HW context only for port A, the other combo - * PHY's HW context for port B is lost after DC transitions, - * so we need to restore it manually. - */ - intel_combo_phy_init(dev_priv); + if (INTEL_GEN(dev_priv) >= 11) + /* + * DMC retains HW context only for port A, the other + * combo PHY's HW context for port B is lost after + * DC transitions, so we need to restore it manually. + */ + intel_combo_phy_init(dev_priv); + } } static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, @@ -987,10 +1019,43 @@ static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, if (!dev_priv->csr.dmc_payload) return; - if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) - skl_enable_dc6(dev_priv); - else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5) - gen9_enable_dc5(dev_priv); + if (dev_priv->csr.max_dc_state & DC_STATE_EN_DC3CO) { + tgl_allow_dc3co(dev_priv); + } else if (dev_priv->csr.max_dc_state & DC_STATE_EN_UPTO_DC5_DC6_MASK) { + if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) + skl_enable_dc6(dev_priv); + else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5) + gen9_enable_dc5(dev_priv); + } +} + +void tgl_set_target_dc_state(struct drm_i915_private *dev_priv, u32 state) +{ + struct i915_power_well *power_well; + bool dc_off_enabled; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + + mutex_lock(&power_domains->lock); + power_well = lookup_power_well(dev_priv, TGL_DISP_DC_OFF); + dc_off_enabled = power_well->desc->ops->is_enabled(dev_priv, + power_well); + if (state == dev_priv->csr.max_dc_state) + goto unlock; + + if (!dc_off_enabled) { + /* + * Need to disable the DC off power well to + * effect target DC state. + */ + power_well->desc->ops->enable(dev_priv, power_well); + dev_priv->csr.max_dc_state = state; + power_well->desc->ops->disable(dev_priv, power_well); + goto unlock; + } + dev_priv->csr.max_dc_state = state; + +unlock: + mutex_unlock(&power_domains->lock); } static void i9xx_power_well_sync_hw_noop(struct drm_i915_private *dev_priv, @@ -3610,7 +3675,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .name = "DC off", .domains = TGL_DISPLAY_DC_OFF_POWER_DOMAINS, .ops = &gen9_dc_off_power_well_ops, - .id = DISP_PW_ID_NONE, + .id = TGL_DISP_DC_OFF, }, { .name = "power well 2", @@ -4039,6 +4104,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv, i915_modparams.enable_dc); + dev_priv->csr.max_dc_state = DC_STATE_EN_UPTO_DC5_DC6_MASK; BUILD_BUG_ON(POWER_DOMAIN_NUM > 64); mutex_init(&power_domains->lock); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 737b5def7fc6..1add626da458 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -100,6 +100,7 @@ enum i915_power_well_id { SKL_DISP_PW_MISC_IO, SKL_DISP_PW_1, SKL_DISP_PW_2, + TGL_DISP_DC_OFF, }; #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) @@ -256,6 +257,7 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915); void intel_display_power_resume_early(struct drm_i915_private *i915); void intel_display_power_suspend(struct drm_i915_private *i915); void intel_display_power_resume(struct drm_i915_private *i915); +void tgl_set_target_dc_state(struct drm_i915_private *dev_priv, u32 state); const char * intel_display_power_domain_str(enum intel_display_power_domain domain); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b42651a387d9..efe2eb121309 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -335,6 +335,7 @@ struct intel_csr { i915_reg_t mmioaddr[20]; u32 mmiodata[20]; u32 dc_state; + u32 max_dc_state; u32 allowed_dc_mask; intel_wakeref_t wakeref; }; From patchwork Fri Aug 30 17:44:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,4/7] drm/i915/tgl: Add helper function for DC3CO exitline. From: Anshuman Gupta X-Patchwork-Id: 328339 Message-Id: <20190830174433.22227-5-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:30 +0530 DC3CO enabling B.Specs sequence requires to enable end configure exit scanlines to TRANS_EXITLINE register, programming this register has to be part of modeset sequence as this can't be change when transcoder or port is enabled. When system boots with only eDP panel there may not be real modeset as BIOS has already programmed the necessary registers, therefore it needs to force a modeset at bootup to enable and configure DC3CO exitline. Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Signed-off-by: Anshuman Gupta --- drivers/gpu/drm/i915/display/intel_display.c | 2 + .../drm/i915/display/intel_display_power.c | 79 +++++++++++++++++++ .../drm/i915/display/intel_display_power.h | 5 ++ drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_pm.h | 2 + 6 files changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4773832b0f49..51576d142163 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13658,6 +13658,8 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + tgl_dc3co_crtc_modeset_check(dev_priv, state); + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!needs_modeset(new_crtc_state) && diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 868197bb4860..fe0a681d8c4d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -19,6 +19,7 @@ #include "intel_hotplug.h" #include "intel_sideband.h" #include "intel_tc.h" +#include "intel_pm.h" bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id); @@ -772,6 +773,84 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state) dev_priv->csr.dc_state = val & mask; } +void tgl_enable_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) +{ + u32 linetime_us, val, exit_scanlines; + u32 crtc_vdisplay = cstate->base.adjusted_mode.crtc_vdisplay; + struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + + linetime_us = fixed16_to_u32_round_up(intel_get_linetime_us(cstate)); + if (WARN_ON(!linetime_us)) + return; + /* + * DC3CO Exit time 200us B.Spec 49196 + * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1 + * Exit line event need to program above calculated scan lines before + * next VBLANK. + */ + exit_scanlines = DIV_ROUND_UP(200, linetime_us) + 1; + if (WARN_ON(exit_scanlines > crtc_vdisplay)) + return; + + exit_scanlines = crtc_vdisplay - exit_scanlines; + exit_scanlines <<= EXITLINE_SHIFT; + val = I915_READ(EXITLINE(cstate->cpu_transcoder)); + val &= ~(EXITLINE_MASK | EXITLINE_ENABLE); + val |= exit_scanlines; + val |= EXITLINE_ENABLE; + I915_WRITE(EXITLINE(cstate->cpu_transcoder), val); +} + +static bool tgl_dc3co_is_edp_connected(struct intel_crtc_state *crtc_state) +{ + struct drm_atomic_state *state = crtc_state->base.state; + struct drm_connector *connector; + struct drm_connector_state *connector_state; + int i; + + for_each_new_connector_in_state(state, connector, connector_state, i) { + if (connector->status == connector_status_connected && + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + return true; + } + } + + return false; +} + +/* + * DC3CO requires to enable exitline and program DC3CO requires + * exit scanlines to TRANS_EXITLINE register, which should only + * change before transcoder or port are enabled. + * This requires to force the modeset at boot for eDP output. + */ +void tgl_dc3co_crtc_modeset_check(struct drm_i915_private *dev_priv, + struct intel_atomic_state *state) +{ + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int i; + + if (!IS_TIGERLAKE(dev_priv)) + return; + + if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO)) + return; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->has_psr2 && crtc_state->base.active) { + if (tgl_dc3co_is_edp_connected(crtc_state)) { + if (!dev_priv->csr.dc3co_crtc) + crtc_state->base.mode_changed = true; + + dev_priv->csr.dc3co_crtc = + to_intel_crtc(crtc_state->base.crtc); + break; + } + } + } +} + static void tgl_allow_dc3co(struct drm_i915_private *dev_priv) { if (!dev_priv->psr.sink_psr2_support) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 1add626da458..63f4729cf5fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -12,6 +12,8 @@ struct drm_i915_private; struct intel_encoder; +struct intel_crtc_state; +struct intel_atomic_state; enum intel_display_power_domain { POWER_DOMAIN_DISPLAY_CORE, @@ -258,6 +260,9 @@ void intel_display_power_resume_early(struct drm_i915_private *i915); void intel_display_power_suspend(struct drm_i915_private *i915); void intel_display_power_resume(struct drm_i915_private *i915); void tgl_set_target_dc_state(struct drm_i915_private *dev_priv, u32 state); +void tgl_dc3co_crtc_modeset_check(struct drm_i915_private *dev_priv, + struct intel_atomic_state *state); +void tgl_enable_psr2_transcoder_exitline(const struct intel_crtc_state *cstate); const char * intel_display_power_domain_str(enum intel_display_power_domain domain); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index efe2eb121309..34e6536166a8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -338,6 +338,8 @@ struct intel_csr { u32 max_dc_state; u32 allowed_dc_mask; intel_wakeref_t wakeref; + /* cache the crtc on which DC3CO will be allowed */ + struct intel_crtc *dc3co_crtc; }; enum i915_cache_level { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4fa9bc83c8b4..3ee104ae3e2d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4584,7 +4584,7 @@ skl_wm_method2(u32 pixel_rate, u32 pipe_htotal, u32 latency, return ret; } -static uint_fixed_16_16_t +uint_fixed_16_16_t intel_get_linetime_us(const struct intel_crtc_state *crtc_state) { u32 pixel_rate; diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h index e3573e1e16e3..454e92c06dff 100644 --- a/drivers/gpu/drm/i915/intel_pm.h +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -8,6 +8,7 @@ #include +#include "i915_drv.h" #include "i915_reg.h" struct drm_device; @@ -76,6 +77,7 @@ u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, i915_reg_t reg); u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, i915_reg_t reg); u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat1); +uint_fixed_16_16_t intel_get_linetime_us(const struct intel_crtc_state *cstate); unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); unsigned long i915_mch_val(struct drm_i915_private *dev_priv); From patchwork Fri Aug 30 17:44:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [RFC,5/7] drm/i915/tgl: DC3CO PSR2 helper From: Anshuman Gupta X-Patchwork-Id: 328341 Message-Id: <20190830174433.22227-6-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:31 +0530 QWRkIGRjM2NvIGhlbHBlciBmdW5jdGlvbnMgdG8gZW5hYmxlL2Rpc2FibGUgcHNyMiBkZWVwIHNs ZWVwLgpBZGhlcmUgQi5TcGVjcyBieSBkaXNhbGxvdyBEQzNDTyBzdGF0ZSBiZWZvcmUgUFNSMiBl eGl0LgpFbmFibGUgUFNSMiBleGl0bGluZSBldmVudCBhbmQgcHJvZ3JhbSB0aGUgZGVzaXJlZCBz Y2FubGluZXMKdG8gZXhpdCBEQzNDTyBpbiBpbnRlbF9wc3JfZW5hYmxlIGZ1bmN0aW9uIGF0IG1v ZGVzZXQgcGF0aC4KCnYxOiBtb3ZlZCBjYWxsaW5nIG9mIHRnbF9lbmFibGVfcHNyMl90cmFuc2Nv ZGVyX2V4aXRsaW5lKCkgdG8KICAgIGludGVsX3Bzcl9lbmFibGUoKS4gW0ltcmVdCgpDYzogSmFu aSBOaWt1bGEgPGphbmkubmlrdWxhQGludGVsLmNvbT4KQ2M6IEltcmUgRGVhayA8aW1yZS5kZWFr QGludGVsLmNvbT4KQ2M6IEFuaW1lc2ggTWFubmEgPGFuaW1lc2gubWFubmFAaW50ZWwuY29tPgpD YzogSm9zw6kgUm9iZXJ0byBkZSBTb3V6YSA8am9zZS5zb3V6YUBpbnRlbC5jb20+ClNpZ25lZC1v ZmYtYnk6IEFuc2h1bWFuIEd1cHRhIDxhbnNodW1hbi5ndXB0YUBpbnRlbC5jb20+Ci0tLQogZHJp dmVycy9ncHUvZHJtL2k5MTUvZGlzcGxheS9pbnRlbF9wc3IuYyB8IDQzICsrKysrKysrKysrKysr KysrKysrKysrKwogZHJpdmVycy9ncHUvZHJtL2k5MTUvZGlzcGxheS9pbnRlbF9wc3IuaCB8ICAy ICsrCiAyIGZpbGVzIGNoYW5nZWQsIDQ1IGluc2VydGlvbnMoKykKCmRpZmYgLS1naXQgYS9kcml2 ZXJzL2dwdS9kcm0vaTkxNS9kaXNwbGF5L2ludGVsX3Bzci5jIGIvZHJpdmVycy9ncHUvZHJtL2k5 MTUvZGlzcGxheS9pbnRlbF9wc3IuYwppbmRleCA2MjliOGI5OGE5N2YuLjAwOTg0NjVlZjU3MyAx MDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvZGlzcGxheS9pbnRlbF9wc3IuYworKysg Yi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9kaXNwbGF5L2ludGVsX3Bzci5jCkBAIC01NDksNiArNTQ5 LDQ0IEBAIHRyYW5zY29kZXJfaGFzX3BzcjIoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmRldl9w cml2LCBlbnVtIHRyYW5zY29kZXIgdHJhbnMpCiAJCXJldHVybiB0cmFucyA9PSBUUkFOU0NPREVS X0VEUDsKIH0KIAorc3RhdGljIHZvaWQgcHNyMl9wcm9ncmFtX2lkbGVfZnJhbWVzKHN0cnVjdCBk cm1faTkxNV9wcml2YXRlICpkZXZfcHJpdiwKKwkJCQkgICAgIHUzMiBpZGxlX2ZyYW1lcykKK3sK Kwl1MzIgdmFsOworCisJaWRsZV9mcmFtZXMgPDw9ICBFRFBfUFNSMl9JRExFX0ZSQU1FX1NISUZU OworCXZhbCA9IEk5MTVfUkVBRChFRFBfUFNSMl9DVEwoZGV2X3ByaXYtPnBzci50cmFuc2NvZGVy KSk7CisJdmFsICY9IH5FRFBfUFNSMl9JRExFX0ZSQU1FX01BU0s7CisJdmFsIHw9IGlkbGVfZnJh bWVzOworCUk5MTVfV1JJVEUoRURQX1BTUjJfQ1RMKGRldl9wcml2LT5wc3IudHJhbnNjb2Rlciks IHZhbCk7Cit9CisKK3ZvaWQgdGdsX3BzcjJfZGVlcF9zbGVlcF9kaXNhYmxlKHN0cnVjdCBkcm1f aTkxNV9wcml2YXRlICpkZXZfcHJpdikKK3sKKwlpbnQgaWRsZV9mcmFtZXMgPSAwOworCisJcHNy Ml9wcm9ncmFtX2lkbGVfZnJhbWVzKGRldl9wcml2LCBpZGxlX2ZyYW1lcyk7Cit9CisKK3ZvaWQg dGdsX3BzcjJfZGVlcF9zbGVlcF9lbmFibGUoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmRldl9w cml2KQoreworCWludCBpZGxlX2ZyYW1lczsKKworCS8qCisJICogTGV0J3MgdXNlIDYgYXMgdGhl IG1pbmltdW0gdG8gY292ZXIgYWxsIGtub3duIGNhc2VzIGluY2x1ZGluZyB0aGUKKwkgKiBvZmYt Ynktb25lIGlzc3VlIHRoYXQgSFcgaGFzIGluIHNvbWUgY2FzZXMuCisJICovCisJaWRsZV9mcmFt ZXMgPSBtYXgoNiwgZGV2X3ByaXYtPnZidC5wc3IuaWRsZV9mcmFtZXMpOworCWlkbGVfZnJhbWVz ID0gbWF4KGlkbGVfZnJhbWVzLCBkZXZfcHJpdi0+cHNyLnNpbmtfc3luY19sYXRlbmN5ICsgMSk7 CisJcHNyMl9wcm9ncmFtX2lkbGVfZnJhbWVzKGRldl9wcml2LCBpZGxlX2ZyYW1lcyk7Cit9CisK K3N0YXRpYyB2b2lkIHRnbF9kaXNhbGxvd19kYzNjb19vbl9wc3IyX2V4aXQoc3RydWN0IGRybV9p OTE1X3ByaXZhdGUgKmRldl9wcml2KQoreworCS8qIEJlZm9yZSBQU1IyIGV4aXQgZGlzYWxsb3cg ZGMzY28qLworCXRnbF9zZXRfdGFyZ2V0X2RjX3N0YXRlKGRldl9wcml2LCBEQ19TVEFURV9FTl9V UFRPX0RDNik7Cit9CisKIHN0YXRpYyBib29sIGludGVsX3BzcjJfY29uZmlnX3ZhbGlkKHN0cnVj dCBpbnRlbF9kcCAqaW50ZWxfZHAsCiAJCQkJICAgIHN0cnVjdCBpbnRlbF9jcnRjX3N0YXRlICpj cnRjX3N0YXRlKQogewpAQCAtODA5LDYgKzg0NywxMCBAQCB2b2lkIGludGVsX3Bzcl9lbmFibGUo c3RydWN0IGludGVsX2RwICppbnRlbF9kcCwKIAogCVdBUk5fT04oZGV2X3ByaXYtPmRycnMuZHAp OwogCisJLyogRW5hYmxlIFBTUjIgdHJhbnNjb2RlciBleGl0IGxpbmUgKi8KKwlpZiAoY3J0Y19z dGF0ZS0+aGFzX3BzcjIpCisJCXRnbF9lbmFibGVfcHNyMl90cmFuc2NvZGVyX2V4aXRsaW5lKGNy dGNfc3RhdGUpOworCiAJbXV0ZXhfbG9jaygmZGV2X3ByaXYtPnBzci5sb2NrKTsKIAogCWlmICgh cHNyX2dsb2JhbF9lbmFibGVkKGRldl9wcml2LT5wc3IuZGVidWcpKSB7CkBAIC04MzksNiArODgx LDcgQEAgc3RhdGljIHZvaWQgaW50ZWxfcHNyX2V4aXQoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUg KmRldl9wcml2KQogCX0KIAogCWlmIChkZXZfcHJpdi0+cHNyLnBzcjJfZW5hYmxlZCkgeworCQl0 Z2xfZGlzYWxsb3dfZGMzY29fb25fcHNyMl9leGl0KGRldl9wcml2KTsKIAkJdmFsID0gSTkxNV9S RUFEKEVEUF9QU1IyX0NUTChkZXZfcHJpdi0+cHNyLnRyYW5zY29kZXIpKTsKIAkJV0FSTl9PTigh KHZhbCAmIEVEUF9QU1IyX0VOQUJMRSkpOwogCQl2YWwgJj0gfkVEUF9QU1IyX0VOQUJMRTsKZGlm ZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2Rpc3BsYXkvaW50ZWxfcHNyLmggYi9kcml2 ZXJzL2dwdS9kcm0vaTkxNS9kaXNwbGF5L2ludGVsX3Bzci5oCmluZGV4IDQ2ZTRkZThiOGNkNS4u NzVhOTg2MmYzNmZkIDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9kaXNwbGF5L2lu dGVsX3Bzci5oCisrKyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2Rpc3BsYXkvaW50ZWxfcHNyLmgK QEAgLTM1LDUgKzM1LDcgQEAgdm9pZCBpbnRlbF9wc3Jfc2hvcnRfcHVsc2Uoc3RydWN0IGludGVs X2RwICppbnRlbF9kcCk7CiBpbnQgaW50ZWxfcHNyX3dhaXRfZm9yX2lkbGUoY29uc3Qgc3RydWN0 IGludGVsX2NydGNfc3RhdGUgKm5ld19jcnRjX3N0YXRlLAogCQkJICAgIHUzMiAqb3V0X3ZhbHVl KTsKIGJvb2wgaW50ZWxfcHNyX2VuYWJsZWQoc3RydWN0IGludGVsX2RwICppbnRlbF9kcCk7Cit2 b2lkIHRnbF9wc3IyX2RlZXBfc2xlZXBfZGlzYWJsZShzdHJ1Y3QgZHJtX2k5MTVfcHJpdmF0ZSAq ZGV2X3ByaXYpOwordm9pZCB0Z2xfcHNyMl9kZWVwX3NsZWVwX2VuYWJsZShzdHJ1Y3QgZHJtX2k5 MTVfcHJpdmF0ZSAqZGV2X3ByaXYpOwogCiAjZW5kaWYgLyogX19JTlRFTF9QU1JfSF9fICovCg== From patchwork Fri Aug 30 17:44:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,6/7] drm/i915/tgl: switch between dc3co and dc5 based on display idleness From: Anshuman Gupta X-Patchwork-Id: 328343 Message-Id: <20190830174433.22227-7-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:32 +0530 DC3CO is useful power state, when DMC detects PSR2 idle frame while an active video playback, playing 30fps video on 60hz panel is the classic example of this use case. DC5 and DC6 saves more power, but can't be entered during video playback because there are not enough idle frames in a row to meet most PSR2 panel deep sleep entry requirement typically 4 frames. It will be worthy to enable DC3CO after completion of each flip and switch back to DC5 when display is idle, as driver doesn't differentiate between video playback and a normal flip. It is safer to allow DC5 after 6 idle frame, as PSR2 requires minimum 6 idle frame. v2: calculated s/w state to switch over dc3co when there is an update. [Imre] used cancel_delayed_work_sync() in order to avoid any race with already scheduled delayed work. [Imre] v3: cancel_delayed_work_sync() may blocked the commit work. Hence dropping it, dc5_idle_thread() checks the valid wakeref before putting the reference count, which avoids any chances of dropping a zero wakeref. [Imre (IRC)] v4: use frontbuffer flush mechanism. [Imre] Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Signed-off-by: Anshuman Gupta --- drivers/gpu/drm/i915/display/intel_display.c | 2 + .../drm/i915/display/intel_display_power.c | 75 +++++++++++++++++++ .../drm/i915/display/intel_display_power.h | 7 ++ .../gpu/drm/i915/display/intel_frontbuffer.c | 1 + drivers/gpu/drm/i915/display/intel_psr.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + 6 files changed, 87 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 51576d142163..00c6d183e87a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -16136,6 +16136,7 @@ int intel_modeset_init(struct drm_device *dev) init_llist_head(&dev_priv->atomic_helper.free_list); INIT_WORK(&dev_priv->atomic_helper.free_work, intel_atomic_helper_free_state_worker); + INIT_DELAYED_WORK(&dev_priv->csr.idle_work, tgl_dc5_idle_thread); intel_init_quirks(dev_priv); @@ -17077,6 +17078,7 @@ void intel_modeset_driver_remove(struct drm_device *dev) flush_workqueue(dev_priv->modeset_wq); flush_work(&dev_priv->atomic_helper.free_work); + flush_delayed_work(&dev_priv->csr.idle_work); WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list)); /* diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index fe0a681d8c4d..4fcd7d71db65 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -20,6 +20,7 @@ #include "intel_sideband.h" #include "intel_tc.h" #include "intel_pm.h" +#include "intel_psr.h" bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id); @@ -773,6 +774,27 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state) dev_priv->csr.dc_state = val & mask; } +static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate) +{ + u32 pixel_rate, crtc_htotal, crtc_vtotal; + u32 frametime_us; + + if (!cstate || !cstate->base.active) + return 0; + + pixel_rate = cstate->pixel_rate; + + if (WARN_ON(pixel_rate == 0)) + return 0; + + crtc_htotal = cstate->base.adjusted_mode.crtc_htotal; + crtc_vtotal = cstate->base.adjusted_mode.crtc_vtotal; + frametime_us = DIV_ROUND_UP(crtc_htotal * crtc_vtotal * 1000ULL, + pixel_rate); + + return frametime_us; +} + void tgl_enable_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) { u32 linetime_us, val, exit_scanlines; @@ -801,6 +823,50 @@ void tgl_enable_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) I915_WRITE(EXITLINE(cstate->cpu_transcoder), val); } +void tgl_dc3co_flush(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits, enum fb_op_origin origin) +{ + struct intel_crtc_state *cstate; + u32 delay; + unsigned int busy_frontbuffer_bits; + + if (!IS_TIGERLAKE(dev_priv)) + return; + + if (origin != ORIGIN_FLIP) + return; + + if (!dev_priv->csr.dc3co_crtc) + return; + + cstate = to_intel_crtc_state(dev_priv->csr.dc3co_crtc->base.state); + frontbuffer_bits &= + INTEL_FRONTBUFFER_ALL_MASK(dev_priv->csr.dc3co_crtc->pipe); + busy_frontbuffer_bits &= ~frontbuffer_bits; + + mutex_lock(&dev_priv->psr.lock); + + if (!dev_priv->psr.psr2_enabled || !dev_priv->psr.active) + goto unlock; + + /* + * At every flip frontbuffer flush first cancel the delayed work, + * when delayed schedules that means display has been idle + * for the 6 idle frame. + */ + if (!busy_frontbuffer_bits) { + cancel_delayed_work(&dev_priv->csr.idle_work); + tgl_psr2_deep_sleep_disable(dev_priv); + tgl_set_target_dc_state(dev_priv, DC_STATE_EN_DC3CO); + delay = DC5_REQ_IDLE_FRAMES * intel_get_frame_time_us(cstate); + schedule_delayed_work(&dev_priv->csr.idle_work, + usecs_to_jiffies(delay)); + } + +unlock: + mutex_unlock(&dev_priv->psr.lock); +} + static bool tgl_dc3co_is_edp_connected(struct intel_crtc_state *crtc_state) { struct drm_atomic_state *state = crtc_state->base.state; @@ -851,6 +917,15 @@ void tgl_dc3co_crtc_modeset_check(struct drm_i915_private *dev_priv, } } +void tgl_dc5_idle_thread(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), csr.idle_work.work); + + tgl_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); + tgl_psr2_deep_sleep_enable(dev_priv); +} + static void tgl_allow_dc3co(struct drm_i915_private *dev_priv) { if (!dev_priv->psr.sink_psr2_support) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 63f4729cf5fc..5dad40c07016 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -9,6 +9,9 @@ #include "intel_display.h" #include "intel_runtime_pm.h" #include "i915_reg.h" +#include "intel_frontbuffer.h" + +#define DC5_REQ_IDLE_FRAMES 6 struct drm_i915_private; struct intel_encoder; @@ -259,10 +262,14 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915); void intel_display_power_resume_early(struct drm_i915_private *i915); void intel_display_power_suspend(struct drm_i915_private *i915); void intel_display_power_resume(struct drm_i915_private *i915); + void tgl_set_target_dc_state(struct drm_i915_private *dev_priv, u32 state); void tgl_dc3co_crtc_modeset_check(struct drm_i915_private *dev_priv, struct intel_atomic_state *state); void tgl_enable_psr2_transcoder_exitline(const struct intel_crtc_state *cstate); +void tgl_dc5_idle_thread(struct work_struct *work); +void tgl_dc3co_flush(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits, enum fb_op_origin origin); const char * intel_display_power_domain_str(enum intel_display_power_domain domain); diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 719379774fa5..4ff1d000d994 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -90,6 +90,7 @@ static void frontbuffer_flush(struct drm_i915_private *i915, might_sleep(); intel_edp_drrs_flush(i915, frontbuffer_bits); intel_psr_flush(i915, frontbuffer_bits, origin); + tgl_dc3co_flush(i915, frontbuffer_bits, origin); intel_fbc_flush(i915, frontbuffer_bits, origin); } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 0098465ef573..cfa4f306af7e 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -583,6 +583,7 @@ void tgl_psr2_deep_sleep_enable(struct drm_i915_private *dev_priv) static void tgl_disallow_dc3co_on_psr2_exit(struct drm_i915_private *dev_priv) { + cancel_delayed_work(&dev_priv->csr.idle_work); /* Before PSR2 exit disallow dc3co*/ tgl_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 34e6536166a8..afebbd9113ef 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -337,6 +337,7 @@ struct intel_csr { u32 dc_state; u32 max_dc_state; u32 allowed_dc_mask; + struct delayed_work idle_work; intel_wakeref_t wakeref; /* cache the crtc on which DC3CO will be allowed */ struct intel_crtc *dc3co_crtc; From patchwork Fri Aug 30 17:44:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,7/7] drm/i915/tgl: Add DC3CO counter in i915_dmc_info From: Anshuman Gupta X-Patchwork-Id: 328342 Message-Id: <20190830174433.22227-8-anshuman.gupta@intel.com> To: intel-gfx@lists.freedesktop.org Cc: jani.nikula@intel.com Date: Fri, 30 Aug 2019 23:14:33 +0530 Adding DC3CO counter in i915_dmc_info debugfs will be useful for DC3CO validation. DMC firmware uses DMC_DEBUG3 register as DC3CO counter register on TGL, as per B.Specs DMC_DEBUG3 is general purpose register. Cc: Jani Nikula Cc: Imre Deak Cc: Animesh Manna Signed-off-by: Anshuman Gupta --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5e81c4fc13ae..820b9b8febec 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2397,6 +2397,12 @@ static int i915_dmc_info(struct seq_file *m, void *unused) seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version)); + /* + * TGL DMC f/w uses DMC_DEBUG3 register for DC3CO counter. + */ + if (IS_TIGERLAKE(dev_priv)) + seq_printf(m, "DC3CO count: %d\n", I915_READ(DMC_DEBUG3)); + if (INTEL_GEN(dev_priv) >= 12) { dc5_reg = TGL_DMC_DEBUG_DC5_COUNT; dc6_reg = TGL_DMC_DEBUG_DC6_COUNT; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d6b6181c1ffd..a0b9289152e9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7238,6 +7238,8 @@ enum { #define TGL_DMC_DEBUG_DC5_COUNT _MMIO(0x101084) #define TGL_DMC_DEBUG_DC6_COUNT _MMIO(0x101088) +#define DMC_DEBUG3 _MMIO(0x101090) + /* interrupts */ #define DE_MASTER_IRQ_CONTROL (1 << 31) #define DE_SPRITEB_FLIP_DONE (1 << 29)