diff options
author | Dave Airlie <airlied@redhat.com> | 2014-11-10 02:59:16 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-11-10 02:59:16 +0300 |
commit | 122387a53eeac62e6546fd707259b63feca2d839 (patch) | |
tree | d186390dad553d7879db3d497c280e8a1b115b35 /include/drm | |
parent | 1f9e14baa9139fce2265206746fe5491be7726e9 (diff) | |
parent | 321ebf04dc7ab5c54d658f93db0ffe35277664ab (diff) | |
download | linux-122387a53eeac62e6546fd707259b63feca2d839.tar.xz |
Merge tag 'topic/atomic-helpers-2014-11-09' of git://anongit.freedesktop.org/drm-intel into drm-next
So here's my atomic series, finally all debugged&reviewed. Sean Paul has
done a full detailed pass over it all, and a lot of other people have
commented and provided feedback on some parts. Rob Clark also converted
msm over the w/e and seems happy. The only small thing is that Rob wants
to export the wait_for_vblank, which imo makes sense. Since there's other
stuff still to do I think we should apply Rob's patch (once it has grown
appropriate kerneldoc) later on top of this.
This is just the core<->driver interface plus a big pile of helpers. Short
recap of the main ideas:
- There are essentially three helper libraries in this patch set:
* Transitional helpers to use the new plane callbacks for legacy plane
updates and in the crtc helper's ->mode_set callback. These helpers are
only temporarily used to convert drivers to atomic, but they allow a
nice separation between changing the driver backend and switching to
the atomic commit logic.
* Legacy helpers to implement all the legacy driver entry points
(page_flip, set_config, plane vfuncs) on top of the new atomic driver
interface. These are completely driver agnostic. The reason for having
the legacy support as helpers is that drivers can switch step-by-step.
And they could e.g. even keep the legacy page_flip code around for some
old platforms where converting to full-blown atomic isn't worth it.
* Atomic helpers which implement the various new ->atomic_* driver
interfaces in terms of the revised crtc helper and new plane helper
hooks.
- The revised crtc helper implemenation essentially implements all the
lessons learned in the i915 modeset rework (when using the atomic helpers
only):
* Enable/disable sequence for a given config are always the same and
callbacks are always called in the same order. This contrast starkly
with the crtc helpers, where the sequence of operations is heavily
dependent on the previous config.
One corollary of this is that if the configuration of a crtc only
partially changes (e.g. a connector moves in a cloned config) the
helper code will still disable/enable the full display pipeline. This
is the only way to ensure that the enable/disable sequence is always
the same.
* It won't call disable or enable hooks more than once any more because
it lost track of state, thanks to the atomic state tracking. And if
drivers implement the ->reset hook properly (by either resetting the hw
or reading out the hw state into the atomic structures) this even
extends to the hardware state. So no more disable-me-harder kind of
nonsense.
* The only thing missing is the hw state readout/cross-check support, but
if drivers have hw state readout support in their ->reset handlers it's
simple to extend that to cross-check the hw state.
* The crtc->mode_set callback is gone and its replacement only sets crtc
timings and no longer updates the primary plane state. This way we can
finally implement primary planes properly.
- The new plane helpers should be suitable enough for pretty much
everything, and a perfect fit for hardware with GO bits. Even if they
don't fit the atomic helper library is rather flexible and exports all
the functions for the individual steps to drivers. So drivers can pick
what matches and implement their own magic for everything else.
- A big difference compared to all previous atomic series is that this one
doesn't implement async commit in a generic way. Imo driver requirements
for that are too diverse to create anything reasonable sane which would
actually work on a reasonable amount of different drivers. Also, we've
never had a helper library for page_flips even, so it's really hard to
know what might work and what's stupid without a bit of experience in the form
of a few driver implementations.
I think with the current flexibility for drivers to pick individual
stages and existing helpers like drm_flip_queue it's rather easy though
to implement proper async commit.
- There's a few other differences of minor importance to earlier atomic
series:
* Common/generic properties are parsed in the callers/core and not in
drivers, and passed to drivers by directly setting the right members in
atomic state structures. That greatly simplifies all the transitional
and legacy helpers an removes a lot of boilerplate code.
* There's no crazy trylock mode used for the async commit since these
helpers don't do async commit. A simple ordered flip queue of atomic
state updates should be sufficient for preventing concurrent hw access
anyway, as long as synchronous updates stall correctly with e.g.
flush_work_queue or similar function. Abusing locks to enforce ordering
isn't a good idea imo anyway.
* These helpers reuse the existing ->mode_fixup hooks in the atomic_check
callback. Which means that drivers need to adapat and move a lot less code
into their atomic_check callbacks.
Now this isn't everything needed in the drm core and helpers for full
atomic support. But it's enough to start with converting drivers, and
except for actually testing multiplane and multicrtc updates also enough to
implement full atomic updates. Still missing are:
- Per-plane locking. Since these helpers here encapsulate the locking
completely this should be fairly easy to implement.
- fbdev support for atomic_check/commit, so that multi-pipe finally works
sanely in fbcon.
- Adding and decoding shared/core properties. That just needs to be rebased
from Rob's latest patch series, with minor adjustments so that the
decoding happens in the core instead of in drivers.
- Actually adding the atomic ioctl. Again just rebasing Rob's latest patch
should be all that's needed.
- Resolving how to deal with DPMS in atomic. Atomic is a good excuse to fix up
the crazy semantics dpms currently has. I'm floating an RFC about this topic
already.
- Finally I couldn't test connector/encoder stealing properly since my test
vehicle here doesn't allow a connector on different crtcs. So drivers
which support this might see some surprises in that area. There is no semantic
change though in how encoder stealing and assignment works (or at least no
intended one), so I think the risk is minimal.
As just mentioned I've done a fake conversion of an existing driver using
crtc helpers to debug the helper code and validate the smooth transition
approach. And that smooth transition was the really big motivation for
this. It seems to actually work and consists of 3 phases:
Phase 1: Rework driver backend for crtc/plane helpers
The requirement here is that universal plane support is already implement. If
universal plane support isn't implement yet it might be better though to just do
it as part of this phase, directly using the new plane helpers. There are two
big things to do:
- Split up the existing ->update/disable_plane hooks into check/commit
hooks and extract the crtc-wide prep/flush parts (like setting/clearing
GO bits).
- The other big change is to split the crtc->mode_set hook into the plane
update (done using the plane helpers) and the crtc setup in a new
->mode_set_nofb hook.
When phase 1 is complete the driver implements all the new callbacks which
push the software state into hardware, but still using all the legacy entry
points and crtc helpers. The transitional helpers serve as impendance
mismatch here.
Phase 2: Rework state handling
This consists of rolling out the state handling helpers for planes, crtcs
and connectors and reviewing all ->mode_fixup and similar hooks to make
sure they don't depend upon implicit global state which might change in the
atomic world. Any such code must be moved into ->atomic_check functions which
just rely on the free-standing atomic state update structures.
This phase also adds a few small pieces of fixup code to make sure the
atomic state doesn't get out of sync in the legacy driver callbacks.
Phase 3: Roll out atomic support
Now it's just about replacing vfuncs with the ones provided by the helper
and filling out the small missing pieces (like atomic_check logic or async
commit support needed for page_flips). Due to the prep work in phase 1 no
changes to the driver backend functions should be required, and because of
the prep work in phase 2 atomic implementations can be rolled out
step-by-step. So if async commit ins't implemented yet page_flip can be
implemented with the legacy functions without wreaking havoc in the other
operations.
* tag 'topic/atomic-helpers-2014-11-09' of git://anongit.freedesktop.org/drm-intel:
drm/atomic: Refcounting for plane_state->fb
drm: Docbook integration and over sections for all the new helpers
drm/atomic-helpers: functions for state duplicate/destroy/reset
drm/atomic-helper: implement ->page_flip
drm/atomic-helpers: document how to implement async commit
drm/atomic: Integrate fence support
drm/atomic-helper: implementatations for legacy interfaces
drm: Atomic crtc/connector updates using crtc/plane helper interfaces
drm/crtc-helper: Transitional functions using atomic plane helpers
drm/plane-helper: transitional atomic plane helpers
drm: Add atomic/plane helpers
drm: Global atomic state handling
drm: Add atomic driver interface definitions for objects
drm/modeset_lock: document trylock_only in kerneldoc
drm: fixup kerneldoc in drm_crtc.h
drm: Pull drm_crtc.h into the kerneldoc template
drm: Move drm_crtc_init from drm_crtc.h to drm_plane_helper.h
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drm_atomic.h | 67 | ||||
-rw-r--r-- | include/drm/drm_atomic_helper.h | 97 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 246 | ||||
-rw-r--r-- | include/drm/drm_crtc_helper.h | 13 | ||||
-rw-r--r-- | include/drm/drm_modeset_lock.h | 1 | ||||
-rw-r--r-- | include/drm/drm_plane_helper.h | 39 |
6 files changed, 431 insertions, 32 deletions
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h new file mode 100644 index 000000000000..9d919168bc11 --- /dev/null +++ b/include/drm/drm_atomic.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 Red Hat + * Copyright (C) 2014 Intel Corp. + * + * 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. + * + * Authors: + * Rob Clark <robdclark@gmail.com> + * Daniel Vetter <daniel.vetter@ffwll.ch> + */ + +#ifndef DRM_ATOMIC_H_ +#define DRM_ATOMIC_H_ + +struct drm_atomic_state * __must_check +drm_atomic_state_alloc(struct drm_device *dev); +void drm_atomic_state_clear(struct drm_atomic_state *state); +void drm_atomic_state_free(struct drm_atomic_state *state); + +struct drm_crtc_state * __must_check +drm_atomic_get_crtc_state(struct drm_atomic_state *state, + struct drm_crtc *crtc); +struct drm_plane_state * __must_check +drm_atomic_get_plane_state(struct drm_atomic_state *state, + struct drm_plane *plane); +struct drm_connector_state * __must_check +drm_atomic_get_connector_state(struct drm_atomic_state *state, + struct drm_connector *connector); + +int __must_check +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, + struct drm_crtc *crtc); +void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, + struct drm_framebuffer *fb); +int __must_check +drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, + struct drm_crtc *crtc); +int __must_check +drm_atomic_add_affected_connectors(struct drm_atomic_state *state, + struct drm_crtc *crtc); +int +drm_atomic_connectors_for_crtc(struct drm_atomic_state *state, + struct drm_crtc *crtc); + +void drm_atomic_legacy_backoff(struct drm_atomic_state *state); + +int __must_check drm_atomic_check_only(struct drm_atomic_state *state); +int __must_check drm_atomic_commit(struct drm_atomic_state *state); +int __must_check drm_atomic_async_commit(struct drm_atomic_state *state); + +#endif /* DRM_ATOMIC_H_ */ diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h new file mode 100644 index 000000000000..67e3c4645ae0 --- /dev/null +++ b/include/drm/drm_atomic_helper.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014 Red Hat + * Copyright (C) 2014 Intel Corp. + * + * 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. + * + * Authors: + * Rob Clark <robdclark@gmail.com> + * Daniel Vetter <daniel.vetter@ffwll.ch> + */ + +#ifndef DRM_ATOMIC_HELPER_H_ +#define DRM_ATOMIC_HELPER_H_ + +int drm_atomic_helper_check(struct drm_device *dev, + struct drm_atomic_state *state); +int drm_atomic_helper_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool async); + +void drm_atomic_helper_commit_pre_planes(struct drm_device *dev, + struct drm_atomic_state *state); +void drm_atomic_helper_commit_post_planes(struct drm_device *dev, + struct drm_atomic_state *old_state); + +int drm_atomic_helper_prepare_planes(struct drm_device *dev, + struct drm_atomic_state *state); +void drm_atomic_helper_commit_planes(struct drm_device *dev, + struct drm_atomic_state *state); +void drm_atomic_helper_cleanup_planes(struct drm_device *dev, + struct drm_atomic_state *old_state); + +void drm_atomic_helper_swap_state(struct drm_device *dev, + struct drm_atomic_state *state); + +/* implementations for legacy interfaces */ +int drm_atomic_helper_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); +int drm_atomic_helper_disable_plane(struct drm_plane *plane); +int drm_atomic_helper_set_config(struct drm_mode_set *set); + +int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, + struct drm_property *property, + uint64_t val); +int drm_atomic_helper_plane_set_property(struct drm_plane *plane, + struct drm_property *property, + uint64_t val); +int drm_atomic_helper_connector_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t val); +int drm_atomic_helper_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags); + +/* default implementations for state handling */ +void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); +struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); +void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); + +void drm_atomic_helper_plane_reset(struct drm_plane *plane); +struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); +void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); + +void drm_atomic_helper_connector_reset(struct drm_connector *connector); +struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state); + + +#endif /* DRM_ATOMIC_HELPER_H_ */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c40070a92d6b..bc1cc3ce05c4 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -42,6 +42,7 @@ struct drm_object_properties; struct drm_file; struct drm_clip_rect; struct device_node; +struct fence; #define DRM_MODE_OBJECT_CRTC 0xcccccccc #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 @@ -142,8 +143,8 @@ struct drm_framebuffer_funcs { int (*create_handle)(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle); - /** - * Optinal callback for the dirty fb ioctl. + /* + * Optional callback for the dirty fb ioctl. * * Userspace can notify the driver via this callback * that a area of the framebuffer has changed and should @@ -224,19 +225,57 @@ struct drm_encoder; struct drm_pending_vblank_event; struct drm_plane; struct drm_bridge; +struct drm_atomic_state; + +/** + * struct drm_crtc_state - mutable CRTC state + * @enable: whether the CRTC should be enabled, gates all other state + * @mode_changed: for use by helpers and drivers when computing state updates + * @last_vblank_count: for helpers and drivers to capture the vblank of the + * update to ensure framebuffer cleanup isn't done too early + * @planes_changed: for use by helpers and drivers when computing state updates + * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings + * @mode: current mode timings + * @event: optional pointer to a DRM event to signal upon completion of the + * state update + * @state: backpointer to global drm_atomic_state + */ +struct drm_crtc_state { + bool enable; + + /* computed state bits used by helpers and drivers */ + bool planes_changed : 1; + bool mode_changed : 1; + + /* last_vblank_count: for vblank waits before cleanup */ + u32 last_vblank_count; + + /* adjusted_mode: for use by helpers and drivers */ + struct drm_display_mode adjusted_mode; + + struct drm_display_mode mode; + + struct drm_pending_vblank_event *event; + + struct drm_atomic_state *state; +}; /** - * drm_crtc_funcs - control CRTCs for a given device + * 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 * * 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 @@ -287,16 +326,28 @@ struct drm_crtc_funcs { int (*set_property)(struct drm_crtc *crtc, struct drm_property *property, uint64_t val); + + /* atomic update handling */ + struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc); + void (*atomic_destroy_state)(struct drm_crtc *crtc, + struct drm_crtc_state *state); + int (*atomic_set_property)(struct drm_crtc *crtc, + struct drm_crtc_state *state, + struct drm_property *property, + uint64_t val); }; /** - * drm_crtc - central CRTC control structure + * struct drm_crtc - central CRTC control structure * @dev: parent DRM device + * @port: OF node used by drm_of_find_possible_crtcs() * @head: list management * @mutex: per-CRTC locking * @base: base KMS object for ID tracking etc. * @primary: primary plane for this CRTC * @cursor: cursor plane for this CRTC + * @cursor_x: current x position of the cursor, used for universal cursor planes + * @cursor_y: current y position of the cursor, used for universal cursor planes * @enabled: is this CRTC enabled? * @mode: current mode timings * @hwmode: mode timings as programmed to hw regs @@ -309,10 +360,13 @@ struct drm_crtc_funcs { * @gamma_size: size of gamma ramp * @gamma_store: gamma ramp values * @framedur_ns: precise frame timing - * @framedur_ns: precise line timing + * @linedur_ns: precise line timing * @pixeldur_ns: precise pixel timing * @helper_private: mid-layer private data * @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 * * Each CRTC may have one or more connectors associated with it. This structure * allows the CRTC to be controlled. @@ -322,7 +376,7 @@ struct drm_crtc { struct device_node *port; struct list_head head; - /** + /* * crtc mutex * * This provides a read lock for the overall crtc state (mode, dpms @@ -368,6 +422,8 @@ struct drm_crtc { struct drm_object_properties properties; + struct drm_crtc_state *state; + /* * For legacy crtc ioctls so that atomic drivers can get at the locking * acquire context. @@ -375,9 +431,22 @@ struct drm_crtc { struct drm_modeset_acquire_ctx *acquire_ctx; }; +/** + * struct drm_connector_state - mutable connector state + * @crtc: CRTC to connect connector to, NULL if disabled + * @best_encoder: can be used by helpers and drivers to select the encoder + * @state: backpointer to global drm_atomic_state + */ +struct drm_connector_state { + struct drm_crtc *crtc; + + struct drm_encoder *best_encoder; + + struct drm_atomic_state *state; +}; /** - * drm_connector_funcs - control connectors on a given device + * struct drm_connector_funcs - control connectors on a given device * @dpms: set power state (see drm_crtc_funcs above) * @save: save connector state * @restore: restore connector state @@ -387,6 +456,9 @@ struct drm_crtc { * @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 * * 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, @@ -411,10 +483,19 @@ struct drm_connector_funcs { uint64_t val); void (*destroy)(struct drm_connector *connector); void (*force)(struct drm_connector *connector); + + /* atomic update handling */ + struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); + void (*atomic_destroy_state)(struct drm_connector *connector, + struct drm_connector_state *state); + int (*atomic_set_property)(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); }; /** - * drm_encoder_funcs - encoder controls + * struct drm_encoder_funcs - encoder controls * @reset: reset state (e.g. at init or resume time) * @destroy: cleanup and free associated data * @@ -428,7 +509,7 @@ struct drm_encoder_funcs { #define DRM_CONNECTOR_MAX_ENCODER 3 /** - * drm_encoder - central DRM encoder structure + * struct drm_encoder - central DRM encoder structure * @dev: parent DRM device * @head: list management * @base: base KMS object @@ -472,7 +553,7 @@ struct drm_encoder { #define MAX_ELD_BYTES 128 /** - * drm_connector - central DRM connector control structure + * struct drm_connector - central DRM connector control structure * @dev: parent DRM device * @kdev: kernel device for sysfs attributes * @attr: sysfs attributes @@ -483,6 +564,7 @@ struct drm_encoder { * @connector_type_id: index into connector type enum * @interlace_allowed: can this connector handle interlaced modes? * @doublescan_allowed: can this connector handle doublescan? + * @stereo_allowed: can this connector handle stereo modes? * @modes: modes available on this connector (from fill_modes() + user) * @status: one of the drm_connector_status enums (connected, not, or unknown) * @probed_modes: list of modes derived directly from the display @@ -490,10 +572,13 @@ struct drm_encoder { * @funcs: connector control functions * @edid_blob_ptr: DRM property containing EDID if present * @properties: property tracking for this connector + * @path_blob_ptr: DRM blob property data for the DP MST path property * @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling * @dpms: current dpms state * @helper_private: mid-layer private data + * @cmdline_mode: mode line parsed from the kernel cmdline for this connector * @force: a %DRM_FORCE_<foo> state for forced mode sets + * @override_edid: has the EDID been overwritten through debugfs for testing? * @encoder_ids: valid encoders for this connector * @encoder: encoder driving this connector, if any * @eld: EDID-like data, if present @@ -503,6 +588,9 @@ struct drm_encoder { * @video_latency: video latency info from ELD, if found * @audio_latency: audio latency info from ELD, if found * @null_edid_counter: track sinks that give us all zeros for the EDID + * @bad_edid_counter: track sinks that give us an EDID with invalid checksum + * @debugfs_entry: debugfs directory for this connector + * @state: current atomic state for this connector * * Each connector may be connected to one or more CRTCs, or may be clonable by * another connector if they can share a CRTC. Each connector also has a specific @@ -563,14 +651,54 @@ struct drm_connector { unsigned bad_edid_counter; struct dentry *debugfs_entry; + + struct drm_connector_state *state; +}; + +/** + * struct drm_plane_state - mutable plane state + * @crtc: currently bound CRTC, NULL if disabled + * @fb: currently bound framebuffer + * @fence: optional fence to wait for before scanning out @fb + * @crtc_x: left position of visible portion of plane on crtc + * @crtc_y: upper position of visible portion of plane on crtc + * @crtc_w: width of visible portion of plane on crtc + * @crtc_h: height of visible portion of plane on crtc + * @src_x: left position of visible portion of plane within + * plane (in 16.16) + * @src_y: upper position of visible portion of plane within + * plane (in 16.16) + * @src_w: width of visible portion of plane (in 16.16) + * @src_h: height of visible portion of plane (in 16.16) + * @state: backpointer to global drm_atomic_state + */ +struct drm_plane_state { + struct drm_crtc *crtc; + struct drm_framebuffer *fb; + struct fence *fence; + + /* Signed dest location allows it to be partially off screen */ + int32_t crtc_x, crtc_y; + uint32_t crtc_w, crtc_h; + + /* Source values are 16.16 fixed point */ + uint32_t src_x, src_y; + uint32_t src_h, src_w; + + struct drm_atomic_state *state; }; + /** - * drm_plane_funcs - driver plane control functions + * 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 */ struct drm_plane_funcs { int (*update_plane)(struct drm_plane *plane, @@ -585,6 +713,15 @@ struct drm_plane_funcs { int (*set_property)(struct drm_plane *plane, struct drm_property *property, uint64_t val); + + /* atomic update handling */ + struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane); + void (*atomic_destroy_state)(struct drm_plane *plane, + struct drm_plane_state *state); + int (*atomic_set_property)(struct drm_plane *plane, + struct drm_plane_state *state, + struct drm_property *property, + uint64_t val); }; enum drm_plane_type { @@ -594,7 +731,7 @@ enum drm_plane_type { }; /** - * drm_plane - central DRM plane control structure + * struct drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to * @head: for list management * @base: base mode object @@ -603,9 +740,12 @@ enum drm_plane_type { * @format_count: number of formats supported * @crtc: currently bound CRTC * @fb: currently bound fb + * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by + * drm_mode_set_config_internal() to implement correct refcounting. * @funcs: helper functions * @properties: property tracking for this plane * @type: type of plane (overlay, primary, cursor) + * @state: current atomic state for this plane */ struct drm_plane { struct drm_device *dev; @@ -620,8 +760,6 @@ struct drm_plane { struct drm_crtc *crtc; struct drm_framebuffer *fb; - /* Temporary tracking of the old fb while a modeset is ongoing. Used - * by drm_mode_set_config_internal to implement correct refcounting. */ struct drm_framebuffer *old_fb; const struct drm_plane_funcs *funcs; @@ -629,10 +767,14 @@ struct drm_plane { struct drm_object_properties properties; enum drm_plane_type type; + + void *helper_private; + + struct drm_plane_state *state; }; /** - * drm_bridge_funcs - drm_bridge control functions + * struct drm_bridge_funcs - drm_bridge control functions * @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 @@ -656,7 +798,7 @@ struct drm_bridge_funcs { }; /** - * drm_bridge - central DRM bridge control structure + * struct drm_bridge - central DRM bridge control structure * @dev: DRM device this bridge belongs to * @head: list management * @base: base mode object @@ -674,8 +816,33 @@ struct drm_bridge { }; /** - * drm_mode_set - new values for a CRTC config change - * @head: list management + * struct struct drm_atomic_state - the global state object for atomic updates + * @dev: parent DRM device + * @flags: state flags like async update + * @planes: pointer to array of plane pointers + * @plane_states: pointer to array of plane states pointers + * @crtcs: pointer to array of CRTC pointers + * @crtc_states: pointer to array of CRTC states pointers + * @connectors: pointer to array of connector pointers + * @connector_states: pointer to array of connector states pointers + * @acquire_ctx: acquire context for this atomic modeset state update + */ +struct drm_atomic_state { + struct drm_device *dev; + uint32_t flags; + struct drm_plane **planes; + struct drm_plane_state **plane_states; + struct drm_crtc **crtcs; + struct drm_crtc_state **crtc_states; + struct drm_connector **connectors; + struct drm_connector_state **connector_states; + + struct drm_modeset_acquire_ctx *acquire_ctx; +}; + + +/** + * struct drm_mode_set - new values for a CRTC config change * @fb: framebuffer to use for new config * @crtc: CRTC whose configuration we're about to change * @mode: mode timings to use @@ -705,6 +872,9 @@ 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 give atomic state update is possible + * @atomic_commit: commit an atomic state update previously verified with + * atomic_check() * * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that * involve drivers. @@ -714,13 +884,20 @@ struct drm_mode_config_funcs { struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd); void (*output_poll_changed)(struct drm_device *dev); + + int (*atomic_check)(struct drm_device *dev, + struct drm_atomic_state *a); + int (*atomic_commit)(struct drm_device *dev, + struct drm_atomic_state *a, + bool async); }; /** - * drm_mode_group - group of mode setting resources for potential sub-grouping + * struct drm_mode_group - group of mode setting resources for potential sub-grouping * @num_crtcs: CRTC count * @num_encoders: encoder count * @num_connectors: connector count + * @num_bridges: bridge count * @id_list: list of KMS object IDs in this group * * Currently this simply tracks the global mode setting state. But in the @@ -740,10 +917,14 @@ struct drm_mode_group { }; /** - * drm_mode_config - Mode configuration control structure + * struct drm_mode_config - Mode configuration control structure * @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 * @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 * @num_fb: number of fbs available * @fb_list: list of framebuffers available * @num_connector: number of connectors on this device @@ -752,17 +933,28 @@ struct drm_mode_group { * @bridge_list: list of bridge objects * @num_encoder: number of encoders on this device * @encoder_list: list of encoder objects + * @num_overlay_plane: number of overlay planes on this device + * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device + * @plane_list: list of plane objects * @num_crtc: number of CRTCs on this device * @crtc_list: list of CRTC objects + * @property_list: list of property objects * @min_width: minimum pixel width on this device * @min_height: minimum pixel height on this device * @max_width: maximum pixel width on this device * @max_height: maximum pixel height on this device * @funcs: core driver provided mode setting functions * @fb_base: base address of the framebuffer - * @poll_enabled: track polling status for this device + * @poll_enabled: track polling support for this device + * @poll_running: track polling status for this device * @output_poll_work: delayed work for polling in process context + * @property_blob_list: list of all the blob property objects * @*_property: core property tracking + * @preferred_depth: preferred RBG pixel depth, used by fb helpers + * @prefer_shadow: hint to userspace to prefer shadow-fb rendering + * @async_page_flip: does this device support async flips on the primary plane? + * @cursor_width: hint to userspace for max cursor width + * @cursor_height: hint to userspace for max cursor height * * Core mode resource tracking structure. All CRTC, encoders, and connectors * enumerated by the driver are added here, as are global properties. Some @@ -776,14 +968,7 @@ struct drm_mode_config { struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ /* this is limited to one for now */ - - /** - * fb_lock - mutex to protect fb state - * - * Besides the global fb list his also protects the fbs list in the - * file_priv - */ - struct mutex fb_lock; + struct mutex fb_lock; /* proctects global and per-file fb lists */ int num_fb; struct list_head fb_list; @@ -880,9 +1065,6 @@ extern int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_plane *primary, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs); -extern int drm_crtc_init(struct drm_device *dev, - struct drm_crtc *crtc, - const struct drm_crtc_funcs *funcs); extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index a3d75fefd010..7adbb65ea8ae 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -68,6 +68,7 @@ struct drm_crtc_helper_funcs { 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); + 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, @@ -81,6 +82,12 @@ struct drm_crtc_helper_funcs { /* disable crtc when not in use - more explicit than dpms off */ void (*disable)(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); + void (*atomic_flush)(struct drm_crtc *crtc); }; /** @@ -161,6 +168,12 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, 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, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb); +int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); + /* drm_probe_helper.c */ extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 75a5c45e21c7..28931a23d96c 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -33,6 +33,7 @@ struct drm_modeset_lock; * @ww_ctx: base acquire ctx * @contended: used internally for -EDEADLK handling * @locked: list of held locks + * @trylock_only: trylock mode used in atomic contexts/panic notifiers * * Each thread competing for a set of locks must use one acquire * ctx. And if any lock fxn returns -EDEADLK, it must backoff and diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 52e6870534b2..c48f14d88690 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -25,6 +25,7 @@ #define DRM_PLANE_HELPER_H #include <drm/drm_rect.h> +#include <drm/drm_crtc.h> /* * Drivers that don't allow primary plane scaling may pass this macro in place @@ -42,6 +43,32 @@ * planes. */ +extern 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 + * + * The helper operations are called by the mid-layer CRTC helper. + */ +struct drm_plane_helper_funcs { + int (*prepare_fb)(struct drm_plane *plane, + struct drm_framebuffer *fb); + void (*cleanup_fb)(struct drm_plane *plane, + struct drm_framebuffer *fb); + + int (*atomic_check)(struct drm_plane *plane, + struct drm_plane_state *state); + void (*atomic_update)(struct drm_plane *plane); +}; + +static inline void drm_plane_helper_add(struct drm_plane *plane, + const struct drm_plane_helper_funcs *funcs) +{ + plane->helper_private = (void *)funcs; +} + extern int drm_plane_helper_check_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -68,4 +95,16 @@ extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, int num_formats); +int drm_plane_helper_update(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); +int drm_plane_helper_disable(struct drm_plane *plane); + +/* For use by drm_crtc_helper.c */ +int drm_plane_helper_commit(struct drm_plane *plane, + struct drm_plane_state *plane_state, + struct drm_framebuffer *old_fb); #endif |