From 264d6970e16c68f851086d6f7fbf9aba18910e62 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:42 +0100 Subject: drm: Polish fbdev helper struct docs Mostly this is just adding extensive docs for the callbacks, but also a few other additions. v2: Use FIXME comments to annotate helper hooks that should be replaced. v3: Small nits (Thierry). Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-2-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_fb_helper.h | 96 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 87b090c4b730..d2d4ad1918ac 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -74,25 +74,76 @@ struct drm_fb_helper_surface_size { /** * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library - * @gamma_set: Set the given gamma lut register on the given crtc. - * @gamma_get: Read the given gamma lut register on the given crtc, used to - * save the current lut when force-restoring the fbdev for e.g. - * kdbg. - * @fb_probe: Driver callback to allocate and initialize the fbdev info - * structure. Furthermore it also needs to allocate the drm - * framebuffer used to back the fbdev. - * @initial_config: Setup an initial fbdev display configuration * * Driver callbacks used by the fbdev emulation helper library. */ struct drm_fb_helper_funcs { + /** + * @gamma_set: + * + * Set the given gamma LUT register on the given CRTC. + * + * This callback is optional. + * + * 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 (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); + /** + * @gamma_get: + * + * Read the given gamma LUT register on the given CRTC, used to save the + * current LUT when force-restoring the fbdev for e.g. kdbg. + * + * This callback is optional. + * + * 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 (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno); + /** + * @fb_probe: + * + * Driver callback to allocate and initialize the fbdev info structure. + * Furthermore it also needs to allocate the DRM framebuffer used to + * back the fbdev. + * + * This callback is mandatory. + * + * RETURNS: + * + * The driver should return 0 on success and a negative error code on + * failure. + */ int (*fb_probe)(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); + + /** + * @initial_config: + * + * Driver callback to setup an initial fbdev display configuration. + * Drivers can use this callback to tell the fbdev emulation what the + * preferred initial configuration is. This is useful to implement + * smooth booting where the fbdev (and subsequently all userspace) never + * changes the mode, but always inherits the existing configuration. + * + * This callback is optional. + * + * RETURNS: + * + * The driver should return true if a suitable initial configuration has + * been filled out and false when the fbdev helper should fall back to + * the default probing logic. + */ bool (*initial_config)(struct drm_fb_helper *fb_helper, struct drm_fb_helper_crtc **crtcs, struct drm_display_mode **modes, @@ -105,18 +156,22 @@ struct drm_fb_helper_connector { }; /** - * struct drm_fb_helper - helper to emulate fbdev on top of kms - * @fb: Scanout framebuffer object - * @dev: DRM device + * struct drm_fb_helper - main structure to emulate fbdev on top of KMS + * @fb: Scanout framebuffer object + * @dev: DRM device * @crtc_count: number of possible CRTCs * @crtc_info: per-CRTC helper state (mode, x/y offset, etc) * @connector_count: number of connected connectors * @connector_info_alloc_count: size of connector_info + * @connector_info: array of per-connector information * @funcs: driver callbacks for fb helper * @fbdev: emulated fbdev device info struct * @pseudo_palette: fake palette of 16 colors - * @kernel_fb_list: list_head in kernel_fb_helper_list - * @delayed_hotplug: was there a hotplug while kms master active? + * + * This is the main structure used by the fbdev helpers. Drivers supporting + * fbdev emulation should embedded this into their overall driver structure. + * Drivers must also fill out a struct &drm_fb_helper_funcs with a few + * operations. */ struct drm_fb_helper { struct drm_framebuffer *fb; @@ -129,10 +184,21 @@ struct drm_fb_helper { const struct drm_fb_helper_funcs *funcs; struct fb_info *fbdev; u32 pseudo_palette[17]; + + /** + * @kernel_fb_list: + * + * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit. + */ struct list_head kernel_fb_list; - /* we got a hotplug but fbdev wasn't running the console - delay until next set_par */ + /** + * @delayed_hotplug: + * + * A hotplug was received while fbdev wasn't in control of the DRM + * device, i.e. another KMS master was active. The output configuration + * needs to be reprobe when fbdev is in control again. + */ bool delayed_hotplug; /** -- cgit v1.2.3 From b516a9efb7af38733ba2308fc7c0f49f034f53bd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:43 +0100 Subject: drm: Move LEAVE/ENTER_ATOMIC_MODESET to fbdev helpers This is only used for kgdb (and previously panic) handlers in the fbdev emulation, so belongs there. Note that this means we'll leave behind a forward declaration, but once all the helper vtables are consolidated (in the next patch) that will make more sense. v2: fixup radone/amdgpu. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-3-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding (v2) --- include/drm/drm_crtc_helper.h | 5 +---- include/drm/drm_fb_helper.h | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index e22ab29d2d00..26cc978f79e7 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -41,10 +41,7 @@ #include -enum mode_set_atomic { - LEAVE_ATOMIC_MODE_SET, - ENTER_ATOMIC_MODE_SET, -}; +enum mode_set_atomic; /** * struct drm_crtc_helper_funcs - helper operations for CRTCs diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index d2d4ad1918ac..d8a40dff0d1d 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -34,6 +34,11 @@ struct drm_fb_helper; #include +enum mode_set_atomic { + LEAVE_ATOMIC_MODE_SET, + ENTER_ATOMIC_MODE_SET, +}; + struct drm_fb_offset { int x, y; }; -- cgit v1.2.3 From 092d01dae09aa6779ed41c3ac637e1e3c835424b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:44 +0100 Subject: drm: Reorganize helper vtables and their docs Currently we have 4 helper libraries (probe, crtc, plane & atomic) that all use the same helper vtables. And that's by necessity since we don't want to litter the core structs with one ops pointer per helper library. Also often the reuse the same hooks (like atomic does, to facilite conversion from existing drivers using crtc and plane helpers). Given all that it doesn't make sense to put the docs for these next to specific helpers. Instead extract them into a new header file and section in the docbook, and add references to them everywhere. Unfortunately kernel-doc complains when an include directive doesn't find anything (and it does by dumping crap into the output file). We have to remove the now empty includes to avoid that, instead of leaving them in for future proofing. v2: More OCD in ordering functions. v3: Spelling plus collate copyright headers properly. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-4-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc_helper.h | 158 +------------------ include/drm/drm_modeset_helper_vtables.h | 257 +++++++++++++++++++++++++++++++ include/drm/drm_plane_helper.h | 38 +---- 3 files changed, 259 insertions(+), 194 deletions(-) create mode 100644 include/drm/drm_modeset_helper_vtables.h (limited to 'include') diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 26cc978f79e7..f94ff54ae25e 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -40,145 +40,7 @@ #include #include - -enum mode_set_atomic; - -/** - * struct drm_crtc_helper_funcs - helper operations for CRTCs - * @dpms: set power state - * @prepare: prepare the CRTC, called before @mode_set - * @commit: commit changes to CRTC, called after @mode_set - * @mode_fixup: try to fixup proposed mode for this CRTC - * @mode_set: set this mode - * @mode_set_nofb: set mode only (no scanout buffer attached) - * @mode_set_base: update the scanout buffer - * @mode_set_base_atomic: non-blocking mode set (used for kgdb support) - * @load_lut: load color palette - * @disable: disable CRTC when no longer in use - * @enable: enable CRTC - * @atomic_check: check for validity of an atomic state - * @atomic_begin: begin atomic update - * @atomic_flush: flush atomic update - * - * The helper operations are called by the mid-layer CRTC helper. - * - * Note that with atomic helpers @dpms, @prepare and @commit hooks are - * deprecated. Used @enable and @disable instead exclusively. - * - * With legacy crtc helpers there's a big semantic difference between @disable - * and the other hooks: @disable also needs to release any resources acquired in - * @mode_set (like shared PLLs). - */ -struct drm_crtc_helper_funcs { - /* - * Control power levels on the CRTC. If the mode passed in is - * unsupported, the provider must use the next lowest power level. - */ - void (*dpms)(struct drm_crtc *crtc, int mode); - void (*prepare)(struct drm_crtc *crtc); - void (*commit)(struct drm_crtc *crtc); - - /* Provider can fixup or change mode timings before modeset occurs */ - bool (*mode_fixup)(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - /* Actually set the mode */ - int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb); - /* Actually set the mode for atomic helpers, optional */ - void (*mode_set_nofb)(struct drm_crtc *crtc); - - /* Move the crtc on the current fb to the given position *optional* */ - int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb); - int (*mode_set_base_atomic)(struct drm_crtc *crtc, - struct drm_framebuffer *fb, int x, int y, - enum mode_set_atomic); - - /* reload the current crtc LUT */ - void (*load_lut)(struct drm_crtc *crtc); - - void (*disable)(struct drm_crtc *crtc); - void (*enable)(struct drm_crtc *crtc); - - /* atomic helpers */ - int (*atomic_check)(struct drm_crtc *crtc, - struct drm_crtc_state *state); - void (*atomic_begin)(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state); - void (*atomic_flush)(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state); -}; - -/** - * struct drm_encoder_helper_funcs - helper operations for encoders - * @dpms: set power state - * @save: save connector state - * @restore: restore connector state - * @mode_fixup: try to fixup proposed mode for this connector - * @prepare: part of the disable sequence, called before the CRTC modeset - * @commit: called after the CRTC modeset - * @mode_set: set this mode, optional for atomic helpers - * @get_crtc: return CRTC that the encoder is currently attached to - * @detect: connection status detection - * @disable: disable encoder when not in use (overrides DPMS off) - * @enable: enable encoder - * @atomic_check: check for validity of an atomic update - * - * The helper operations are called by the mid-layer CRTC helper. - * - * Note that with atomic helpers @dpms, @prepare and @commit hooks are - * deprecated. Used @enable and @disable instead exclusively. - * - * With legacy crtc helpers there's a big semantic difference between @disable - * and the other hooks: @disable also needs to release any resources acquired in - * @mode_set (like shared PLLs). - */ -struct drm_encoder_helper_funcs { - void (*dpms)(struct drm_encoder *encoder, int mode); - void (*save)(struct drm_encoder *encoder); - void (*restore)(struct drm_encoder *encoder); - - bool (*mode_fixup)(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - void (*prepare)(struct drm_encoder *encoder); - void (*commit)(struct drm_encoder *encoder); - void (*mode_set)(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); - /* detect for DAC style encoders */ - enum drm_connector_status (*detect)(struct drm_encoder *encoder, - struct drm_connector *connector); - void (*disable)(struct drm_encoder *encoder); - - void (*enable)(struct drm_encoder *encoder); - - /* atomic helpers */ - int (*atomic_check)(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state); -}; - -/** - * struct drm_connector_helper_funcs - helper operations for connectors - * @get_modes: get mode list for this connector - * @mode_valid: is this mode valid on the given connector? (optional) - * @best_encoder: return the preferred encoder for this connector - * @atomic_best_encoder: atomic version of @best_encoder - * - * The helper operations are called by the mid-layer CRTC helper. - */ -struct drm_connector_helper_funcs { - int (*get_modes)(struct drm_connector *connector); - enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode); - struct drm_encoder *(*best_encoder)(struct drm_connector *connector); - struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, - struct drm_connector_state *connector_state); -}; +#include extern void drm_helper_disable_unused_functions(struct drm_device *dev); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); @@ -196,24 +58,6 @@ extern void drm_helper_move_panel_connectors_to_head(struct drm_device *); extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd); -static inline void drm_crtc_helper_add(struct drm_crtc *crtc, - const struct drm_crtc_helper_funcs *funcs) -{ - crtc->helper_private = funcs; -} - -static inline void drm_encoder_helper_add(struct drm_encoder *encoder, - const struct drm_encoder_helper_funcs *funcs) -{ - encoder->helper_private = funcs; -} - -static inline void drm_connector_helper_add(struct drm_connector *connector, - const struct drm_connector_helper_funcs *funcs) -{ - connector->helper_private = funcs; -} - extern void drm_helper_resume_force_mode(struct drm_device *dev); int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h new file mode 100644 index 000000000000..875809158fc4 --- /dev/null +++ b/include/drm/drm_modeset_helper_vtables.h @@ -0,0 +1,257 @@ +/* + * Copyright © 2006 Keith Packard + * Copyright © 2007-2008 Dave Airlie + * Copyright © 2007-2008 Intel Corporation + * Jesse Barnes + * Copyright © 2011-2013 Intel Corporation + * Copyright © 2015 Intel Corporation + * Daniel Vetter + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DRM_MODESET_HELPER_VTABLES_H__ +#define __DRM_MODESET_HELPER_VTABLES_H__ + +#include + +/** + * DOC: overview + * + * The DRM mode setting helper functions are common code for drivers to use if + * they wish. Drivers are not forced to use this code in their + * implementations but it would be useful if the code they do use at least + * provides a consistent interface and operation to userspace. Therefore it is + * highly recommended to use the provided helpers as much as possible. + * + * Because there is only one pointer per modeset object to hold a vfunc table + * for helper libraries they are by necessity shared among the different + * helpers. + * + * To make this clear all the helper vtables are pulled together in this location here. + */ + +enum mode_set_atomic; + +/** + * struct drm_crtc_helper_funcs - helper operations for CRTCs + * @dpms: set power state + * @prepare: prepare the CRTC, called before @mode_set + * @commit: commit changes to CRTC, called after @mode_set + * @mode_fixup: try to fixup proposed mode for this CRTC + * @mode_set: set this mode + * @mode_set_nofb: set mode only (no scanout buffer attached) + * @mode_set_base: update the scanout buffer + * @mode_set_base_atomic: non-blocking mode set (used for kgdb support) + * @load_lut: load color palette + * @disable: disable CRTC when no longer in use + * @enable: enable CRTC + * @atomic_check: check for validity of an atomic state + * @atomic_begin: begin atomic update + * @atomic_flush: flush atomic update + * + * The helper operations are called by the mid-layer CRTC helper. + * + * Note that with atomic helpers @dpms, @prepare and @commit hooks are + * deprecated. Used @enable and @disable instead exclusively. + * + * With legacy crtc helpers there's a big semantic difference between @disable + * and the other hooks: @disable also needs to release any resources acquired in + * @mode_set (like shared PLLs). + */ +struct drm_crtc_helper_funcs { + /* + * Control power levels on the CRTC. If the mode passed in is + * unsupported, the provider must use the next lowest power level. + */ + void (*dpms)(struct drm_crtc *crtc, int mode); + void (*prepare)(struct drm_crtc *crtc); + void (*commit)(struct drm_crtc *crtc); + + /* Provider can fixup or change mode timings before modeset occurs */ + bool (*mode_fixup)(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + /* Actually set the mode */ + int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb); + /* Actually set the mode for atomic helpers, optional */ + void (*mode_set_nofb)(struct drm_crtc *crtc); + + /* Move the crtc on the current fb to the given position *optional* */ + int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); + int (*mode_set_base_atomic)(struct drm_crtc *crtc, + struct drm_framebuffer *fb, int x, int y, + enum mode_set_atomic); + + /* reload the current crtc LUT */ + void (*load_lut)(struct drm_crtc *crtc); + + void (*disable)(struct drm_crtc *crtc); + void (*enable)(struct drm_crtc *crtc); + + /* atomic helpers */ + int (*atomic_check)(struct drm_crtc *crtc, + struct drm_crtc_state *state); + void (*atomic_begin)(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state); + void (*atomic_flush)(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state); +}; + +/** + * drm_crtc_helper_add - sets the helper vtable for a crtc + * @crtc: DRM CRTC + * @funcs: helper vtable to set for @crtc + */ +static inline void drm_crtc_helper_add(struct drm_crtc *crtc, + const struct drm_crtc_helper_funcs *funcs) +{ + crtc->helper_private = funcs; +} + +/** + * struct drm_encoder_helper_funcs - helper operations for encoders + * @dpms: set power state + * @save: save connector state + * @restore: restore connector state + * @mode_fixup: try to fixup proposed mode for this connector + * @prepare: part of the disable sequence, called before the CRTC modeset + * @commit: called after the CRTC modeset + * @mode_set: set this mode, optional for atomic helpers + * @get_crtc: return CRTC that the encoder is currently attached to + * @detect: connection status detection + * @disable: disable encoder when not in use (overrides DPMS off) + * @enable: enable encoder + * @atomic_check: check for validity of an atomic update + * + * The helper operations are called by the mid-layer CRTC helper. + * + * Note that with atomic helpers @dpms, @prepare and @commit hooks are + * deprecated. Used @enable and @disable instead exclusively. + * + * With legacy crtc helpers there's a big semantic difference between @disable + * and the other hooks: @disable also needs to release any resources acquired in + * @mode_set (like shared PLLs). + */ +struct drm_encoder_helper_funcs { + void (*dpms)(struct drm_encoder *encoder, int mode); + void (*save)(struct drm_encoder *encoder); + void (*restore)(struct drm_encoder *encoder); + + bool (*mode_fixup)(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + void (*prepare)(struct drm_encoder *encoder); + void (*commit)(struct drm_encoder *encoder); + void (*mode_set)(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); + /* detect for DAC style encoders */ + enum drm_connector_status (*detect)(struct drm_encoder *encoder, + struct drm_connector *connector); + void (*disable)(struct drm_encoder *encoder); + + void (*enable)(struct drm_encoder *encoder); + + /* atomic helpers */ + int (*atomic_check)(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); +}; + +/** + * drm_encoder_helper_add - sets the helper vtable for a encoder + * @encoder: DRM encoder + * @funcs: helper vtable to set for @encoder + */ +static inline void drm_encoder_helper_add(struct drm_encoder *encoder, + const struct drm_encoder_helper_funcs *funcs) +{ + encoder->helper_private = funcs; +} + +/** + * struct drm_connector_helper_funcs - helper operations for connectors + * @get_modes: get mode list for this connector + * @mode_valid: is this mode valid on the given connector? (optional) + * @best_encoder: return the preferred encoder for this connector + * @atomic_best_encoder: atomic version of @best_encoder + * + * The helper operations are called by the mid-layer CRTC helper. + */ +struct drm_connector_helper_funcs { + int (*get_modes)(struct drm_connector *connector); + enum drm_mode_status (*mode_valid)(struct drm_connector *connector, + struct drm_display_mode *mode); + struct drm_encoder *(*best_encoder)(struct drm_connector *connector); + struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, + struct drm_connector_state *connector_state); +}; + +/** + * drm_connector_helper_add - sets the helper vtable for a connector + * @connector: DRM connector + * @funcs: helper vtable to set for @connector + */ +static inline void drm_connector_helper_add(struct drm_connector *connector, + const struct drm_connector_helper_funcs *funcs) +{ + connector->helper_private = funcs; +} + +/** + * struct drm_plane_helper_funcs - helper operations for CRTCs + * @prepare_fb: prepare a framebuffer for use by the plane + * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane + * @atomic_check: check that a given atomic state is valid and can be applied + * @atomic_update: apply an atomic state to the plane (mandatory) + * @atomic_disable: disable the plane + * + * The helper operations are called by the mid-layer CRTC helper. + */ +struct drm_plane_helper_funcs { + int (*prepare_fb)(struct drm_plane *plane, + const struct drm_plane_state *new_state); + void (*cleanup_fb)(struct drm_plane *plane, + const struct drm_plane_state *old_state); + + int (*atomic_check)(struct drm_plane *plane, + struct drm_plane_state *state); + void (*atomic_update)(struct drm_plane *plane, + struct drm_plane_state *old_state); + void (*atomic_disable)(struct drm_plane *plane, + struct drm_plane_state *old_state); +}; + +/** + * drm_plane_helper_add - sets the helper vtable for a plane + * @plane: DRM plane + * @funcs: helper vtable to set for @plane + */ +static inline void drm_plane_helper_add(struct drm_plane *plane, + const struct drm_plane_helper_funcs *funcs) +{ + plane->helper_private = funcs; +} + +#endif diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 5a7f9d4efb1d..4421f3f4ca8d 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -26,6 +26,7 @@ #include #include +#include /* * Drivers that don't allow primary plane scaling may pass this macro in place @@ -36,46 +37,9 @@ */ #define DRM_PLANE_HELPER_NO_SCALING (1<<16) -/** - * DOC: plane helpers - * - * Helper functions to assist with creation and handling of CRTC primary - * planes. - */ - int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs); -/** - * drm_plane_helper_funcs - helper operations for CRTCs - * @prepare_fb: prepare a framebuffer for use by the plane - * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane - * @atomic_check: check that a given atomic state is valid and can be applied - * @atomic_update: apply an atomic state to the plane (mandatory) - * @atomic_disable: disable the plane - * - * The helper operations are called by the mid-layer CRTC helper. - */ -struct drm_plane_helper_funcs { - int (*prepare_fb)(struct drm_plane *plane, - const struct drm_plane_state *new_state); - void (*cleanup_fb)(struct drm_plane *plane, - const struct drm_plane_state *old_state); - - int (*atomic_check)(struct drm_plane *plane, - struct drm_plane_state *state); - void (*atomic_update)(struct drm_plane *plane, - struct drm_plane_state *old_state); - void (*atomic_disable)(struct drm_plane *plane, - struct drm_plane_state *old_state); -}; - -static inline void drm_plane_helper_add(struct drm_plane *plane, - const struct drm_plane_helper_funcs *funcs) -{ - plane->helper_private = funcs; -} - int drm_plane_helper_check_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, -- cgit v1.2.3 From 4490d4c7111e1ebf748ea2c3e1e64d103d73bae7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:45 +0100 Subject: drm: Make helper vtable pointers type-safe Originally the idea behind void* was to allow different sets of helpers. But now we have that (with probe, plane, crtc and atomic helpers) and we still just use the same set of vtables. That's the only way to make the individual helpers modular and allow drivers to pick&choose and transition between them. So this flexibility isn't really needed. Also we have lots of non-vtable data meanwhile in core structures too, this is not the first one at all. Given that the void * is only trouble since gcc can't warn you if you mix them up. Let's fix that and make them typesafe. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-5-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4765df331002..e8f8e4e9a6a1 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -254,6 +254,11 @@ struct drm_plane; struct drm_bridge; struct drm_atomic_state; +struct drm_crtc_helper_funcs; +struct drm_encoder_helper_funcs; +struct drm_connector_helper_funcs; +struct drm_plane_helper_funcs; + /** * struct drm_crtc_state - mutable CRTC state * @crtc: backpointer to the CRTC @@ -467,7 +472,7 @@ struct drm_crtc { uint16_t *gamma_store; /* if you are using the helper */ - const void *helper_private; + const struct drm_crtc_helper_funcs *helper_private; struct drm_object_properties properties; @@ -597,7 +602,7 @@ struct drm_encoder { struct drm_crtc *crtc; struct drm_bridge *bridge; const struct drm_encoder_funcs *funcs; - const void *helper_private; + const struct drm_encoder_helper_funcs *helper_private; }; /* should we poll this connector for connects and disconnects */ @@ -702,7 +707,7 @@ struct drm_connector { /* requested DPMS state */ int dpms; - const void *helper_private; + const struct drm_connector_helper_funcs *helper_private; /* forced on connector */ struct drm_cmdline_mode cmdline_mode; @@ -870,7 +875,7 @@ struct drm_plane { enum drm_plane_type type; - const void *helper_private; + const struct drm_plane_helper_funcs *helper_private; struct drm_plane_state *state; }; -- cgit v1.2.3 From da024fe58680a46346cfbeba5db705d33f39b313 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:47 +0100 Subject: drm/bridge: Improve kerneldoc Especially document the assumptions and semantics of the callbacks carefully. Just a warm-up excercise really. v2: Spelling fixes (Eric). v3: Consolidate more with existing docs: - Remove the overview section explaining the bridge funcs, that's now all in the drm_bridge_funcs kerneldoc in much more detail. - Use & to reference structs so that kerneldoc automatically inserts hyperlinks. v4: Review from Thierry. Cc: Eric Anholt Cc: Archit Taneja Signed-off-by: Daniel Vetter Reviewed-by: Archit Taneja (v3) Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-7-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 102 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e8f8e4e9a6a1..7f80fae1a45f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -883,24 +883,114 @@ struct drm_plane { /** * struct drm_bridge_funcs - drm_bridge control functions * @attach: Called during drm_bridge_attach - * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge - * @disable: Called right before encoder prepare, disables the bridge - * @post_disable: Called right after encoder prepare, for lockstepped disable - * @mode_set: Set this mode to the bridge - * @pre_enable: Called right before encoder commit, for lockstepped commit - * @enable: Called right after encoder commit, enables the bridge */ struct drm_bridge_funcs { int (*attach)(struct drm_bridge *bridge); + + /** + * @mode_fixup: + * + * This callback is used to validate and adjust a mode. The paramater + * mode is the display mode that should be fed to the next element in + * the display chain, either the final &drm_connector or the next + * &drm_bridge. The parameter adjusted_mode is the input mode the bridge + * requires. It can be modified by this callback and does not need to + * match mode. + * + * This is the only hook that allows a bridge to reject a modeset. If + * this function passes all other callbacks must succeed for this + * configuration. + * + * NOTE: + * + * This function is called in the check phase of atomic modesets, which + * can be aborted for any reason (including on userspace's request to + * just check whether a configuration would be possible). Drivers MUST + * NOT touch any persistent state (hardware or software) or data + * structures except the passed in adjusted_mode parameter. + * + * RETURNS: + * + * True if an acceptable configuration is possible, false if the modeset + * operation should be rejected. + */ bool (*mode_fixup)(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); + /** + * @disable: + * + * This callback should disable the bridge. It is called right before + * the preceding element in the display pipe is disabled. If the + * preceding element is a bridge this means it's called before that + * bridge's ->disable() function. If the preceding element is a + * &drm_encoder it's called right before the encoder's ->disable(), + * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs. + * + * The bridge can assume that the display pipe (i.e. clocks and timing + * signals) feeding it is still running when this callback is called. + */ void (*disable)(struct drm_bridge *bridge); + + /** + * @post_disable: + * + * This callback should disable the bridge. It is called right after + * the preceding element in the display pipe is disabled. If the + * preceding element is a bridge this means it's called after that + * bridge's ->post_disable() function. If the preceding element is a + * &drm_encoder it's called right after the encoder's ->disable(), + * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs. + * + * The bridge must assume that the display pipe (i.e. clocks and timing + * singals) feeding it is no longer running when this callback is + * called. + */ void (*post_disable)(struct drm_bridge *bridge); + + /** + * @mode_set: + * + * This callback should set the given mode on the bridge. It is called + * after the ->mode_set() callback for the preceding element in the + * display pipeline has been called already. The display pipe (i.e. + * clocks and timing signals) is off when this function is called. + */ void (*mode_set)(struct drm_bridge *bridge, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); + /** + * @pre_enable: + * + * This callback should enable the bridge. It is called right before + * the preceding element in the display pipe is enabled. If the + * preceding element is a bridge this means it's called before that + * bridge's ->pre_enable() function. If the preceding element is a + * &drm_encoder it's called right before the encoder's ->enable(), + * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs. + * + * The display pipe (i.e. clocks and timing signals) feeding this bridge + * will not yet be running when this callback is called. The bridge must + * not enable the display link feeding the next bridge in the chain (if + * there is one) when this callback is called. + */ void (*pre_enable)(struct drm_bridge *bridge); + + /** + * @enable: + * + * This callback should enable the bridge. It is called right after + * the preceding element in the display pipe is enabled. If the + * preceding element is a bridge this means it's called after that + * bridge's ->enable() function. If the preceding element is a + * &drm_encoder it's called right after the encoder's ->enable(), + * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs. + * + * The bridge can assume that the display pipe (i.e. clocks and timing + * signals) feeding it is running when this callback is called. This + * callback must enable the display link feeding the next bridge in the + * chain if there is one. + */ void (*enable)(struct drm_bridge *bridge); }; -- cgit v1.2.3 From 88548636406c08ef4b3d32d12d1860a216389177 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:48 +0100 Subject: drm: Update drm_plane_funcs kerneldoc - Merge the docbook into the kerneldoc comments. - Spec in detail the precise semantics of the callbacks. - For consistency in wording and easier review roll out kerneldoc also for crtc, encoder and connector for the standard hooks they share with planes. v2: Suggestions from Thierry. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-8-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 496 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 459 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7f80fae1a45f..1bcfa094af16 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -322,21 +322,12 @@ struct drm_crtc_state { * struct drm_crtc_funcs - control CRTCs for a given device * @save: save CRTC state * @restore: restore CRTC state - * @reset: reset CRTC after state has been invalidated (e.g. resume) * @cursor_set: setup the cursor * @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set * @cursor_move: move the cursor * @gamma_set: specify color ramp for CRTC - * @destroy: deinit and free object - * @set_property: called when a property is changed * @set_config: apply a new CRTC configuration * @page_flip: initiate a page flip - * @atomic_duplicate_state: duplicate the atomic state for this CRTC - * @atomic_destroy_state: destroy an atomic state for this CRTC - * @atomic_set_property: set a property on an atomic state for this CRTC - * (do not call directly, use drm_atomic_crtc_set_property()) - * @atomic_get_property: get a property on an atomic state for this CRTC - * (do not call directly, use drm_atomic_crtc_get_property()) * * The drm_crtc_funcs structure is the central CRTC management structure * in the DRM. Each CRTC controls one or more connectors (note that the name @@ -352,7 +343,17 @@ struct drm_crtc_funcs { void (*save)(struct drm_crtc *crtc); /* suspend? */ /* Restore CRTC state */ void (*restore)(struct drm_crtc *crtc); /* resume? */ - /* Reset CRTC state */ + + /** + * @reset: + * + * Reset CRTC hardware and software state to off. This function isn't + * called by the core directly, only through drm_mode_config_reset(). + * It's not a helper hook only for historical reasons. + * + * Atomic drivers can use drm_atomic_helper_crtc_reset() to reset + * atomic state using this hook. + */ void (*reset)(struct drm_crtc *crtc); /* cursor controls */ @@ -366,7 +367,14 @@ struct drm_crtc_funcs { /* Set gamma on the CRTC */ void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, uint32_t size); - /* Object destroy routine */ + + /** + * @destroy: + * + * Clean up plane resources. This is only called at driver unload time + * through drm_mode_config_cleanup() since a CRTC cannot be hotplugged + * in DRM. + */ void (*destroy)(struct drm_crtc *crtc); int (*set_config)(struct drm_mode_set *set); @@ -385,17 +393,129 @@ struct drm_crtc_funcs { struct drm_pending_vblank_event *event, uint32_t flags); + /** + * @set_property: + * + * This is the legacy entry point to update a property attached to the + * CRTC. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_crtc_set_property() to implement this hook. + * + * This callback is optional if the driver does not support any legacy + * driver-private properties. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*set_property)(struct drm_crtc *crtc, struct drm_property *property, uint64_t val); - /* atomic update handling */ + /** + * @atomic_duplicate_state: + * + * Duplicate the current atomic state for this CRTC and return it. + * The core and helpers gurantee that any atomic state duplicated with + * this hook and still owned by the caller (i.e. not transferred to the + * driver by calling ->atomic_commit() from struct + * &drm_mode_config_funcs) will be cleaned up by calling the + * @atomic_destroy_state hook in this structure. + * + * Atomic drivers which don't subclass struct &drm_crtc should use + * drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the + * state structure to extend it with driver-private state should use + * __drm_atomic_helper_crtc_duplicate_state() to make sure shared state is + * duplicated in a consistent fashion across drivers. + * + * It is an error to call this hook before crtc->state has been + * initialized correctly. + * + * NOTE: + * + * If the duplicate state references refcounted resources this hook must + * acquire a reference for each of them. The driver must release these + * references again in @atomic_destroy_state. + * + * RETURNS: + * + * Duplicated atomic state or NULL when the allocation failed. + */ struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc); + + /** + * @atomic_destroy_state: + * + * Destroy a state duplicated with @atomic_duplicate_state and release + * or unreference all resources it references + */ void (*atomic_destroy_state)(struct drm_crtc *crtc, struct drm_crtc_state *state); + + /** + * @atomic_set_property: + * + * Decode a driver-private property value and store the decoded value + * into the passed-in state structure. Since the atomic core decodes all + * standardized properties (even for extensions beyond the core set of + * properties which might not be implemented by all drivers) this + * requires drivers to subclass the state structure. + * + * Such driver-private properties should really only be implemented for + * truly hardware/vendor specific state. Instead it is preferred to + * standardize atomic extension and decode the properties used to expose + * such an extension in the core. + * + * Do not call this function directly, use + * drm_atomic_crtc_set_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * NOTE: + * + * This function is called in the state assembly phase of atomic + * modesets, which can be aborted for any reason (including on + * userspace's request to just check whether a configuration would be + * possible). Drivers MUST NOT touch any persistent state (hardware or + * software) or data structures except the passed in @state parameter. + * + * Also since userspace controls in which order properties are set this + * function must not do any input validation (since the state update is + * incomplete and hence likely inconsistent). Instead any such input + * validation must be done in the various atomic_check callbacks. + * + * RETURNS: + * + * 0 if the property has been found, -EINVAL if the property isn't + * implemented by the driver (which should never happen, the core only + * asks for properties attached to this CRTC). No other validation is + * allowed by the driver. The core already checks that the property + * value is within the range (integer, valid enum value, ...) the driver + * set when registering the property. + */ int (*atomic_set_property)(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val); + /** + * @atomic_get_property: + * + * Reads out the decoded driver-private property. This is used to + * implement the GETCRTC ioctl. + * + * Do not call this function directly, use + * drm_atomic_crtc_get_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * RETURNS: + * + * 0 on success, -EINVAL if the property isn't implemented by the + * driver (which should never happen, the core only asks for + * properties attached to this CRTC). + */ int (*atomic_get_property)(struct drm_crtc *crtc, const struct drm_crtc_state *state, struct drm_property *property, @@ -507,18 +627,9 @@ struct drm_connector_state { * @dpms: set power state * @save: save connector state * @restore: restore connector state - * @reset: reset connector after state has been invalidated (e.g. resume) * @detect: is this connector active? * @fill_modes: fill mode list for this connector - * @set_property: property for this connector may need an update - * @destroy: make object go away * @force: notify the driver that the connector is forced on - * @atomic_duplicate_state: duplicate the atomic state for this connector - * @atomic_destroy_state: destroy an atomic state for this connector - * @atomic_set_property: set a property on an atomic state for this connector - * (do not call directly, use drm_atomic_connector_set_property()) - * @atomic_get_property: get a property on an atomic state for this connector - * (do not call directly, use drm_atomic_connector_get_property()) * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes, @@ -528,6 +639,17 @@ struct drm_connector_funcs { int (*dpms)(struct drm_connector *connector, int mode); void (*save)(struct drm_connector *connector); void (*restore)(struct drm_connector *connector); + + /** + * @reset: + * + * Reset connector hardware and software state to off. This function isn't + * called by the core directly, only through drm_mode_config_reset(). + * It's not a helper hook only for historical reasons. + * + * Atomic drivers can use drm_atomic_helper_connector_reset() to reset + * atomic state using this hook. + */ void (*reset)(struct drm_connector *connector); /* Check to see if anything is attached to the connector. @@ -539,19 +661,142 @@ struct drm_connector_funcs { enum drm_connector_status (*detect)(struct drm_connector *connector, bool force); int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); + + /** + * @set_property: + * + * This is the legacy entry point to update a property attached to the + * connector. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_connector_set_property() to implement this hook. + * + * This callback is optional if the driver does not support any legacy + * driver-private properties. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*set_property)(struct drm_connector *connector, struct drm_property *property, uint64_t val); + + /** + * @destroy: + * + * Clean up connector resources. This is called at driver unload time + * through drm_mode_config_cleanup(). It can also be called at runtime + * when a connector is being hot-unplugged for drivers that support + * connector hotplugging (e.g. DisplayPort MST). + */ void (*destroy)(struct drm_connector *connector); void (*force)(struct drm_connector *connector); - /* atomic update handling */ + /** + * @atomic_duplicate_state: + * + * Duplicate the current atomic state for this connector and return it. + * The core and helpers gurantee that any atomic state duplicated with + * this hook and still owned by the caller (i.e. not transferred to the + * driver by calling ->atomic_commit() from struct + * &drm_mode_config_funcs) will be cleaned up by calling the + * @atomic_destroy_state hook in this structure. + * + * Atomic drivers which don't subclass struct &drm_connector_state should use + * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the + * state structure to extend it with driver-private state should use + * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is + * duplicated in a consistent fashion across drivers. + * + * It is an error to call this hook before connector->state has been + * initialized correctly. + * + * NOTE: + * + * If the duplicate state references refcounted resources this hook must + * acquire a reference for each of them. The driver must release these + * references again in @atomic_destroy_state. + * + * RETURNS: + * + * Duplicated atomic state or NULL when the allocation failed. + */ struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); + + /** + * @atomic_destroy_state: + * + * Destroy a state duplicated with @atomic_duplicate_state and release + * or unreference all resources it references + */ void (*atomic_destroy_state)(struct drm_connector *connector, struct drm_connector_state *state); + + /** + * @atomic_set_property: + * + * Decode a driver-private property value and store the decoded value + * into the passed-in state structure. Since the atomic core decodes all + * standardized properties (even for extensions beyond the core set of + * properties which might not be implemented by all drivers) this + * requires drivers to subclass the state structure. + * + * Such driver-private properties should really only be implemented for + * truly hardware/vendor specific state. Instead it is preferred to + * standardize atomic extension and decode the properties used to expose + * such an extension in the core. + * + * Do not call this function directly, use + * drm_atomic_connector_set_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * NOTE: + * + * This function is called in the state assembly phase of atomic + * modesets, which can be aborted for any reason (including on + * userspace's request to just check whether a configuration would be + * possible). Drivers MUST NOT touch any persistent state (hardware or + * software) or data structures except the passed in @state parameter. + * + * Also since userspace controls in which order properties are set this + * function must not do any input validation (since the state update is + * incomplete and hence likely inconsistent). Instead any such input + * validation must be done in the various atomic_check callbacks. + * + * RETURNS: + * + * 0 if the property has been found, -EINVAL if the property isn't + * implemented by the driver (which shouldn't ever happen, the core only + * asks for properties attached to this connector). No other validation + * is allowed by the driver. The core already checks that the property + * value is within the range (integer, valid enum value, ...) the driver + * set when registering the property. + */ int (*atomic_set_property)(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); + + /** + * @atomic_get_property: + * + * Reads out the decoded driver-private property. This is used to + * implement the GETCONNECTOR ioctl. + * + * Do not call this function directly, use + * drm_atomic_connector_get_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * RETURNS: + * + * 0 on success, -EINVAL if the property isn't implemented by the + * driver (which shouldn't ever happen, the core only asks for + * properties attached to this connector). + */ int (*atomic_get_property)(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, @@ -560,13 +805,26 @@ struct drm_connector_funcs { /** * struct drm_encoder_funcs - encoder controls - * @reset: reset state (e.g. at init or resume time) - * @destroy: cleanup and free associated data * * Encoders sit between CRTCs and connectors. */ struct drm_encoder_funcs { + /** + * @reset: + * + * Reset encoder hardware and software state to off. This function isn't + * called by the core directly, only through drm_mode_config_reset(). + * It's not a helper hook only for historical reasons. + */ void (*reset)(struct drm_encoder *encoder); + + /** + * @destroy: + * + * Clean up encoder resources. This is only called at driver unload time + * through drm_mode_config_cleanup() since an encoder cannot be + * hotplugged in DRM. + */ void (*destroy)(struct drm_encoder *encoder); }; @@ -787,40 +1045,203 @@ struct drm_plane_state { /** * struct drm_plane_funcs - driver plane control functions - * @update_plane: update the plane configuration - * @disable_plane: shut down the plane - * @destroy: clean up plane resources - * @reset: reset plane after state has been invalidated (e.g. resume) - * @set_property: called when a property is changed - * @atomic_duplicate_state: duplicate the atomic state for this plane - * @atomic_destroy_state: destroy an atomic state for this plane - * @atomic_set_property: set a property on an atomic state for this plane - * (do not call directly, use drm_atomic_plane_set_property()) - * @atomic_get_property: get a property on an atomic state for this plane - * (do not call directly, use drm_atomic_plane_get_property()) */ struct drm_plane_funcs { + /** + * @update_plane: + * + * This is the legacy entry point to enable and configure the plane for + * the given CRTC and framebuffer. It is never called to disable the + * plane, i.e. the passed-in crtc and fb paramters are never NULL. + * + * The source rectangle in frame buffer memory coordinates is given by + * the src_x, src_y, src_w and src_h parameters (as 16.16 fixed point + * values). Devices that don't support subpixel plane coordinates can + * ignore the fractional part. + * + * The destination rectangle in CRTC coordinates is given by the + * crtc_x, crtc_y, crtc_w and crtc_h parameters (as integer values). + * Devices scale the source rectangle to the destination rectangle. If + * scaling is not supported, and the source rectangle size doesn't match + * the destination rectangle size, the driver must return a + * -EINVAL error. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_update_plane() to implement this hook. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*update_plane)(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); + + /** + * @disable_plane: + * + * This is the legacy entry point to disable the plane. The DRM core + * calls this method in response to a DRM_IOCTL_MODE_SETPLANE ioctl call + * with the frame buffer ID set to 0. Disabled planes must not be + * processed by the CRTC. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_disable_plane() to implement this hook. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*disable_plane)(struct drm_plane *plane); + + /** + * @destroy: + * + * Clean up plane resources. This is only called at driver unload time + * through drm_mode_config_cleanup() since a plane cannot be hotplugged + * in DRM. + */ void (*destroy)(struct drm_plane *plane); + + /** + * @reset: + * + * Reset plane hardware and software state to off. This function isn't + * called by the core directly, only through drm_mode_config_reset(). + * It's not a helper hook only for historical reasons. + * + * Atomic drivers can use drm_atomic_helper_plane_reset() to reset + * atomic state using this hook. + */ void (*reset)(struct drm_plane *plane); + /** + * @set_property: + * + * This is the legacy entry point to update a property attached to the + * plane. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_plane_set_property() to implement this hook. + * + * This callback is optional if the driver does not support any legacy + * driver-private properties. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*set_property)(struct drm_plane *plane, struct drm_property *property, uint64_t val); - /* atomic update handling */ + /** + * @atomic_duplicate_state: + * + * Duplicate the current atomic state for this plane and return it. + * The core and helpers gurantee that any atomic state duplicated with + * this hook and still owned by the caller (i.e. not transferred to the + * driver by calling ->atomic_commit() from struct + * &drm_mode_config_funcs) will be cleaned up by calling the + * @atomic_destroy_state hook in this structure. + * + * Atomic drivers which don't subclass struct &drm_plane_state should use + * drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the + * state structure to extend it with driver-private state should use + * __drm_atomic_helper_plane_duplicate_state() to make sure shared state is + * duplicated in a consistent fashion across drivers. + * + * It is an error to call this hook before plane->state has been + * initialized correctly. + * + * NOTE: + * + * If the duplicate state references refcounted resources this hook must + * acquire a reference for each of them. The driver must release these + * references again in @atomic_destroy_state. + * + * RETURNS: + * + * Duplicated atomic state or NULL when the allocation failed. + */ struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane); + + /** + * @atomic_destroy_state: + * + * Destroy a state duplicated with @atomic_duplicate_state and release + * or unreference all resources it references + */ void (*atomic_destroy_state)(struct drm_plane *plane, struct drm_plane_state *state); + + /** + * @atomic_set_property: + * + * Decode a driver-private property value and store the decoded value + * into the passed-in state structure. Since the atomic core decodes all + * standardized properties (even for extensions beyond the core set of + * properties which might not be implemented by all drivers) this + * requires drivers to subclass the state structure. + * + * Such driver-private properties should really only be implemented for + * truly hardware/vendor specific state. Instead it is preferred to + * standardize atomic extension and decode the properties used to expose + * such an extension in the core. + * + * Do not call this function directly, use + * drm_atomic_plane_set_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * NOTE: + * + * This function is called in the state assembly phase of atomic + * modesets, which can be aborted for any reason (including on + * userspace's request to just check whether a configuration would be + * possible). Drivers MUST NOT touch any persistent state (hardware or + * software) or data structures except the passed in @state parameter. + * + * Also since userspace controls in which order properties are set this + * function must not do any input validation (since the state update is + * incomplete and hence likely inconsistent). Instead any such input + * validation must be done in the various atomic_check callbacks. + * + * RETURNS: + * + * 0 if the property has been found, -EINVAL if the property isn't + * implemented by the driver (which shouldn't ever happen, the core only + * asks for properties attached to this plane). No other validation is + * allowed by the driver. The core already checks that the property + * value is within the range (integer, valid enum value, ...) the driver + * set when registering the property. + */ int (*atomic_set_property)(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val); + + /** + * @atomic_get_property: + * + * Reads out the decoded driver-private property. This is used to + * implement the GETPLANE ioctl. + * + * Do not call this function directly, use + * drm_atomic_plane_get_property() instead. + * + * This callback is optional if the driver does not support any + * driver-private atomic properties. + * + * RETURNS: + * + * 0 on success, -EINVAL if the property isn't implemented by the + * driver (which should never happen, the core only asks for + * properties attached to this plane). + */ int (*atomic_get_property)(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, @@ -833,6 +1254,7 @@ enum drm_plane_type { DRM_PLANE_TYPE_CURSOR, }; + /** * struct drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to @@ -907,7 +1329,7 @@ struct drm_bridge_funcs { * can be aborted for any reason (including on userspace's request to * just check whether a configuration would be possible). Drivers MUST * NOT touch any persistent state (hardware or software) or data - * structures except the passed in adjusted_mode parameter. + * structures except the passed in @state parameter. * * RETURNS: * -- cgit v1.2.3 From 813b0f3e00d402279718403aeb621c965f97180e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:55 +0100 Subject: drm: Remove crtc/connector->save/restore hooks They're not how system suspend/resume should be done with atomic (there's new helpers for that developed by Thierry Reding), and for legacy drivers this really should be a helper hook and not a core one. But there's not even helper code to use them, and only 2 drivers (which now have their own private hooks) set them. Ditch them. Saves me typing some kerneldoc, too ;-) Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-15-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1bcfa094af16..e75b06b61143 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -320,8 +320,6 @@ struct drm_crtc_state { /** * struct drm_crtc_funcs - control CRTCs for a given device - * @save: save CRTC state - * @restore: restore CRTC state * @cursor_set: setup the cursor * @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set * @cursor_move: move the cursor @@ -339,11 +337,6 @@ struct drm_crtc_state { * bus accessors. */ struct drm_crtc_funcs { - /* Save CRTC state */ - void (*save)(struct drm_crtc *crtc); /* suspend? */ - /* Restore CRTC state */ - void (*restore)(struct drm_crtc *crtc); /* resume? */ - /** * @reset: * @@ -625,8 +618,6 @@ struct drm_connector_state { /** * struct drm_connector_funcs - control connectors on a given device * @dpms: set power state - * @save: save connector state - * @restore: restore connector state * @detect: is this connector active? * @fill_modes: fill mode list for this connector * @force: notify the driver that the connector is forced on @@ -637,8 +628,6 @@ struct drm_connector_state { */ struct drm_connector_funcs { int (*dpms)(struct drm_connector *connector, int mode); - void (*save)(struct drm_connector *connector); - void (*restore)(struct drm_connector *connector); /** * @reset: -- cgit v1.2.3 From 129b782008a537a0d222d9e23b39d78a323ed595 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 17:14:07 +0100 Subject: drm: Move encoder->save/restore into nouveau Nouveau is the only user, and atomic drivers should do state save/restoring differently. So move it into noveau. Saves me typing some kerneldoc, too ;-) v2: Move misplaced hunk into earlier nouveau patch. Cc: Ilia Mirkin Cc: Ben Skeggs Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449245647-1315-1-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_modeset_helper_vtables.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 875809158fc4..56dadfe7a181 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -131,8 +131,6 @@ static inline void drm_crtc_helper_add(struct drm_crtc *crtc, /** * struct drm_encoder_helper_funcs - helper operations for encoders * @dpms: set power state - * @save: save connector state - * @restore: restore connector state * @mode_fixup: try to fixup proposed mode for this connector * @prepare: part of the disable sequence, called before the CRTC modeset * @commit: called after the CRTC modeset @@ -154,8 +152,6 @@ static inline void drm_crtc_helper_add(struct drm_crtc *crtc, */ struct drm_encoder_helper_funcs { void (*dpms)(struct drm_encoder *encoder, int mode); - void (*save)(struct drm_encoder *encoder); - void (*restore)(struct drm_encoder *encoder); bool (*mode_fixup)(struct drm_encoder *encoder, const struct drm_display_mode *mode, -- cgit v1.2.3 From 6fe14acd496e7ca27d6dfbeaa71b4f16656d10c2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:45:58 +0100 Subject: drm: Document drm_connector_funcs The special case here is that both ->detect and ->force are actually functions only called by the probe helpers and hence really shouldn't be here. But since they've used by pretty much every driver I figured it's better to just document this for now instead of holding this doc patch hostage until that's all fixed. For that reason also group force right next to detect. v2: Use FIXME comments to annotate where we should move a hook to helpers. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-18-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 84 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e75b06b61143..819eb45821cd 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -617,16 +617,28 @@ struct drm_connector_state { /** * struct drm_connector_funcs - control connectors on a given device - * @dpms: set power state - * @detect: is this connector active? - * @fill_modes: fill mode list for this connector - * @force: notify the driver that the connector is forced on * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes, * etc. */ struct drm_connector_funcs { + /** + * @dpms: + * + * Legacy entry point to set the per-connector DPMS state. Legacy DPMS + * is exposed as a standard property on the connector, but diverted to + * this callback in the drm core. Note that atomic drivers don't + * implement the 4 level DPMS support on the connector any more, but + * instead only have an on/off "ACTIVE" property on the CRTC object. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_connector_dpms() to implement this hook. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*dpms)(struct drm_connector *connector, int mode); /** @@ -641,14 +653,67 @@ struct drm_connector_funcs { */ void (*reset)(struct drm_connector *connector); - /* Check to see if anything is attached to the connector. - * @force is set to false whilst polling, true when checking the - * connector due to user request. @force can be used by the driver - * to avoid expensive, destructive operations during automated - * probing. + /** + * @detect: + * + * Check to see if anything is attached to the connector. The parameter + * force is set to false whilst polling, true when checking the + * connector due to a user request. force can be used by the driver to + * avoid expensive, destructive operations during automated probing. + * + * FIXME: + * + * Note that this hook is only called by the probe helper. It's not in + * the helper library vtable purely for historical reasons. The only DRM + * core entry point to probe connector state is @fill_modes. + * + * RETURNS: + * + * drm_connector_status indicating the connector's status. */ enum drm_connector_status (*detect)(struct drm_connector *connector, bool force); + + /** + * @force: + * + * This function is called to update internal encoder state when the + * connector is forced to a certain state by userspace, either through + * the sysfs interfaces or on the kernel cmdline. In that case the + * @detect callback isn't called. + * + * FIXME: + * + * Note that this hook is only called by the probe helper. It's not in + * the helper library vtable purely for historical reasons. The only DRM + * core entry point to probe connector state is @fill_modes. + */ + void (*force)(struct drm_connector *connector); + + /** + * @fill_modes: + * + * Entry point for output detection and basic mode validation. The + * driver should reprobe the output if needed (e.g. when hotplug + * handling is unreliable), add all detected modes to connector->modes + * and filter out any the device can't support in any configuration. It + * also needs to filter out any modes wider or higher than the + * parameters max_width and max_height indicate. + * + * The drivers must also prune any modes no longer valid from + * connector->modes. Furthermore it must update connector->status and + * connector->edid. If no EDID has been received for this output + * connector->edid must be NULL. + * + * Drivers using the probe helpers should use + * drm_helper_probe_single_connector_modes() or + * drm_helper_probe_single_connector_modes_nomerge() to implement this + * function. + * + * RETURNS: + * + * The number of modes detected and filled into connector->modes. + */ int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); /** @@ -679,7 +744,6 @@ struct drm_connector_funcs { * connector hotplugging (e.g. DisplayPort MST). */ void (*destroy)(struct drm_connector *connector); - void (*force)(struct drm_connector *connector); /** * @atomic_duplicate_state: -- cgit v1.2.3 From f6da8c6e5ee378c82f20ad07f84556befc7b58e9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:00 +0100 Subject: drm: document drm_crtc_funcs And merge any docbook we have into the kerneldoc comments. Since it's a legacy entry point with only two implementation (one each in atomic and legacy crtc helpers) I've made the documentation for set_config fairly sparse - no one should ever need to look at this again, all the ABI we have is baked into code. For ->page_flip otoh I kept all the extensive docs from the docbook and even extended it where it was lacking: Currently we have a pile of legacy page_flip implemantations, and even for atomic drivers there's not yet a standard implementation in the helpers. Which means every driver needs to implement this itself, and precise specs are really valuable. Otherwise there's just cursor, which really just boils down to "use at least universal planes". And gamma tables (where we have a bit a mess with the fbdev helper gamma hooks). v2: Spelling fixes (Eric). v3: Suggestions from Thierry. Cc: Eric Anholt Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-20-git-send-email-daniel.vetter@ffwll.ch --- include/drm/drm_crtc.h | 164 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 148 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 819eb45821cd..44a98082d409 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -320,12 +320,6 @@ struct drm_crtc_state { /** * struct drm_crtc_funcs - control CRTCs for a given device - * @cursor_set: setup the cursor - * @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set - * @cursor_move: move the cursor - * @gamma_set: specify color ramp for CRTC - * @set_config: apply a new CRTC configuration - * @page_flip: initiate a page flip * * The drm_crtc_funcs structure is the central CRTC management structure * in the DRM. Each CRTC controls one or more connectors (note that the name @@ -349,15 +343,86 @@ struct drm_crtc_funcs { */ void (*reset)(struct drm_crtc *crtc); - /* cursor controls */ + /** + * @cursor_set: + * + * Update the cursor image. The cursor position is relative to the CRTC + * and can be partially or fully outside of the visible area. + * + * Note that contrary to all other KMS functions the legacy cursor entry + * points don't take a framebuffer object, but instead take directly a + * raw buffer object id from the driver's buffer manager (which is + * either GEM or TTM for current drivers). + * + * This entry point is deprecated, drivers should instead implement + * universal plane support and register a proper cursor plane using + * drm_crtc_init_with_planes(). + * + * This callback is optional + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height); + + /** + * @cursor_set2: + * + * Update the cursor image, including hotspot information. The hotspot + * must not affect the cursor position in CRTC coordinates, but is only + * meant as a hint for virtualized display hardware to coordinate the + * guests and hosts cursor position. The cursor hotspot is relative to + * the cursor image. Otherwise this works exactly like @cursor_set. + * + * This entry point is deprecated, drivers should instead implement + * universal plane support and register a proper cursor plane using + * drm_crtc_init_with_planes(). + * + * This callback is optional. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*cursor_set2)(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y); + + /** + * @cursor_move: + * + * Update the cursor position. The cursor does not need to be visible + * when this hook is called. + * + * This entry point is deprecated, drivers should instead implement + * universal plane support and register a proper cursor plane using + * drm_crtc_init_with_planes(). + * + * This callback is optional. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*cursor_move)(struct drm_crtc *crtc, int x, int y); - /* Set gamma on the CRTC */ + /** + * @gamma_set: + * + * Set gamma on the CRTC. + * + * This callback is optional. + * + * NOTE: + * + * Drivers that support gamma tables and also fbdev emulation through + * the provided helper library need to take care to fill out the gamma + * hooks for both. Currently there's a bit an unfortunate duplication + * going on, which should eventually be unified to just one set of + * hooks. + */ void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, uint32_t size); @@ -370,16 +435,83 @@ struct drm_crtc_funcs { */ void (*destroy)(struct drm_crtc *crtc); + /** + * @set_config: + * + * This is the main legacy entry point to change the modeset state on a + * CRTC. All the details of the desired configuration are passed in a + * struct &drm_mode_set - see there for details. + * + * Drivers implementing atomic modeset should use + * drm_atomic_helper_set_config() to implement this hook. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*set_config)(struct drm_mode_set *set); - /* - * Flip to the given framebuffer. This implements the page - * flip ioctl described in drm_mode.h, specifically, the - * implementation must return immediately and block all - * rendering to the current fb until the flip has completed. - * If userspace set the event flag in the ioctl, the event - * argument will point to an event to send back when the flip - * completes, otherwise it will be NULL. + /** + * @page_flip: + * + * Legacy entry point to schedule a flip to the given framebuffer. + * + * Page flipping is a synchronization mechanism that replaces the frame + * buffer being scanned out by the CRTC with a new frame buffer during + * vertical blanking, avoiding tearing (except when requested otherwise + * through the DRM_MODE_PAGE_FLIP_ASYNC flag). When an application + * requests a page flip the DRM core verifies that the new frame buffer + * is large enough to be scanned out by the CRTC in the currently + * configured mode and then calls the CRTC ->page_flip() operation with a + * pointer to the new frame buffer. + * + * The driver must wait for any pending rendering to the new framebuffer + * to complete before executing the flip. It should also wait for any + * pending rendering from other drivers if the underlying buffer is a + * shared dma-buf. + * + * An application can request to be notified when the page flip has + * completed. The drm core will supply a struct &drm_event in the event + * parameter in this case. This can be handled by the + * drm_crtc_send_vblank_event() function, which the driver should call on + * the provided event upon completion of the flip. Note that if + * the driver supports vblank signalling and timestamping the vblank + * counters and timestamps must agree with the ones returned from page + * flip events. With the current vblank helper infrastructure this can + * be achieved by holding a vblank reference while the page flip is + * pending, acquired through drm_crtc_vblank_get() and released with + * drm_crtc_vblank_put(). Drivers are free to implement their own vblank + * counter and timestamp tracking though, e.g. if they have accurate + * timestamp registers in hardware. + * + * FIXME: + * + * Up to that point drivers need to manage events themselves and can use + * even->base.list freely for that. Specifically they need to ensure + * that they don't send out page flip (or vblank) events for which the + * corresponding drm file has been closed already. The drm core + * unfortunately does not (yet) take care of that. Therefore drivers + * currently must clean up and release pending events in their + * ->preclose driver function. + * + * This callback is optional. + * + * NOTE: + * + * Very early versions of the KMS ABI mandated that the driver must + * block (but not reject) any rendering to the old framebuffer until the + * flip operation has completed and the old framebuffer is no longer + * visible. This requirement has been lifted, and userspace is instead + * expected to request delivery of an event and wait with recycling old + * buffers until such has been received. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. Note that if a + * ->page_flip() operation is already pending the callback should return + * -EBUSY. Pageflips on a disabled CRTC (either by setting a NULL mode + * or just runtime disabled through DPMS respectively the new atomic + * "ACTIVE" state) should result in an -EINVAL error code. */ int (*page_flip)(struct drm_crtc *crtc, struct drm_framebuffer *fb, -- cgit v1.2.3 From c6b0ca3ea8366d1954c7825d0f67bc833b8e10df Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:01 +0100 Subject: drm: Add kerneldoc for drm_framebuffer_funcs While typing these I noticed that ->dirty is a bit a can of worms and even supports blt/fill semantics ... shocked me a bit. Oh well it's defined in a way that nothing bad (just a bit of inefficiency) will happen for drivers which supports this. So I didn't bother copying the detailed spec into the new kerneldoc. v2: Suggestions from Thierry. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-21-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 68 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 44a98082d409..f09391f9cac0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -162,23 +162,55 @@ struct drm_tile_group { u8 group_data[8]; }; +/** + * struct drm_framebuffer_funcs - framebuffer hooks + */ struct drm_framebuffer_funcs { - /* note: use drm_framebuffer_remove() */ + /** + * @destroy: + * + * Clean up framebuffer resources, specifically also unreference the + * backing storage. The core guarantees to call this function for every + * framebuffer successfully created by ->fb_create() in + * &drm_mode_config_funcs. + */ void (*destroy)(struct drm_framebuffer *framebuffer); + + /** + * @create_handle: + * + * Create a buffer handle in the driver-specific buffer manager (either + * GEM or TTM) valid for the passed-in struct &drm_file. This is used by + * the core to implement the GETFB IOCTL, which returns (for + * sufficiently priviledged user) also a native buffer handle. This can + * be used for seamless transitions between modesetting clients by + * copying the current screen contents to a private buffer and blending + * between that and the new contents. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*create_handle)(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle); - /* - * Optional callback for the dirty fb ioctl. + /** + * @dirty: * - * Userspace can notify the driver via this callback - * that a area of the framebuffer has changed and should - * be flushed to the display hardware. + * Optional callback for the dirty fb IOCTL. * - * See documentation in drm_mode.h for the struct - * drm_mode_fb_dirty_cmd for more information as all - * the semantics and arguments have a one to one mapping - * on this function. + * Userspace can notify the driver via this callback that an area of the + * framebuffer has changed and should be flushed to the display + * hardware. This can also be used internally, e.g. by the fbdev + * emulation, though that's not the case currently. + * + * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd + * for more information as all the semantics and arguments have a one to + * one mapping on this function. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. */ int (*dirty)(struct drm_framebuffer *framebuffer, struct drm_file *file_priv, unsigned flags, @@ -627,7 +659,7 @@ struct drm_crtc_funcs { * @atomic_get_property: * * Reads out the decoded driver-private property. This is used to - * implement the GETCRTC ioctl. + * implement the GETCRTC IOCTL. * * Do not call this function directly, use * drm_atomic_crtc_get_property() instead. @@ -670,7 +702,7 @@ struct drm_crtc_funcs { * @properties: property tracking for this CRTC * @state: current atomic state for this CRTC * @acquire_ctx: per-CRTC implicit acquire context used by atomic drivers for - * legacy ioctls + * legacy IOCTLs * * Each CRTC may have one or more connectors associated with it. This structure * allows the CRTC to be controlled. @@ -724,7 +756,7 @@ struct drm_crtc { struct drm_crtc_state *state; /* - * For legacy crtc ioctls so that atomic drivers can get at the locking + * For legacy crtc IOCTLs so that atomic drivers can get at the locking * acquire context. */ struct drm_modeset_acquire_ctx *acquire_ctx; @@ -968,7 +1000,7 @@ struct drm_connector_funcs { * @atomic_get_property: * * Reads out the decoded driver-private property. This is used to - * implement the GETCONNECTOR ioctl. + * implement the GETCONNECTOR IOCTL. * * Do not call this function directly, use * drm_atomic_connector_get_property() instead. @@ -1269,7 +1301,7 @@ struct drm_plane_funcs { * @disable_plane: * * This is the legacy entry point to disable the plane. The DRM core - * calls this method in response to a DRM_IOCTL_MODE_SETPLANE ioctl call + * calls this method in response to a DRM_IOCTL_MODE_SETPLANE IOCTL call * with the frame buffer ID set to 0. Disabled planes must not be * processed by the CRTC. * @@ -1413,7 +1445,7 @@ struct drm_plane_funcs { * @atomic_get_property: * * Reads out the decoded driver-private property. This is used to - * implement the GETPLANE ioctl. + * implement the GETPLANE IOCTL. * * Do not call this function directly, use * drm_atomic_plane_get_property() instead. @@ -1628,7 +1660,7 @@ struct drm_bridge { * struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device * @allow_modeset: allow full modeset - * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics + * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics * @planes: pointer to array of plane pointers * @plane_states: pointer to array of plane states pointers * @crtcs: pointer to array of CRTC pointers @@ -1716,7 +1748,7 @@ struct drm_mode_config_funcs { * @mutex: mutex protecting KMS related lists and structures * @connection_mutex: ww mutex protecting connector state and routing * @acquire_ctx: global implicit acquire context used by atomic drivers for - * legacy ioctls + * legacy IOCTLs * @idr_mutex: mutex for KMS ID allocation and management * @crtc_idr: main KMS ID tracking object * @fb_lock: mutex to protect fb state and lists -- cgit v1.2.3 From 9953f41799bdad34c367196541a7a9a3b6e13a6c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:02 +0100 Subject: drm: Kerneldoc for drm_mode_config_funcs The meat here is definitely the detailed specs for what atomic_check and atomic_commit are supposed to do. And another candidate for a core vfunc that should be in a helper really (output_poll_changed this time around). v2: Feedback from Eric on irc: - spelling fixes. - spec what async should do - copy the event related paragraphs from page_flip and adjust - make it clear that a successful async commit is not allowed to leave the pipe dead or disabled. v3: Use FIXME comments to annotate functions that we should move to some helpers. v4: Suggestions from Thierry. Cc: Eric Anholt Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-22-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_crtc.h | 243 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 233 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f09391f9cac0..4f587a5bc88f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1715,31 +1715,254 @@ struct drm_mode_set { /** * struct drm_mode_config_funcs - basic driver provided mode setting functions - * @fb_create: create a new framebuffer object - * @output_poll_changed: function to handle output configuration changes - * @atomic_check: check whether a given atomic state update is possible - * @atomic_commit: commit an atomic state update previously verified with - * atomic_check() - * @atomic_state_alloc: allocate a new atomic state - * @atomic_state_clear: clear the atomic state - * @atomic_state_free: free the atomic state * * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that * involve drivers. */ struct drm_mode_config_funcs { + /** + * @fb_create: + * + * Create a new framebuffer object. The core does basic checks on the + * requested metadata, but most of that is left to the driver. See + * struct &drm_mode_fb_cmd2 for details. + * + * RETURNS: + * + * A new framebuffer with an initial reference count of 1 or a negative + * error code encoded with ERR_PTR(). + */ struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd); + + /** + * @output_poll_changed: + * + * Callback used by helpers to inform the driver of output configuration + * changes. + * + * Drivers implementing fbdev emulation with the helpers can call + * drm_fb_helper_hotplug_changed from this hook to inform the fbdev + * helper of output changes. + * + * FIXME: + * + * Except that there's no vtable for device-level helper callbacks + * there's no reason this is a core function. + */ void (*output_poll_changed)(struct drm_device *dev); + /** + * @atomic_check: + * + * This is the only hook to validate an atomic modeset update. This + * function must reject any modeset and state changes which the hardware + * or driver doesn't support. This includes but is of course not limited + * to: + * + * - Checking that the modes, framebuffers, scaling and placement + * requirements and so on are within the limits of the hardware. + * + * - Checking that any hidden shared resources are not oversubscribed. + * This can be shared PLLs, shared lanes, overall memory bandwidth, + * display fifo space (where shared between planes or maybe even + * CRTCs). + * + * - Checking that virtualized resources exported to userspace are not + * oversubscribed. For various reasons it can make sense to expose + * more planes, crtcs or encoders than which are physically there. One + * example is dual-pipe operations (which generally should be hidden + * from userspace if when lockstepped in hardware, exposed otherwise), + * where a plane might need 1 hardware plane (if it's just on one + * pipe), 2 hardware planes (when it spans both pipes) or maybe even + * shared a hardware plane with a 2nd plane (if there's a compatible + * plane requested on the area handled by the other pipe). + * + * - Check that any transitional state is possible and that if + * requested, the update can indeed be done in the vblank period + * without temporarily disabling some functions. + * + * - Check any other constraints the driver or hardware might have. + * + * - This callback also needs to correctly fill out the &drm_crtc_state + * in this update to make sure that drm_atomic_crtc_needs_modeset() + * reflects the nature of the possible update and returns true if and + * only if the update cannot be applied without tearing within one + * vblank on that CRTC. The core uses that information to reject + * updates which require a full modeset (i.e. blanking the screen, or + * at least pausing updates for a substantial amount of time) if + * userspace has disallowed that in its request. + * + * - The driver also does not need to repeat basic input validation + * like done for the corresponding legacy entry points. The core does + * that before calling this hook. + * + * See the documentation of @atomic_commit for an exhaustive list of + * error conditions which don't have to be checked at the + * ->atomic_check() stage? + * + * See the documentation for struct &drm_atomic_state for how exactly + * an atomic modeset update is described. + * + * Drivers using the atomic helpers can implement this hook using + * drm_atomic_helper_check(), or one of the exported sub-functions of + * it. + * + * RETURNS: + * + * 0 on success or one of the below negative error codes: + * + * - -EINVAL, if any of the above constraints are violated. + * + * - -EDEADLK, when returned from an attempt to acquire an additional + * &drm_modeset_lock through drm_modeset_lock(). + * + * - -ENOMEM, if allocating additional state sub-structures failed due + * to lack of memory. + * + * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. + * This can either be due to a pending signal, or because the driver + * needs to completely bail out to recover from an exceptional + * situation like a GPU hang. From a userspace point all errors are + * treated equally. + */ int (*atomic_check)(struct drm_device *dev, - struct drm_atomic_state *a); + struct drm_atomic_state *state); + + /** + * @atomic_commit: + * + * This is the only hook to commit an atomic modeset update. The core + * guarantees that @atomic_check has been called successfully before + * calling this function, and that nothing has been changed in the + * interim. + * + * See the documentation for struct &drm_atomic_state for how exactly + * an atomic modeset update is described. + * + * Drivers using the atomic helpers can implement this hook using + * drm_atomic_helper_commit(), or one of the exported sub-functions of + * it. + * + * Asynchronous commits (as indicated with the async parameter) must + * do any preparatory work which might result in an unsuccessful commit + * in the context of this callback. The only exceptions are hardware + * errors resulting in -EIO. But even in that case the driver must + * ensure that the display pipe is at least running, to avoid + * compositors crashing when pageflips don't work. Anything else, + * specifically committing the update to the hardware, should be done + * without blocking the caller. For updates which do not require a + * modeset this must be guaranteed. + * + * The driver must wait for any pending rendering to the new + * framebuffers to complete before executing the flip. It should also + * wait for any pending rendering from other drivers if the underlying + * buffer is a shared dma-buf. Asynchronous commits must not wait for + * rendering in the context of this callback. + * + * An application can request to be notified when the atomic commit has + * completed. These events are per-CRTC and can be distinguished by the + * CRTC index supplied in &drm_event to userspace. + * + * The drm core will supply a struct &drm_event in the event + * member of each CRTC's &drm_crtc_state structure. This can be handled by the + * drm_crtc_send_vblank_event() function, which the driver should call on + * the provided event upon completion of the atomic commit. Note that if + * the driver supports vblank signalling and timestamping the vblank + * counters and timestamps must agree with the ones returned from page + * flip events. With the current vblank helper infrastructure this can + * be achieved by holding a vblank reference while the page flip is + * pending, acquired through drm_crtc_vblank_get() and released with + * drm_crtc_vblank_put(). Drivers are free to implement their own vblank + * counter and timestamp tracking though, e.g. if they have accurate + * timestamp registers in hardware. + * + * NOTE: + * + * Drivers are not allowed to shut down any display pipe successfully + * enabled through an atomic commit on their own. Doing so can result in + * compositors crashing if a page flip is suddenly rejected because the + * pipe is off. + * + * RETURNS: + * + * 0 on success or one of the below negative error codes: + * + * - -EBUSY, if an asynchronous updated is requested and there is + * an earlier updated pending. Drivers are allowed to support a queue + * of outstanding updates, but currently no driver supports that. + * Note that drivers must wait for preceding updates to complete if a + * synchronous update is requested, they are not allowed to fail the + * commit in that case. + * + * - -ENOMEM, if the driver failed to allocate memory. Specifically + * this can happen when trying to pin framebuffers, which must only + * be done when committing the state. + * + * - -ENOSPC, as a refinement of the more generic -ENOMEM to indicate + * that the driver has run out of vram, iommu space or similar GPU + * address space needed for framebuffer. + * + * - -EIO, if the hardware completely died. + * + * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. + * This can either be due to a pending signal, or because the driver + * needs to completely bail out to recover from an exceptional + * situation like a GPU hang. From a userspace point of view all errors are + * treated equally. + * + * This list is exhaustive. Specifically this hook is not allowed to + * return -EINVAL (any invalid requests should be caught in + * @atomic_check) or -EDEADLK (this function must not acquire + * additional modeset locks). + */ int (*atomic_commit)(struct drm_device *dev, - struct drm_atomic_state *a, + struct drm_atomic_state *state, bool async); + + /** + * @atomic_state_alloc: + * + * This optional hook can be used by drivers that want to subclass struct + * &drm_atomic_state to be able to track their own driver-private global + * state easily. If this hook is implemented, drivers must also + * implement @atomic_state_clear and @atomic_state_free. + * + * RETURNS: + * + * A new &drm_atomic_state on success or NULL on failure. + */ struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev); + + /** + * @atomic_state_clear: + * + * This hook must clear any driver private state duplicated into the + * passed-in &drm_atomic_state. This hook is called when the caller + * encountered a &drm_modeset_lock deadlock and needs to drop all + * already acquired locks as part of the deadlock avoidance dance + * implemented in drm_modeset_lock_backoff(). + * + * Any duplicated state must be invalidated since a concurrent atomic + * update might change it, and the drm atomic interfaces always apply + * updates as relative changes to the current state. + * + * Drivers that implement this must call drm_atomic_state_default_clear() + * to clear common state. + */ void (*atomic_state_clear)(struct drm_atomic_state *state); + + /** + * @atomic_state_free: + * + * This hook needs driver private resources and the &drm_atomic_state + * itself. Note that the core first calls drm_atomic_state_clear() to + * avoid code duplicate between the clear and free hooks. + * + * Drivers that implement this must call drm_atomic_state_default_free() + * to release common resources. + */ void (*atomic_state_free)(struct drm_atomic_state *state); }; -- cgit v1.2.3 From 11a0ba972d55dd21d88b62e918d6cf072c9c67af Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:04 +0100 Subject: drm: Document drm_plane_helper_funcs Plus related hooks used to do atomic plane updates since they only really make sense as a package. v2: Suggestions from Thierry. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-24-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_modeset_helper_vtables.h | 210 +++++++++++++++++++++++++++++-- 1 file changed, 199 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 56dadfe7a181..c77b7dcf343b 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -62,9 +62,6 @@ enum mode_set_atomic; * @load_lut: load color palette * @disable: disable CRTC when no longer in use * @enable: enable CRTC - * @atomic_check: check for validity of an atomic state - * @atomic_begin: begin atomic update - * @atomic_flush: flush atomic update * * The helper operations are called by the mid-layer CRTC helper. * @@ -108,11 +105,96 @@ struct drm_crtc_helper_funcs { void (*disable)(struct drm_crtc *crtc); void (*enable)(struct drm_crtc *crtc); - /* atomic helpers */ + /** + * @atomic_check: + * + * Drivers should check plane-update related CRTC constraints in this + * hook. They can also check mode related limitations but need to be + * aware of the calling order, since this hook is used by + * drm_atomic_helper_check_planes() whereas the preparations needed to + * check output routing and the display mode is done in + * drm_atomic_helper_check_modeset(). Therefore drivers that want to + * check output routing and display mode constraints in this callback + * must ensure that drm_atomic_helper_check_modeset() has been called + * beforehand. This is calling order used by the default helper + * implementation in drm_atomic_helper_check(). + * + * When using drm_atomic_helper_check_planes() CRTCs' ->atomic_check() + * hooks are called after the ones for planes, which allows drivers to + * assign shared resources requested by planes in the CRTC callback + * here. For more complicated dependencies the driver can call the provided + * check helpers multiple times until the computed state has a final + * configuration and everything has been checked. + * + * This function is also allowed to inspect any other object's state and + * can add more state objects to the atomic commit if needed. Care must + * be taken though to ensure that state check&compute functions for + * these added states are all called, and derived state in other objects + * 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. + * + * 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. + * + * RETURNS: + * + * 0 on success, -EINVAL if the state or the transition can't be + * supported, -ENOMEM on memory allocation failure and -EDEADLK if an + * attempt to obtain another state object ran into a &drm_modeset_lock + * deadlock. + */ int (*atomic_check)(struct drm_crtc *crtc, struct drm_crtc_state *state); + + /** + * @atomic_begin: + * + * Drivers should prepare for an atomic update of multiple planes on + * a CRTC in this hook. Depending upon hardware this might be vblank + * evasion, blocking updates by setting bits or doing preparatory work + * for e.g. manual update display. + * + * This hook is called before any plane commit functions are called. + * + * 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_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. + */ void (*atomic_begin)(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state); + /** + * @atomic_flush: + * + * Drivers should finalize an atomic update of multiple planes on + * a CRTC in this hook. Depending upon hardware this might include + * checking that vblank evasion was successful, unblocking updates by + * setting bits or setting the GO bit to flush out all updates. + * + * Simple hardware or hardware with special requirements can commit and + * flush out all updates for all planes from this hook and forgo all the + * other commit hooks for plane updates. + * + * This hook is called after any plane commit functions are called. + * + * 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_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. + */ void (*atomic_flush)(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state); }; @@ -216,25 +298,131 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, } /** - * struct drm_plane_helper_funcs - helper operations for CRTCs - * @prepare_fb: prepare a framebuffer for use by the plane - * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane - * @atomic_check: check that a given atomic state is valid and can be applied - * @atomic_update: apply an atomic state to the plane (mandatory) - * @atomic_disable: disable the plane + * struct drm_plane_helper_funcs - helper operations for planes * - * The helper operations are called by the mid-layer CRTC helper. + * These functions are used by the atomic helpers and by the transitional plane + * 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 + * 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 + * &drm_plane_state. If the driver doesn't support native fences then + * equivalent functionality should be implemented through private + * members in the plane structure. + * + * 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. + * + * RETURNS: + * + * 0 on success or one of the following negative error codes allowed by + * the atomic_commit hook in &drm_mode_config_funcs. When using helpers + * this callback is the only one which can fail an atomic commit, + * everything else must complete successfully. + */ int (*prepare_fb)(struct drm_plane *plane, const struct drm_plane_state *new_state); + /** + * @cleanup_fb: + * + * 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. + */ void (*cleanup_fb)(struct drm_plane *plane, const struct drm_plane_state *old_state); + /** + * @atomic_check: + * + * Drivers should check plane specific constraints in this hook. + * + * When using drm_atomic_helper_check_planes() plane's ->atomic_check() + * hooks are called before the ones for CRTCs, which allows drivers to + * request shared resources that the CRTC controls here. For more + * complicated dependencies the driver can call the provided check helpers + * multiple times until the computed state has a final configuration and + * everything has been checked. + * + * This function is also allowed to inspect any other object's state and + * can add more state objects to the atomic commit if needed. Care must + * be taken though to ensure that state check&compute functions for + * these added states are all called, and derived state in other objects + * 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. + * + * 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. + * + * RETURNS: + * + * 0 on success, -EINVAL if the state or the transition can't be + * supported, -ENOMEM on memory allocation failure and -EDEADLK if an + * attempt to obtain another state object ran into a &drm_modeset_lock + * deadlock. + */ int (*atomic_check)(struct drm_plane *plane, struct drm_plane_state *state); + + /** + * @atomic_update: + * + * Drivers should use this function to update the plane state. This + * hook is called in-between the ->atomic_begin() and + * ->atomic_flush() of &drm_crtc_helper_funcs. + * + * 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_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. + */ void (*atomic_update)(struct drm_plane *plane, struct drm_plane_state *old_state); + /** + * @atomic_disable: + * + * Drivers should use this function to unconditionally disable a plane. + * This hook is called in-between the ->atomic_begin() and + * ->atomic_flush() of &drm_crtc_helper_funcs. It is an alternative to + * @atomic_update, which will be called for disabling planes, too, if + * the @atomic_disable hook isn't implemented. + * + * This hook is also useful to disable planes in preparation of a modeset, + * by calling drm_atomic_helper_disable_planes_on_crtc() from the + * ->disable() hook in &drm_crtc_helper_funcs. + * + * 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_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. + */ void (*atomic_disable)(struct drm_plane *plane, struct drm_plane_state *old_state); }; -- cgit v1.2.3 From 4ee6034c80c50b6e788f0f4291c3ad64debde390 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:05 +0100 Subject: drm: Document drm_connector_helper_funcs Nothing special, except the somewhat awkward split in probe helper callbacks between here and drm_crtc_funcs. v2: Suggestions from Thierry. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-25-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_modeset_helper_vtables.h | 106 +++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index c77b7dcf343b..4b3869bd49b5 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -270,18 +270,114 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder, /** * struct drm_connector_helper_funcs - helper operations for connectors - * @get_modes: get mode list for this connector - * @mode_valid: is this mode valid on the given connector? (optional) - * @best_encoder: return the preferred encoder for this connector - * @atomic_best_encoder: atomic version of @best_encoder * - * The helper operations are called by the mid-layer CRTC helper. + * These functions are used by the atomic and legacy modeset helpers and by the + * probe helpers. */ struct drm_connector_helper_funcs { + /** + * @get_modes: + * + * This function should fill in all modes currently valid for the sink + * into the connector->probed_modes list. It should also update the + * EDID property by calling drm_mode_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 + * fixed panel can also manually add specific modes using + * drm_mode_probed_add(). 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. + * + * This callback is used by the probe helpers in e.g. + * drm_helper_probe_single_connector_modes(). + * + * RETURNS: + * + * The number of modes added by calling drm_mode_probed_add(). + */ int (*get_modes)(struct drm_connector *connector); + + /** + * @mode_valid: + * + * 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(). + * + * NOTE: + * + * This only filters the mode list supplied to userspace in the + * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and + * ask the kernel to use them. It this case the atomic helpers or legacy + * CRTC helpers will not call this function. Drivers therefore must + * still fully validate any mode passed in in a modeset request. + * + * RETURNS: + * + * Either MODE_OK or one of the failure reasons in enum + * &drm_mode_status. + */ enum drm_mode_status (*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode); + /** + * @best_encoder: + * + * This function should select the best encoder for the given connector. + * + * This function is used by both the atomic helpers (in the + * drm_atomic_helper_check_modeset() function) and in the legacy CRTC + * helpers. + * + * NOTE: + * + * In atomic drivers this function is called in the check phase of an + * atomic update. The driver is not allowed to change or inspect + * anything outside of arguments passed-in. Atomic drivers which need to + * inspect dynamic configuration state should instead use + * @atomic_best_encoder. + * + * RETURNS: + * + * Encoder that should be used for the given connector and connector + * state, or NULL if no suitable encoder exists. Note that the helpers + * will ensure that encoders aren't used twice, drivers should not check + * for this. + */ struct drm_encoder *(*best_encoder)(struct drm_connector *connector); + + /** + * @atomic_best_encoder: + * + * This is the atomic version of @best_encoder for atomic drivers which + * need to select the best encoder depending upon the desired + * configuration and can't select it statically. + * + * This function is used by drm_atomic_helper_check_modeset() and either + * this or @best_encoder is required. + * + * 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. + * + * RETURNS: + * + * Encoder that should be used for the given connector and connector + * state, or NULL if no suitable encoder exists. Note that the helpers + * will ensure that encoders aren't used twice, drivers should not check + * for this. + */ struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, struct drm_connector_state *connector_state); }; -- cgit v1.2.3 From 30ecad77fe849b60c9a1f8df24dca50e3f083d41 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 9 Dec 2015 09:29:36 +0100 Subject: drm: Move drm_display_mode an related docs into kerneldoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was in the documentation for modeset helper hooks, where it is a bit misplaced. v2: Reindent the drm_mode_status enum, inspired by Ville. v3: Suggestions from Ville and Thierry. v4: Small fixup that 0day spotted. v5: Slight change to avoid accidental headings in kerneldoc output. Cc: ville.syrjala@linux.intel.com Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-27-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Ville Syrjälä (v3) Reviewed-by: Thierry Reding (v3) --- include/drm/drm_modes.h | 343 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 296 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index f9115aee43f4..9e6d7a1cd19b 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -35,46 +35,91 @@ * structures). */ +/** + * enum drm_mode_status - hardware support status of a mode + * @MODE_OK: Mode OK + * @MODE_HSYNC: hsync out of range + * @MODE_VSYNC: vsync out of range + * @MODE_H_ILLEGAL: mode has illegal horizontal timings + * @MODE_V_ILLEGAL: mode has illegal horizontal timings + * @MODE_BAD_WIDTH: requires an unsupported linepitch + * @MODE_NOMODE: no mode with a matching name + * @MODE_NO_INTERLACE: interlaced mode not supported + * @MODE_NO_DBLESCAN: doublescan mode not supported + * @MODE_NO_VSCAN: multiscan mode not supported + * @MODE_MEM: insufficient video memory + * @MODE_VIRTUAL_X: mode width too large for specified virtual size + * @MODE_VIRTUAL_Y: mode height too large for specified virtual size + * @MODE_MEM_VIRT: insufficient video memory given virtual size + * @MODE_NOCLOCK: no fixed clock available + * @MODE_CLOCK_HIGH: clock required is too high + * @MODE_CLOCK_LOW: clock required is too low + * @MODE_CLOCK_RANGE: clock/mode isn't in a ClockRange + * @MODE_BAD_HVALUE: horizontal timing was out of range + * @MODE_BAD_VVALUE: vertical timing was out of range + * @MODE_BAD_VSCAN: VScan value out of range + * @MODE_HSYNC_NARROW: horizontal sync too narrow + * @MODE_HSYNC_WIDE: horizontal sync too wide + * @MODE_HBLANK_NARROW: horizontal blanking too narrow + * @MODE_HBLANK_WIDE: horizontal blanking too wide + * @MODE_VSYNC_NARROW: vertical sync too narrow + * @MODE_VSYNC_WIDE: vertical sync too wide + * @MODE_VBLANK_NARROW: vertical blanking too narrow + * @MODE_VBLANK_WIDE: vertical blanking too wide + * @MODE_PANEL: exceeds panel dimensions + * @MODE_INTERLACE_WIDTH: width too large for interlaced mode + * @MODE_ONE_WIDTH: only one width is supported + * @MODE_ONE_HEIGHT: only one height is supported + * @MODE_ONE_SIZE: only one resolution is supported + * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking + * @MODE_NO_STEREO: stereo modes not supported + * @MODE_UNVERIFIED: mode needs to reverified + * @MODE_BAD: unspecified reason + * @MODE_ERROR: error condition + * + * This enum is used to filter out modes not supported by the driver/hardware + * combination. + */ enum drm_mode_status { - MODE_OK = 0, /* Mode OK */ - MODE_HSYNC, /* hsync out of range */ - MODE_VSYNC, /* vsync out of range */ - MODE_H_ILLEGAL, /* mode has illegal horizontal timings */ - MODE_V_ILLEGAL, /* mode has illegal horizontal timings */ - MODE_BAD_WIDTH, /* requires an unsupported linepitch */ - MODE_NOMODE, /* no mode with a matching name */ - MODE_NO_INTERLACE, /* interlaced mode not supported */ - MODE_NO_DBLESCAN, /* doublescan mode not supported */ - MODE_NO_VSCAN, /* multiscan mode not supported */ - MODE_MEM, /* insufficient video memory */ - MODE_VIRTUAL_X, /* mode width too large for specified virtual size */ - MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */ - MODE_MEM_VIRT, /* insufficient video memory given virtual size */ - MODE_NOCLOCK, /* no fixed clock available */ - MODE_CLOCK_HIGH, /* clock required is too high */ - MODE_CLOCK_LOW, /* clock required is too low */ - MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */ - MODE_BAD_HVALUE, /* horizontal timing was out of range */ - MODE_BAD_VVALUE, /* vertical timing was out of range */ - MODE_BAD_VSCAN, /* VScan value out of range */ - MODE_HSYNC_NARROW, /* horizontal sync too narrow */ - MODE_HSYNC_WIDE, /* horizontal sync too wide */ - MODE_HBLANK_NARROW, /* horizontal blanking too narrow */ - MODE_HBLANK_WIDE, /* horizontal blanking too wide */ - MODE_VSYNC_NARROW, /* vertical sync too narrow */ - MODE_VSYNC_WIDE, /* vertical sync too wide */ - MODE_VBLANK_NARROW, /* vertical blanking too narrow */ - MODE_VBLANK_WIDE, /* vertical blanking too wide */ - MODE_PANEL, /* exceeds panel dimensions */ - MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ - MODE_ONE_WIDTH, /* only one width is supported */ - MODE_ONE_HEIGHT, /* only one height is supported */ - MODE_ONE_SIZE, /* only one resolution is supported */ - MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ - MODE_NO_STEREO, /* stereo modes not supported */ - MODE_UNVERIFIED = -3, /* mode needs to reverified */ - MODE_BAD = -2, /* unspecified reason */ - MODE_ERROR = -1 /* error condition */ + MODE_OK = 0, + MODE_HSYNC, + MODE_VSYNC, + MODE_H_ILLEGAL, + MODE_V_ILLEGAL, + MODE_BAD_WIDTH, + MODE_NOMODE, + MODE_NO_INTERLACE, + MODE_NO_DBLESCAN, + MODE_NO_VSCAN, + MODE_MEM, + MODE_VIRTUAL_X, + MODE_VIRTUAL_Y, + MODE_MEM_VIRT, + MODE_NOCLOCK, + MODE_CLOCK_HIGH, + MODE_CLOCK_LOW, + MODE_CLOCK_RANGE, + MODE_BAD_HVALUE, + MODE_BAD_VVALUE, + MODE_BAD_VSCAN, + MODE_HSYNC_NARROW, + MODE_HSYNC_WIDE, + MODE_HBLANK_NARROW, + MODE_HBLANK_WIDE, + MODE_VSYNC_NARROW, + MODE_VSYNC_WIDE, + MODE_VBLANK_NARROW, + MODE_VBLANK_WIDE, + MODE_PANEL, + MODE_INTERLACE_WIDTH, + MODE_ONE_WIDTH, + MODE_ONE_HEIGHT, + MODE_ONE_SIZE, + MODE_NO_REDUCED, + MODE_NO_STEREO, + MODE_UNVERIFIED = -3, + MODE_BAD = -2, + MODE_ERROR = -1 }; #define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ @@ -96,17 +141,125 @@ enum drm_mode_status { #define DRM_MODE_FLAG_3D_MAX DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF +/** + * struct drm_display_mode - DRM kernel-internal display mode structure + * @hdisplay: horizontal display size + * @hsync_start: horizontal sync start + * @hsync_end: horizontal sync end + * @htotal: horizontal total size + * @hskew: horizontal skew?! + * @vdisplay: vertical display size + * @vsync_start: vertical sync start + * @vsync_end: vertical sync end + * @vtotal: vertical total size + * @vscan: vertical scan?! + * @crtc_hdisplay: hardware mode horizontal display size + * @crtc_hblank_start: hardware mode horizontal blank start + * @crtc_hblank_end: hardware mode horizontal blank end + * @crtc_hsync_start: hardware mode horizontal sync start + * @crtc_hsync_end: hardware mode horizontal sync end + * @crtc_htotal: hardware mode horizontal total size + * @crtc_hskew: hardware mode horizontal skew?! + * @crtc_vdisplay: hardware mode vertical display size + * @crtc_vblank_start: hardware mode vertical blank start + * @crtc_vblank_end: hardware mode vertical blank end + * @crtc_vsync_start: hardware mode vertical sync start + * @crtc_vsync_end: hardware mode vertical sync end + * @crtc_vtotal: hardware mode vertical total size + * + * The horizontal and vertical timings are defined per the following diagram. + * + * + * Active Front Sync Back + * Region Porch Porch + * <-----------------------><----------------><-------------><--------------> + * //////////////////////| + * ////////////////////// | + * ////////////////////// |.................. ................ + * _______________ + * <----- [hv]display -----> + * <------------- [hv]sync_start ------------> + * <--------------------- [hv]sync_end ---------------------> + * <-------------------------------- [hv]total ----------------------------->* + * + * This structure contains two copies of timings. First are the plain timings, + * which specify the logical mode, as it would be for a progressive 1:1 scanout + * at the refresh rate userspace can observe through vblank timestamps. Then + * there's the hardware timings, which are corrected for interlacing, + * double-clocking and similar things. They are provided as a convenience, and + * can be appropriately computed using drm_mode_set_crtcinfo(). + */ struct drm_display_mode { - /* Header */ + /** + * @head: + * + * struct list_head for mode lists. + */ struct list_head head; + + /** + * @base: + * + * A display mode is a normal modeset object, possibly including public + * userspace id. + * + * FIXME: + * + * This can probably be removed since the entire concept of userspace + * managing modes explicitly has never landed in upstream kernel mode + * setting support. + */ struct drm_mode_object base; + /** + * @name: + * + * Human-readable name of the mode, filled out with drm_mode_set_name(). + */ char name[DRM_DISPLAY_MODE_LEN]; + /** + * @status: + * + * Status of the mode, used to filter out modes not supported by the + * hardware. See enum &drm_mode_status. + */ enum drm_mode_status status; + + /** + * @type: + * + * A bitmask of flags, mostly about the source of a mode. Possible flags + * are: + * + * - DRM_MODE_TYPE_BUILTIN: Meant for hard-coded modes, effectively + * unused. + * - DRM_MODE_TYPE_PREFERRED: Preferred mode, usually the native + * resolution of an LCD panel. There should only be one preferred + * mode per connector at any given time. + * - DRM_MODE_TYPE_DRIVER: Mode created by the driver, which is all of + * them really. Drivers must set this bit for all modes they create + * and expose to userspace. + * + * Plus a big list of flags which shouldn't be used at all, but are + * still around since these flags are also used in the userspace ABI: + * + * - DRM_MODE_TYPE_DEFAULT: Again a leftover, use + * DRM_MODE_TYPE_PREFERRED instead. + * - DRM_MODE_TYPE_CLOCK_C and DRM_MODE_TYPE_CRTC_C: Define leftovers + * which are stuck around for hysterical raisins only. No one has an + * idea what they were meant for. Don't use. + * - DRM_MODE_TYPE_USERDEF: Mode defined by userspace, again a vestige + * from older kms designs where userspace had to first add a custom + * mode to the kernel's mode list before it could use it. Don't use. + */ unsigned int type; - /* Proposed mode values */ + /** + * @clock: + * + * Pixel clock in kHz. + */ int clock; /* in kHz */ int hdisplay; int hsync_start; @@ -118,14 +271,74 @@ struct drm_display_mode { int vsync_end; int vtotal; int vscan; + /** + * @flags: + * + * Sync and timing flags: + * + * - DRM_MODE_FLAG_PHSYNC: horizontal sync is active high. + * - DRM_MODE_FLAG_NHSYNC: horizontal sync is active low. + * - DRM_MODE_FLAG_PVSYNC: vertical sync is active high. + * - DRM_MODE_FLAG_NVSYNC: vertical sync is active low. + * - DRM_MODE_FLAG_INTERLACE: mode is interlaced. + * - DRM_MODE_FLAG_DBLSCAN: mode uses doublescan. + * - DRM_MODE_FLAG_CSYNC: mode uses composite sync. + * - DRM_MODE_FLAG_PCSYNC: composite sync is active high. + * - DRM_MODE_FLAG_NCSYNC: composite sync is active low. + * - DRM_MODE_FLAG_HSKEW: hskew provided (not used?). + * - DRM_MODE_FLAG_BCAST: not used? + * - DRM_MODE_FLAG_PIXMUX: not used? + * - DRM_MODE_FLAG_DBLCLK: double-clocked mode. + * - DRM_MODE_FLAG_CLKDIV2: half-clocked mode. + * + * Additionally there's flags to specify how 3D modes are packed: + * + * - DRM_MODE_FLAG_3D_NONE: normal, non-3D mode. + * - DRM_MODE_FLAG_3D_FRAME_PACKING: 2 full frames for left and right. + * - DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE: interleaved like fields. + * - DRM_MODE_FLAG_3D_LINE_ALTERNATIVE: interleaved lines. + * - DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL: side-by-side full frames. + * - DRM_MODE_FLAG_3D_L_DEPTH: ? + * - DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH: ? + * - DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: frame split into top and bottom + * parts. + * - DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: frame split into left and + * right parts. + */ unsigned int flags; - /* Addressable image size (may be 0 for projectors, etc.) */ + /** + * @width_mm: + * + * Addressable size of the output in mm, projectors should set this to + * 0. + */ int width_mm; + + /** + * @height_mm: + * + * Addressable size of the output in mm, projectors should set this to + * 0. + */ int height_mm; - /* Actual mode we give to hw */ - int crtc_clock; /* in KHz */ + /** + * @crtc_clock: + * + * Actual pixel or dot clock in the hardware. This differs from the + * logical @clock when e.g. using interlacing, double-clocking, stereo + * modes or other fancy stuff that changes the timings and signals + * actually sent over the wire. + * + * This is again in kHz. + * + * Note that with digital outputs like HDMI or DP there's usually a + * massive confusion between the dot clock and the signal clock at the + * bit encoding level. Especially when a 8b/10b encoding is used and the + * difference is exactly a factor of 10. + */ + int crtc_clock; int crtc_hdisplay; int crtc_hblank_start; int crtc_hblank_end; @@ -140,12 +353,48 @@ struct drm_display_mode { int crtc_vsync_end; int crtc_vtotal; - /* Driver private mode info */ + /** + * @private: + * + * Pointer for driver private data. This can only be used for mode + * objects passed to drivers in modeset operations. It shouldn't be used + * by atomic drivers since they can store any additional data by + * subclassing state structures. + */ int *private; + + /** + * @private_flags: + * + * Similar to @private, but just an integer. + */ int private_flags; - int vrefresh; /* in Hz */ - int hsync; /* in kHz */ + /** + * @vrefresh: + * + * Vertical refresh rate, for debug output in human readable form. Not + * used in a functional way. + * + * This value is in Hz. + */ + int vrefresh; + + /** + * @hsync: + * + * Horizontal refresh rate, for debug output in human readable form. Not + * used in a functional way. + * + * This value is in kHz. + */ + int hsync; + + /** + * @picture_aspect_ratio: + * + * Field for setting the HDMI picture aspect ratio of a mode. + */ enum hdmi_picture_aspect picture_aspect_ratio; }; -- cgit v1.2.3 From 36b66080dc66ab08ff6c36237147638e2d060874 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 4 Dec 2015 09:46:08 +0100 Subject: drm: Document drm_encoder/crtc_helper_funcs Mostly this is about all the callbacks used for modesets by both legacy CRTC helpers and atomic helpers and I figured it doesn't make all that much sense to split this up. v2: Suggestions from Thierry. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449218769-16577-28-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Thierry Reding --- include/drm/drm_modeset_helper_vtables.h | 449 +++++++++++++++++++++++++++---- 1 file changed, 401 insertions(+), 48 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 4b3869bd49b5..29e0dc50031d 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -51,58 +51,236 @@ enum mode_set_atomic; /** * struct drm_crtc_helper_funcs - helper operations for CRTCs - * @dpms: set power state - * @prepare: prepare the CRTC, called before @mode_set - * @commit: commit changes to CRTC, called after @mode_set - * @mode_fixup: try to fixup proposed mode for this CRTC - * @mode_set: set this mode - * @mode_set_nofb: set mode only (no scanout buffer attached) - * @mode_set_base: update the scanout buffer - * @mode_set_base_atomic: non-blocking mode set (used for kgdb support) - * @load_lut: load color palette - * @disable: disable CRTC when no longer in use - * @enable: enable CRTC * - * The helper operations are called by the mid-layer CRTC helper. - * - * Note that with atomic helpers @dpms, @prepare and @commit hooks are - * deprecated. Used @enable and @disable instead exclusively. - * - * With legacy crtc helpers there's a big semantic difference between @disable - * and the other hooks: @disable also needs to release any resources acquired in - * @mode_set (like shared PLLs). + * These hooks are used by the legacy CRTC helpers, the transitional plane + * helpers and the new atomic modesetting helpers. */ struct drm_crtc_helper_funcs { - /* - * Control power levels on the CRTC. If the mode passed in is - * unsupported, the provider must use the next lowest power level. + /** + * @dpms: + * + * Callback to control power levels on the CRTC. If the mode passed in + * is unsupported, the provider must use the next lowest power level. + * This is used by the legacy CRTC helpers to implement DPMS + * functionality in drm_helper_connector_dpms(). + * + * This callback is also used to disable a CRTC by calling it with + * DRM_MODE_DPMS_OFF if the @disable hook isn't used. + * + * 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. */ void (*dpms)(struct drm_crtc *crtc, int mode); + + /** + * @prepare: + * + * This callback should prepare the CRTC for a subsequent modeset, which + * in practice means the driver should disable the CRTC if it is + * running. Most drivers ended up implementing this by calling their + * @dpms hook with DRM_MODE_DPMS_OFF. + * + * 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. + */ void (*prepare)(struct drm_crtc *crtc); + + /** + * @commit: + * + * This callback should commit the new mode on the CRTC after a modeset, + * which in practice means the driver should enable the CRTC. Most + * drivers ended up implementing this by calling their @dpms hook with + * DRM_MODE_DPMS_ON. + * + * 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. + */ void (*commit)(struct drm_crtc *crtc); - /* Provider can fixup or change mode timings before modeset occurs */ + /** + * @mode_fixup: + * + * This callback is used to validate a mode. The parameter mode is the + * display mode that userspace requested, adjusted_mode is the mode the + * encoders need to be fed with. Note that this is the inverse semantics + * of the meaning for the &drm_encoder and &drm_bridge + * ->mode_fixup() functions. If the CRTC cannot support the requested + * conversion from mode to adjusted_mode it should reject the modeset. + * + * This function is used by both legacy CRTC helpers and atomic helpers. + * With atomic helpers it is optional. + * + * NOTE: + * + * This function is called in the check phase of atomic modesets, which + * can be aborted for any reason (including on userspace's request to + * just check whether a configuration would be possible). Atomic drivers + * MUST NOT touch any persistent state (hardware or software) or data + * structures except the passed in adjusted_mode parameter. + * + * This is in contrast to the legacy CRTC helpers where this was + * allowed. + * + * Atomic drivers which need to inspect and adjust more state should + * instead use the @atomic_check callback. + * + * RETURNS: + * + * True if an acceptable configuration is possible, false if the modeset + * operation should be rejected. + */ bool (*mode_fixup)(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); - /* Actually set the mode */ + + /** + * @mode_set: + * + * This callback is used by the legacy CRTC helpers to set a new mode, + * position and framebuffer. Since it ties the primary plane to every + * mode change it is incompatible with universal plane support. And + * since it can't update other planes it's incompatible with atomic + * modeset support. + * + * This callback is only used by CRTC helpers and deprecated. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb); - /* Actually set the mode for atomic helpers, optional */ + + /** + * @mode_set_nofb: + * + * 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(). + * + * Note that the display pipe is completely off when this function is + * called. Atomic drivers which need hardware to be running before they + * program the new display mode (e.g. because they implement runtime PM) + * should not use this hook. This is because the helper library calls + * this hook only once per mode change and not every time the display + * 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. + * + * This callback is optional. + */ void (*mode_set_nofb)(struct drm_crtc *crtc); - /* Move the crtc on the current fb to the given position *optional* */ + /** + * @mode_set_base: + * + * This callback is used by the legacy CRTC helpers to set a new + * framebuffer and scanout position. It is optional and used as an + * optimized fast-path instead of a full mode set operation with all the + * resulting flickering. Since it can't update other planes it's + * incompatible with atomic modeset support. + * + * This callback is only used by the CRTC helpers and deprecated. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); + + /** + * @mode_set_base_atomic: + * + * This callback is used by the fbdev helpers to set a new framebuffer + * and scanout without sleeping, i.e. from an atomic calling context. It + * is only used to implement kgdb support. + * + * This callback is optional and only needed for kgdb support in the fbdev + * helpers. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ int (*mode_set_base_atomic)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, enum mode_set_atomic); - /* reload the current crtc LUT */ + /** + * @load_lut: + * + * Load a LUT prepared with the @gamma_set functions from + * &drm_fb_helper_funcs. + * + * 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 + * drivers it is called after all encoders connected to this CRTC have + * been shut off already using their own ->disable 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 both by legacy CRTC helpers and atomic helpers. + * 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. + * + * NOTE: + * + * With legacy CRTC helpers there's a big semantic difference between + * @disable and other hooks (like @prepare or @dpms) used to shut down a + * CRTC: @disable is only called when also logically disabling the + * display pipeline and needs to release any resources acquired in + * @mode_set (like shared PLLs, or again release pinned framebuffers). + * + * Therefore @disable must be the inverse of @mode_set plus @commit for + * drivers still using legacy CRTC helpers, which is different from the + * rules under atomic. + */ 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 ->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); /** @@ -212,53 +390,228 @@ static inline void drm_crtc_helper_add(struct drm_crtc *crtc, /** * struct drm_encoder_helper_funcs - helper operations for encoders - * @dpms: set power state - * @mode_fixup: try to fixup proposed mode for this connector - * @prepare: part of the disable sequence, called before the CRTC modeset - * @commit: called after the CRTC modeset - * @mode_set: set this mode, optional for atomic helpers - * @get_crtc: return CRTC that the encoder is currently attached to - * @detect: connection status detection - * @disable: disable encoder when not in use (overrides DPMS off) - * @enable: enable encoder - * @atomic_check: check for validity of an atomic update - * - * The helper operations are called by the mid-layer CRTC helper. * - * Note that with atomic helpers @dpms, @prepare and @commit hooks are - * deprecated. Used @enable and @disable instead exclusively. - * - * With legacy crtc helpers there's a big semantic difference between @disable - * and the other hooks: @disable also needs to release any resources acquired in - * @mode_set (like shared PLLs). + * These hooks are used by the legacy CRTC helpers, the transitional plane + * helpers and the new atomic modesetting helpers. */ struct drm_encoder_helper_funcs { + /** + * @dpms: + * + * Callback to control power levels on the encoder. If the mode passed in + * is unsupported, the provider must use the next lowest power level. + * This is used by the legacy encoder helpers to implement DPMS + * functionality in drm_helper_connector_dpms(). + * + * This callback is also used to disable an encoder by calling it with + * DRM_MODE_DPMS_OFF if the @disable hook isn't used. + * + * This callback is used by the legacy CRTC helpers. Atomic helpers + * also support using this hook for enabling and disabling an encoder to + * facilitate transitions to atomic, but it is deprecated. Instead + * @enable and @disable should be used. + */ void (*dpms)(struct drm_encoder *encoder, int mode); + /** + * @mode_fixup: + * + * This callback is used to validate and adjust a mode. The parameter + * mode is the display mode that should be fed to the next element in + * the display chain, either the final &drm_connector or a &drm_bridge. + * The parameter adjusted_mode is the input mode the encoder requires. It + * can be modified by this callback and does not need to match mode. + * + * This function is used by both legacy CRTC helpers and atomic helpers. + * With atomic helpers it is optional. + * + * NOTE: + * + * This function is called in the check phase of atomic modesets, which + * can be aborted for any reason (including on userspace's request to + * just check whether a configuration would be possible). Atomic drivers + * MUST NOT touch any persistent state (hardware or software) or data + * structures except the passed in adjusted_mode parameter. + * + * This is in contrast to the legacy CRTC helpers where this was + * allowed. + * + * Atomic drivers which need to inspect and adjust more state should + * instead use the @atomic_check callback. + * + * RETURNS: + * + * True if an acceptable configuration is possible, false if the modeset + * operation should be rejected. + */ bool (*mode_fixup)(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); + + /** + * @prepare: + * + * This callback should prepare the encoder for a subsequent modeset, + * which in practice means the driver should disable the encoder if it + * is running. Most drivers ended up implementing this by calling their + * @dpms hook with DRM_MODE_DPMS_OFF. + * + * This callback is used by the legacy CRTC helpers. Atomic helpers + * also support using this hook for disabling an encoder to facilitate + * transitions to atomic, but it is deprecated. Instead @disable should + * be used. + */ void (*prepare)(struct drm_encoder *encoder); + + /** + * @commit: + * + * This callback should commit the new mode on the encoder after a modeset, + * which in practice means the driver should enable the encoder. Most + * drivers ended up implementing this by calling their @dpms hook with + * DRM_MODE_DPMS_ON. + * + * This callback is used by the legacy CRTC helpers. Atomic helpers + * also support using this hook for enabling an encoder to facilitate + * transitions to atomic, but it is deprecated. Instead @enable should + * be used. + */ void (*commit)(struct drm_encoder *encoder); + + /** + * @mode_set: + * + * This callback is used to update the display mode of an encoder. + * + * Note that the display pipe is completely off when this function is + * called. Drivers which need hardware to be running before they program + * the new display mode (because they implement runtime PM) should not + * use this hook, because the helper library calls it only once and not + * every time the display pipeline is suspend using either DPMS or the + * new "ACTIVE" property. Such drivers should instead move all their + * encoder setup into the ->enable() callback. + * + * This callback is used both by the legacy CRTC helpers and the atomic + * modeset helpers. It is optional in the atomic helpers. + */ void (*mode_set)(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); + + /** + * @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 for DAC style encoders */ + + /** + * @detect: + * + * This callback can be used by drivers who want to do detection on the + * encoder object instead of in connector functions. + * + * It is not used by any helper and therefore has purely driver-specific + * semantics. New drivers shouldn't use this and instead just implement + * their own private callbacks. + * + * FIXME: + * + * This should just be converted into a pile of driver vfuncs. + * Currently radeon, amdgpu and nouveau are using it. + */ enum drm_connector_status (*detect)(struct drm_encoder *encoder, struct drm_connector *connector); + + /** + * @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 the CRTC's own ->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 hook is used both by legacy CRTC helpers and 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 + * @disable must be the inverse of @enable for atomic drivers. + * + * NOTE: + * + * With legacy CRTC helpers there's a big semantic difference between + * @disable and other hooks (like @prepare or @dpms) used to shut down a + * encoder: @disable is only called when also logically disabling the + * display pipeline and needs to release any resources acquired in + * @mode_set (like shared PLLs, or again release pinned framebuffers). + * + * Therefore @disable must be the inverse of @mode_set plus @commit for + * drivers still using legacy CRTC helpers, which is different from the + * rules under atomic. + */ void (*disable)(struct drm_encoder *encoder); + /** + * @enable: + * + * This callback should be used to enable the encoder. With the atomic + * drivers it is called after this encoder's CRTC has been enabled using + * the CRTC's own ->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 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. + */ void (*enable)(struct drm_encoder *encoder); - /* atomic helpers */ + /** + * @atomic_check: + * + * This callback is used to validate encoder state for atomic drivers. + * Since the encoder is the object connecting the CRTC and connector it + * gets passed both states, to be able to validate interactions and + * update the CRTC to match what the encoder needs for the requested + * connector. + * + * This function is used by the atomic 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. + * + * RETURNS: + * + * 0 on success, -EINVAL if the state or the transition can't be + * supported, -ENOMEM on memory allocation failure and -EDEADLK if an + * attempt to obtain another state object ran into a &drm_modeset_lock + * deadlock. + */ int (*atomic_check)(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); }; /** - * drm_encoder_helper_add - sets the helper vtable for a encoder + * drm_encoder_helper_add - sets the helper vtable for an encoder * @encoder: DRM encoder * @funcs: helper vtable to set for @encoder */ -- cgit v1.2.3 From f98828769c8838f526703ef180b3088a714af2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Dec 2015 16:19:31 +0200 Subject: drm: Pass 'name' to drm_crtc_init_with_planes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done with coccinelle for the most part. However, it thinks '...' is part of the semantic patch, so I put an 'int DOTDOTDOT' placeholder in its place and got rid of it with sed afterwards. I didn't convert drm_crtc_init() since passing the varargs through would mean either cpp macros or va_list, and I figured we don't care about these legacy functions enough to warrant the extra pain. @@ identifier dev, crtc, primary, cursor, funcs; @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs + ,const char *name, int DOTDOTDOT ) { ... } @@ identifier dev, crtc, primary, cursor, funcs; @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs + ,const char *name, int DOTDOTDOT ); @@ expression E1, E2, E3, E4, E5; @@ drm_crtc_init_with_planes(E1, E2, E3, E4, E5 + ,NULL ) v2: Split crtc and plane changes apart Pass NULL for no-name instead of "" Leave drm_crtc_init() alone v3: Add ', or NULL...' to @name kernel doc (Jani) Annotate the function with __printf() attribute (Jani) Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449670771-2751-1-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_crtc.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4f587a5bc88f..f0127e7b0ee2 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2144,11 +2144,13 @@ struct drm_prop_enum_list { char *name; }; -extern int drm_crtc_init_with_planes(struct drm_device *dev, - struct drm_crtc *crtc, - struct drm_plane *primary, - struct drm_plane *cursor, - const struct drm_crtc_funcs *funcs); +extern __printf(6, 7) +int drm_crtc_init_with_planes(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const char *name, ...); extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc); -- cgit v1.2.3 From b0b3b7951114315d65398c27648705ca1c322faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Dec 2015 16:19:55 +0200 Subject: drm: Pass 'name' to drm_universal_plane_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done with coccinelle for the most part. It choked on msm/mdp/mdp5/mdp5_plane.c like so: "BAD:!!!!! enum drm_plane_type type;" No idea how to deal with that, so I just fixed that up by hand. Also it thinks '...' is part of the semantic patch, so I put an 'int DOTDOTDOT' placeholder in its place and got rid of it with sed afterwards. I didn't convert drm_plane_init() since passing the varargs through would mean either cpp macros or va_list, and I figured we don't care about these legacy functions enough to warrant the extra pain. @@ typedef uint32_t; identifier dev, plane, possible_crtcs, funcs, formats, format_count, type; @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, enum drm_plane_type type + ,const char *name, int DOTDOTDOT ) { ... } @@ identifier dev, plane, possible_crtcs, funcs, formats, format_count, type; @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, enum drm_plane_type type + ,const char *name, int DOTDOTDOT ); @@ expression E1, E2, E3, E4, E5, E6, E7; @@ drm_universal_plane_init(E1, E2, E3, E4, E5, E6, E7 + ,NULL ) v2: Split crtc and plane changes apart Pass NUL for no-name instead of "" Leave drm_plane_init() alone v3: Add ', or NULL...' to @name kernel doc (Jani) Annotate the function with __printf() attribute (Jani) Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449670795-2853-1-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_crtc.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f0127e7b0ee2..a6f0e25cbd51 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2214,13 +2214,15 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder, return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); } -extern int drm_universal_plane_init(struct drm_device *dev, - struct drm_plane *plane, - unsigned long possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, - unsigned int format_count, - enum drm_plane_type type); +extern __printf(8, 9) +int drm_universal_plane_init(struct drm_device *dev, + struct drm_plane *plane, + unsigned long possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, + unsigned int format_count, + enum drm_plane_type type, + const char *name, ...); extern int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, -- cgit v1.2.3 From 13a3d91f17a5f7ed2acd275d18b6acfdb131fb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Dec 2015 16:20:18 +0200 Subject: drm: Pass 'name' to drm_encoder_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done with coccinelle for the most part. However, it thinks '...' is part of the semantic patch, so I put an 'int DOTDOTDOT' placeholder in its place and got rid of it with sed afterwards. @@ identifier dev, encoder, funcs; @@ int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type + ,const char *name, int DOTDOTDOT ) { ... } @@ identifier dev, encoder, funcs; @@ int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type + ,const char *name, int DOTDOTDOT ); @@ expression E1, E2, E3, E4; @@ drm_encoder_init(E1, E2, E3, E4 + ,NULL ) v2: Add ', or NULL...' to @name kernel doc (Jani) Annotate the function with __printf() attribute (Jani) Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449670818-2966-1-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_crtc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a6f0e25cbd51..5b5e6b650c11 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2196,10 +2196,11 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, void drm_bridge_pre_enable(struct drm_bridge *bridge); void drm_bridge_enable(struct drm_bridge *bridge); -extern int drm_encoder_init(struct drm_device *dev, - struct drm_encoder *encoder, - const struct drm_encoder_funcs *funcs, - int encoder_type); +extern __printf(5, 6) +int drm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type, const char *name, ...); /** * drm_encoder_crtc_ok - can a given crtc drive a given encoder? -- cgit v1.2.3 From fa3ab4c2113c74a9eae9b6a718b167f7c8833e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Dec 2015 18:41:53 +0200 Subject: drm: Add crtc->name and use it in debug messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show a sensible name for the crtc in debug mesages. The driver may supply its own name, otherwise the core genrates the name ("crtc-0", "crtc-1" etc.). v2: kstrdup() the name passed by the caller (Jani) v3: Generate a default name if the driver doesn't supply one Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449592922-5545-6-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_crtc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 5b5e6b650c11..4bea0a1151bc 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -712,6 +712,8 @@ struct drm_crtc { struct device_node *port; struct list_head head; + char *name; + /* * crtc mutex * -- cgit v1.2.3 From 9f4c97a236d35b9fe45168a979adb5e1522c0968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Dec 2015 18:41:54 +0200 Subject: drm: Add plane->name and use it in debug prints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show a sensible name for the plane in debug mesages. The driver may supply its own name, otherwise the core genrates the name ("plane-0", "plane-1" etc.). v2: kstrdup() the name passed by the caller (Jani) v3: Generate a default name if the driver doesn't supply one Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449592922-5545-7-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_crtc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4bea0a1151bc..c2f98ba2bb98 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1496,6 +1496,8 @@ struct drm_plane { struct drm_device *dev; struct list_head head; + char *name; + struct drm_modeset_lock mutex; struct drm_mode_object base; -- cgit v1.2.3 From 5ba894064d98547c82a1efd50eba40a92df777a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Dec 2015 22:39:08 +0200 Subject: drm: Rename MODE_UNVERIFIED to MODE_STALE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MODE_UNVERIFIED actually means that the mode came from a previous probe, and if the new probe doesn't produce a matching mode it will get pruned from the list. Rename the flag to MODE_STALE to better convey the meaning. v2: Rebased due to conflicts with Daniel's doc stuff Cc: Adam Jackson Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449779948-10906-1-git-send-email-ville.syrjala@linux.intel.com --- include/drm/drm_modes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 9e6d7a1cd19b..d7445ccd958d 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -73,7 +73,7 @@ * @MODE_ONE_SIZE: only one resolution is supported * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking * @MODE_NO_STEREO: stereo modes not supported - * @MODE_UNVERIFIED: mode needs to reverified + * @MODE_STALE: mode has become stale * @MODE_BAD: unspecified reason * @MODE_ERROR: error condition * @@ -117,7 +117,7 @@ enum drm_mode_status { MODE_ONE_SIZE, MODE_NO_REDUCED, MODE_NO_STEREO, - MODE_UNVERIFIED = -3, + MODE_STALE = -3, MODE_BAD = -2, MODE_ERROR = -1 }; -- cgit v1.2.3 From 6af3e6561243f167dabc03f732d27ff5365cd4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Dec 2015 23:14:14 +0200 Subject: drm: Drop drm_helper_probe_single_connector_modes_nomerge() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the mode type bit merge logic is fixed to only merge between new probed modes, hopefully we can eliminat the special case for qxl and virtio. That is make the merge the mode type bits from all matching new probed modes, just like every other driver. qxl and virtio got excluded from the merging in commit 3fbd6439e463 ("drm: copy mode type in drm_mode_connector_list_update()") commit abce1ec9b08a ("Revert "drm: copy mode type in drm_mode_connector_list_update()"") commit b87577b7c768 ("drm: try harder to avoid regression when merging mode bits") Cc: Marc-André Lureau Cc: Dave Airlie Cc: Daniel Vetter Cc: Adam Jackson Signed-off-by: Ville Syrjälä [danvet: Resolve conflicts with doc updates.] Signed-off-by: Daniel Vetter --- include/drm/drm_crtc_helper.h | 4 ---- include/drm/drm_modes.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index f94ff54ae25e..4b37afa2b73b 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -70,10 +70,6 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); -extern int drm_helper_probe_single_connector_modes_nomerge(struct drm_connector - *connector, - uint32_t maxX, - uint32_t maxY); extern void drm_kms_helper_poll_init(struct drm_device *dev); extern void drm_kms_helper_poll_fini(struct drm_device *dev); extern bool drm_helper_hpd_irq_event(struct drm_device *dev); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index d7445ccd958d..625966a906f2 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -483,7 +483,7 @@ enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, void drm_mode_prune_invalid(struct drm_device *dev, struct list_head *mode_list, bool verbose); void drm_mode_sort(struct list_head *mode_list); -void drm_mode_connector_list_update(struct drm_connector *connector, bool merge_type_bits); +void drm_mode_connector_list_update(struct drm_connector *connector); /* parsing cmdline modes */ bool -- cgit v1.2.3