[Intel-gfx] [PATCH 4/4] drm/i915: Introduce PSR Block Power Domains.
Rodrigo Vivi
rodrigo.vivi at intel.com
Wed Aug 3 21:44:38 UTC 2016
Issue: By the spec panels can emmit HPD when find some erros.
Some of the errors we see are on reserved bits of spec so we
end up not handling any of them.
Our handling functions uses aux communications. However if the
link is in a deep off state like in PSR2 for gen9 we will have
trouble and link is never restablished. Also even with PSR1 case
we see flickering screens or hard lock depending on the panel.
Solution: Prevent PSR in some situations where we know link
shouldn't be off.
Propose: Reuse the runtime PM domains to block PSR. PSR is not
a Power Well but it is a power saving runtime component.
Also it is better reuse something that is stablish and safe
then get back to old times where we had psr_exits and
psr_disables spread all over our code.
Cc: Imre Deak <imre.deak at intel.com>
Cc: Tarun Vyas <tarun.vyas at intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
---
drivers/gpu/drm/i915/i915_drv.c | 1 +
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_display.c | 2 --
drivers/gpu/drm/i915/intel_runtime_pm.c | 56 +++++++++++++++++++++++++++++++++
4 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 83afdd0..d1bf060 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -840,6 +840,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
intel_pm_setup(&dev_priv->drm);
intel_init_dpio(dev_priv);
+ intel_psr_init(dev_priv);
intel_power_domains_init(dev_priv);
intel_irq_init(dev_priv);
intel_init_display_hooks(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2f93d4a..1cd939f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -718,6 +718,7 @@ enum skl_disp_power_wells {
/* Not actual bit groups. Used as IDs for lookup_power_well() */
SKL_DISP_PW_ALWAYS_ON,
SKL_DISP_PW_DC_OFF,
+ SKL_DISP_PW_PSR_BLOCK,
BXT_DPIO_CMN_A,
BXT_DPIO_CMN_BC,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e114886..cfff3ed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14824,8 +14824,6 @@ static void intel_setup_outputs(struct drm_device *dev)
if (SUPPORTS_TV(dev))
intel_tv_init(dev);
- intel_psr_init(dev_priv);
-
for_each_intel_encoder(dev, encoder) {
encoder->base.possible_crtcs = encoder->crtc_mask;
encoder->base.possible_clones =
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 1c603bb..6e6e079 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -420,6 +420,10 @@ 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 SKL_DISPLAY_PSR_BLOCK_POWER_DOMAINS ( \
+ BIT(POWER_DOMAIN_MODESET) | \
+ BIT(POWER_DOMAIN_AUX_A) | \
+ BIT(POWER_DOMAIN_INIT))
#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_TRANSCODER_A) | \
@@ -442,6 +446,10 @@ 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_DISPLAY_PSR_BLOCK_POWER_DOMAINS ( \
+ 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) | \
@@ -909,6 +917,35 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
bxt_power_well_to_phy(power_well));
}
+static bool gen9_psr_blk_power_well_enabled(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ return (dev_priv->psr.rpm_block);
+}
+
+static void gen9_psr_blk_power_well_enable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ intel_psr_rpm_block(dev_priv);
+
+ WARN_ON(dev_priv->psr.active);
+}
+
+static void gen9_psr_blk_power_well_disable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ intel_psr_rpm_unblock(dev_priv);
+}
+
+static void gen9_psr_blk_power_well_sync_hw(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ if (power_well->count > 0)
+ gen9_psr_blk_power_well_enable(dev_priv, power_well);
+ else
+ gen9_psr_blk_power_well_disable(dev_priv, power_well);
+}
+
static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
@@ -1910,6 +1947,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 gen9_psr_blk_power_well_ops = {
+ .sync_hw = gen9_psr_blk_power_well_sync_hw,
+ .enable = gen9_psr_blk_power_well_enable,
+ .disable = gen9_psr_blk_power_well_disable,
+ .is_enabled = gen9_psr_blk_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,
@@ -2097,6 +2141,12 @@ static struct i915_power_well skl_power_wells[] = {
.data = SKL_DISP_PW_DC_OFF,
},
{
+ .name = "PSR Block",
+ .domains = SKL_DISPLAY_PSR_BLOCK_POWER_DOMAINS,
+ .ops = &gen9_psr_blk_power_well_ops,
+ .data = SKL_DISP_PW_PSR_BLOCK,
+ },
+ {
.name = "power well 2",
.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
@@ -2148,6 +2198,12 @@ static struct i915_power_well bxt_power_wells[] = {
.data = SKL_DISP_PW_DC_OFF,
},
{
+ .name = "PSR Block",
+ .domains = BXT_DISPLAY_PSR_BLOCK_POWER_DOMAINS,
+ .ops = &gen9_psr_blk_power_well_ops,
+ .data = SKL_DISP_PW_PSR_BLOCK,
+ },
+ {
.name = "power well 2",
.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
--
2.4.3
More information about the Intel-gfx
mailing list