return 0;
}
-static void drrs_status_per_crtc(struct seq_file *m,
- struct drm_device *dev,
- struct intel_crtc *crtc)
+static int i915_drrs_status(struct seq_file *m, void *unused)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_drrs *drrs = &dev_priv->drrs;
- struct intel_connector *connector;
+ struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct drm_connector_list_iter conn_iter;
+ struct intel_connector *connector;
+ struct intel_crtc *crtc;
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
- if (connector->base.state->crtc != &crtc->base)
- continue;
-
seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n",
connector->base.base.id, connector->base.name,
intel_drrs_type_str(intel_panel_drrs_type(connector)));
seq_puts(m, "\n");
- if (to_intel_crtc_state(crtc->base.state)->has_drrs) {
- mutex_lock(&drrs->mutex);
- /* DRRS Supported */
- seq_puts(m, "\tDRRS Enabled: Yes\n");
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ seq_printf(m, "[CRTC:%d:%s]:\n",
+ crtc->base.base.id, crtc->base.name);
- /* disable_drrs() will make drrs->dp NULL */
- if (!drrs->crtc) {
- seq_puts(m, "Idleness DRRS: Disabled\n");
- mutex_unlock(&drrs->mutex);
- return;
- }
+ mutex_lock(&crtc->drrs.mutex);
- seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
- drrs->busy_frontbuffer_bits);
+ /* DRRS Supported */
+ seq_printf(m, "\tDRRS Enabled: %s\n",
+ str_yes_no(intel_drrs_is_enabled(crtc)));
- seq_puts(m, "\n\t\t");
+ seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n",
+ crtc->drrs.busy_frontbuffer_bits);
seq_printf(m, "DRRS refresh rate: %s\n",
- drrs->refresh_rate == DRRS_REFRESH_RATE_LOW ?
+ crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
"low" : "high");
- seq_puts(m, "\n\t\t");
-
- mutex_unlock(&drrs->mutex);
- } else {
- /* DRRS not supported. Print the VBT parameter*/
- seq_puts(m, "\tDRRS Enabled : No");
- }
- seq_puts(m, "\n");
-}
-static int i915_drrs_status(struct seq_file *m, void *unused)
-{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc;
- int active_crtc_cnt = 0;
-
- drm_modeset_lock_all(dev);
- for_each_intel_crtc(dev, crtc) {
- if (crtc->base.state->active) {
- active_crtc_cnt++;
- seq_printf(m, "\nCRTC %d: ", active_crtc_cnt);
-
- drrs_status_per_crtc(m, dev, crtc);
- }
+ mutex_unlock(&crtc->drrs.mutex);
}
- drm_modeset_unlock_all(dev);
-
- if (!active_crtc_cnt)
- seq_puts(m, "No active crtc found\n");
return 0;
}
}
static void
-intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
+intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc,
enum drrs_refresh_rate refresh_rate)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder;
u32 val, bit;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
}
static void
-intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state,
+intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc,
enum drrs_refresh_rate refresh_rate)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
- intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder,
+ intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder,
refresh_rate == DRRS_REFRESH_RATE_LOW ?
- &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n);
+ &crtc->drrs.m2_n2 : &crtc->drrs.m_n);
}
-static void intel_drrs_set_state(struct drm_i915_private *dev_priv,
- const struct intel_crtc_state *crtc_state,
- enum drrs_refresh_rate refresh_rate)
+bool intel_drrs_is_enabled(struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
- if (!dev_priv->drrs.crtc) {
- drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
- return;
- }
-
- if (!crtc) {
- drm_dbg_kms(&dev_priv->drm,
- "DRRS: intel_crtc not initialized\n");
- return;
- }
-
- if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) {
- drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
- return;
- }
+ return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER;
+}
- if (refresh_rate == dev_priv->drrs.refresh_rate)
- return;
+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);
- if (!crtc_state->hw.active) {
- drm_dbg_kms(&dev_priv->drm,
- "eDP encoder disabled. CRTC not Active\n");
+ if (refresh_rate == crtc->drrs.refresh_rate)
return;
- }
if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv))
- intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_rate);
+ intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate);
else if (DISPLAY_VER(dev_priv) > 6)
- intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_rate);
-
- dev_priv->drrs.refresh_rate = refresh_rate;
-
- drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %s\n",
- refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high");
-}
-
-static void
-intel_drrs_enable_locked(struct intel_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate);
- dev_priv->drrs.busy_frontbuffer_bits = 0;
- dev_priv->drrs.crtc = crtc;
+ crtc->drrs.refresh_rate = refresh_rate;
}
/**
if (!crtc_state->has_drrs)
return;
- drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
-
- mutex_lock(&dev_priv->drrs.mutex);
-
- if (dev_priv->drrs.crtc) {
- drm_warn(&dev_priv->drm, "DRRS already enabled\n");
- goto unlock;
- }
+ drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Enabling DRRS\n",
+ crtc->base.base.id, crtc->base.name);
- intel_drrs_enable_locked(crtc);
+ mutex_lock(&crtc->drrs.mutex);
-unlock:
- mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-static void
-intel_drrs_disable_locked(const struct intel_crtc_state *crtc_state)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder;
+ crtc->drrs.m_n = crtc_state->dp_m_n;
+ crtc->drrs.m2_n2 = crtc_state->dp_m2_n2;
+ crtc->drrs.busy_frontbuffer_bits = 0;
- intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH);
- dev_priv->drrs.crtc = NULL;
+ mutex_unlock(&crtc->drrs.mutex);
}
/**
if (!old_crtc_state->has_drrs)
return;
- mutex_lock(&dev_priv->drrs.mutex);
- if (dev_priv->drrs.crtc != crtc) {
- mutex_unlock(&dev_priv->drrs.mutex);
- return;
- }
+ drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Disabling DRRS\n",
+ crtc->base.base.id, crtc->base.name);
+
+ mutex_lock(&crtc->drrs.mutex);
+
+ if (intel_drrs_is_enabled(crtc))
+ intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
+
+ crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
+ crtc->drrs.busy_frontbuffer_bits = 0;
- intel_drrs_disable_locked(old_crtc_state);
- mutex_unlock(&dev_priv->drrs.mutex);
+ mutex_unlock(&crtc->drrs.mutex);
- cancel_delayed_work_sync(&dev_priv->drrs.work);
+ cancel_delayed_work_sync(&crtc->drrs.work);
}
/**
- * intel_drrs_update - Update DRRS state
- * @crtc_state: new CRTC state
- *
- * This function will update DRRS states, disabling or enabling DRRS when
- * executing fastsets. For full modeset, intel_drrs_disable() and
- * intel_drrs_enable() should be called instead.
+ * intel_drrs_update - Update DRRS during fastset
+ * @state: atomic state
+ * @crtc: crtc
*/
-void
-intel_drrs_update(const struct intel_crtc_state *crtc_state)
+void intel_drrs_update(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
- if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
+ if (old_crtc_state->has_drrs == new_crtc_state->has_drrs)
return;
- mutex_lock(&dev_priv->drrs.mutex);
-
- /* New state matches current one? */
- if (crtc_state->has_drrs == !!dev_priv->drrs.crtc)
- goto unlock;
-
- if (crtc_state->has_drrs)
- intel_drrs_enable_locked(crtc);
+ if (new_crtc_state->has_drrs)
+ intel_drrs_enable(new_crtc_state);
else
- intel_drrs_disable_locked(crtc_state);
-
-unlock:
- mutex_unlock(&dev_priv->drrs.mutex);
+ intel_drrs_disable(old_crtc_state);
}
static void intel_drrs_downclock_work(struct work_struct *work)
{
- struct drm_i915_private *dev_priv =
- container_of(work, typeof(*dev_priv), drrs.work.work);
- struct intel_crtc *crtc;
-
- mutex_lock(&dev_priv->drrs.mutex);
+ struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work);
- crtc = dev_priv->drrs.crtc;
- if (!crtc)
- goto unlock;
+ mutex_lock(&crtc->drrs.mutex);
- /*
- * The delayed work can race with an invalidate hence we need to
- * recheck.
- */
-
- if (!dev_priv->drrs.busy_frontbuffer_bits) {
- intel_drrs_set_state(dev_priv, crtc->config,
- DRRS_REFRESH_RATE_LOW);
- }
+ if (intel_drrs_is_enabled(crtc) && !crtc->drrs.busy_frontbuffer_bits)
+ intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW);
-unlock:
- mutex_unlock(&dev_priv->drrs.mutex);
+ mutex_unlock(&crtc->drrs.mutex);
}
static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv,
if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
return;
- cancel_delayed_work(&dev_priv->drrs.work);
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ cancel_delayed_work(&crtc->drrs.work);
- mutex_lock(&dev_priv->drrs.mutex);
+ mutex_lock(&crtc->drrs.mutex);
- crtc = dev_priv->drrs.crtc;
- if (!crtc) {
- mutex_unlock(&dev_priv->drrs.mutex);
- return;
- }
+ if (!intel_drrs_is_enabled(crtc)) {
+ mutex_unlock(&crtc->drrs.mutex);
+ continue;
+ }
- frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
- if (invalidate)
- dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
- else
- dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
+ frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
+ if (invalidate)
+ crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
+ else
+ crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
- /* flush/invalidate means busy screen hence upclock */
- if (frontbuffer_bits)
- intel_drrs_set_state(dev_priv, crtc->config,
- DRRS_REFRESH_RATE_HIGH);
+ /* flush/invalidate means busy screen hence upclock */
+ if (frontbuffer_bits)
+ intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
- /*
- * flush also means no more activity hence schedule downclock, if all
- * other fbs are quiescent too
- */
- if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits)
- schedule_delayed_work(&dev_priv->drrs.work,
- msecs_to_jiffies(1000));
- mutex_unlock(&dev_priv->drrs.mutex);
+ /*
+ * flush also means no more activity hence schedule downclock, if all
+ * other fbs are quiescent too
+ */
+ if (!invalidate && !crtc->drrs.busy_frontbuffer_bits)
+ schedule_delayed_work(&crtc->drrs.work,
+ msecs_to_jiffies(1000));
+
+ mutex_unlock(&crtc->drrs.mutex);
+ }
}
/**
intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
}
-void intel_drrs_page_flip(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
+void intel_drrs_page_flip(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
}
/**
- * intel_drrs_init - Init basic DRRS work and mutex.
+ * intel_crtc_drrs_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)
+{
+ INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work);
+ mutex_init(&crtc->drrs.mutex);
+ crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
+}
+
+/**
+ * intel_drrs_init - Init DRRS for eDP connector
* @connector: eDP connector
* @fixed_mode: preferred mode of panel
*
- * This function is called only once at driver load to initialize basic
- * DRRS stuff.
+ * This function is called only once at driver load to initialize
+ * DRRS support for the connector.
*
* Returns:
* Downclock mode if panel supports it, else return NULL.
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_encoder *encoder = connector->encoder;
- struct drm_display_mode *downclock_mode = NULL;
-
- INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work);
- mutex_init(&dev_priv->drrs.mutex);
+ struct drm_display_mode *downclock_mode;
if (DISPLAY_VER(dev_priv) <= 6) {
drm_dbg_kms(&dev_priv->drm,
return NULL;
}
- dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH;
drm_dbg_kms(&dev_priv->drm,
"[CONNECTOR:%d:%s] %s DRRS supported\n",
connector->base.base.id, connector->base.name,