/*
* Copyright © 2014 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* DOC: Panel Self Refresh (PSR/SRD)
*
* Since Haswell Display controller supports Panel Self-Refresh on display
* panels witch have a remote frame buffer (RFB) implemented according to PSR
* spec in eDP1.3. PSR feature allows the display to go to lower standby states
* when system is idle but display is on as it eliminates display refresh
* request to DDR memory completely as long as the frame buffer for that
* display is unchanged.
*
* Panel Self Refresh must be supported by both Hardware (source) and
* Panel (sink).
*
* PSR saves power by caching the framebuffer in the panel RFB, which allows us
* to power down the link and memory controller. For DSI panels the same idea
* is called "manual mode".
*
* The implementation uses the hardware-based PSR support which automatically
* enters/exits self-refresh mode. The hardware takes care of sending the
* required DP aux message and could even retrain the link (that part isn't
* enabled yet though). The hardware also keeps track of any frontbuffer
* changes to know when to exit self-refresh mode again. Unfortunately that
* part doesn't work too well, hence why the i915 PSR support uses the
* software frontbuffer tracking to make sure it doesn't miss a screen
* update. For this integration intel_psr_invalidate() and intel_psr_flush()
* get called by the frontbuffer tracking code. Note that because of locking
* issues the self-refresh re-enable code is done from a work queue, which
* must be correctly synchronized/cancelled when shutting down the pipe."
*/
#include <drm/drmP.h>
#include "intel_drv.h"
#include "i915_drv.h"
static bool psr_global_enabled(u32 debug)
{
switch (debug & I915_PSR_DEBUG_MODE_MASK) {
case I915_PSR_DEBUG_DEFAULT:
return i915_modparams.enable_psr;
case I915_PSR_DEBUG_DISABLE:
return false;
default:
return true;
}
}
static bool intel_psr2_enabled(struct drm_i915_private *dev_priv,
const struct intel_crtc_state *crtc_state)
{
/* Disable PSR2 by default for all platforms */
if (i915_modparams.enable_psr == -1)
return false;
switch (dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
case I915_PSR_DEBUG_FORCE_PSR1:
return false;
default:
return crtc_state->has_psr2;
}
}
void intel_psr_irq_control(struct drm_i915_private *dev_priv, u32 debug)
{
u32 debug_mask, mask;
mask = EDP_PSR_ERROR(TRANSCODER_EDP);
debug_mask = EDP_PSR_POST_EXIT(TRANSCODER_EDP) |
EDP_PSR_PRE_ENTRY(TRANSCODER_EDP);
if (INTEL_GEN(dev_priv) >= 8) {
mask |= EDP_PSR_ERROR(TRANSCODER_A) |
EDP_PSR_ERROR(TRANSCODER_B) |
EDP_PSR_ERROR(TRANSCODER_C);
debug_mask |= EDP_PSR_POST_EXIT(TRANSCODER_A) |
EDP_PSR_PRE_ENTRY(TRANSCODER_A) |
EDP_PSR_POST_EXIT(TRANSCODER_B) |
EDP_PSR_PRE_ENTRY(TRANSCODER_B) |
EDP_PSR_POST_EXIT(TRANSCODER_C) |
EDP_PSR_PRE_ENTRY(TRANSCODER_C);
}
if (debug & I915_PSR_DEBUG_IRQ)
mask |= debug_mask;
I915_WRITE(EDP_PSR_IMR, ~mask);
}
static void psr_event_print(u32 val, bool psr2_enabled)
{
DRM_DEBUG_KMS("PSR exit events: 0x%x\n", val);
if (val & PSR_EVENT_PSR2_WD_TIMER_EXPIRE)
DRM_DEBUG_KMS("\tPSR2 watchdog timer expired\n");
if ((val & PSR_EVENT_PSR2_DISABLED) && psr2_enabled)
DRM_DEBUG_KMS("\tPSR2 disabled\n");
if (val & PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN)
DRM_DEBUG_KMS("\tSU dirty FIFO underrun\n");
if (val & PSR_EVENT_SU_CRC_FIFO_UNDERRUN)
DRM_DEBUG_KMS("\tSU CRC FIFO underrun\n");
if (val & PSR_EVENT_GRAPHICS_RESET)
DRM_DEBUG_KMS("\tGraphics reset\n");
if (val & PSR_EVENT_PCH_INTERRUPT)
DRM_DEBUG_KMS("\tPCH interrupt\n");
if (val & PSR_EVENT_MEMORY_UP)
DRM_DEBUG_KMS("\tMemory up\n");
if (val & PSR_EVENT_FRONT_BUFFER_MODIFY)
DRM_DEBUG_KMS("\tFront buffer modification\n");
if (val & PSR_EVENT_WD_TIMER_EXPIRE)
DRM_DEBUG_KMS("\tPSR watchdog timer expired\n");
if (val & PSR_EVENT_PIPE_REGISTERS_UPDATE)
DRM_DEBUG_KMS("\tPIPE registers updated\n&quo