diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_runtime_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_runtime_pm.c | 144 |
1 files changed, 123 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index fe8faf30bda7..e856d49d6dc3 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -65,6 +65,9 @@ bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, int power_well_id); +static struct i915_power_well * +lookup_power_well(struct drm_i915_private *dev_priv, int power_well_id); + const char * intel_display_power_domain_str(enum intel_display_power_domain domain) { @@ -151,6 +154,23 @@ static void intel_power_well_disable(struct drm_i915_private *dev_priv, power_well->ops->disable(dev_priv, power_well); } +static void intel_power_well_get(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + if (!power_well->count++) + intel_power_well_enable(dev_priv, power_well); +} + +static void intel_power_well_put(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + WARN(!power_well->count, "Use count on power well %s is already zero", + power_well->name); + + if (!--power_well->count) + intel_power_well_disable(dev_priv, power_well); +} + /* * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to @@ -419,6 +439,16 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BIT(POWER_DOMAIN_MODESET) | \ BIT(POWER_DOMAIN_AUX_A) | \ BIT(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_A_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT(POWER_DOMAIN_AUX_A) | \ + BIT(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_BC_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT(POWER_DOMAIN_AUX_B) | \ + BIT(POWER_DOMAIN_AUX_C) | \ + BIT(POWER_DOMAIN_INIT)) static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) { @@ -800,6 +830,72 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv, skl_set_power_well(dev_priv, power_well, false); } +static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well) +{ + enum skl_disp_power_wells power_well_id = power_well->data; + + return power_well_id == BXT_DPIO_CMN_A ? DPIO_PHY1 : DPIO_PHY0; +} + +static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum skl_disp_power_wells power_well_id = power_well->data; + struct i915_power_well *cmn_a_well; + + if (power_well_id == BXT_DPIO_CMN_BC) { + /* + * We need to copy the GRC calibration value from the eDP PHY, + * so make sure it's powered up. + */ + cmn_a_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A); + intel_power_well_get(dev_priv, cmn_a_well); + } + + bxt_ddi_phy_init(dev_priv, bxt_power_well_to_phy(power_well)); + + if (power_well_id == BXT_DPIO_CMN_BC) + intel_power_well_put(dev_priv, cmn_a_well); +} + +static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + bxt_ddi_phy_uninit(dev_priv, bxt_power_well_to_phy(power_well)); +} + +static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + return bxt_ddi_phy_is_enabled(dev_priv, + bxt_power_well_to_phy(power_well)); +} + +static void bxt_dpio_cmn_power_well_sync_hw(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + if (power_well->count > 0) + bxt_dpio_cmn_power_well_enable(dev_priv, power_well); + else + bxt_dpio_cmn_power_well_disable(dev_priv, power_well); +} + + +static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *power_well; + + power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A); + if (power_well->count > 0) + bxt_ddi_phy_verify_state(dev_priv, + bxt_power_well_to_phy(power_well)); + + power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC); + if (power_well->count > 0) + bxt_ddi_phy_verify_state(dev_priv, + bxt_power_well_to_phy(power_well)); +} + static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -826,7 +922,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, gen9_assert_dbuf_enabled(dev_priv); if (IS_BROXTON(dev_priv)) - broxton_ddi_phy_verify_state(dev_priv); + bxt_verify_ddi_phy_power_wells(dev_priv); } static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, @@ -1518,10 +1614,8 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv, struct i915_power_well *power_well; int i; - for_each_power_well(i, power_well, BIT(domain), power_domains) { - if (!power_well->count++) - intel_power_well_enable(dev_priv, power_well); - } + for_each_power_well(i, power_well, BIT(domain), power_domains) + intel_power_well_get(dev_priv, power_well); power_domains->domain_use_count[domain]++; } @@ -1615,14 +1709,8 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, intel_display_power_domain_str(domain)); power_domains->domain_use_count[domain]--; - for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { - WARN(!power_well->count, - "Use count on power well %s is already zero", - power_well->name); - - if (!--power_well->count) - intel_power_well_disable(dev_priv, power_well); - } + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) + intel_power_well_put(dev_priv, power_well); mutex_unlock(&power_domains->lock); @@ -1793,6 +1881,13 @@ static const struct i915_power_well_ops gen9_dc_off_power_well_ops = { .is_enabled = gen9_dc_off_power_well_enabled, }; +static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = { + .sync_hw = bxt_dpio_cmn_power_well_sync_hw, + .enable = bxt_dpio_cmn_power_well_enable, + .disable = bxt_dpio_cmn_power_well_disable, + .is_enabled = bxt_dpio_cmn_power_well_enabled, +}; + static struct i915_power_well hsw_power_wells[] = { { .name = "always-on", @@ -2029,6 +2124,18 @@ static struct i915_power_well bxt_power_wells[] = { .ops = &skl_power_well_ops, .data = SKL_DISP_PW_2, }, + { + .name = "dpio-common-a", + .domains = BXT_DPIO_CMN_A_POWER_DOMAINS, + .ops = &bxt_dpio_cmn_power_well_ops, + .data = BXT_DPIO_CMN_A, + }, + { + .name = "dpio-common-bc", + .domains = BXT_DPIO_CMN_BC_POWER_DOMAINS, + .ops = &bxt_dpio_cmn_power_well_ops, + .data = BXT_DPIO_CMN_BC, + }, }; static int @@ -2294,14 +2401,10 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv, mutex_unlock(&power_domains->lock); - broxton_init_cdclk(dev_priv); + bxt_init_cdclk(dev_priv); gen9_dbuf_enable(dev_priv); - broxton_ddi_phy_init(dev_priv); - - broxton_ddi_phy_verify_state(dev_priv); - if (resume && dev_priv->csr.dmc_payload) intel_csr_load_program(dev_priv); } @@ -2313,11 +2416,9 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv) gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); - broxton_ddi_phy_uninit(dev_priv); - gen9_dbuf_disable(dev_priv); - broxton_uninit_cdclk(dev_priv); + bxt_uninit_cdclk(dev_priv); /* The spec doesn't call for removing the reset handshake flag */ @@ -2448,6 +2549,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) /** * intel_power_domains_init_hw - initialize hardware power domain state * @dev_priv: i915 device instance + * @resume: Called from resume code paths or not * * This function initializes the hardware power domain state and enables all * power domains using intel_display_set_init_power(). |