diff options
author | Rodrigo Vivi <rodrigo.vivi@gmail.com> | 2013-07-11 17:45:00 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-07-18 04:17:21 -0400 |
commit | 3f51e4713fc57ab0fc225c3f0e67578a53c24a11 (patch) | |
tree | 805ccec916c12cc168dfb34a8bd07d957d69e654 /drivers/gpu | |
parent | e91fd8c6dec2ffa903b4f695fce4b9d7248ed2d5 (diff) |
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 67 |
4 files changed, 123 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 65619e6fde86..973f2727d703 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -1550,17 +1550,49 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) | |||
1550 | struct drm_info_node *node = m->private; | 1550 | struct drm_info_node *node = m->private; |
1551 | struct drm_device *dev = node->minor->dev; | 1551 | struct drm_device *dev = node->minor->dev; |
1552 | struct drm_i915_private *dev_priv = dev->dev_private; | 1552 | struct drm_i915_private *dev_priv = dev->dev_private; |
1553 | u32 psrctl, psrstat, psrperf; | 1553 | u32 psrstat, psrperf; |
1554 | 1554 | ||
1555 | if (!IS_HASWELL(dev)) { | 1555 | if (!IS_HASWELL(dev)) { |
1556 | seq_puts(m, "PSR not supported on this platform\n"); | 1556 | 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"); | ||
1557 | return 0; | 1593 | return 0; |
1558 | } | 1594 | } |
1559 | 1595 | ||
1560 | psrctl = I915_READ(EDP_PSR_CTL); | ||
1561 | seq_printf(m, "PSR Enabled: %s\n", | ||
1562 | yesno(psrctl & EDP_PSR_ENABLE)); | ||
1563 | |||
1564 | psrstat = I915_READ(EDP_PSR_STATUS_CTL); | 1596 | psrstat = I915_READ(EDP_PSR_STATUS_CTL); |
1565 | 1597 | ||
1566 | seq_puts(m, "PSR Current State: "); | 1598 | seq_puts(m, "PSR Current State: "); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bd1b95ea6a28..21d55f855d16 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -593,6 +593,17 @@ struct i915_fbc { | |||
593 | } no_fbc_reason; | 593 | } no_fbc_reason; |
594 | }; | 594 | }; |
595 | 595 | ||
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 | }; | ||
596 | 607 | ||
597 | enum intel_pch { | 608 | enum intel_pch { |
598 | PCH_NONE = 0, /* No PCH present */ | 609 | PCH_NONE = 0, /* No PCH present */ |
@@ -1173,6 +1184,8 @@ typedef struct drm_i915_private { | |||
1173 | /* Haswell power well */ | 1184 | /* Haswell power well */ |
1174 | struct i915_power_well power_well; | 1185 | struct i915_power_well power_well; |
1175 | 1186 | ||
1187 | enum no_psr_reason no_psr_reason; | ||
1188 | |||
1176 | struct i915_gpu_error gpu_error; | 1189 | struct i915_gpu_error gpu_error; |
1177 | 1190 | ||
1178 | struct drm_i915_gem_object *vlv_pctx; | 1191 | struct drm_i915_gem_object *vlv_pctx; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bb898bfe053d..1d710966983e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -4150,6 +4150,13 @@ | |||
4150 | #define HSW_TVIDEO_DIP_VSC_DATA(trans) \ | 4150 | #define HSW_TVIDEO_DIP_VSC_DATA(trans) \ |
4151 | _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B) | 4151 | _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B) |
4152 | 4152 | ||
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 | |||
4153 | #define _PCH_TRANS_HTOTAL_B 0xe1000 | 4160 | #define _PCH_TRANS_HTOTAL_B 0xe1000 |
4154 | #define _PCH_TRANS_HBLANK_B 0xe1004 | 4161 | #define _PCH_TRANS_HBLANK_B 0xe1004 |
4155 | #define _PCH_TRANS_HSYNC_B 0xe1008 | 4162 | #define _PCH_TRANS_HSYNC_B 0xe1008 |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bb3593db42e9..3ce1b872935e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1492,11 +1492,76 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp) | |||
1492 | EDP_PSR_ENABLE); | 1492 | EDP_PSR_ENABLE); |
1493 | } | 1493 | } |
1494 | 1494 | ||
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 | |||
1495 | void intel_edp_psr_enable(struct intel_dp *intel_dp) | 1559 | void intel_edp_psr_enable(struct intel_dp *intel_dp) |
1496 | { | 1560 | { |
1497 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | 1561 | struct drm_device *dev = intel_dp_to_dev(intel_dp); |
1498 | 1562 | ||
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)) | ||
1500 | return; | 1565 | return; |
1501 | 1566 | ||
1502 | /* Setup PSR once */ | 1567 | /* Setup PSR once */ |