• Anshuman Gupta's avatar
    drm/i915/tgl: Switch between dc3co and dc5 based on display idleness · 1c4d821d
    Anshuman Gupta authored
    DC3CO is useful power state, when DMC detects PSR2 idle frame
    while an active video playback, playing 30fps video on 60hz panel
    is the classic example of this use case.
    
    B.Specs:49196 has a restriction to enable DC3CO only for Video Playback.
    It will be worthy to enable DC3CO after completion of each pageflip
    and switch back to DC5 when display is idle because driver doesn't
    differentiate between video playback and a normal pageflip.
    We will use Frontbuffer flush call tgl_dc3co_flush() to enable DC3CO
    state only for ORIGIN_FLIP flush call, because DC3CO state has primarily
    targeted for VPB use case. We are not interested here for frontbuffer
    invalidates calls because that triggers PSR2 exit, which will
    explicitly disable DC3CO.
    
    DC5 and DC6 saves more power, but can't be entered during video
    playback because there are not enough idle frames in a row to meet
    most PSR2 panel deep sleep entry requirement typically 4 frames.
    As PSR2 existing implementation is using minimum 6 idle frames for
    deep sleep, it is safer to enable DC5/6 after 6 idle frames
    (By scheduling a delayed work of 6 idle frames, once DC3CO has been
    enabled after a pageflip).
    
    After manually waiting for 6 idle frames DC5/6 will be enabled and
    PSR2 deep sleep idle frames will be restored to 6 idle frames, at this
    point DMC will triggers DC5/6 once PSR2 enters to deep sleep after
    6 idle frames.
    In future when we will enable S/W PSR2 tracking, we can change the
    PSR2 required deep sleep idle frames to 1 so DMC can trigger the
    DC5/6 immediately after S/W manual waiting of 6 idle frames get
    complete.
    
    v2: calculated s/w state to switch over dc3co when there is an
        update. [Imre]
        Used cancel_delayed_work_sync() in order to avoid any race
        with already scheduled delayed work. [Imre]
    v3: Cancel_delayed_work_sync() may blocked the commit work.
        hence dropping it, dc5_idle_thread() checks the valid wakeref before
        putting the reference count, which avoids any chances of dropping
        a zero wakeref. [Imre (IRC)]
    v4: Used frontbuffer flush mechanism. [Imre]
    v5: Used psr.pipe to extract frontbuffer busy bits. [Imre]
        Used cancel_delayed_work_sync() in encoder disable path. [Imre]
        Used mod_delayed_work() instead of cancelling and scheduling a
        delayed work. [Imre]
        Used psr.lock in tgl_dc5_idle_thread() to enable psr2 deep
        sleep. [Imre]
        Removed DC5_REQ_IDLE_FRAMES macro. [Imre]
    v6: Used dc3co_exitline check instead of TGL and dc3co allowed_dc_mask
        checks, used delayed_work_pending with the psr lock and removed the
        psr2_deep_slp_disabled flag. [Imre]
    v7: Code refactoring, moved most of functional code to inte_psr.c [Imre]
        Using frontbuffer_bits on psr.pipe check instead of
        busy_frontbuffer_bits. [Imre]
        Calculating dc3co_exit_delay in intel_psr_enable_locked. [Imre]
    
    Cc: Jani Nikula <jani.nikula@intel.com>
    Cc: Imre Deak <imre.deak@intel.com>
    Cc: Animesh Manna <animesh.manna@intel.com>
    Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
    Signed-off-by: default avatarAnshuman Gupta <anshuman.gupta@intel.com>
    Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
    Link: https://patchwork.freedesktop.org/patch/msgid/20191003081738.22101-6-anshuman.gupta@intel.com
    1c4d821d
intel_display_power.c 149 KB