diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display_power.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display_power.c | 368 |
1 files changed, 181 insertions, 187 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index d3b8453a1705..ec96b141c74c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3,11 +3,12 @@ * Copyright © 2019 Intel Corporation */ +#include <linux/iopoll.h> #include <linux/string_helpers.h> -#include "i915_drv.h" -#include "i915_irq.h" -#include "i915_reg.h" +#include <drm/drm_print.h> +#include <drm/intel/intel_pcode_regs.h> + #include "intel_backlight_regs.h" #include "intel_cdclk.h" #include "intel_clock_gating.h" @@ -16,14 +17,20 @@ #include "intel_display_power.h" #include "intel_display_power_map.h" #include "intel_display_power_well.h" +#include "intel_display_regs.h" +#include "intel_display_rpm.h" #include "intel_display_types.h" +#include "intel_display_utils.h" +#include "intel_display_wa.h" #include "intel_dmc.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" +#include "intel_parent.h" #include "intel_pch_refclk.h" -#include "intel_pcode.h" #include "intel_pmdemand.h" #include "intel_pps_regs.h" #include "intel_snps_phy.h" +#include "intel_step.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_sideband.h" @@ -204,7 +211,7 @@ static bool __intel_display_power_is_enabled(struct intel_display *display, struct i915_power_well *power_well; bool is_enabled; - if (pm_runtime_suspended(display->drm->dev)) + if (intel_display_rpm_suspended(display)) return false; is_enabled = true; @@ -224,7 +231,7 @@ static bool __intel_display_power_is_enabled(struct intel_display *display, /** * intel_display_power_is_enabled - check for a power domain - * @dev_priv: i915 device instance + * @display: display device instance * @domain: power domain to check * * This function can be used to check the hw power domain state. It is mostly @@ -239,10 +246,9 @@ static bool __intel_display_power_is_enabled(struct intel_display *display, * Returns: * True when the power domain is enabled, false otherwise. */ -bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv, +bool intel_display_power_is_enabled(struct intel_display *display, enum intel_display_power_domain domain) { - struct intel_display *display = &dev_priv->display; struct i915_power_domains *power_domains = &display->power.domains; bool ret; @@ -323,6 +329,35 @@ unlock: mutex_unlock(&power_domains->lock); } +/** + * intel_display_power_get_current_dc_state - Set target dc state. + * @display: display device + * + * This function set the "DC off" power well target_dc_state, + * based upon this target_dc_stste, "DC off" power well will + * enable desired DC state. + */ +u32 intel_display_power_get_current_dc_state(struct intel_display *display) +{ + struct i915_power_well *power_well; + struct i915_power_domains *power_domains = &display->power.domains; + u32 current_dc_state = DC_STATE_DISABLE; + + mutex_lock(&power_domains->lock); + power_well = lookup_power_well(display, SKL_DISP_DC_OFF); + + if (drm_WARN_ON(display->drm, !power_well)) + goto unlock; + + current_dc_state = intel_power_well_is_enabled(display, power_well) ? + DC_STATE_DISABLE : power_domains->target_dc_state; + +unlock: + mutex_unlock(&power_domains->lock); + + return current_dc_state; +} + static void __async_put_domains_mask(struct i915_power_domains *power_domains, struct intel_power_domain_mask *mask) { @@ -456,7 +491,6 @@ static bool intel_display_power_grab_async_put_ref(struct intel_display *display, enum intel_display_power_domain domain) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; struct intel_power_domain_mask async_put_mask; bool ret = false; @@ -474,8 +508,8 @@ intel_display_power_grab_async_put_ref(struct intel_display *display, goto out_verify; cancel_async_put_work(power_domains, false); - intel_runtime_pm_put_raw(&dev_priv->runtime_pm, - fetch_and_zero(&power_domains->async_put_wakeref)); + intel_display_rpm_put_raw(display, + fetch_and_zero(&power_domains->async_put_wakeref)); out_verify: verify_async_put_domains_state(power_domains); @@ -500,7 +534,7 @@ __intel_display_power_get_domain(struct intel_display *display, /** * intel_display_power_get - grab a power domain reference - * @dev_priv: i915 device instance + * @display: display device instance * @domain: power domain to reference * * This function grabs a power domain reference for @domain and ensures that the @@ -510,12 +544,13 @@ __intel_display_power_get_domain(struct intel_display *display, * Any power domain reference obtained by this function must have a symmetric * call to intel_display_power_put() to release the reference again. */ -intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv, - enum intel_display_power_domain domain) +struct ref_tracker *intel_display_power_get(struct intel_display *display, + enum intel_display_power_domain domain) { - struct intel_display *display = &dev_priv->display; struct i915_power_domains *power_domains = &display->power.domains; - intel_wakeref_t wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); + struct ref_tracker *wakeref; + + wakeref = intel_display_rpm_get(display); mutex_lock(&power_domains->lock); __intel_display_power_get_domain(display, domain); @@ -526,7 +561,7 @@ intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv, /** * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain - * @dev_priv: i915 device instance + * @display: display device instance * @domain: power domain to reference * * This function grabs a power domain reference for @domain and ensures that the @@ -536,16 +571,15 @@ intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv, * Any power domain reference obtained by this function must have a symmetric * call to intel_display_power_put() to release the reference again. */ -intel_wakeref_t -intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, +struct ref_tracker * +intel_display_power_get_if_enabled(struct intel_display *display, enum intel_display_power_domain domain) { - struct intel_display *display = &dev_priv->display; struct i915_power_domains *power_domains = &display->power.domains; - intel_wakeref_t wakeref; + struct ref_tracker *wakeref; bool is_enabled; - wakeref = intel_runtime_pm_get_if_in_use(&dev_priv->runtime_pm); + wakeref = intel_display_rpm_get_if_in_use(display); if (!wakeref) return NULL; @@ -561,7 +595,7 @@ intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, mutex_unlock(&power_domains->lock); if (!is_enabled) { - intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); + intel_display_rpm_put(display, wakeref); wakeref = NULL; } @@ -604,7 +638,7 @@ static void __intel_display_power_put(struct intel_display *display, static void queue_async_put_domains_work(struct i915_power_domains *power_domains, - intel_wakeref_t wakeref, + struct ref_tracker *wakeref, int delay_ms) { struct intel_display *display = container_of(power_domains, @@ -612,7 +646,7 @@ queue_async_put_domains_work(struct i915_power_domains *power_domains, power.domains); drm_WARN_ON(display->drm, power_domains->async_put_wakeref); power_domains->async_put_wakeref = wakeref; - drm_WARN_ON(display->drm, !queue_delayed_work(system_unbound_wq, + drm_WARN_ON(display->drm, !queue_delayed_work(system_dfl_wq, &power_domains->async_put_work, msecs_to_jiffies(delay_ms))); } @@ -624,12 +658,10 @@ release_async_put_domains(struct i915_power_domains *power_domains, struct intel_display *display = container_of(power_domains, struct intel_display, power.domains); - struct drm_i915_private *dev_priv = to_i915(display->drm); - struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; enum intel_display_power_domain domain; - intel_wakeref_t wakeref; + struct ref_tracker *wakeref; - wakeref = intel_runtime_pm_get_noresume(rpm); + wakeref = intel_display_rpm_get_noresume(display); for_each_power_domain(domain, mask) { /* Clear before put, so put's sanity check is happy. */ @@ -637,7 +669,7 @@ release_async_put_domains(struct i915_power_domains *power_domains, __intel_display_power_put_domain(display, domain); } - intel_runtime_pm_put(rpm, wakeref); + intel_display_rpm_put(display, wakeref); } static void @@ -645,11 +677,10 @@ intel_display_power_put_async_work(struct work_struct *work) { struct intel_display *display = container_of(work, struct intel_display, power.domains.async_put_work.work); - struct drm_i915_private *dev_priv = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; - struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; - intel_wakeref_t new_work_wakeref = intel_runtime_pm_get_raw(rpm); - intel_wakeref_t old_work_wakeref = NULL; + struct ref_tracker *new_work_wakeref, *old_work_wakeref = NULL; + + new_work_wakeref = intel_display_rpm_get_raw(display); mutex_lock(&power_domains->lock); @@ -689,14 +720,14 @@ out_verify: mutex_unlock(&power_domains->lock); if (old_work_wakeref) - intel_runtime_pm_put_raw(rpm, old_work_wakeref); + intel_display_rpm_put_raw(display, old_work_wakeref); if (new_work_wakeref) - intel_runtime_pm_put_raw(rpm, new_work_wakeref); + intel_display_rpm_put_raw(display, new_work_wakeref); } /** * __intel_display_power_put_async - release a power domain reference asynchronously - * @i915: i915 device instance + * @display: display device instance * @domain: power domain to reference * @wakeref: wakeref acquired for the reference that is being released * @delay_ms: delay of powering down the power domain @@ -707,15 +738,15 @@ out_verify: * The power down is delayed by @delay_ms if this is >= 0, or by a default * 100 ms otherwise. */ -void __intel_display_power_put_async(struct drm_i915_private *i915, +void __intel_display_power_put_async(struct intel_display *display, enum intel_display_power_domain domain, - intel_wakeref_t wakeref, + struct ref_tracker *wakeref, int delay_ms) { - struct intel_display *display = &i915->display; struct i915_power_domains *power_domains = &display->power.domains; - struct intel_runtime_pm *rpm = &i915->runtime_pm; - intel_wakeref_t work_wakeref = intel_runtime_pm_get_raw(rpm); + struct ref_tracker *work_wakeref; + + work_wakeref = intel_display_rpm_get_raw(display); delay_ms = delay_ms >= 0 ? delay_ms : 100; @@ -747,14 +778,14 @@ out_verify: mutex_unlock(&power_domains->lock); if (work_wakeref) - intel_runtime_pm_put_raw(rpm, work_wakeref); + intel_display_rpm_put_raw(display, work_wakeref); - intel_runtime_pm_put(rpm, wakeref); + intel_display_rpm_put(display, wakeref); } /** * intel_display_power_flush_work - flushes the async display power disabling work - * @i915: i915 device instance + * @display: display device instance * * Flushes any pending work that was scheduled by a preceding * intel_display_power_put_async() call, completing the disabling of the @@ -764,12 +795,11 @@ out_verify: * function returns; to ensure that the work handler isn't running use * intel_display_power_flush_work_sync() instead. */ -void intel_display_power_flush_work(struct drm_i915_private *i915) +void intel_display_power_flush_work(struct intel_display *display) { - struct intel_display *display = &i915->display; struct i915_power_domains *power_domains = &display->power.domains; struct intel_power_domain_mask async_put_mask; - intel_wakeref_t work_wakeref; + struct ref_tracker *work_wakeref; mutex_lock(&power_domains->lock); @@ -787,7 +817,7 @@ out_verify: mutex_unlock(&power_domains->lock); if (work_wakeref) - intel_runtime_pm_put_raw(&i915->runtime_pm, work_wakeref); + intel_display_rpm_put_raw(display, work_wakeref); } /** @@ -800,10 +830,9 @@ out_verify: static void intel_display_power_flush_work_sync(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; - intel_display_power_flush_work(i915); + intel_display_power_flush_work(display); cancel_async_put_work(power_domains, true); verify_async_put_domains_state(power_domains); @@ -814,7 +843,7 @@ intel_display_power_flush_work_sync(struct intel_display *display) #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) /** * intel_display_power_put - release a power domain reference - * @dev_priv: i915 device instance + * @display: display device instance * @domain: power domain to reference * @wakeref: wakeref acquired for the reference that is being released * @@ -822,19 +851,17 @@ intel_display_power_flush_work_sync(struct intel_display *display) * intel_display_power_get() and might power down the corresponding hardware * block right away if this is the last reference. */ -void intel_display_power_put(struct drm_i915_private *dev_priv, +void intel_display_power_put(struct intel_display *display, enum intel_display_power_domain domain, - intel_wakeref_t wakeref) + struct ref_tracker *wakeref) { - struct intel_display *display = &dev_priv->display; - __intel_display_power_put(display, domain); - intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); + intel_display_rpm_put(display, wakeref); } #else /** * intel_display_power_put_unchecked - release an unchecked power domain reference - * @dev_priv: i915 device instance + * @display: display device instance * @domain: power domain to reference * * This function drops the power domain reference obtained by @@ -842,30 +869,27 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, * block right away if this is the last reference. * * This function is only for the power domain code's internal use to suppress wakeref - * tracking when the correspondig debug kconfig option is disabled, should not + * tracking when the corresponding debug kconfig option is disabled, should not * be used otherwise. */ -void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv, +void intel_display_power_put_unchecked(struct intel_display *display, enum intel_display_power_domain domain) { - struct intel_display *display = &dev_priv->display; - __intel_display_power_put(display, domain); - intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm); + intel_display_rpm_put_unchecked(display); } #endif void -intel_display_power_get_in_set(struct drm_i915_private *i915, +intel_display_power_get_in_set(struct intel_display *display, struct intel_display_power_domain_set *power_domain_set, enum intel_display_power_domain domain) { - struct intel_display *display = &i915->display; - intel_wakeref_t __maybe_unused wf; + struct ref_tracker *__maybe_unused wf; drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits)); - wf = intel_display_power_get(i915, domain); + wf = intel_display_power_get(display, domain); #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) power_domain_set->wakerefs[domain] = wf; #endif @@ -873,16 +897,15 @@ intel_display_power_get_in_set(struct drm_i915_private *i915, } bool -intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915, +intel_display_power_get_in_set_if_enabled(struct intel_display *display, struct intel_display_power_domain_set *power_domain_set, enum intel_display_power_domain domain) { - struct intel_display *display = &i915->display; - intel_wakeref_t wf; + struct ref_tracker *wf; drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits)); - wf = intel_display_power_get_if_enabled(i915, domain); + wf = intel_display_power_get_if_enabled(display, domain); if (!wf) return false; @@ -895,23 +918,22 @@ intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915, } void -intel_display_power_put_mask_in_set(struct drm_i915_private *i915, +intel_display_power_put_mask_in_set(struct intel_display *display, struct intel_display_power_domain_set *power_domain_set, struct intel_power_domain_mask *mask) { - struct intel_display *display = &i915->display; enum intel_display_power_domain domain; drm_WARN_ON(display->drm, !bitmap_subset(mask->bits, power_domain_set->mask.bits, POWER_DOMAIN_NUM)); for_each_power_domain(domain, mask) { - intel_wakeref_t __maybe_unused wf = INTEL_WAKEREF_DEF; + struct ref_tracker *__maybe_unused wf = INTEL_WAKEREF_DEF; #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) wf = fetch_and_zero(&power_domain_set->wakerefs[domain]); #endif - intel_display_power_put(i915, domain, wf); + intel_display_power_put(display, domain, wf); clear_bit(domain, power_domain_set->mask.bits); } } @@ -999,7 +1021,7 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc) * intel_power_domains_init - initializes the power domain structures * @display: display device instance * - * Initializes the power domain structures for @dev_priv depending upon the + * Initializes the power domain structures for @display depending upon the * supported platform. */ int intel_power_domains_init(struct intel_display *display) @@ -1061,10 +1083,9 @@ static void gen9_dbuf_slice_set(struct intel_display *display, slice, str_enable_disable(enable)); } -void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, +void gen9_dbuf_slices_update(struct intel_display *display, u8 req_slices) { - struct intel_display *display = &dev_priv->display; struct i915_power_domains *power_domains = &display->power.domains; u8 slice_mask = DISPLAY_INFO(display)->dbuf.slice_mask; enum dbuf_slice slice; @@ -1095,10 +1116,9 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, static void gen9_dbuf_enable(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u8 slices_mask; - display->dbuf.enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv); + display->dbuf.enabled_slices = intel_enabled_dbuf_slices_mask(display); slices_mask = BIT(DBUF_S1) | display->dbuf.enabled_slices; @@ -1109,14 +1129,12 @@ static void gen9_dbuf_enable(struct intel_display *display) * Just power up at least 1 slice, we will * figure out later which slices we have and what we need. */ - gen9_dbuf_slices_update(dev_priv, slices_mask); + gen9_dbuf_slices_update(display, slices_mask); } static void gen9_dbuf_disable(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - - gen9_dbuf_slices_update(dev_priv, 0); + gen9_dbuf_slices_update(display, 0); if (DISPLAY_VER(display) >= 14) intel_pmdemand_program_dbuf(display, 0); @@ -1126,9 +1144,6 @@ static void gen12_dbuf_slices_config(struct intel_display *display) { enum dbuf_slice slice; - if (display->platform.alderlake_p) - return; - for_each_dbuf_slice(display, slice) intel_de_rmw(display, DBUF_CTL_S(slice), DBUF_TRACKER_STATE_SERVICE_MASK, @@ -1160,7 +1175,7 @@ static void icl_mbus_init(struct intel_display *display) if (DISPLAY_VER(display) == 12) abox_regs |= BIT(0); - for_each_set_bit(i, &abox_regs, sizeof(abox_regs)) + for_each_set_bit(i, &abox_regs, BITS_PER_TYPE(abox_regs)) intel_de_rmw(display, MBUS_ABOX_CTL(i), mask, val); } @@ -1186,7 +1201,6 @@ static void hsw_assert_cdclk(struct intel_display *display) static void assert_can_disable_lcpll(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_crtc *crtc; for_each_intel_crtc(display->drm, crtc) @@ -1231,7 +1245,7 @@ static void assert_can_disable_lcpll(struct intel_display *display) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - INTEL_DISPLAY_STATE_WARN(display, intel_irqs_enabled(dev_priv), + INTEL_DISPLAY_STATE_WARN(display, intel_parent_irq_enabled(display), "IRQs enabled\n"); } @@ -1245,10 +1259,8 @@ static u32 hsw_read_dcomp(struct intel_display *display) static void hsw_write_dcomp(struct intel_display *display, u32 val) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - if (display->platform.haswell) { - if (snb_pcode_write(&dev_priv->uncore, GEN6_PCODE_WRITE_D_COMP, val)) + if (intel_parent_pcode_write(display, GEN6_PCODE_WRITE_D_COMP, val)) drm_dbg_kms(display->drm, "Failed to write to D_COMP\n"); } else { intel_de_write(display, D_COMP_BDW, val); @@ -1268,6 +1280,7 @@ static void hsw_disable_lcpll(struct intel_display *display, bool switch_to_fclk, bool allow_power_down) { u32 val; + int ret; assert_can_disable_lcpll(display); @@ -1277,8 +1290,9 @@ static void hsw_disable_lcpll(struct intel_display *display, val |= LCPLL_CD_SOURCE_FCLK; intel_de_write(display, LCPLL_CTL, val); - if (wait_for_us(intel_de_read(display, LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE, 1)) + ret = intel_de_wait_for_set_us(display, LCPLL_CTL, + LCPLL_CD_SOURCE_FCLK_DONE, 1); + if (ret) drm_err(display->drm, "Switching to FCLK failed\n"); val = intel_de_read(display, LCPLL_CTL); @@ -1288,7 +1302,7 @@ static void hsw_disable_lcpll(struct intel_display *display, intel_de_write(display, LCPLL_CTL, val); intel_de_posting_read(display, LCPLL_CTL); - if (intel_de_wait_for_clear(display, LCPLL_CTL, LCPLL_PLL_LOCK, 1)) + if (intel_de_wait_for_clear_ms(display, LCPLL_CTL, LCPLL_PLL_LOCK, 1)) drm_err(display->drm, "LCPLL still locked\n"); val = hsw_read_dcomp(display); @@ -1296,8 +1310,10 @@ static void hsw_disable_lcpll(struct intel_display *display, hsw_write_dcomp(display, val); ndelay(100); - if (wait_for((hsw_read_dcomp(display) & - D_COMP_RCOMP_IN_PROGRESS) == 0, 1)) + ret = poll_timeout_us(val = hsw_read_dcomp(display), + (val & D_COMP_RCOMP_IN_PROGRESS) == 0, + 100, 1000, false); + if (ret) drm_err(display->drm, "D_COMP RCOMP still in progress\n"); if (allow_power_down) { @@ -1312,8 +1328,8 @@ static void hsw_disable_lcpll(struct intel_display *display, */ static void hsw_restore_lcpll(struct intel_display *display) { - struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm); u32 val; + int ret; val = intel_de_read(display, LCPLL_CTL); @@ -1322,10 +1338,10 @@ static void hsw_restore_lcpll(struct intel_display *display) return; /* - * Make sure we're not on PC8 state before disabling PC8, otherwise - * we'll hang the machine. To prevent PC8 state, just enable force_wake. + * Make sure we're not on PC8 state before disabling + * PC8, otherwise we'll hang the machine. */ - intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL); + intel_parent_pc8_block(display); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -1342,19 +1358,20 @@ static void hsw_restore_lcpll(struct intel_display *display) val &= ~LCPLL_PLL_DISABLE; intel_de_write(display, LCPLL_CTL, val); - if (intel_de_wait_for_set(display, LCPLL_CTL, LCPLL_PLL_LOCK, 5)) + if (intel_de_wait_for_set_ms(display, LCPLL_CTL, LCPLL_PLL_LOCK, 5)) drm_err(display->drm, "LCPLL not locked yet\n"); if (val & LCPLL_CD_SOURCE_FCLK) { intel_de_rmw(display, LCPLL_CTL, LCPLL_CD_SOURCE_FCLK, 0); - if (wait_for_us((intel_de_read(display, LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1)) + ret = intel_de_wait_for_clear_us(display, LCPLL_CTL, + LCPLL_CD_SOURCE_FCLK_DONE, 1); + if (ret) drm_err(display->drm, "Switching back to LCPLL failed\n"); } - intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); + intel_parent_pc8_unblock(display); intel_update_cdclk(display); intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK"); @@ -1385,30 +1402,26 @@ static void hsw_restore_lcpll(struct intel_display *display) */ static void hsw_enable_pc8(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - drm_dbg_kms(display->drm, "Enabling package C8+\n"); - if (HAS_PCH_LPT_LP(dev_priv)) + if (HAS_PCH_LPT_LP(display)) intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, PCH_LP_PARTITION_LEVEL_DISABLE, 0); - lpt_disable_clkout_dp(dev_priv); + lpt_disable_clkout_dp(display); hsw_disable_lcpll(display, true, true); } static void hsw_disable_pc8(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - drm_dbg_kms(display->drm, "Disabling package C8+\n"); hsw_restore_lcpll(display); - intel_init_pch_refclk(dev_priv); + intel_init_pch_refclk(display); /* Many display registers don't survive PC8+ */ #ifdef I915 /* FIXME */ - intel_clock_gating_init(dev_priv); + intel_clock_gating_init(display->drm); #endif } @@ -1418,6 +1431,9 @@ static void intel_pch_reset_handshake(struct intel_display *display, i915_reg_t reg; u32 reset_bits; + if (DISPLAY_VER(display) >= 35) + return; + if (display->platform.ivybridge) { reg = GEN7_MSG_CTL; reset_bits = WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK; @@ -1435,14 +1451,13 @@ static void intel_pch_reset_handshake(struct intel_display *display, static void skl_display_core_init(struct intel_display *display, bool resume) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; struct i915_power_well *well; gen9_set_dc_state(display, DC_STATE_DISABLE); /* enable PCH reset handshake */ - intel_pch_reset_handshake(display, !HAS_PCH_NOP(dev_priv)); + intel_pch_reset_handshake(display, !HAS_PCH_NOP(display)); if (!HAS_DISPLAY(display)) return; @@ -1598,9 +1613,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = { static void tgl_bw_buddy_init(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - enum intel_dram_type type = dev_priv->dram_info.type; - u8 num_channels = dev_priv->dram_info.num_channels; + const struct dram_info *dram_info = intel_dram_info(display); const struct buddy_page_mask *table; unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask; int config, i; @@ -1609,31 +1622,30 @@ static void tgl_bw_buddy_init(struct intel_display *display) if (display->platform.dgfx && !display->platform.dg1) return; - if (display->platform.alderlake_s || - (display->platform.rocketlake && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0))) + if (intel_display_wa(display, INTEL_DISPLAY_WA_1409767108)) /* Wa_1409767108 */ table = wa_1409767108_buddy_page_masks; else table = tgl_buddy_page_masks; for (config = 0; table[config].page_mask != 0; config++) - if (table[config].num_channels == num_channels && - table[config].type == type) + if (table[config].num_channels == dram_info->num_channels && + table[config].type == dram_info->type) break; if (table[config].page_mask == 0) { drm_dbg_kms(display->drm, "Unknown memory configuration; disabling address buddy logic.\n"); - for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) + for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) intel_de_write(display, BW_BUDDY_CTL(i), BW_BUDDY_DISABLE); } else { - for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) { + for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) { intel_de_write(display, BW_BUDDY_PAGE_MASK(i), table[config].page_mask); /* Wa_22010178259:tgl,dg1,rkl,adl-s */ - if (DISPLAY_VER(display) == 12) + if (intel_display_wa(display, INTEL_DISPLAY_WA_22010178259)) intel_de_rmw(display, BW_BUDDY_CTL(i), BW_BUDDY_TLB_REQ_TIMER_MASK, BW_BUDDY_TLB_REQ_TIMER(0x8)); @@ -1644,26 +1656,24 @@ static void tgl_bw_buddy_init(struct intel_display *display) static void icl_display_core_init(struct intel_display *display, bool resume) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; struct i915_power_well *well; gen9_set_dc_state(display, DC_STATE_DISABLE); /* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */ - if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && - INTEL_PCH_TYPE(dev_priv) < PCH_DG1) + if (intel_display_wa(display, INTEL_DISPLAY_WA_14011294188)) intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0, PCH_DPMGUNIT_CLOCK_GATE_DISABLE); /* 1. Enable PCH reset handshake. */ - intel_pch_reset_handshake(display, !HAS_PCH_NOP(dev_priv)); + intel_pch_reset_handshake(display, !HAS_PCH_NOP(display)); if (!HAS_DISPLAY(display)) return; /* 2. Initialize all combo phys */ - intel_combo_phy_init(dev_priv); + intel_combo_phy_init(display); /* * 3. Enable Power Well 1 (PG1). @@ -1681,7 +1691,7 @@ static void icl_display_core_init(struct intel_display *display, /* 4. Enable CDCLK. */ intel_cdclk_init_hw(display); - if (DISPLAY_VER(display) >= 12) + if (DISPLAY_VER(display) == 12 || display->platform.dg2) gen12_dbuf_slices_config(display); /* 5. Enable DBUF. */ @@ -1696,7 +1706,7 @@ static void icl_display_core_init(struct intel_display *display, /* 8. Ensure PHYs have completed calibration and adaptation */ if (display->platform.dg2) - intel_snps_phy_wait_for_calibration(dev_priv); + intel_snps_phy_wait_for_calibration(display); /* 9. XE2_HPD: Program CHICKEN_MISC_2 before any cursor or planes are enabled */ if (DISPLAY_VERx100(display) == 1401) @@ -1706,17 +1716,17 @@ static void icl_display_core_init(struct intel_display *display, intel_dmc_load_program(display); /* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p,dg2 */ - if (IS_DISPLAY_VERx100(display, 1200, 1300)) + if (intel_display_wa(display, INTEL_DISPLAY_WA_14011508470)) intel_de_rmw(display, GEN11_CHICKEN_DCPR_2, 0, DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM | DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR); /* Wa_14011503030:xelpd */ - if (DISPLAY_VER(display) == 13) + if (intel_display_wa(display, INTEL_DISPLAY_WA_14011503030)) intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, ~0); /* Wa_15013987218 */ - if (DISPLAY_VER(display) == 20) { + if (intel_display_wa(display, INTEL_DISPLAY_WA_15013987218)) { intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0, PCH_GMBUSUNIT_CLOCK_GATE_DISABLE); intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, @@ -1726,7 +1736,6 @@ static void icl_display_core_init(struct intel_display *display, static void icl_display_core_uninit(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; struct i915_power_well *well; @@ -1736,7 +1745,7 @@ static void icl_display_core_uninit(struct intel_display *display) gen9_disable_dc_states(display); intel_dmc_disable_program(display); - /* 1. Disable all display engine functions -> aready done */ + /* 1. Disable all display engine functions -> already done */ /* 2. Disable DBUF */ gen9_dbuf_disable(display); @@ -1759,7 +1768,7 @@ static void icl_display_core_uninit(struct intel_display *display) mutex_unlock(&power_domains->lock); /* 5. */ - intel_combo_phy_uninit(dev_priv); + intel_combo_phy_uninit(display); } static void chv_phy_control_init(struct intel_display *display) @@ -1879,12 +1888,11 @@ static void vlv_cmnlane_wa(struct intel_display *display) static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0) { - struct drm_i915_private *dev_priv = to_i915(display->drm); bool ret; - vlv_punit_get(dev_priv); - ret = (vlv_punit_read(dev_priv, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; - vlv_punit_put(dev_priv); + vlv_punit_get(display->drm); + ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; + vlv_punit_put(display->drm); return ret; } @@ -1929,7 +1937,6 @@ static void intel_power_domains_verify_state(struct intel_display *display); */ void intel_power_domains_init_hw(struct intel_display *display, bool resume) { - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; power_domains->initializing = true; @@ -1953,9 +1960,9 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume) assert_isp_power_gated(display); } else if (display->platform.broadwell || display->platform.haswell) { hsw_assert_cdclk(display); - intel_pch_reset_handshake(display, !HAS_PCH_NOP(i915)); + intel_pch_reset_handshake(display, !HAS_PCH_NOP(display)); } else if (display->platform.ivybridge) { - intel_pch_reset_handshake(display, !HAS_PCH_NOP(i915)); + intel_pch_reset_handshake(display, !HAS_PCH_NOP(display)); } /* @@ -1966,12 +1973,12 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume) */ drm_WARN_ON(display->drm, power_domains->init_wakeref); power_domains->init_wakeref = - intel_display_power_get(i915, POWER_DOMAIN_INIT); + intel_display_power_get(display, POWER_DOMAIN_INIT); /* Disable power support if the user asked so. */ if (!display->params.disable_power_well) { drm_WARN_ON(display->drm, power_domains->disable_wakeref); - display->power.domains.disable_wakeref = intel_display_power_get(i915, + display->power.domains.disable_wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT); } intel_power_domains_sync_hw(display); @@ -1992,13 +1999,12 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume) */ void intel_power_domains_driver_remove(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - intel_wakeref_t wakeref __maybe_unused = + struct ref_tracker *wakeref __maybe_unused = fetch_and_zero(&display->power.domains.init_wakeref); /* Remove the refcount we took to keep power well support disabled. */ if (!display->params.disable_power_well) - intel_display_power_put(i915, POWER_DOMAIN_INIT, + intel_display_power_put(display, POWER_DOMAIN_INIT, fetch_and_zero(&display->power.domains.disable_wakeref)); intel_display_power_flush_work_sync(display); @@ -2006,7 +2012,7 @@ void intel_power_domains_driver_remove(struct intel_display *display) intel_power_domains_verify_state(display); /* Keep the power well enabled, but cancel its rpm wakeref. */ - intel_runtime_pm_put(&i915->runtime_pm, wakeref); + intel_display_rpm_put(display, wakeref); } /** @@ -2054,11 +2060,10 @@ void intel_power_domains_sanitize_state(struct intel_display *display) */ void intel_power_domains_enable(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - intel_wakeref_t wakeref __maybe_unused = + struct ref_tracker *wakeref __maybe_unused = fetch_and_zero(&display->power.domains.init_wakeref); - intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref); + intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref); intel_power_domains_verify_state(display); } @@ -2071,12 +2076,11 @@ void intel_power_domains_enable(struct intel_display *display) */ void intel_power_domains_disable(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; drm_WARN_ON(display->drm, power_domains->init_wakeref); power_domains->init_wakeref = - intel_display_power_get(i915, POWER_DOMAIN_INIT); + intel_display_power_get(display, POWER_DOMAIN_INIT); intel_power_domains_verify_state(display); } @@ -2094,12 +2098,11 @@ void intel_power_domains_disable(struct intel_display *display) */ void intel_power_domains_suspend(struct intel_display *display, bool s2idle) { - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; - intel_wakeref_t wakeref __maybe_unused = + struct ref_tracker *wakeref __maybe_unused = fetch_and_zero(&power_domains->init_wakeref); - intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref); + intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref); /* * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9 @@ -2110,7 +2113,7 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle) */ if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) && s2idle && intel_dmc_has_payload(display)) { - intel_display_power_flush_work(i915); + intel_display_power_flush_work(display); intel_power_domains_verify_state(display); return; } @@ -2120,10 +2123,10 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle) * power wells if power domains must be deinitialized for suspend. */ if (!display->params.disable_power_well) - intel_display_power_put(i915, POWER_DOMAIN_INIT, + intel_display_power_put(display, POWER_DOMAIN_INIT, fetch_and_zero(&display->power.domains.disable_wakeref)); - intel_display_power_flush_work(i915); + intel_display_power_flush_work(display); intel_power_domains_verify_state(display); if (DISPLAY_VER(display) >= 11) @@ -2148,7 +2151,6 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle) */ void intel_power_domains_resume(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct i915_power_domains *power_domains = &display->power.domains; if (power_domains->display_core_suspended) { @@ -2157,10 +2159,8 @@ void intel_power_domains_resume(struct intel_display *display) } else { drm_WARN_ON(display->drm, power_domains->init_wakeref); power_domains->init_wakeref = - intel_display_power_get(i915, POWER_DOMAIN_INIT); + intel_display_power_get(display, POWER_DOMAIN_INIT); } - - intel_power_domains_verify_state(display); } #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) @@ -2255,8 +2255,6 @@ static void intel_power_domains_verify_state(struct intel_display *display) void intel_display_power_suspend_late(struct intel_display *display, bool s2idle) { - struct drm_i915_private *i915 = to_i915(display->drm); - intel_power_domains_suspend(display, s2idle); if (DISPLAY_VER(display) >= 11 || display->platform.geminilake || @@ -2267,14 +2265,13 @@ void intel_display_power_suspend_late(struct intel_display *display, bool s2idle } /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */ - if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1) - intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); + if (intel_display_wa(display, INTEL_DISPLAY_WA_14010685332)) + intel_de_rmw(display, SOUTH_CHICKEN1, + SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); } void intel_display_power_resume_early(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - if (DISPLAY_VER(display) >= 11 || display->platform.geminilake || display->platform.broxton) { gen9_sanitize_dc_state(display); @@ -2284,8 +2281,8 @@ void intel_display_power_resume_early(struct intel_display *display) } /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */ - if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1) - intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0); + if (intel_display_wa(display, INTEL_DISPLAY_WA_14010685332)) + intel_de_rmw(display, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0); intel_power_domains_resume(display); } @@ -2327,14 +2324,16 @@ void intel_display_power_resume(struct intel_display *display) } } -void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m) +void intel_display_power_debug(struct intel_display *display, struct seq_file *m) { - struct intel_display *display = &i915->display; struct i915_power_domains *power_domains = &display->power.domains; int i; mutex_lock(&power_domains->lock); + seq_printf(m, "Runtime power status: %s\n", + str_enabled_disabled(!power_domains->init_wakeref)); + seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count"); for (i = 0; i < power_domains->power_well_count; i++) { struct i915_power_well *power_well; @@ -2510,9 +2509,8 @@ intel_port_domains_for_port(struct intel_display *display, enum port port) } enum intel_display_power_domain -intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port) +intel_display_power_ddi_io_domain(struct intel_display *display, enum port port) { - struct intel_display *display = &i915->display; const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(display, port); if (drm_WARN_ON(display->drm, !domains || domains->ddi_io == POWER_DOMAIN_INVALID)) @@ -2522,9 +2520,8 @@ intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port) } enum intel_display_power_domain -intel_display_power_ddi_lanes_domain(struct drm_i915_private *i915, enum port port) +intel_display_power_ddi_lanes_domain(struct intel_display *display, enum port port) { - struct intel_display *display = &i915->display; const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(display, port); if (drm_WARN_ON(display->drm, !domains || domains->ddi_lanes == POWER_DOMAIN_INVALID)) @@ -2549,9 +2546,8 @@ intel_port_domains_for_aux_ch(struct intel_display *display, enum aux_ch aux_ch) } enum intel_display_power_domain -intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch) +intel_display_power_aux_io_domain(struct intel_display *display, enum aux_ch aux_ch) { - struct intel_display *display = &i915->display; const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch); if (drm_WARN_ON(display->drm, !domains || domains->aux_io == POWER_DOMAIN_INVALID)) @@ -2561,9 +2557,8 @@ intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux } enum intel_display_power_domain -intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch) +intel_display_power_legacy_aux_domain(struct intel_display *display, enum aux_ch aux_ch) { - struct intel_display *display = &i915->display; const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch); if (drm_WARN_ON(display->drm, !domains || domains->aux_legacy_usbc == POWER_DOMAIN_INVALID)) @@ -2573,9 +2568,8 @@ intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch } enum intel_display_power_domain -intel_display_power_tbt_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch) +intel_display_power_tbt_aux_domain(struct intel_display *display, enum aux_ch aux_ch) { - struct intel_display *display = &i915->display; const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch); if (drm_WARN_ON(display->drm, !domains || domains->aux_tbt == POWER_DOMAIN_INVALID)) |
