On Wed, May 08, 2019 at 12:09:10PM -0400, Sean Paul wrote:
> From: Sean Paul <seanp...@chromium.org>
> 
> This patch adds a new drm helper library to help drivers implement
> self refresh. Drivers choosing to use it will register crtcs and
> will receive callbacks when it's time to enter or exit self refresh
> mode.
> 
> In its current form, it has a timer which will trigger after a
> driver-specified amount of inactivity. When the timer triggers, the
> helpers will submit a new atomic commit to shut the refreshing pipe
> off. On the next atomic commit, the drm core will revert the self
> refresh state and bring everything back up to be actively driven.
> 
> From the driver's perspective, this works like a regular disable/enable
> cycle. The driver need only check the 'self_refresh_active' state in
> crtc_state. It should initiate self refresh mode on the panel and enter
> an off or low-power state.
> 
> Changes in v2:
> - s/psr/self_refresh/ (Daniel)
> - integrated the psr exit into the commit that wakes it up (Jose/Daniel)
> - made the psr state per-crtc (Jose/Daniel)
> Changes in v3:
> - Remove the self_refresh_(active|changed) from connector state (Daniel)
> - Simplify loop in drm_self_refresh_helper_alter_state (Daniel)
> - Improve self_refresh_aware comment (Daniel)
> - s/self_refresh_state/self_refresh_data/ (Daniel)
> Changes in v4:
> - Move docbook location below panel (Daniel)
> - Improve docbook with references and more detailed explanation (Daniel)
> - Instead of register/unregister, use init/cleanup (Daniel)

Again missed my r-b or didn't apply all my suggestions? I'm feeling a bit
blue and all that today so don't want to do more than necessary with
actual patch review :-)

Cheers, Daniel


> 
> Link to v1: 
> https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-2-s...@poorly.run
> Link to v2: 
> https://patchwork.freedesktop.org/patch/msgid/20190326204509.96515-1-s...@poorly.run
> Link to v3: 
> https://patchwork.freedesktop.org/patch/msgid/20190502194956.218441-6-s...@poorly.run
> 
> Cc: Daniel Vetter <dan...@ffwll.ch>
> Cc: Jose Souza <jose.so...@intel.com>
> Cc: Zain Wang <w...@rock-chips.com>
> Cc: Tomasz Figa <tf...@chromium.org>
> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
> Signed-off-by: Sean Paul <seanp...@chromium.org>
> ---
>  Documentation/gpu/drm-kms-helpers.rst     |   9 +
>  drivers/gpu/drm/Makefile                  |   2 +-
>  drivers/gpu/drm/drm_atomic.c              |   2 +
>  drivers/gpu/drm/drm_atomic_helper.c       |  35 +++-
>  drivers/gpu/drm/drm_atomic_state_helper.c |   4 +
>  drivers/gpu/drm/drm_atomic_uapi.c         |   7 +-
>  drivers/gpu/drm/drm_self_refresh_helper.c | 213 ++++++++++++++++++++++
>  include/drm/drm_atomic.h                  |  15 ++
>  include/drm/drm_connector.h               |  14 ++
>  include/drm/drm_crtc.h                    |  19 ++
>  include/drm/drm_self_refresh_helper.h     |  22 +++
>  11 files changed, 337 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_self_refresh_helper.c
>  create mode 100644 include/drm/drm_self_refresh_helper.h
> 
> diff --git a/Documentation/gpu/drm-kms-helpers.rst 
> b/Documentation/gpu/drm-kms-helpers.rst
> index 14102ae035dc..86dbb56aef51 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -181,6 +181,15 @@ Panel Helper Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_panel_orientation_quirks.c
>     :export:
>  
> +Panel Self Refresh Helper Reference
> +===================================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c
> +   :doc: overview
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c
> +   :export:
> +
>  Display Port Helper Functions Reference
>  =======================================
>  
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 3d0c75cd687c..c4852604fc1d 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -39,7 +39,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o 
> drm_dsc.o drm_probe_helper
>               drm_simple_kms_helper.o drm_modeset_helper.o \
>               drm_scdc_helper.o drm_gem_framebuffer_helper.o \
>               drm_atomic_state_helper.o drm_damage_helper.o \
> -             drm_format_helper.o
> +             drm_format_helper.o drm_self_refresh_helper.o
>  
>  drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
>  drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 936002495523..2b92648ce196 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -379,6 +379,7 @@ static void drm_atomic_crtc_print_state(struct 
> drm_printer *p,
>       drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
>       drm_printf(p, "\tenable=%d\n", state->enable);
>       drm_printf(p, "\tactive=%d\n", state->active);
> +     drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active);
>       drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
>       drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
>       drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
> @@ -951,6 +952,7 @@ static void drm_atomic_connector_print_state(struct 
> drm_printer *p,
>  
>       drm_printf(p, "connector[%u]: %s\n", connector->base.id, 
> connector->name);
>       drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : 
> "(null)");
> +     drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
>  
>       if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
>               if (state->writeback_job && state->writeback_job->fb)
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index ee945d6f1cba..9ee7a288f52a 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -30,6 +30,7 @@
>  #include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_self_refresh_helper.h>
>  #include <drm/drm_writeback.h>
>  #include <drm/drm_damage_helper.h>
>  #include <linux/dma-fence.h>
> @@ -950,10 +951,33 @@ int drm_atomic_helper_check(struct drm_device *dev,
>       if (state->legacy_cursor_update)
>               state->async_update = !drm_atomic_helper_async_check(dev, 
> state);
>  
> +     drm_self_refresh_helper_alter_state(state);
> +
>       return ret;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_check);
>  
> +static bool
> +crtc_needs_disable(struct drm_crtc_state *old_state,
> +                struct drm_crtc_state *new_state)
> +{
> +     /*
> +      * No new_state means the crtc is off, so the only criteria is whether
> +      * it's currently active or in self refresh mode.
> +      */
> +     if (!new_state)
> +             return drm_atomic_crtc_effectively_active(old_state);
> +
> +     /*
> +      * We need to run through the crtc_funcs->disable() function if the crtc
> +      * is currently on, if it's transitioning to self refresh mode, or if
> +      * it's in self refresh mode and needs to be fully disabled.
> +      */
> +     return old_state->active ||
> +            (old_state->self_refresh_active && !new_state->enable) ||
> +            new_state->self_refresh_active;
> +}
> +
>  static void
>  disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
>  {
> @@ -974,7 +998,14 @@ disable_outputs(struct drm_device *dev, struct 
> drm_atomic_state *old_state)
>  
>               old_crtc_state = drm_atomic_get_old_crtc_state(old_state, 
> old_conn_state->crtc);
>  
> -             if (!old_crtc_state->active ||
> +             if (new_conn_state->crtc)
> +                     new_crtc_state = drm_atomic_get_new_crtc_state(
> +                                             old_state,
> +                                             new_conn_state->crtc);
> +             else
> +                     new_crtc_state = NULL;
> +
> +             if (!crtc_needs_disable(old_crtc_state, new_crtc_state) ||
>                   !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
>                       continue;
>  
> @@ -1020,7 +1051,7 @@ disable_outputs(struct drm_device *dev, struct 
> drm_atomic_state *old_state)
>               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>                       continue;
>  
> -             if (!old_crtc_state->active)
> +             if (!crtc_needs_disable(old_crtc_state, new_crtc_state))
>                       continue;
>  
>               funcs = crtc->helper_private;
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index ac929f68ff31..ca18008043e5 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -128,6 +128,10 @@ void __drm_atomic_helper_crtc_duplicate_state(struct 
> drm_crtc *crtc,
>       state->commit = NULL;
>       state->event = NULL;
>       state->pageflip_flags = 0;
> +
> +     /* Self refresh should be canceled when a new update is available */
> +     state->active = drm_atomic_crtc_effectively_active(state);
> +     state->self_refresh_active = false;
>  }
>  EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
>  
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
> b/drivers/gpu/drm/drm_atomic_uapi.c
> index ea797d4c82ee..a75c633ff0c0 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -490,7 +490,7 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
>       struct drm_mode_config *config = &dev->mode_config;
>  
>       if (property == config->prop_active)
> -             *val = state->active;
> +             *val = drm_atomic_crtc_effectively_active(state);
>       else if (property == config->prop_mode_id)
>               *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
>       else if (property == config->prop_vrr_enabled)
> @@ -772,7 +772,10 @@ drm_atomic_connector_get_property(struct drm_connector 
> *connector,
>       if (property == config->prop_crtc_id) {
>               *val = (state->crtc) ? state->crtc->base.id : 0;
>       } else if (property == config->dpms_property) {
> -             *val = connector->dpms;
> +             if (state->crtc && state->crtc->state->self_refresh_active)
> +                     *val = DRM_MODE_DPMS_ON;
> +             else
> +                     *val = connector->dpms;
>       } else if (property == config->tv_select_subconnector_property) {
>               *val = state->tv.subconnector;
>       } else if (property == config->tv_left_margin_property) {
> diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c 
> b/drivers/gpu/drm/drm_self_refresh_helper.c
> new file mode 100644
> index 000000000000..c7083c5694fe
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_self_refresh_helper.c
> @@ -0,0 +1,213 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright (C) 2019 Google, Inc.
> + *
> + * Authors:
> + * Sean Paul <seanp...@chromium.org>
> + */
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_mode_config.h>
> +#include <drm/drm_modeset_lock.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_self_refresh_helper.h>
> +#include <linux/bitops.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>
> +
> +/**
> + * DOC: overview
> + *
> + * This helper library provides an easy way for drivers to leverage the 
> atomic
> + * framework to implement panel self refresh (SR) support. Drivers are
> + * responsible for initializing and cleaning up the SR helpers on load/unload
> + * (see &drm_self_refresh_helper_init/&drm_self_refresh_helper_cleanup).
> + * The connector is responsible for setting
> + * &drm_connector_state.self_refresh_aware to true at runtime if it is 
> SR-aware
> + * (meaning it knows how to initiate self refresh on the panel).
> + *
> + * Once a crtc has enabled SR using &drm_self_refresh_helper_init, the
> + * helpers will monitor activity and call back into the driver to 
> enable/disable
> + * SR as appropriate. The best way to think about this is that it's a DPMS
> + * on/off request with &drm_crtc_state.self_refresh_active set in crtc state
> + * that tells you to disable/enable SR on the panel instead of power-cycling 
> it.
> + *
> + * During SR, drivers may choose to fully disable their crtc/encoder/bridge
> + * hardware (in which case no driver changes are necessary), or they can 
> inspect
> + * &drm_crtc_state.self_refresh_active if they want to enter low power mode
> + * without full disable (in case full disable/enable is too slow).
> + *
> + * SR will be deactivated if there are any atomic updates affecting the
> + * pipe that is in SR mode. If a crtc is driving multiple connectors, all
> + * connectors must be SR aware and all will enter/exit SR mode at the same 
> time.
> + *
> + * If the crtc and connector are SR aware, but the panel connected does not
> + * support it (or is otherwise unable to enter SR), the driver should fail
> + * atomic_check when &drm_crtc_state.self_refresh_active is true.
> + */
> +
> +struct drm_self_refresh_data {
> +     struct drm_crtc *crtc;
> +     struct delayed_work entry_work;
> +     struct drm_atomic_state *save_state;
> +     unsigned int entry_delay_ms;
> +};
> +
> +static void drm_self_refresh_helper_entry_work(struct work_struct *work)
> +{
> +     struct drm_self_refresh_data *sr_data = container_of(
> +                             to_delayed_work(work),
> +                             struct drm_self_refresh_data, entry_work);
> +     struct drm_crtc *crtc = sr_data->crtc;
> +     struct drm_device *dev = crtc->dev;
> +     struct drm_modeset_acquire_ctx ctx;
> +     struct drm_atomic_state *state;
> +     struct drm_connector *conn;
> +     struct drm_connector_state *conn_state;
> +     struct drm_crtc_state *crtc_state;
> +     int i, ret;
> +
> +     drm_modeset_acquire_init(&ctx, 0);
> +
> +     state = drm_atomic_state_alloc(dev);
> +     if (!state) {
> +             ret = -ENOMEM;
> +             goto out;
> +     }
> +
> +retry:
> +     state->acquire_ctx = &ctx;
> +
> +     crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +     if (IS_ERR(crtc_state)) {
> +             ret = PTR_ERR(crtc_state);
> +             goto out;
> +     }
> +
> +     if (!crtc_state->enable)
> +             goto out;
> +
> +     ret = drm_atomic_add_affected_connectors(state, crtc);
> +     if (ret)
> +             goto out;
> +
> +     for_each_new_connector_in_state(state, conn, conn_state, i) {
> +             if (!conn_state->self_refresh_aware)
> +                     goto out;
> +     }
> +
> +     crtc_state->active = false;
> +     crtc_state->self_refresh_active = true;
> +
> +     ret = drm_atomic_commit(state);
> +     if (ret)
> +             goto out;
> +
> +out:
> +     if (ret == -EDEADLK) {
> +             drm_atomic_state_clear(state);
> +             ret = drm_modeset_backoff(&ctx);
> +             if (!ret)
> +                     goto retry;
> +     }
> +
> +     drm_atomic_state_put(state);
> +     drm_modeset_drop_locks(&ctx);
> +     drm_modeset_acquire_fini(&ctx);
> +}
> +
> +/**
> + * drm_self_refresh_helper_alter_state - Alters the atomic state for SR exit
> + * @state: the state currently being checked
> + *
> + * Called at the end of atomic check. This function checks the state for 
> flags
> + * incompatible with self refresh exit and changes them. This is a bit
> + * disingenuous since userspace is expecting one thing and we're giving it
> + * another. However in order to keep self refresh entirely hidden from
> + * userspace, this is required.
> + *
> + * At the end, we queue up the self refresh entry work so we can enter PSR 
> after
> + * the desired delay.
> + */
> +void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state)
> +{
> +     struct drm_crtc *crtc;
> +     struct drm_crtc_state *crtc_state;
> +     int i;
> +
> +     if (state->async_update || !state->allow_modeset) {
> +             for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
> +                     if (crtc_state->self_refresh_active) {
> +                             state->async_update = false;
> +                             state->allow_modeset = true;
> +                             break;
> +                     }
> +             }
> +     }
> +
> +     for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +             struct drm_self_refresh_data *sr_data;
> +
> +             /* Don't trigger the entry timer when we're already in SR */
> +             if (crtc_state->self_refresh_active)
> +                     continue;
> +
> +             sr_data = crtc->self_refresh_data;
> +             if (!sr_data)
> +                     continue;
> +
> +             mod_delayed_work(system_wq, &sr_data->entry_work,
> +                              msecs_to_jiffies(sr_data->entry_delay_ms));
> +     }
> +}
> +EXPORT_SYMBOL(drm_self_refresh_helper_alter_state);
> +
> +/**
> + * drm_self_refresh_helper_init - Initializes self refresh helpers for a crtc
> + * @crtc: the crtc which supports self refresh supported displays
> + * @entry_delay_ms: amount of inactivity to wait before entering self refresh
> + */
> +int drm_self_refresh_helper_init(struct drm_crtc *crtc,
> +                              unsigned int entry_delay_ms)
> +{
> +     struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
> +
> +     /* Helper is already initialized */
> +     if (WARN_ON(sr_data))
> +             return -EINVAL;
> +
> +     sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL);
> +     if (!sr_data)
> +             return -ENOMEM;
> +
> +     INIT_DELAYED_WORK(&sr_data->entry_work,
> +                       drm_self_refresh_helper_entry_work);
> +     sr_data->entry_delay_ms = entry_delay_ms;
> +     sr_data->crtc = crtc;
> +
> +     crtc->self_refresh_data = sr_data;
> +     return 0;
> +}
> +EXPORT_SYMBOL(drm_self_refresh_helper_init);
> +
> +/**
> + * drm_self_refresh_helper_cleanup - Cleans up self refresh helpers for a 
> crtc
> + * @crtc: the crtc to cleanup
> + */
> +void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc)
> +{
> +     struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
> +
> +     /* Helper is already uninitialized */
> +     if (sr_data)
> +             return;
> +
> +     crtc->self_refresh_data = NULL;
> +
> +     cancel_delayed_work_sync(&sr_data->entry_work);
> +     kfree(sr_data);
> +}
> +EXPORT_SYMBOL(drm_self_refresh_helper_cleanup);
> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> index d6b3acd34e1c..f76777c72264 100644
> --- a/include/drm/drm_atomic.h
> +++ b/include/drm/drm_atomic.h
> @@ -951,4 +951,19 @@ drm_atomic_crtc_needs_modeset(const struct 
> drm_crtc_state *state)
>              state->connectors_changed;
>  }
>  
> +/**
> + * drm_atomic_crtc_effectively_active - compute whether crtc is actually 
> active
> + * @state: &drm_crtc_state for the CRTC
> + *
> + * When in self refresh mode, the crtc_state->active value will be false, 
> since
> + * the crtc is off. However in some cases we're interested in whether the 
> crtc
> + * is active, or effectively active (ie: it's connected to an active 
> display).
> + * In these cases, use this function instead of just checking active.
> + */
> +static inline bool
> +drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state)
> +{
> +     return state->active || state->self_refresh_active;
> +}
> +
>  #endif /* DRM_ATOMIC_H_ */
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index f43f40d5888a..02d0c73e267d 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -543,6 +543,20 @@ struct drm_connector_state {
>       /** @tv: TV connector state */
>       struct drm_tv_connector_state tv;
>  
> +     /**
> +      * @self_refresh_aware:
> +      *
> +      * This tracks whether a connector is aware of the self refresh state.
> +      * It should be set to true for those connector implementations which
> +      * understand the self refresh state. This is needed since the crtc
> +      * registers the self refresh helpers and it doesn't know if the
> +      * connectors downstream have implemented self refresh entry/exit.
> +      *
> +      * Drivers should set this to true in atomic_check if they know how to
> +      * handle self_refresh requests.
> +      */
> +     bool self_refresh_aware;
> +
>       /**
>        * @picture_aspect_ratio: Connector property to control the
>        * HDMI infoframe aspect ratio setting.
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 58ad983d7cd6..67e3075a8784 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -53,6 +53,7 @@ struct drm_mode_set;
>  struct drm_file;
>  struct drm_clip_rect;
>  struct drm_printer;
> +struct drm_self_refresh_data;
>  struct device_node;
>  struct dma_fence;
>  struct edid;
> @@ -299,6 +300,17 @@ struct drm_crtc_state {
>        */
>       bool vrr_enabled;
>  
> +     /**
> +      * @self_refresh_active:
> +      *
> +      * Used by the self refresh helpers to denote when a self refresh
> +      * transition is occuring. This will be set on enable/disable callbacks
> +      * when self refresh is being enabled or disabled. In some cases, it may
> +      * not be desirable to fully shut off the crtc during self refresh.
> +      * CRTC's can inspect this flag and determine the best course of action.
> +      */
> +     bool self_refresh_active;
> +
>       /**
>        * @event:
>        *
> @@ -1087,6 +1099,13 @@ struct drm_crtc {
>        * The name of the CRTC's fence timeline.
>        */
>       char timeline_name[32];
> +
> +     /**
> +      * @self_refresh_data: Holds the state for the self refresh helpers
> +      *
> +      * Initialized via drm_self_refresh_helper_register().
> +      */
> +     struct drm_self_refresh_data *self_refresh_data;
>  };
>  
>  /**
> diff --git a/include/drm/drm_self_refresh_helper.h 
> b/include/drm/drm_self_refresh_helper.h
> new file mode 100644
> index 000000000000..405e86fb8461
> --- /dev/null
> +++ b/include/drm/drm_self_refresh_helper.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright (C) 2019 Google, Inc.
> + *
> + * Authors:
> + * Sean Paul <seanp...@chromium.org>
> + */
> +#ifndef DRM_SELF_REFRESH_HELPER_H_
> +#define DRM_SELF_REFRESH_HELPER_H_
> +
> +struct drm_atomic_state;
> +struct drm_connector;
> +struct drm_device;
> +struct drm_modeset_acquire_ctx;
> +
> +void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state);
> +
> +int drm_self_refresh_helper_init(struct drm_crtc *crtc,
> +                                  unsigned int entry_delay_ms);
> +
> +void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc);
> +#endif
> -- 
> Sean Paul, Software Engineer, Google / Chromium OS
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to