Skip to content

Commit 3f51e47

Browse files
rodrigovividanvet
authored andcommitted
drm/i915: Match all PSR mode entry conditions before enabling it.
v2: Prefer seq_puts to seq_printf by Paulo Zanoni. v3: small changes like avoiding calling dp_to_dig_port twice as noticed by Paulo Zanoni. v4: Avoiding reading non-existent registers - noticed by Paulo on first psr debugfs patch. v5: Accepting more suggestions from Paulo: * check sw interlace flag instead of i915_read * introduce PSR_S3D_ENABLED to avoid forgeting it whenever added. Cc: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Shobhit Kumar <shobhit.kumar@intel.com> [danvet: Fix up debugfs output (spotted by Paulo) and rip out the power well check since we really can't do that in a race-free manner, so it's bogus.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent e91fd8c commit 3f51e47

File tree

4 files changed

+123
-6
lines changed

4 files changed

+123
-6
lines changed

drivers/gpu/drm/i915/i915_debugfs.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,17 +1550,49 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
15501550
struct drm_info_node *node = m->private;
15511551
struct drm_device *dev = node->minor->dev;
15521552
struct drm_i915_private *dev_priv = dev->dev_private;
1553-
u32 psrctl, psrstat, psrperf;
1553+
u32 psrstat, psrperf;
15541554

15551555
if (!IS_HASWELL(dev)) {
15561556
seq_puts(m, "PSR not supported on this platform\n");
1557+
} else if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
1558+
seq_puts(m, "PSR enabled\n");
1559+
} else {
1560+
seq_puts(m, "PSR disabled: ");
1561+
switch (dev_priv->no_psr_reason) {
1562+
case PSR_NO_SOURCE:
1563+
seq_puts(m, "not supported on this platform");
1564+
break;
1565+
case PSR_NO_SINK:
1566+
seq_puts(m, "not supported by panel");
1567+
break;
1568+
case PSR_CRTC_NOT_ACTIVE:
1569+
seq_puts(m, "crtc not active");
1570+
break;
1571+
case PSR_PWR_WELL_ENABLED:
1572+
seq_puts(m, "power well enabled");
1573+
break;
1574+
case PSR_NOT_TILED:
1575+
seq_puts(m, "not tiled");
1576+
break;
1577+
case PSR_SPRITE_ENABLED:
1578+
seq_puts(m, "sprite enabled");
1579+
break;
1580+
case PSR_S3D_ENABLED:
1581+
seq_puts(m, "stereo 3d enabled");
1582+
break;
1583+
case PSR_INTERLACED_ENABLED:
1584+
seq_puts(m, "interlaced enabled");
1585+
break;
1586+
case PSR_HSW_NOT_DDIA:
1587+
seq_puts(m, "HSW ties PSR to DDI A (eDP)");
1588+
break;
1589+
default:
1590+
seq_puts(m, "unknown reason");
1591+
}
1592+
seq_puts(m, "\n");
15571593
return 0;
15581594
}
15591595

1560-
psrctl = I915_READ(EDP_PSR_CTL);
1561-
seq_printf(m, "PSR Enabled: %s\n",
1562-
yesno(psrctl & EDP_PSR_ENABLE));
1563-
15641596
psrstat = I915_READ(EDP_PSR_STATUS_CTL);
15651597

15661598
seq_puts(m, "PSR Current State: ");

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,17 @@ struct i915_fbc {
593593
} no_fbc_reason;
594594
};
595595

596+
enum no_psr_reason {
597+
PSR_NO_SOURCE, /* Not supported on platform */
598+
PSR_NO_SINK, /* Not supported by panel */
599+
PSR_CRTC_NOT_ACTIVE,
600+
PSR_PWR_WELL_ENABLED,
601+
PSR_NOT_TILED,
602+
PSR_SPRITE_ENABLED,
603+
PSR_S3D_ENABLED,
604+
PSR_INTERLACED_ENABLED,
605+
PSR_HSW_NOT_DDIA,
606+
};
596607

597608
enum intel_pch {
598609
PCH_NONE = 0, /* No PCH present */
@@ -1173,6 +1184,8 @@ typedef struct drm_i915_private {
11731184
/* Haswell power well */
11741185
struct i915_power_well power_well;
11751186

1187+
enum no_psr_reason no_psr_reason;
1188+
11761189
struct i915_gpu_error gpu_error;
11771190

11781191
struct drm_i915_gem_object *vlv_pctx;

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4150,6 +4150,13 @@
41504150
#define HSW_TVIDEO_DIP_VSC_DATA(trans) \
41514151
_TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B)
41524152

4153+
#define HSW_STEREO_3D_CTL_A 0x70020
4154+
#define S3D_ENABLE (1<<31)
4155+
#define HSW_STEREO_3D_CTL_B 0x71020
4156+
4157+
#define HSW_STEREO_3D_CTL(trans) \
4158+
_TRANSCODER(trans, HSW_STEREO_3D_CTL_A, HSW_STEREO_3D_CTL_A)
4159+
41534160
#define _PCH_TRANS_HTOTAL_B 0xe1000
41544161
#define _PCH_TRANS_HBLANK_B 0xe1004
41554162
#define _PCH_TRANS_HSYNC_B 0xe1008

drivers/gpu/drm/i915/intel_dp.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1492,11 +1492,76 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
14921492
EDP_PSR_ENABLE);
14931493
}
14941494

1495+
static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
1496+
{
1497+
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
1498+
struct drm_device *dev = dig_port->base.base.dev;
1499+
struct drm_i915_private *dev_priv = dev->dev_private;
1500+
struct drm_crtc *crtc = dig_port->base.base.crtc;
1501+
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1502+
struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
1503+
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
1504+
1505+
if (!IS_HASWELL(dev)) {
1506+
DRM_DEBUG_KMS("PSR not supported on this platform\n");
1507+
dev_priv->no_psr_reason = PSR_NO_SOURCE;
1508+
return false;
1509+
}
1510+
1511+
if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
1512+
(dig_port->port != PORT_A)) {
1513+
DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
1514+
dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
1515+
return false;
1516+
}
1517+
1518+
if (!is_edp_psr(intel_dp)) {
1519+
DRM_DEBUG_KMS("PSR not supported by this panel\n");
1520+
dev_priv->no_psr_reason = PSR_NO_SINK;
1521+
return false;
1522+
}
1523+
1524+
if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
1525+
DRM_DEBUG_KMS("crtc not active for PSR\n");
1526+
dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
1527+
return false;
1528+
}
1529+
1530+
if (obj->tiling_mode != I915_TILING_X ||
1531+
obj->fence_reg == I915_FENCE_REG_NONE) {
1532+
DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
1533+
dev_priv->no_psr_reason = PSR_NOT_TILED;
1534+
return false;
1535+
}
1536+
1537+
if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
1538+
DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
1539+
dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
1540+
return false;
1541+
}
1542+
1543+
if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
1544+
S3D_ENABLE) {
1545+
DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
1546+
dev_priv->no_psr_reason = PSR_S3D_ENABLED;
1547+
return false;
1548+
}
1549+
1550+
if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
1551+
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
1552+
dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
1553+
return false;
1554+
}
1555+
1556+
return true;
1557+
}
1558+
14951559
void intel_edp_psr_enable(struct intel_dp *intel_dp)
14961560
{
14971561
struct drm_device *dev = intel_dp_to_dev(intel_dp);
14981562

1499-
if (!is_edp_psr(intel_dp) || intel_edp_is_psr_enabled(dev))
1563+
if (!intel_edp_psr_match_conditions(intel_dp) ||
1564+
intel_edp_is_psr_enabled(dev))
15001565
return;
15011566

15021567
/* Setup PSR once */

0 commit comments

Comments
 (0)