diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_drrs.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_drrs.c | 186 |
1 files changed, 154 insertions, 32 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 7da4a9cbe4ba..0fdb32ef241c 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -3,11 +3,16 @@ * Copyright © 2021 Intel Corporation */ -#include "i915_drv.h" +#include <linux/debugfs.h> + +#include <drm/drm_print.h> + #include "intel_atomic.h" #include "intel_de.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_drrs.h" +#include "intel_frontbuffer.h" #include "intel_panel.h" /** @@ -61,27 +66,30 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type) return str[drrs_type]; } +bool intel_cpu_transcoder_has_drrs(struct intel_display *display, + enum transcoder cpu_transcoder) +{ + if (HAS_DOUBLE_BUFFERED_M_N(display)) + return true; + + return intel_cpu_transcoder_has_m2_n2(display, cpu_transcoder); +} + static void intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc, enum drrs_refresh_rate refresh_rate) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder; - u32 val, bit; + u32 bit; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - bit = PIPECONF_REFRESH_RATE_ALT_VLV; + if (display->platform.valleyview || display->platform.cherryview) + bit = TRANSCONF_REFRESH_RATE_ALT_VLV; else - bit = PIPECONF_REFRESH_RATE_ALT_ILK; - - val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder)); + bit = TRANSCONF_REFRESH_RATE_ALT_ILK; - if (refresh_rate == DRRS_REFRESH_RATE_LOW) - val |= bit; - else - val &= ~bit; - - intel_de_write(dev_priv, PIPECONF(cpu_transcoder), val); + intel_de_rmw(display, TRANSCONF(display, cpu_transcoder), + bit, refresh_rate == DRRS_REFRESH_RATE_LOW ? bit : 0); } static void @@ -101,12 +109,12 @@ bool intel_drrs_is_active(struct intel_crtc *crtc) static void intel_drrs_set_state(struct intel_crtc *crtc, enum drrs_refresh_rate refresh_rate) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); if (refresh_rate == crtc->drrs.refresh_rate) return; - if (intel_cpu_transcoder_has_m2_n2(dev_priv, crtc->drrs.cpu_transcoder)) + if (intel_cpu_transcoder_has_m2_n2(display, crtc->drrs.cpu_transcoder)) intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate); else intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate); @@ -116,19 +124,21 @@ static void intel_drrs_set_state(struct intel_crtc *crtc, static void intel_drrs_schedule_work(struct intel_crtc *crtc) { - mod_delayed_work(system_wq, &crtc->drrs.work, msecs_to_jiffies(1000)); + struct intel_display *display = to_intel_display(crtc); + + mod_delayed_work(display->wq.unordered, &crtc->drrs.work, msecs_to_jiffies(1000)); } static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); unsigned int frontbuffer_bits; frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); - for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, - crtc_state->bigjoiner_pipes) + for_each_intel_crtc_in_pipe_mask(display->drm, crtc, + crtc_state->joiner_pipes) frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); return frontbuffer_bits; @@ -150,7 +160,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) if (!crtc_state->hw.active) return; - if (intel_crtc_is_bigjoiner_slave(crtc_state)) + if (intel_crtc_is_joiner_secondary(crtc_state)) return; mutex_lock(&crtc->drrs.mutex); @@ -182,7 +192,7 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->hw.active) return; - if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) + if (intel_crtc_is_joiner_secondary(old_crtc_state)) return; mutex_lock(&crtc->drrs.mutex); @@ -211,13 +221,13 @@ static void intel_drrs_downclock_work(struct work_struct *work) mutex_unlock(&crtc->drrs.mutex); } -static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, +static void intel_drrs_frontbuffer_update(struct intel_display *display, unsigned int all_frontbuffer_bits, bool invalidate) { struct intel_crtc *crtc; - for_each_intel_crtc(&dev_priv->drm, crtc) { + for_each_intel_crtc(display->drm, crtc) { unsigned int frontbuffer_bits; mutex_lock(&crtc->drrs.mutex); @@ -251,7 +261,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, /** * intel_drrs_invalidate - Disable Idleness DRRS - * @dev_priv: i915 device + * @display: display device * @frontbuffer_bits: frontbuffer plane tracking bits * * This function gets called everytime rendering on the given planes start. @@ -259,15 +269,15 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, * * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. */ -void intel_drrs_invalidate(struct drm_i915_private *dev_priv, +void intel_drrs_invalidate(struct intel_display *display, unsigned int frontbuffer_bits) { - intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, true); + intel_drrs_frontbuffer_update(display, frontbuffer_bits, true); } /** * intel_drrs_flush - Restart Idleness DRRS - * @dev_priv: i915 device + * @display: display device * @frontbuffer_bits: frontbuffer plane tracking bits * * This function gets called every time rendering on the given planes has @@ -277,23 +287,135 @@ void intel_drrs_invalidate(struct drm_i915_private *dev_priv, * * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. */ -void intel_drrs_flush(struct drm_i915_private *dev_priv, +void intel_drrs_flush(struct intel_display *display, unsigned int frontbuffer_bits) { - intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); + intel_drrs_frontbuffer_update(display, frontbuffer_bits, false); } /** - * intel_crtc_drrs_init - Init DRRS for CRTC + * intel_drrs_crtc_init - Init DRRS for CRTC * @crtc: crtc * * This function is called only once at driver load to initialize basic * DRRS stuff. * */ -void intel_crtc_drrs_init(struct intel_crtc *crtc) +void intel_drrs_crtc_init(struct intel_crtc *crtc) { INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work); mutex_init(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; } + +static int intel_drrs_debugfs_status_show(struct seq_file *m, void *unused) +{ + struct intel_crtc *crtc = m->private; + struct intel_display *display = to_intel_display(crtc); + const struct intel_crtc_state *crtc_state; + int ret; + + ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); + if (ret) + return ret; + + crtc_state = to_intel_crtc_state(crtc->base.state); + + mutex_lock(&crtc->drrs.mutex); + + seq_printf(m, "DRRS capable: %s\n", + str_yes_no(intel_cpu_transcoder_has_drrs(display, + crtc_state->cpu_transcoder))); + + seq_printf(m, "DRRS enabled: %s\n", + str_yes_no(crtc_state->has_drrs)); + + seq_printf(m, "DRRS active: %s\n", + str_yes_no(intel_drrs_is_active(crtc))); + + seq_printf(m, "DRRS refresh rate: %s\n", + crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? + "low" : "high"); + + seq_printf(m, "DRRS busy frontbuffer bits: 0x%x\n", + crtc->drrs.busy_frontbuffer_bits); + + mutex_unlock(&crtc->drrs.mutex); + + drm_modeset_unlock(&crtc->base.mutex); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_status); + +static int intel_drrs_debugfs_ctl_set(void *data, u64 val) +{ + struct intel_crtc *crtc = data; + struct intel_display *display = to_intel_display(crtc); + struct intel_crtc_state *crtc_state; + struct drm_crtc_commit *commit; + int ret; + + ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex); + if (ret) + return ret; + + crtc_state = to_intel_crtc_state(crtc->base.state); + + if (!crtc_state->hw.active || + !crtc_state->has_drrs) + goto out; + + commit = crtc_state->uapi.commit; + if (commit) { + ret = wait_for_completion_interruptible(&commit->hw_done); + if (ret) + goto out; + } + + drm_dbg_kms(display->drm, "Manually %sactivating DRRS\n", val ? "" : "de"); + + if (val) + intel_drrs_activate(crtc_state); + else + intel_drrs_deactivate(crtc_state); + +out: + drm_modeset_unlock(&crtc->base.mutex); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, + NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); + +void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc) +{ + debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_status_fops); + + debugfs_create_file_unsafe("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_ctl_fops); +} + +static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused) +{ + struct intel_connector *connector = m->private; + + seq_printf(m, "DRRS type: %s\n", + intel_drrs_type_str(intel_panel_drrs_type(connector))); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_type); + +void intel_drrs_connector_debugfs_add(struct intel_connector *connector) +{ + if (intel_panel_drrs_type(connector) == DRRS_TYPE_NONE) + return; + + debugfs_create_file("i915_drrs_type", 0444, connector->base.debugfs_entry, + connector, &intel_drrs_debugfs_type_fops); +} |
