diff options
Diffstat (limited to 'include/drm/drm_modeset_helper_vtables.h')
| -rw-r--r-- | include/drm/drm_modeset_helper_vtables.h | 648 |
1 files changed, 520 insertions, 128 deletions
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 85984b208218..fe32854b7ffe 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -48,13 +48,20 @@ * To make this clear all the helper vtables are pulled together in this location here. */ -enum mode_set_atomic; +struct drm_scanout_buffer; +struct drm_writeback_connector; +struct drm_writeback_job; + +enum mode_set_atomic { + LEAVE_ATOMIC_MODE_SET, + ENTER_ATOMIC_MODE_SET, +}; /** * struct drm_crtc_helper_funcs - helper operations for CRTCs * - * These hooks are used by the legacy CRTC helpers, the transitional plane - * helpers and the new atomic modesetting helpers. + * These hooks are used by the legacy CRTC helpers and the new atomic + * modesetting helpers. */ struct drm_crtc_helper_funcs { /** @@ -71,7 +78,7 @@ struct drm_crtc_helper_funcs { * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling and disabling a CRTC to * facilitate transitions to atomic, but it is deprecated. Instead - * @enable and @disable should be used. + * @atomic_enable and @atomic_disable should be used. */ void (*dpms)(struct drm_crtc *crtc, int mode); @@ -85,8 +92,8 @@ struct drm_crtc_helper_funcs { * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for disabling a CRTC to facilitate - * transitions to atomic, but it is deprecated. Instead @disable should - * be used. + * transitions to atomic, but it is deprecated. Instead @atomic_disable + * should be used. */ void (*prepare)(struct drm_crtc *crtc); @@ -100,8 +107,8 @@ struct drm_crtc_helper_funcs { * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling a CRTC to facilitate - * transitions to atomic, but it is deprecated. Instead @enable should - * be used. + * transitions to atomic, but it is deprecated. Instead @atomic_enable + * should be used. */ void (*commit)(struct drm_crtc *crtc); @@ -128,7 +135,7 @@ struct drm_crtc_helper_funcs { * Since this function is both called from the check phase of an atomic * commit, and the mode validation in the probe paths it is not allowed * to look at anything else but the passed-in mode, and validate it - * against configuration-invariant hardward constraints. Any further + * against configuration-invariant hardware constraints. Any further * limits which depend upon the configuration can only be checked in * @mode_fixup or @atomic_check. * @@ -210,9 +217,7 @@ struct drm_crtc_helper_funcs { * * This callback is used to update the display mode of a CRTC without * changing anything of the primary plane configuration. This fits the - * requirement of atomic and hence is used by the atomic helpers. It is - * also used by the transitional plane helpers to implement a - * @mode_set hook in drm_helper_crtc_mode_set(). + * requirement of atomic and hence is used by the atomic helpers. * * Note that the display pipe is completely off when this function is * called. Atomic drivers which need hardware to be running before they @@ -222,7 +227,7 @@ struct drm_crtc_helper_funcs { * pipeline is suspended using either DPMS or the new "ACTIVE" property. * Which means register values set in this callback might get reset when * the CRTC is suspended, but not restored. Such drivers should instead - * move all their CRTC setup into the @enable callback. + * move all their CRTC setup into the @atomic_enable callback. * * This callback is optional. */ @@ -267,22 +272,6 @@ struct drm_crtc_helper_funcs { enum mode_set_atomic); /** - * @load_lut: - * - * Load a LUT prepared with the &drm_fb_helper_funcs.gamma_set vfunc. - * - * This callback is optional and is only used by the fbdev emulation - * helpers. - * - * FIXME: - * - * This callback is functionally redundant with the core gamma table - * support and simply exists because the fbdev hasn't yet been - * refactored to use the core gamma table interfaces. - */ - void (*load_lut)(struct drm_crtc *crtc); - - /** * @disable: * * This callback should be used to disable the CRTC. With the atomic @@ -297,7 +286,7 @@ struct drm_crtc_helper_funcs { * Atomic drivers don't need to implement it if there's no need to * disable anything at the CRTC level. To ensure that runtime PM * handling (using either DPMS or the new "ACTIVE" property) works - * @disable must be the inverse of @enable for atomic drivers. + * @disable must be the inverse of @atomic_enable for atomic drivers. * Atomic drivers should consider to use @atomic_disable instead of * this one. * @@ -316,24 +305,6 @@ struct drm_crtc_helper_funcs { void (*disable)(struct drm_crtc *crtc); /** - * @enable: - * - * This callback should be used to enable the CRTC. With the atomic - * drivers it is called before all encoders connected to this CRTC are - * enabled through the encoder's own &drm_encoder_helper_funcs.enable - * hook. If that sequence is too simple drivers can just add their own - * hooks and call it from this CRTC callback here by looping over all - * encoders connected to it using for_each_encoder_on_crtc(). - * - * This hook is used only by atomic helpers, for symmetry with @disable. - * Atomic drivers don't need to implement it if there's no need to - * enable anything at the CRTC level. To ensure that runtime PM handling - * (using either DPMS or the new "ACTIVE" property) works - * @enable must be the inverse of @disable for atomic drivers. - */ - void (*enable)(struct drm_crtc *crtc); - - /** * @atomic_check: * * Drivers should check plane-update related CRTC constraints in this @@ -348,7 +319,7 @@ struct drm_crtc_helper_funcs { * implementation in drm_atomic_helper_check(). * * When using drm_atomic_helper_check_planes() this hook is called - * after the &drm_plane_helper_funcs.atomc_check hook for planes, which + * after the &drm_plane_helper_funcs.atomic_check hook for planes, which * allows drivers to assign shared resources requested by planes in this * callback here. For more complicated dependencies the driver can call * the provided check helpers multiple times until the computed state @@ -361,15 +332,14 @@ struct drm_crtc_helper_funcs { * all updated. Again the recommendation is to just call check helpers * until a maximal configuration is reached. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. * * NOTE: * * This function is called in the check phase of an atomic update. The * driver is not allowed to change anything outside of the free-standing - * state objects passed-in or assembled in the overall &drm_atomic_state - * update tracking structure. + * state object passed-in. * * Also beware that userspace can request its own custom modes, neither * core nor helpers filter modes to the list of probe modes reported by @@ -385,7 +355,7 @@ struct drm_crtc_helper_funcs { * deadlock. */ int (*atomic_check)(struct drm_crtc *crtc, - struct drm_crtc_state *state); + struct drm_atomic_state *state); /** * @atomic_begin: @@ -402,11 +372,11 @@ struct drm_crtc_helper_funcs { * has picked. See drm_atomic_helper_commit_planes() for a discussion of * the tradeoffs and variants of plane commit helpers. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. */ void (*atomic_begin)(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state); + struct drm_atomic_state *state); /** * @atomic_flush: * @@ -426,11 +396,33 @@ struct drm_crtc_helper_funcs { * has picked. See drm_atomic_helper_commit_planes() for a discussion of * the tradeoffs and variants of plane commit helpers. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. */ void (*atomic_flush)(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state); + struct drm_atomic_state *state); + + /** + * @atomic_enable: + * + * This callback should be used to enable the CRTC. With the atomic + * drivers it is called before all encoders connected to this CRTC are + * enabled through the encoder's own &drm_encoder_helper_funcs.enable + * hook. If that sequence is too simple drivers can just add their own + * hooks and call it from this CRTC callback here by looping over all + * encoders connected to it using for_each_encoder_on_crtc(). + * + * This hook is used only by atomic helpers, for symmetry with + * @atomic_disable. Atomic drivers don't need to implement it if there's + * no need to enable anything at the CRTC level. To ensure that runtime + * PM handling (using either DPMS or the new "ACTIVE" property) works + * @atomic_enable must be the inverse of @atomic_disable for atomic + * drivers. + * + * This function is optional. + */ + void (*atomic_enable)(struct drm_crtc *crtc, + struct drm_atomic_state *state); /** * @atomic_disable: @@ -447,13 +439,69 @@ struct drm_crtc_helper_funcs { * need to implement it if there's no need to disable anything at the * CRTC level. * - * Comparing to @disable, this one provides the additional input - * parameter @old_crtc_state which could be used to access the old - * state. Atomic drivers should consider to use this one instead - * of @disable. + * This function is optional. */ void (*atomic_disable)(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state); + struct drm_atomic_state *state); + + /** + * @get_scanout_position: + * + * Called by vblank timestamping code. + * + * Returns the current display scanout position from a CRTC and an + * optional accurate ktime_get() timestamp of when the position was + * measured. Note that this is a helper callback which is only used + * if a driver uses drm_crtc_vblank_helper_get_vblank_timestamp() + * for the @drm_crtc_funcs.get_vblank_timestamp callback. + * + * Parameters: + * + * crtc: + * The CRTC. + * in_vblank_irq: + * True when called from drm_crtc_handle_vblank(). Some drivers + * need to apply some workarounds for gpu-specific vblank irq + * quirks if the flag is set. + * vpos: + * Target location for current vertical scanout position. + * hpos: + * Target location for current horizontal scanout position. + * stime: + * Target location for timestamp taken immediately before + * scanout position query. Can be NULL to skip timestamp. + * etime: + * Target location for timestamp taken immediately after + * scanout position query. Can be NULL to skip timestamp. + * mode: + * Current display timings. + * + * Returns vpos as a positive number while in active scanout area. + * Returns vpos as a negative number inside vblank, counting the number + * of scanlines to go until end of vblank, e.g., -1 means "one scanline + * until start of active scanout / end of vblank." + * + * Returns: + * + * True on success, false if a reliable scanout position counter could + * not be read out. + */ + bool (*get_scanout_position)(struct drm_crtc *crtc, + bool in_vblank_irq, int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode); + + /** + * @handle_vblank_timeout: Handles timeouts of the vblank timer. + * + * Called by CRTC's the vblank timer on each timeout. Semantics is + * equivalient to drm_crtc_handle_vblank(). Implementations should + * invoke drm_crtc_handle_vblank() as part of processing the timeout. + * + * This callback is optional. If unset, the vblank timer invokes + * drm_crtc_handle_vblank() directly. + */ + bool (*handle_vblank_timeout)(struct drm_crtc *crtc); }; /** @@ -470,8 +518,8 @@ static inline void drm_crtc_helper_add(struct drm_crtc *crtc, /** * struct drm_encoder_helper_funcs - helper operations for encoders * - * These hooks are used by the legacy CRTC helpers, the transitional plane - * helpers and the new atomic modesetting helpers. + * These hooks are used by the legacy CRTC helpers and the new atomic + * modesetting helpers. */ struct drm_encoder_helper_funcs { /** @@ -515,7 +563,7 @@ struct drm_encoder_helper_funcs { * Since this function is both called from the check phase of an atomic * commit, and the mode validation in the probe paths it is not allowed * to look at anything else but the passed-in mode, and validate it - * against configuration-invariant hardward constraints. Any further + * against configuration-invariant hardware constraints. Any further * limits which depend upon the configuration can only be checked in * @mode_fixup or @atomic_check. * @@ -650,22 +698,6 @@ struct drm_encoder_helper_funcs { struct drm_connector_state *conn_state); /** - * @get_crtc: - * - * This callback is used by the legacy CRTC helpers to work around - * deficiencies in its own book-keeping. - * - * Do not use, use atomic helpers instead, which get the book keeping - * right. - * - * FIXME: - * - * Currently only nouveau is using this, and as soon as nouveau is - * atomic we can ditch this hook. - */ - struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); - - /** * @detect: * * This callback can be used by drivers who want to do detection on the @@ -684,6 +716,52 @@ struct drm_encoder_helper_funcs { struct drm_connector *connector); /** + * @atomic_disable: + * + * This callback should be used to disable the encoder. With the atomic + * drivers it is called before this encoder's CRTC has been shut off + * using their own &drm_crtc_helper_funcs.atomic_disable hook. If that + * sequence is too simple drivers can just add their own driver private + * encoder hooks and call them from CRTC's callback by looping over all + * encoders connected to it using for_each_encoder_on_crtc(). + * + * This callback is a variant of @disable that provides the atomic state + * to the driver. If @atomic_disable is implemented, @disable is not + * called by the helpers. + * + * This hook is only used by atomic helpers. Atomic drivers don't need + * to implement it if there's no need to disable anything at the encoder + * level. To ensure that runtime PM handling (using either DPMS or the + * new "ACTIVE" property) works @atomic_disable must be the inverse of + * @atomic_enable. + */ + void (*atomic_disable)(struct drm_encoder *encoder, + struct drm_atomic_state *state); + + /** + * @atomic_enable: + * + * This callback should be used to enable the encoder. It is called + * after this encoder's CRTC has been enabled using their own + * &drm_crtc_helper_funcs.atomic_enable hook. If that sequence is + * too simple drivers can just add their own driver private encoder + * hooks and call them from CRTC's callback by looping over all encoders + * connected to it using for_each_encoder_on_crtc(). + * + * This callback is a variant of @enable that provides the atomic state + * to the driver. If @atomic_enable is implemented, @enable is not + * called by the helpers. + * + * This hook is only used by atomic helpers, it is the opposite of + * @atomic_disable. Atomic drivers don't need to implement it if there's + * no need to enable anything at the encoder level. To ensure that + * runtime PM handling works @atomic_enable must be the inverse of + * @atomic_disable. + */ + void (*atomic_enable)(struct drm_encoder *encoder, + struct drm_atomic_state *state); + + /** * @disable: * * This callback should be used to disable the encoder. With the atomic @@ -699,6 +777,9 @@ struct drm_encoder_helper_funcs { * handling (using either DPMS or the new "ACTIVE" property) works * @disable must be the inverse of @enable for atomic drivers. * + * For atomic drivers also consider @atomic_disable and save yourself + * from having to read the NOTE below! + * * NOTE: * * With legacy CRTC helpers there's a big semantic difference between @@ -723,11 +804,11 @@ struct drm_encoder_helper_funcs { * hooks and call them from CRTC's callback by looping over all encoders * connected to it using for_each_encoder_on_crtc(). * - * This hook is used only by atomic helpers, for symmetry with @disable. - * Atomic drivers don't need to implement it if there's no need to - * enable anything at the encoder level. To ensure that runtime PM handling - * (using either DPMS or the new "ACTIVE" property) works - * @enable must be the inverse of @disable for atomic drivers. + * This hook is only used by atomic helpers, it is the opposite of + * @disable. Atomic drivers don't need to implement it if there's no + * need to enable anything at the encoder level. To ensure that + * runtime PM handling (using either DPMS or the new "ACTIVE" property) + * works @enable must be the inverse of @disable for atomic drivers. */ void (*enable)(struct drm_encoder *encoder); @@ -795,25 +876,28 @@ struct drm_connector_helper_funcs { * * This function should fill in all modes currently valid for the sink * into the &drm_connector.probed_modes list. It should also update the - * EDID property by calling drm_mode_connector_update_edid_property(). + * EDID property by calling drm_connector_update_edid_property(). * * The usual way to implement this is to cache the EDID retrieved in the * probe callback somewhere in the driver-private connector structure. * In this function drivers then parse the modes in the EDID and add - * them by calling drm_add_edid_modes(). But connectors that driver a + * them by calling drm_add_edid_modes(). But connectors that drive a * fixed panel can also manually add specific modes using * drm_mode_probed_add(). Drivers which manually add modes should also * make sure that the &drm_connector.display_info, * &drm_connector.width_mm and &drm_connector.height_mm fields are * filled in. * + * Note that the caller function will automatically add standard VESA + * DMT modes up to 1024x768 if the .get_modes() helper operation returns + * no mode and if the connector status is connector_status_connected or + * connector_status_unknown. There is no need to call + * drm_add_modes_noedid() manually in that case. + * * Virtual drivers that just want some standard VESA mode with a given * resolution can call drm_add_modes_noedid(), and mark the preferred * one using drm_set_preferred_mode(). * - * Finally drivers that support audio probably want to update the ELD - * data, too, using drm_edid_to_eld(). - * * This function is only called after the @detect hook has indicated * that a sink is connected and when the EDID isn't overridden through * sysfs or the kernel commandline. @@ -827,7 +911,8 @@ struct drm_connector_helper_funcs { * * RETURNS: * - * The number of modes added by calling drm_mode_probed_add(). + * The number of modes added by calling drm_mode_probed_add(). Return 0 + * on failures (no modes) instead of negative error codes. */ int (*get_modes)(struct drm_connector *connector); @@ -894,7 +979,49 @@ struct drm_connector_helper_funcs { * drm_mode_status. */ enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); + + /** + * @mode_valid_ctx: + * + * Callback to validate a mode for a connector, irrespective of the + * specific display configuration. + * + * This callback is used by the probe helpers to filter the mode list + * (which is usually derived from the EDID data block from the sink). + * See e.g. drm_helper_probe_single_connector_modes(). + * + * This function is optional, and is the atomic version of + * &drm_connector_helper_funcs.mode_valid. + * + * To allow for accessing the atomic state of modesetting objects, the + * helper libraries always call this with ctx set to a valid context, + * and &drm_mode_config.connection_mutex will always be locked with + * the ctx parameter set to @ctx. This allows for taking additional + * locks as required. + * + * Even though additional locks may be acquired, this callback is + * still expected not to take any constraints into account which would + * be influenced by the currently set display state - such constraints + * should be handled in the driver's atomic check. For example, if a + * connector shares display bandwidth with other connectors then it + * would be ok to validate the minimum bandwidth requirement of a mode + * against the maximum possible bandwidth of the connector. But it + * wouldn't be ok to take the current bandwidth usage of other + * connectors into account, as this would change depending on the + * display state. + * + * Returns: + * 0 if &drm_connector_helper_funcs.mode_valid_ctx succeeded and wrote + * the &enum drm_mode_status value to @status, or a negative error + * code otherwise. + * + */ + int (*mode_valid_ctx)(struct drm_connector *connector, + const struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx, + enum drm_mode_status *status); + /** * @best_encoder: * @@ -913,9 +1040,8 @@ struct drm_connector_helper_funcs { * @atomic_best_encoder. * * You can leave this function to NULL if the connector is only - * attached to a single encoder and you are using the atomic helpers. - * In this case, the core will call drm_atomic_helper_best_encoder() - * for you. + * attached to a single encoder. In this case, the core will call + * drm_connector_get_single_encoder() for you. * * RETURNS: * @@ -935,14 +1061,13 @@ struct drm_connector_helper_funcs { * * This function is used by drm_atomic_helper_check_modeset(). * If it is not implemented, the core will fallback to @best_encoder - * (or drm_atomic_helper_best_encoder() if @best_encoder is NULL). + * (or drm_connector_get_single_encoder() if @best_encoder is NULL). * * NOTE: * * This function is called in the check phase of an atomic update. The - * driver is not allowed to change anything outside of the free-standing - * state objects passed-in or assembled in the overall &drm_atomic_state - * update tracking structure. + * driver is not allowed to change anything outside of the + * &drm_atomic_state update tracking structure passed in. * * RETURNS: * @@ -952,7 +1077,7 @@ struct drm_connector_helper_funcs { * for this. */ struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, - struct drm_connector_state *connector_state); + struct drm_atomic_state *state); /** * @atomic_check: @@ -986,7 +1111,86 @@ struct drm_connector_helper_funcs { * deadlock. */ int (*atomic_check)(struct drm_connector *connector, - struct drm_connector_state *state); + struct drm_atomic_state *state); + + /** + * @atomic_commit: + * + * This hook is to be used by drivers implementing writeback connectors + * that need a point when to commit the writeback job to the hardware. + * The writeback_job to commit is available in the new connector state, + * in &drm_connector_state.writeback_job. + * + * This hook is optional. + * + * This callback is used by the atomic modeset helpers. + */ + void (*atomic_commit)(struct drm_connector *connector, + struct drm_atomic_state *state); + + /** + * @prepare_writeback_job: + * + * As writeback jobs contain a framebuffer, drivers may need to + * prepare and clean them up the same way they can prepare and + * clean up framebuffers for planes. This optional connector operation + * is used to support the preparation of writeback jobs. The job + * prepare operation is called from drm_atomic_helper_prepare_planes() + * for struct &drm_writeback_connector connectors only. + * + * This operation is optional. + * + * This callback is used by the atomic modeset helpers. + */ + int (*prepare_writeback_job)(struct drm_writeback_connector *connector, + struct drm_writeback_job *job); + /** + * @cleanup_writeback_job: + * + * This optional connector operation is used to support the + * cleanup of writeback jobs. The job cleanup operation is called + * from the existing drm_writeback_cleanup_job() function, invoked + * both when destroying the job as part of an aborted commit, or when + * the job completes. + * + * This operation is optional. + * + * This callback is used by the atomic modeset helpers. + */ + void (*cleanup_writeback_job)(struct drm_writeback_connector *connector, + struct drm_writeback_job *job); + + /** + * @enable_hpd: + * + * Enable hot-plug detection for the connector. + * + * This operation is optional. + * + * This callback is used by the drm_kms_helper_poll_enable() helpers. + * + * This operation does not need to perform any hpd state tracking as + * the DRM core handles that maintenance and ensures the calls to enable + * and disable hpd are balanced. + * + */ + void (*enable_hpd)(struct drm_connector *connector); + + /** + * @disable_hpd: + * + * Disable hot-plug detection for the connector. + * + * This operation is optional. + * + * This callback is used by the drm_kms_helper_poll_disable() helpers. + * + * This operation does not need to perform any hpd state tracking as + * the DRM core handles that maintenance and ensures the calls to enable + * and disable hpd are balanced. + * + */ + void (*disable_hpd)(struct drm_connector *connector); }; /** @@ -1003,30 +1207,43 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, /** * struct drm_plane_helper_funcs - helper operations for planes * - * These functions are used by the atomic helpers and by the transitional plane - * helpers. + * These functions are used by the atomic helpers. */ struct drm_plane_helper_funcs { /** * @prepare_fb: * * This hook is to prepare a framebuffer for scanout by e.g. pinning - * it's backing storage or relocating it into a contiguous block of + * its backing storage or relocating it into a contiguous block of * VRAM. Other possible preparatory work includes flushing caches. * * This function must not block for outstanding rendering, since it is * called in the context of the atomic IOCTL even for async commits to * be able to return any errors to userspace. Instead the recommended - * way is to fill out the fence member of the passed-in + * way is to fill out the &drm_plane_state.fence of the passed-in * &drm_plane_state. If the driver doesn't support native fences then * equivalent functionality should be implemented through private * members in the plane structure. * + * For GEM drivers who neither have a @prepare_fb nor @cleanup_fb hook + * set drm_gem_plane_helper_prepare_fb() is called automatically to + * implement this. Other drivers which need additional plane processing + * can call drm_gem_plane_helper_prepare_fb() from their @prepare_fb + * hook. + * + * The resources acquired in @prepare_fb persist after the end of + * the atomic commit. Resources that can be release at the commit's end + * should be acquired in @begin_fb_access and released in @end_fb_access. + * For example, a GEM buffer's pin operation belongs into @prepare_fb to + * keep the buffer pinned after the commit. But a vmap operation for + * shadow-plane helpers belongs into @begin_fb_access, so that atomic + * helpers remove the mapping at the end of the commit. + * * The helpers will call @cleanup_fb with matching arguments for every * successful call to this hook. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. See @begin_fb_access for preparing per-commit resources. * * RETURNS: * @@ -1043,13 +1260,43 @@ struct drm_plane_helper_funcs { * This hook is called to clean up any resources allocated for the given * framebuffer and plane configuration in @prepare_fb. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. */ void (*cleanup_fb)(struct drm_plane *plane, struct drm_plane_state *old_state); /** + * @begin_fb_access: + * + * This hook prepares the plane for access during an atomic commit. + * In contrast to @prepare_fb, resources acquired in @begin_fb_access, + * are released at the end of the atomic commit in @end_fb_access. + * + * For example, with shadow-plane helpers, the GEM buffer's vmap + * operation belongs into @begin_fb_access, so that the buffer's + * memory will be unmapped at the end of the commit in @end_fb_access. + * But a GEM buffer's pin operation belongs into @prepare_fb + * to keep the buffer pinned after the commit. + * + * The callback is used by the atomic modeset helpers, but it is optional. + * See @end_fb_cleanup for undoing the effects of @begin_fb_access and + * @prepare_fb for acquiring resources until the next pageflip. + * + * Returns: + * 0 on success, or a negative errno code otherwise. + */ + int (*begin_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state); + + /** + * @end_fb_access: + * + * This hook cleans up resources allocated by @begin_fb_access. It it called + * at the end of a commit for the new plane state. + */ + void (*end_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state); + + /** * @atomic_check: * * Drivers should check plane specific constraints in this hook. @@ -1068,15 +1315,14 @@ struct drm_plane_helper_funcs { * all updated. Again the recommendation is to just call check helpers * until a maximal configuration is reached. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. * * NOTE: * * This function is called in the check phase of an atomic update. The - * driver is not allowed to change anything outside of the free-standing - * state objects passed-in or assembled in the overall &drm_atomic_state - * update tracking structure. + * driver is not allowed to change anything outside of the + * &drm_atomic_state update tracking structure. * * RETURNS: * @@ -1086,7 +1332,7 @@ struct drm_plane_helper_funcs { * deadlock. */ int (*atomic_check)(struct drm_plane *plane, - struct drm_plane_state *state); + struct drm_atomic_state *state); /** * @atomic_update: @@ -1100,11 +1346,36 @@ struct drm_plane_helper_funcs { * has picked. See drm_atomic_helper_commit_planes() for a discussion of * the tradeoffs and variants of plane commit helpers. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is optional. */ void (*atomic_update)(struct drm_plane *plane, - struct drm_plane_state *old_state); + struct drm_atomic_state *state); + + /** + * @atomic_enable: + * + * Drivers should use this function to unconditionally enable a plane. + * This hook is called in-between the &drm_crtc_helper_funcs.atomic_begin + * and drm_crtc_helper_funcs.atomic_flush callbacks. It is called after + * @atomic_update, which will be called for all enabled planes. Drivers + * that use @atomic_enable should set up a plane in @atomic_update and + * afterwards enable the plane in @atomic_enable. If a plane needs to be + * enabled before installing the scanout buffer, drivers can still do + * so in @atomic_update. + * + * Note that the power state of the display pipe when this function is + * called depends upon the exact helpers and calling sequence the driver + * has picked. See drm_atomic_helper_commit_planes() for a discussion of + * the tradeoffs and variants of plane commit helpers. + * + * This callback is used by the atomic modeset helpers, but it is + * optional. If implemented, @atomic_enable should be the inverse of + * @atomic_disable. Drivers that don't want to use either can still + * implement the complete plane update in @atomic_update. + */ + void (*atomic_enable)(struct drm_plane *plane, + struct drm_atomic_state *state); + /** * @atomic_disable: * @@ -1124,11 +1395,110 @@ struct drm_plane_helper_funcs { * has picked. See drm_atomic_helper_commit_planes() for a discussion of * the tradeoffs and variants of plane commit helpers. * - * This callback is used by the atomic modeset helpers and by the - * transitional plane helpers, but it is optional. + * This callback is used by the atomic modeset helpers, but it is + * optional. It's intended to reverse the effects of @atomic_enable. */ void (*atomic_disable)(struct drm_plane *plane, - struct drm_plane_state *old_state); + struct drm_atomic_state *state); + + /** + * @atomic_async_check: + * + * Drivers should set this function pointer to check if the plane's + * atomic state can be updated in a async fashion. Here async means + * "not vblank synchronized". + * + * This hook is called by drm_atomic_async_check() to establish if a + * given update can be committed asynchronously, that is, if it can + * jump ahead of the state currently queued for update. + * + * This function is also used by drm_atomic_set_property() to determine + * if the plane can be flipped in async. The flip flag is used to + * distinguish if the function is used for just the plane state or for a + * flip. + * + * RETURNS: + * + * Return 0 on success and any error returned indicates that the update + * can not be applied in asynchronous manner. + */ + int (*atomic_async_check)(struct drm_plane *plane, + struct drm_atomic_state *state, bool flip); + + /** + * @atomic_async_update: + * + * Drivers should set this function pointer to perform asynchronous + * updates of planes, that is, jump ahead of the currently queued + * state and update the plane. Here async means "not vblank + * synchronized". + * + * This hook is called by drm_atomic_helper_async_commit(). + * + * An async update will happen on legacy cursor updates. An async + * update won't happen if there is an outstanding commit modifying + * the same plane. + * + * When doing async_update drivers shouldn't replace the + * &drm_plane_state but update the current one with the new plane + * configurations in the new plane_state. + * + * Drivers should also swap the framebuffers between current plane + * state (&drm_plane.state) and new_state. + * This is required since cleanup for async commits is performed on + * the new state, rather than old state like for traditional commits. + * Since we want to give up the reference on the current (old) fb + * instead of our brand new one, swap them in the driver during the + * async commit. + * + * FIXME: + * - It only works for single plane updates + * - Async Pageflips are not supported yet + * - Some hw might still scan out the old buffer until the next + * vblank, however we let go of the fb references as soon as + * we run this hook. For now drivers must implement their own workers + * for deferring if needed, until a common solution is created. + */ + void (*atomic_async_update)(struct drm_plane *plane, + struct drm_atomic_state *state); + + /** + * @get_scanout_buffer: + * + * Get the current scanout buffer, to display a message with drm_panic. + * The driver should do the minimum changes to provide a buffer, + * that can be used to display the panic screen. Currently only linear + * buffers are supported. Non-linear buffer support is on the TODO list. + * The device &dev.mode_config.panic_lock is taken before calling this + * function, so you can safely access the &plane.state + * It is called from a panic callback, and must follow its restrictions. + * Please look the documentation at drm_panic_trylock() for an in-depth + * discussions of what's safe and what is not allowed. + * It's a best effort mode, so it's expected that in some complex cases + * the panic screen won't be displayed. + * The returned &drm_scanout_buffer.map must be valid if no error code is + * returned. + * + * Return: + * %0 on success, negative errno on failure. + */ + int (*get_scanout_buffer)(struct drm_plane *plane, + struct drm_scanout_buffer *sb); + + /** + * @panic_flush: + * + * It is used by drm_panic, and is called after the panic screen is + * drawn to the scanout buffer. In this function, the driver + * can send additional commands to the hardware, to make the scanout + * buffer visible. + * It is only called if get_scanout_buffer() returned successfully, and + * the &dev.mode_config.panic_lock is held during the entire sequence. + * It is called from a panic callback, and must follow its restrictions. + * Please look the documentation at drm_panic_trylock() for an in-depth + * discussions of what's safe and what is not allowed. + */ + void (*panic_flush)(struct drm_plane *plane); }; /** @@ -1161,15 +1531,16 @@ struct drm_mode_config_helper_funcs { * swapped into the various state pointers. The passed in state * therefore contains copies of the old/previous state. This hook should * commit the new state into hardware. Note that the helpers have - * already waited for preceeding atomic commits and fences, but drivers + * already waited for preceding atomic commits and fences, but drivers * can add more waiting calls at the start of their implementation, e.g. * to wait for driver-internal request for implicit syncing, before * starting to commit the update to the hardware. * * After the atomic update is committed to the hardware this hook needs - * to call drm_atomic_helper_commit_hw_done(). Then wait for the upate + * to call drm_atomic_helper_commit_hw_done(). Then wait for the update * to be executed by the hardware, for example using - * drm_atomic_helper_wait_for_vblanks(), and then clean up the old + * drm_atomic_helper_wait_for_vblanks() or + * drm_atomic_helper_wait_for_flip_done(), and then clean up the old * framebuffers using drm_atomic_helper_cleanup_planes(). * * When disabling a CRTC this hook _must_ stall for the commit to @@ -1183,6 +1554,27 @@ struct drm_mode_config_helper_funcs { * drm_atomic_helper_commit_tail(). */ void (*atomic_commit_tail)(struct drm_atomic_state *state); + + /** + * @atomic_commit_setup: + * + * This hook is used by the default atomic_commit() hook implemented in + * drm_atomic_helper_commit() together with the nonblocking helpers (see + * drm_atomic_helper_setup_commit()) to extend the DRM commit setup. It + * is not used by the atomic helpers. + * + * This function is called at the end of + * drm_atomic_helper_setup_commit(), so once the commit has been + * properly setup across the generic DRM object states. It allows + * drivers to do some additional commit tracking that isn't related to a + * CRTC, plane or connector, tracked in a &drm_private_obj structure. + * + * Note that the documentation of &drm_private_obj has more details on + * how one should implement this. + * + * This hook is optional. + */ + int (*atomic_commit_setup)(struct drm_atomic_state *state); }; #endif |
