2008-11-08 06:05:41 +08:00
|
|
|
/*
|
|
|
|
* Copyright © 2006 Keith Packard
|
|
|
|
* Copyright © 2007-2008 Dave Airlie
|
|
|
|
* Copyright © 2007-2008 Intel Corporation
|
|
|
|
* Jesse Barnes <jesse.barnes@intel.com>
|
|
|
|
*
|
|
|
|
* 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_CRTC_H__
|
|
|
|
#define __DRM_CRTC_H__
|
|
|
|
|
|
|
|
#include <linux/i2c.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/fb.h>
|
2013-12-19 18:04:07 +08:00
|
|
|
#include <linux/hdmi.h>
|
2014-07-22 18:09:10 +08:00
|
|
|
#include <linux/media-bus-format.h>
|
2014-08-29 18:12:40 +08:00
|
|
|
#include <uapi/drm/drm_mode.h>
|
|
|
|
#include <uapi/drm/drm_fourcc.h>
|
2013-11-20 01:10:12 +08:00
|
|
|
#include <drm/drm_modeset_lock.h>
|
2016-07-27 00:06:57 +08:00
|
|
|
#include <drm/drm_rect.h>
|
2016-08-29 16:27:51 +08:00
|
|
|
#include <drm/drm_mode_object.h>
|
2016-08-15 22:07:02 +08:00
|
|
|
#include <drm/drm_framebuffer.h>
|
|
|
|
#include <drm/drm_modes.h>
|
2016-08-13 04:48:50 +08:00
|
|
|
#include <drm/drm_connector.h>
|
2016-08-29 16:27:49 +08:00
|
|
|
#include <drm/drm_encoder.h>
|
2016-08-29 16:27:55 +08:00
|
|
|
#include <drm/drm_property.h>
|
2016-09-01 00:09:05 +08:00
|
|
|
#include <drm/drm_bridge.h>
|
2016-09-01 00:09:06 +08:00
|
|
|
#include <drm/drm_edid.h>
|
2016-09-21 16:59:24 +08:00
|
|
|
#include <drm/drm_plane.h>
|
2016-09-21 16:59:26 +08:00
|
|
|
#include <drm/drm_blend.h>
|
2016-09-21 16:59:28 +08:00
|
|
|
#include <drm/drm_color_mgmt.h>
|
2016-10-06 23:21:06 +08:00
|
|
|
#include <drm/drm_debugfs_crc.h>
|
2016-11-14 19:58:23 +08:00
|
|
|
#include <drm/drm_mode_config.h>
|
2011-11-15 06:51:28 +08:00
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
struct drm_device;
|
|
|
|
struct drm_mode_set;
|
2012-11-21 22:00:47 +08:00
|
|
|
struct drm_file;
|
|
|
|
struct drm_clip_rect;
|
2016-11-05 23:08:09 +08:00
|
|
|
struct drm_printer;
|
2014-06-15 18:07:12 +08:00
|
|
|
struct device_node;
|
2016-10-25 20:00:45 +08:00
|
|
|
struct dma_fence;
|
2016-06-21 16:54:13 +08:00
|
|
|
struct edid;
|
2008-11-08 06:05:41 +08:00
|
|
|
|
2012-09-13 11:22:31 +08:00
|
|
|
static inline int64_t U642I64(uint64_t val)
|
|
|
|
{
|
|
|
|
return (int64_t)*((int64_t *)&val);
|
|
|
|
}
|
|
|
|
static inline uint64_t I642U64(int64_t val)
|
|
|
|
{
|
|
|
|
return (uint64_t)*((uint64_t *)&val);
|
|
|
|
}
|
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
struct drm_crtc;
|
|
|
|
struct drm_encoder;
|
2009-11-18 01:43:55 +08:00
|
|
|
struct drm_pending_vblank_event;
|
2011-11-15 06:51:27 +08:00
|
|
|
struct drm_plane;
|
2013-08-15 04:47:37 +08:00
|
|
|
struct drm_bridge;
|
2014-10-28 03:28:44 +08:00
|
|
|
struct drm_atomic_state;
|
|
|
|
|
2015-12-04 16:45:45 +08:00
|
|
|
struct drm_crtc_helper_funcs;
|
|
|
|
struct drm_encoder_helper_funcs;
|
|
|
|
struct drm_plane_helper_funcs;
|
|
|
|
|
2014-10-28 03:28:44 +08:00
|
|
|
/**
|
2014-07-26 03:30:38 +08:00
|
|
|
* struct drm_crtc_state - mutable CRTC state
|
2014-11-27 22:49:39 +08:00
|
|
|
* @crtc: backpointer to the CRTC
|
2014-10-28 03:28:44 +08:00
|
|
|
* @enable: whether the CRTC should be enabled, gates all other state
|
2014-11-26 23:57:41 +08:00
|
|
|
* @active: whether the CRTC is actively displaying (used for DPMS)
|
2015-07-21 19:28:57 +08:00
|
|
|
* @planes_changed: planes on this crtc are updated
|
|
|
|
* @mode_changed: crtc_state->mode or crtc_state->enable has been changed
|
|
|
|
* @active_changed: crtc_state->active has been toggled.
|
|
|
|
* @connectors_changed: connectors to this crtc have been updated
|
2016-06-13 17:11:26 +08:00
|
|
|
* @zpos_changed: zpos values of planes on this crtc have been updated
|
2016-02-27 01:05:00 +08:00
|
|
|
* @color_mgmt_changed: color management properties have changed (degamma or
|
|
|
|
* gamma LUT or CSC matrix)
|
2014-11-22 04:28:31 +08:00
|
|
|
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
|
2016-01-04 19:53:18 +08:00
|
|
|
* @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
|
2016-01-28 22:04:58 +08:00
|
|
|
* @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
|
drm: Atomic crtc/connector updates using crtc/plane helper interfaces
So this is finally the integration of the crtc and plane helper
interfaces into the atomic helper functions.
In the check function we now have a few steps:
- First we update the output routing and figure out which crtcs need a
full mode set. Suitable encoders are selected using ->best_encoder,
with the same semantics as the crtc helpers of implicitly disabling
all connectors currently using the encoder.
- Then we pull all other connectors into the state update which feed
from a crtc which changes. This must be done do catch mode changes
and similar updates - atomic updates are differences on top of the
current state.
- Then we call all the various ->mode_fixup to compute the adjusted
mode. Note that here we have a slight semantic difference compared
to the crtc helpers: We have not yet updated the encoder->crtc link
when calling the encoder's ->mode_fixup function. But that's a
requirement when converting to atomic since we want to prepare the
entire state completely contained with the over drm_atomic_state
structure. So this must be carefully checked when converting drivers
over to atomic helpers.
- Finally we do call the atomic_check functions on planes and crtcs.
The commit function is also quite a beast:
- The only step that can fail is done first, namely pinning the
framebuffers. After that we cross the point of no return, an async
commit would push all that into the worker thread.
- The disabling of encoders and connectors is a bit tricky, since
depending upon the final state we need to select different crtc
helper functions.
- Software tracking is a bit clarified compared to the crtc helpers:
We commit the software state before starting to touch the hardware,
like crtc helpers. But since we just swap them we still have the old
state (i.e. the current hw state) around, which is really handy to
write simple disable functions. So no more
drm_crtc_helper_disable_all_unused_functions kind of fun because
we're leaving unused crtcs/encoders behind. Everything gets shut
down in-order now, which is one of the key differences of the i915
helpers compared to crtc helpers and a really nice additional
guarantee.
- Like with the plane helpers the atomic commit function waits for one
vblank to pass before calling the framebuffer cleanup function.
Compared to Rob's helper approach there's a bunch of upsides:
- All the interfaces which can fail are called in the ->check hook
(i.e. ->best_match and the various ->mode_fixup hooks). This means
that drivers can just reuse those functions and don't need to move
everything into ->atomic_check callbacks. If drivers have no need
for additional constraint checking beyong their existing crtc
helper callbacks they don't need to do anything.
- The actual commit operation is properly stage: First we prepare
framebuffers, which can potentially still fail (due to memory
exhausting). This is important for the async case, where this must
be done synchronously to correctly return errors.
- The output configuration changes (done with crtc helper functions)
and the plane update (using atomic plane helpers) are correctly
interleaved: First we shut down any crtcs that need changing, then
we update planes and finally we enable everything again. Hardware
without GO bits must be more careful with ordering, which this
sequence enables.
- Also for hardware with shared output resources (like display PLLs)
we first must shut down the old configuration before we can enable
the new one. Otherwise we can hit an impossible intermediate state
where there's not enough PLLs (which is the point behind atomic
updates).
v2:
- Ensure that users of ->check update crtc_state->enable correctly.
- Update the legacy state in crtc/plane structures. Eventually we want
to remove that, but for now the drm core still expects this (especially
the plane->fb pointer).
v3: A few changes for better async handling:
- Reorder the software side state commit so that it happens all before
we touch the hardware. This way async support becomes very easy
since we can punt all the actual hw touching to a worker thread. And
as long as we synchronize with that thread (flushing or cancelling,
depending upon what the driver can handle) before we commit the next
software state there's no need for any locking in the worker thread
at all. Which greatly simplifies things.
And as long as we synchronize with all relevant threads we can have
a lot of them (e.g. per-crtc for per-crtc updates) running in
parallel.
- Expose pre/post plane commit steps separately. We need to expose the
actual hw commit step anyway for drivers to be able to implement
asynchronous commit workers. But if we expose pre/post and plane
commit steps individually we allow drivers to selectively use atomic
helpers.
- I've forgotten to call encoder/bridge ->mode_set functions, fix
this.
v4: Add debug output and fix a mixup between current and new state
that resulted in crtcs not getting updated correctly. And in an
Oops ...
v5:
- Be kind to driver writers in the vblank wait functions.. if thing
aren't working yet, and vblank irq will never come, then let's not
block forever.. especially under console-lock.
- Correctly clear connector_state->best_encoder when disabling.
Spotted while trying to understand a report from Rob Clark.
- Only steal encoder if it actually changed, otherwise hilarity ensues
if we steal from the current connector and so set the ->crtc pointer
unexpectedly to NULL. Reported by Rob Clark.
- Bail out in disable_outputs if an output currently doesn't have a
best_encoder - this means it's already disabled.
v6: Fixupe kerneldoc as reported by Paulo. And also fix up kerneldoc
in drm_crtc.h.
v7: Take ownership of the atomic state and clean it up with
drm_atomic_state_free().
v8 Various improvements all over:
- Polish code comments and kerneldoc.
- Improve debug output to make sure all failure cases are logged.
- Treat enabled crtc with no connectors as invalid input from userspace.
- Don't ignore the return value from mode_fixup().
v9:
- Improve debug output for crtc_state->mode_changed.
v10:
- Fixup the vblank waiting code to properly balance the vblank_get/put
calls.
- Better comments when checking/computing crtc->mode_changed
v11: Fixup the encoder stealing logic: We can't look at encoder->crtc
since that's not in the atomic state structures and might be updated
asynchronously in and async commit. Instead we need to inspect all the
connector states and check whether the encoder is currently in used
and if so, on which crtc.
v12: Review from Sean:
- A few spelling fixes.
- Flatten control flow indent by converting if blocks to early
continue/return in 2 places.
- Capture connectors_for_crtc return value in int num_connectors
instead of bool has_connectors and do an explicit int->bool
conversion with !!. I think the helper is more useful for drivers if
it returns the number of connectors (e.g. to detect cloning
configurations), so decided to keep that return value.
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-16 23:50:47 +08:00
|
|
|
* @last_vblank_count: for helpers and drivers to capture the vblank of the
|
|
|
|
* update to ensure framebuffer cleanup isn't done too early
|
2014-10-29 18:13:47 +08:00
|
|
|
* @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
|
2014-10-28 03:28:44 +08:00
|
|
|
* @mode: current mode timings
|
2016-06-01 05:11:10 +08:00
|
|
|
* @mode_blob: &drm_property_blob for @mode
|
2016-02-27 01:05:00 +08:00
|
|
|
* @degamma_lut: Lookup table for converting framebuffer pixel data
|
|
|
|
* before apply the conversion matrix
|
|
|
|
* @ctm: Transformation matrix
|
|
|
|
* @gamma_lut: Lookup table for converting pixel data after the
|
|
|
|
* conversion matrix
|
2014-10-28 03:28:44 +08:00
|
|
|
* @state: backpointer to global drm_atomic_state
|
2014-11-26 23:57:41 +08:00
|
|
|
*
|
|
|
|
* Note that the distinction between @enable and @active is rather subtile:
|
|
|
|
* Flipping @active while @enable is set without changing anything else may
|
|
|
|
* never return in a failure from the ->atomic_check callback. Userspace assumes
|
|
|
|
* that a DPMS On will always succeed. In other words: @enable controls resource
|
|
|
|
* assignment, @active controls the actual hardware state.
|
2016-10-13 17:47:08 +08:00
|
|
|
*
|
|
|
|
* The three booleans active_changed, connectors_changed and mode_changed are
|
|
|
|
* intended to indicate whether a full modeset is needed, rather than strictly
|
|
|
|
* describing what has changed in a commit.
|
|
|
|
* See also: drm_atomic_crtc_needs_modeset()
|
2014-10-28 03:28:44 +08:00
|
|
|
*/
|
|
|
|
struct drm_crtc_state {
|
2014-11-27 22:49:39 +08:00
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
2014-07-26 03:30:38 +08:00
|
|
|
bool enable;
|
2014-11-26 23:57:41 +08:00
|
|
|
bool active;
|
2014-10-28 03:28:44 +08:00
|
|
|
|
2014-11-05 07:14:14 +08:00
|
|
|
/* computed state bits used by helpers and drivers */
|
|
|
|
bool planes_changed : 1;
|
drm: Atomic crtc/connector updates using crtc/plane helper interfaces
So this is finally the integration of the crtc and plane helper
interfaces into the atomic helper functions.
In the check function we now have a few steps:
- First we update the output routing and figure out which crtcs need a
full mode set. Suitable encoders are selected using ->best_encoder,
with the same semantics as the crtc helpers of implicitly disabling
all connectors currently using the encoder.
- Then we pull all other connectors into the state update which feed
from a crtc which changes. This must be done do catch mode changes
and similar updates - atomic updates are differences on top of the
current state.
- Then we call all the various ->mode_fixup to compute the adjusted
mode. Note that here we have a slight semantic difference compared
to the crtc helpers: We have not yet updated the encoder->crtc link
when calling the encoder's ->mode_fixup function. But that's a
requirement when converting to atomic since we want to prepare the
entire state completely contained with the over drm_atomic_state
structure. So this must be carefully checked when converting drivers
over to atomic helpers.
- Finally we do call the atomic_check functions on planes and crtcs.
The commit function is also quite a beast:
- The only step that can fail is done first, namely pinning the
framebuffers. After that we cross the point of no return, an async
commit would push all that into the worker thread.
- The disabling of encoders and connectors is a bit tricky, since
depending upon the final state we need to select different crtc
helper functions.
- Software tracking is a bit clarified compared to the crtc helpers:
We commit the software state before starting to touch the hardware,
like crtc helpers. But since we just swap them we still have the old
state (i.e. the current hw state) around, which is really handy to
write simple disable functions. So no more
drm_crtc_helper_disable_all_unused_functions kind of fun because
we're leaving unused crtcs/encoders behind. Everything gets shut
down in-order now, which is one of the key differences of the i915
helpers compared to crtc helpers and a really nice additional
guarantee.
- Like with the plane helpers the atomic commit function waits for one
vblank to pass before calling the framebuffer cleanup function.
Compared to Rob's helper approach there's a bunch of upsides:
- All the interfaces which can fail are called in the ->check hook
(i.e. ->best_match and the various ->mode_fixup hooks). This means
that drivers can just reuse those functions and don't need to move
everything into ->atomic_check callbacks. If drivers have no need
for additional constraint checking beyong their existing crtc
helper callbacks they don't need to do anything.
- The actual commit operation is properly stage: First we prepare
framebuffers, which can potentially still fail (due to memory
exhausting). This is important for the async case, where this must
be done synchronously to correctly return errors.
- The output configuration changes (done with crtc helper functions)
and the plane update (using atomic plane helpers) are correctly
interleaved: First we shut down any crtcs that need changing, then
we update planes and finally we enable everything again. Hardware
without GO bits must be more careful with ordering, which this
sequence enables.
- Also for hardware with shared output resources (like display PLLs)
we first must shut down the old configuration before we can enable
the new one. Otherwise we can hit an impossible intermediate state
where there's not enough PLLs (which is the point behind atomic
updates).
v2:
- Ensure that users of ->check update crtc_state->enable correctly.
- Update the legacy state in crtc/plane structures. Eventually we want
to remove that, but for now the drm core still expects this (especially
the plane->fb pointer).
v3: A few changes for better async handling:
- Reorder the software side state commit so that it happens all before
we touch the hardware. This way async support becomes very easy
since we can punt all the actual hw touching to a worker thread. And
as long as we synchronize with that thread (flushing or cancelling,
depending upon what the driver can handle) before we commit the next
software state there's no need for any locking in the worker thread
at all. Which greatly simplifies things.
And as long as we synchronize with all relevant threads we can have
a lot of them (e.g. per-crtc for per-crtc updates) running in
parallel.
- Expose pre/post plane commit steps separately. We need to expose the
actual hw commit step anyway for drivers to be able to implement
asynchronous commit workers. But if we expose pre/post and plane
commit steps individually we allow drivers to selectively use atomic
helpers.
- I've forgotten to call encoder/bridge ->mode_set functions, fix
this.
v4: Add debug output and fix a mixup between current and new state
that resulted in crtcs not getting updated correctly. And in an
Oops ...
v5:
- Be kind to driver writers in the vblank wait functions.. if thing
aren't working yet, and vblank irq will never come, then let's not
block forever.. especially under console-lock.
- Correctly clear connector_state->best_encoder when disabling.
Spotted while trying to understand a report from Rob Clark.
- Only steal encoder if it actually changed, otherwise hilarity ensues
if we steal from the current connector and so set the ->crtc pointer
unexpectedly to NULL. Reported by Rob Clark.
- Bail out in disable_outputs if an output currently doesn't have a
best_encoder - this means it's already disabled.
v6: Fixupe kerneldoc as reported by Paulo. And also fix up kerneldoc
in drm_crtc.h.
v7: Take ownership of the atomic state and clean it up with
drm_atomic_state_free().
v8 Various improvements all over:
- Polish code comments and kerneldoc.
- Improve debug output to make sure all failure cases are logged.
- Treat enabled crtc with no connectors as invalid input from userspace.
- Don't ignore the return value from mode_fixup().
v9:
- Improve debug output for crtc_state->mode_changed.
v10:
- Fixup the vblank waiting code to properly balance the vblank_get/put
calls.
- Better comments when checking/computing crtc->mode_changed
v11: Fixup the encoder stealing logic: We can't look at encoder->crtc
since that's not in the atomic state structures and might be updated
asynchronously in and async commit. Instead we need to inspect all the
connector states and check whether the encoder is currently in used
and if so, on which crtc.
v12: Review from Sean:
- A few spelling fixes.
- Flatten control flow indent by converting if blocks to early
continue/return in 2 places.
- Capture connectors_for_crtc return value in int num_connectors
instead of bool has_connectors and do an explicit int->bool
conversion with !!. I think the helper is more useful for drivers if
it returns the number of connectors (e.g. to detect cloning
configurations), so decided to keep that return value.
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-16 23:50:47 +08:00
|
|
|
bool mode_changed : 1;
|
2015-01-22 23:36:21 +08:00
|
|
|
bool active_changed : 1;
|
2015-07-21 19:28:57 +08:00
|
|
|
bool connectors_changed : 1;
|
2016-06-13 17:11:26 +08:00
|
|
|
bool zpos_changed : 1;
|
2016-02-27 01:05:00 +08:00
|
|
|
bool color_mgmt_changed : 1;
|
drm: Atomic crtc/connector updates using crtc/plane helper interfaces
So this is finally the integration of the crtc and plane helper
interfaces into the atomic helper functions.
In the check function we now have a few steps:
- First we update the output routing and figure out which crtcs need a
full mode set. Suitable encoders are selected using ->best_encoder,
with the same semantics as the crtc helpers of implicitly disabling
all connectors currently using the encoder.
- Then we pull all other connectors into the state update which feed
from a crtc which changes. This must be done do catch mode changes
and similar updates - atomic updates are differences on top of the
current state.
- Then we call all the various ->mode_fixup to compute the adjusted
mode. Note that here we have a slight semantic difference compared
to the crtc helpers: We have not yet updated the encoder->crtc link
when calling the encoder's ->mode_fixup function. But that's a
requirement when converting to atomic since we want to prepare the
entire state completely contained with the over drm_atomic_state
structure. So this must be carefully checked when converting drivers
over to atomic helpers.
- Finally we do call the atomic_check functions on planes and crtcs.
The commit function is also quite a beast:
- The only step that can fail is done first, namely pinning the
framebuffers. After that we cross the point of no return, an async
commit would push all that into the worker thread.
- The disabling of encoders and connectors is a bit tricky, since
depending upon the final state we need to select different crtc
helper functions.
- Software tracking is a bit clarified compared to the crtc helpers:
We commit the software state before starting to touch the hardware,
like crtc helpers. But since we just swap them we still have the old
state (i.e. the current hw state) around, which is really handy to
write simple disable functions. So no more
drm_crtc_helper_disable_all_unused_functions kind of fun because
we're leaving unused crtcs/encoders behind. Everything gets shut
down in-order now, which is one of the key differences of the i915
helpers compared to crtc helpers and a really nice additional
guarantee.
- Like with the plane helpers the atomic commit function waits for one
vblank to pass before calling the framebuffer cleanup function.
Compared to Rob's helper approach there's a bunch of upsides:
- All the interfaces which can fail are called in the ->check hook
(i.e. ->best_match and the various ->mode_fixup hooks). This means
that drivers can just reuse those functions and don't need to move
everything into ->atomic_check callbacks. If drivers have no need
for additional constraint checking beyong their existing crtc
helper callbacks they don't need to do anything.
- The actual commit operation is properly stage: First we prepare
framebuffers, which can potentially still fail (due to memory
exhausting). This is important for the async case, where this must
be done synchronously to correctly return errors.
- The output configuration changes (done with crtc helper functions)
and the plane update (using atomic plane helpers) are correctly
interleaved: First we shut down any crtcs that need changing, then
we update planes and finally we enable everything again. Hardware
without GO bits must be more careful with ordering, which this
sequence enables.
- Also for hardware with shared output resources (like display PLLs)
we first must shut down the old configuration before we can enable
the new one. Otherwise we can hit an impossible intermediate state
where there's not enough PLLs (which is the point behind atomic
updates).
v2:
- Ensure that users of ->check update crtc_state->enable correctly.
- Update the legacy state in crtc/plane structures. Eventually we want
to remove that, but for now the drm core still expects this (especially
the plane->fb pointer).
v3: A few changes for better async handling:
- Reorder the software side state commit so that it happens all before
we touch the hardware. This way async support becomes very easy
since we can punt all the actual hw touching to a worker thread. And
as long as we synchronize with that thread (flushing or cancelling,
depending upon what the driver can handle) before we commit the next
software state there's no need for any locking in the worker thread
at all. Which greatly simplifies things.
And as long as we synchronize with all relevant threads we can have
a lot of them (e.g. per-crtc for per-crtc updates) running in
parallel.
- Expose pre/post plane commit steps separately. We need to expose the
actual hw commit step anyway for drivers to be able to implement
asynchronous commit workers. But if we expose pre/post and plane
commit steps individually we allow drivers to selectively use atomic
helpers.
- I've forgotten to call encoder/bridge ->mode_set functions, fix
this.
v4: Add debug output and fix a mixup between current and new state
that resulted in crtcs not getting updated correctly. And in an
Oops ...
v5:
- Be kind to driver writers in the vblank wait functions.. if thing
aren't working yet, and vblank irq will never come, then let's not
block forever.. especially under console-lock.
- Correctly clear connector_state->best_encoder when disabling.
Spotted while trying to understand a report from Rob Clark.
- Only steal encoder if it actually changed, otherwise hilarity ensues
if we steal from the current connector and so set the ->crtc pointer
unexpectedly to NULL. Reported by Rob Clark.
- Bail out in disable_outputs if an output currently doesn't have a
best_encoder - this means it's already disabled.
v6: Fixupe kerneldoc as reported by Paulo. And also fix up kerneldoc
in drm_crtc.h.
v7: Take ownership of the atomic state and clean it up with
drm_atomic_state_free().
v8 Various improvements all over:
- Polish code comments and kerneldoc.
- Improve debug output to make sure all failure cases are logged.
- Treat enabled crtc with no connectors as invalid input from userspace.
- Don't ignore the return value from mode_fixup().
v9:
- Improve debug output for crtc_state->mode_changed.
v10:
- Fixup the vblank waiting code to properly balance the vblank_get/put
calls.
- Better comments when checking/computing crtc->mode_changed
v11: Fixup the encoder stealing logic: We can't look at encoder->crtc
since that's not in the atomic state structures and might be updated
asynchronously in and async commit. Instead we need to inspect all the
connector states and check whether the encoder is currently in used
and if so, on which crtc.
v12: Review from Sean:
- A few spelling fixes.
- Flatten control flow indent by converting if blocks to early
continue/return in 2 places.
- Capture connectors_for_crtc return value in int num_connectors
instead of bool has_connectors and do an explicit int->bool
conversion with !!. I think the helper is more useful for drivers if
it returns the number of connectors (e.g. to detect cloning
configurations), so decided to keep that return value.
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-16 23:50:47 +08:00
|
|
|
|
2014-11-22 04:28:31 +08:00
|
|
|
/* attached planes bitmask:
|
|
|
|
* WARNING: transitional helpers do not maintain plane_mask so
|
|
|
|
* drivers not converted over to atomic helpers should not rely
|
|
|
|
* on plane_mask being accurate!
|
|
|
|
*/
|
|
|
|
u32 plane_mask;
|
|
|
|
|
2016-01-04 19:53:18 +08:00
|
|
|
u32 connector_mask;
|
2016-01-28 22:04:58 +08:00
|
|
|
u32 encoder_mask;
|
2016-01-04 19:53:18 +08:00
|
|
|
|
drm: Atomic crtc/connector updates using crtc/plane helper interfaces
So this is finally the integration of the crtc and plane helper
interfaces into the atomic helper functions.
In the check function we now have a few steps:
- First we update the output routing and figure out which crtcs need a
full mode set. Suitable encoders are selected using ->best_encoder,
with the same semantics as the crtc helpers of implicitly disabling
all connectors currently using the encoder.
- Then we pull all other connectors into the state update which feed
from a crtc which changes. This must be done do catch mode changes
and similar updates - atomic updates are differences on top of the
current state.
- Then we call all the various ->mode_fixup to compute the adjusted
mode. Note that here we have a slight semantic difference compared
to the crtc helpers: We have not yet updated the encoder->crtc link
when calling the encoder's ->mode_fixup function. But that's a
requirement when converting to atomic since we want to prepare the
entire state completely contained with the over drm_atomic_state
structure. So this must be carefully checked when converting drivers
over to atomic helpers.
- Finally we do call the atomic_check functions on planes and crtcs.
The commit function is also quite a beast:
- The only step that can fail is done first, namely pinning the
framebuffers. After that we cross the point of no return, an async
commit would push all that into the worker thread.
- The disabling of encoders and connectors is a bit tricky, since
depending upon the final state we need to select different crtc
helper functions.
- Software tracking is a bit clarified compared to the crtc helpers:
We commit the software state before starting to touch the hardware,
like crtc helpers. But since we just swap them we still have the old
state (i.e. the current hw state) around, which is really handy to
write simple disable functions. So no more
drm_crtc_helper_disable_all_unused_functions kind of fun because
we're leaving unused crtcs/encoders behind. Everything gets shut
down in-order now, which is one of the key differences of the i915
helpers compared to crtc helpers and a really nice additional
guarantee.
- Like with the plane helpers the atomic commit function waits for one
vblank to pass before calling the framebuffer cleanup function.
Compared to Rob's helper approach there's a bunch of upsides:
- All the interfaces which can fail are called in the ->check hook
(i.e. ->best_match and the various ->mode_fixup hooks). This means
that drivers can just reuse those functions and don't need to move
everything into ->atomic_check callbacks. If drivers have no need
for additional constraint checking beyong their existing crtc
helper callbacks they don't need to do anything.
- The actual commit operation is properly stage: First we prepare
framebuffers, which can potentially still fail (due to memory
exhausting). This is important for the async case, where this must
be done synchronously to correctly return errors.
- The output configuration changes (done with crtc helper functions)
and the plane update (using atomic plane helpers) are correctly
interleaved: First we shut down any crtcs that need changing, then
we update planes and finally we enable everything again. Hardware
without GO bits must be more careful with ordering, which this
sequence enables.
- Also for hardware with shared output resources (like display PLLs)
we first must shut down the old configuration before we can enable
the new one. Otherwise we can hit an impossible intermediate state
where there's not enough PLLs (which is the point behind atomic
updates).
v2:
- Ensure that users of ->check update crtc_state->enable correctly.
- Update the legacy state in crtc/plane structures. Eventually we want
to remove that, but for now the drm core still expects this (especially
the plane->fb pointer).
v3: A few changes for better async handling:
- Reorder the software side state commit so that it happens all before
we touch the hardware. This way async support becomes very easy
since we can punt all the actual hw touching to a worker thread. And
as long as we synchronize with that thread (flushing or cancelling,
depending upon what the driver can handle) before we commit the next
software state there's no need for any locking in the worker thread
at all. Which greatly simplifies things.
And as long as we synchronize with all relevant threads we can have
a lot of them (e.g. per-crtc for per-crtc updates) running in
parallel.
- Expose pre/post plane commit steps separately. We need to expose the
actual hw commit step anyway for drivers to be able to implement
asynchronous commit workers. But if we expose pre/post and plane
commit steps individually we allow drivers to selectively use atomic
helpers.
- I've forgotten to call encoder/bridge ->mode_set functions, fix
this.
v4: Add debug output and fix a mixup between current and new state
that resulted in crtcs not getting updated correctly. And in an
Oops ...
v5:
- Be kind to driver writers in the vblank wait functions.. if thing
aren't working yet, and vblank irq will never come, then let's not
block forever.. especially under console-lock.
- Correctly clear connector_state->best_encoder when disabling.
Spotted while trying to understand a report from Rob Clark.
- Only steal encoder if it actually changed, otherwise hilarity ensues
if we steal from the current connector and so set the ->crtc pointer
unexpectedly to NULL. Reported by Rob Clark.
- Bail out in disable_outputs if an output currently doesn't have a
best_encoder - this means it's already disabled.
v6: Fixupe kerneldoc as reported by Paulo. And also fix up kerneldoc
in drm_crtc.h.
v7: Take ownership of the atomic state and clean it up with
drm_atomic_state_free().
v8 Various improvements all over:
- Polish code comments and kerneldoc.
- Improve debug output to make sure all failure cases are logged.
- Treat enabled crtc with no connectors as invalid input from userspace.
- Don't ignore the return value from mode_fixup().
v9:
- Improve debug output for crtc_state->mode_changed.
v10:
- Fixup the vblank waiting code to properly balance the vblank_get/put
calls.
- Better comments when checking/computing crtc->mode_changed
v11: Fixup the encoder stealing logic: We can't look at encoder->crtc
since that's not in the atomic state structures and might be updated
asynchronously in and async commit. Instead we need to inspect all the
connector states and check whether the encoder is currently in used
and if so, on which crtc.
v12: Review from Sean:
- A few spelling fixes.
- Flatten control flow indent by converting if blocks to early
continue/return in 2 places.
- Capture connectors_for_crtc return value in int num_connectors
instead of bool has_connectors and do an explicit int->bool
conversion with !!. I think the helper is more useful for drivers if
it returns the number of connectors (e.g. to detect cloning
configurations), so decided to keep that return value.
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-16 23:50:47 +08:00
|
|
|
/* last_vblank_count: for vblank waits before cleanup */
|
|
|
|
u32 last_vblank_count;
|
2014-11-05 07:14:14 +08:00
|
|
|
|
2014-10-29 18:13:47 +08:00
|
|
|
/* adjusted_mode: for use by helpers and drivers */
|
|
|
|
struct drm_display_mode adjusted_mode;
|
|
|
|
|
2014-10-28 03:28:44 +08:00
|
|
|
struct drm_display_mode mode;
|
|
|
|
|
2015-05-26 02:11:51 +08:00
|
|
|
/* blob property to expose current mode to atomic userspace */
|
|
|
|
struct drm_property_blob *mode_blob;
|
|
|
|
|
2016-02-27 01:05:00 +08:00
|
|
|
/* blob property to expose color management to userspace */
|
|
|
|
struct drm_property_blob *degamma_lut;
|
|
|
|
struct drm_property_blob *ctm;
|
|
|
|
struct drm_property_blob *gamma_lut;
|
|
|
|
|
2016-09-30 18:04:56 +08:00
|
|
|
/**
|
|
|
|
* @event:
|
|
|
|
*
|
|
|
|
* Optional pointer to a DRM event to signal upon completion of the
|
|
|
|
* state update. The driver must send out the event when the atomic
|
|
|
|
* commit operation completes. There are two cases:
|
|
|
|
*
|
|
|
|
* - The event is for a CRTC which is being disabled through this
|
|
|
|
* atomic commit. In that case the event can be send out any time
|
|
|
|
* after the hardware has stopped scanning out the current
|
|
|
|
* framebuffers. It should contain the timestamp and counter for the
|
|
|
|
* last vblank before the display pipeline was shut off.
|
|
|
|
*
|
|
|
|
* - For a CRTC which is enabled at the end of the commit (even when it
|
|
|
|
* undergoes an full modeset) the vblank timestamp and counter must
|
|
|
|
* be for the vblank right before the first frame that scans out the
|
|
|
|
* new set of buffers. Again the event can only be sent out after the
|
|
|
|
* hardware has stopped scanning out the old buffers.
|
|
|
|
*
|
|
|
|
* - Events for disabled CRTCs are not allowed, and drivers can ignore
|
|
|
|
* that 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 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.
|
|
|
|
*
|
|
|
|
* For hardware which supports some means to synchronize vblank
|
|
|
|
* interrupt delivery with committing display state there's also
|
|
|
|
* drm_crtc_arm_vblank_event(). See the documentation of that function
|
|
|
|
* for a detailed discussion of the constraints it needs to be used
|
|
|
|
* safely.
|
|
|
|
*/
|
2014-10-28 03:28:44 +08:00
|
|
|
struct drm_pending_vblank_event *event;
|
|
|
|
|
|
|
|
struct drm_atomic_state *state;
|
|
|
|
};
|
2008-11-08 06:05:41 +08:00
|
|
|
|
|
|
|
/**
|
2014-10-27 23:54:27 +08:00
|
|
|
* struct drm_crtc_funcs - control CRTCs for a given device
|
2008-11-08 06:05:41 +08:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc.
|
|
|
|
* connectors, not just CRTs).
|
|
|
|
*
|
|
|
|
* Each driver is responsible for filling out this structure at startup time,
|
|
|
|
* in addition to providing other modesetting features, like i2c and DDC
|
|
|
|
* bus accessors.
|
|
|
|
*/
|
|
|
|
struct drm_crtc_funcs {
|
2015-12-04 16:45:48 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2011-01-24 23:11:08 +08:00
|
|
|
void (*reset)(struct drm_crtc *crtc);
|
2008-11-08 06:05:41 +08:00
|
|
|
|
2015-12-04 16:46:00 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2008-11-08 06:05:41 +08:00
|
|
|
int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv,
|
|
|
|
uint32_t handle, uint32_t width, uint32_t height);
|
2015-12-04 16:46:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2013-06-20 09:48:52 +08:00
|
|
|
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);
|
2015-12-04 16:46:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2008-11-08 06:05:41 +08:00
|
|
|
int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
|
|
|
|
|
2015-12-04 16:46:00 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2016-06-07 18:49:30 +08:00
|
|
|
int (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
|
|
|
|
uint32_t size);
|
2015-12-04 16:45:48 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2008-11-08 06:05:41 +08:00
|
|
|
void (*destroy)(struct drm_crtc *crtc);
|
|
|
|
|
2015-12-04 16:46:00 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2008-11-08 06:05:41 +08:00
|
|
|
int (*set_config)(struct drm_mode_set *set);
|
2009-11-18 01:43:55 +08:00
|
|
|
|
2015-12-04 16:46:00 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*
|
|
|
|
* 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
|
2015-12-08 16:49:20 +08:00
|
|
|
* "ACTIVE" state) should result in an -EINVAL error code. Note that
|
|
|
|
* drm_atomic_helper_page_flip() checks this already for atomic drivers.
|
2009-11-18 01:43:55 +08:00
|
|
|
*/
|
|
|
|
int (*page_flip)(struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-23 09:49:58 +08:00
|
|
|
struct drm_pending_vblank_event *event,
|
|
|
|
uint32_t flags);
|
2012-05-16 05:09:05 +08:00
|
|
|
|
2016-08-08 15:23:03 +08:00
|
|
|
/**
|
|
|
|
* @page_flip_target:
|
|
|
|
*
|
|
|
|
* Same as @page_flip but with an additional parameter specifying the
|
|
|
|
* absolute target vertical blank period (as reported by
|
|
|
|
* drm_crtc_vblank_count()) when the flip should take effect.
|
|
|
|
*
|
|
|
|
* Note that the core code calls drm_crtc_vblank_get before this entry
|
|
|
|
* point, and will call drm_crtc_vblank_put if this entry point returns
|
|
|
|
* any non-0 error code. It's the driver's responsibility to call
|
|
|
|
* drm_crtc_vblank_put after this entry point returns 0, typically when
|
|
|
|
* the flip completes.
|
|
|
|
*/
|
|
|
|
int (*page_flip_target)(struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_pending_vblank_event *event,
|
|
|
|
uint32_t flags, uint32_t target);
|
|
|
|
|
2015-12-04 16:45:48 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2012-05-16 05:09:05 +08:00
|
|
|
int (*set_property)(struct drm_crtc *crtc,
|
|
|
|
struct drm_property *property, uint64_t val);
|
2014-10-28 03:28:44 +08:00
|
|
|
|
2015-12-04 16:45:48 +08:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2014-10-28 03:28:44 +08:00
|
|
|
struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
|
2015-12-04 16:45:48 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @atomic_destroy_state:
|
|
|
|
*
|
|
|
|
* Destroy a state duplicated with @atomic_duplicate_state and release
|
|
|
|
* or unreference all resources it references
|
|
|
|
*/
|
2014-10-28 03:28:44 +08:00
|
|
|
void (*atomic_destroy_state)(struct drm_crtc *crtc,
|
2014-07-26 03:30:38 +08:00
|
|
|
struct drm_crtc_state *state);
|
2015-12-04 16:45:48 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2014-10-28 03:28:44 +08:00
|
|
|
int (*atomic_set_property)(struct drm_crtc *crtc,
|
|
|
|
struct drm_crtc_state *state,
|
|
|
|
struct drm_property *property,
|
|
|
|
uint64_t val);
|
2015-12-04 16:45:48 +08:00
|
|
|
/**
|
|
|
|
* @atomic_get_property:
|
|
|
|
*
|
|
|
|
* Reads out the decoded driver-private property. This is used to
|
2015-12-04 16:46:01 +08:00
|
|
|
* implement the GETCRTC IOCTL.
|
2015-12-04 16:45:48 +08:00
|
|
|
*
|
|
|
|
* 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).
|
|
|
|
*/
|
2014-12-19 05:01:47 +08:00
|
|
|
int (*atomic_get_property)(struct drm_crtc *crtc,
|
|
|
|
const struct drm_crtc_state *state,
|
|
|
|
struct drm_property *property,
|
|
|
|
uint64_t *val);
|
2016-06-21 22:37:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @late_register:
|
|
|
|
*
|
|
|
|
* This optional hook can be used to register additional userspace
|
|
|
|
* interfaces attached to the crtc like debugfs interfaces.
|
|
|
|
* It is called late in the driver load sequence from drm_dev_register().
|
|
|
|
* Everything added from this callback should be unregistered in
|
|
|
|
* the early_unregister callback.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
*
|
|
|
|
* 0 on success, or a negative error code on failure.
|
|
|
|
*/
|
|
|
|
int (*late_register)(struct drm_crtc *crtc);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @early_unregister:
|
|
|
|
*
|
|
|
|
* This optional hook should be used to unregister the additional
|
|
|
|
* userspace interfaces attached to the crtc from
|
|
|
|
* late_unregister(). It is called from drm_dev_unregister(),
|
|
|
|
* early in the driver unload sequence to disable userspace access
|
|
|
|
* before data structures are torndown.
|
|
|
|
*/
|
|
|
|
void (*early_unregister)(struct drm_crtc *crtc);
|
2016-10-06 23:21:06 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @set_crc_source:
|
|
|
|
*
|
|
|
|
* Changes the source of CRC checksums of frames at the request of
|
|
|
|
* userspace, typically for testing purposes. The sources available are
|
|
|
|
* specific of each driver and a %NULL value indicates that CRC
|
|
|
|
* generation is to be switched off.
|
|
|
|
*
|
|
|
|
* When CRC generation is enabled, the driver should call
|
|
|
|
* drm_crtc_add_crc_entry() at each frame, providing any information
|
|
|
|
* that characterizes the frame contents in the crcN arguments, as
|
|
|
|
* provided from the configured source. Drivers must accept a "auto"
|
|
|
|
* source name that will select a default source for this CRTC.
|
|
|
|
*
|
|
|
|
* This callback is optional if the driver does not support any CRC
|
|
|
|
* generation functionality.
|
|
|
|
*
|
|
|
|
* RETURNS:
|
|
|
|
*
|
|
|
|
* 0 on success or a negative error code on failure.
|
|
|
|
*/
|
|
|
|
int (*set_crc_source)(struct drm_crtc *crtc, const char *source,
|
|
|
|
size_t *values_cnt);
|
2016-11-05 23:08:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @atomic_print_state:
|
|
|
|
*
|
|
|
|
* If driver subclasses struct &drm_crtc_state, it should implement
|
|
|
|
* this optional hook for printing additional driver specific state.
|
|
|
|
*
|
|
|
|
* Do not call this directly, use drm_atomic_crtc_print_state()
|
|
|
|
* instead.
|
|
|
|
*/
|
|
|
|
void (*atomic_print_state)(struct drm_printer *p,
|
|
|
|
const struct drm_crtc_state *state);
|
2008-11-08 06:05:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2014-10-27 23:54:27 +08:00
|
|
|
* struct drm_crtc - central CRTC control structure
|
2011-11-08 04:03:14 +08:00
|
|
|
* @dev: parent DRM device
|
2014-10-28 03:19:38 +08:00
|
|
|
* @port: OF node used by drm_of_find_possible_crtcs()
|
2011-11-08 04:03:14 +08:00
|
|
|
* @head: list management
|
2016-06-01 05:11:10 +08:00
|
|
|
* @name: human readable name, can be overwritten by the driver
|
2013-11-20 01:10:12 +08:00
|
|
|
* @mutex: per-CRTC locking
|
2011-11-08 04:03:14 +08:00
|
|
|
* @base: base KMS object for ID tracking etc.
|
2014-04-02 06:22:38 +08:00
|
|
|
* @primary: primary plane for this CRTC
|
|
|
|
* @cursor: cursor plane for this CRTC
|
2014-10-28 03:19:38 +08:00
|
|
|
* @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
|
2008-11-08 06:05:41 +08:00
|
|
|
* @enabled: is this CRTC enabled?
|
2011-11-08 04:03:14 +08:00
|
|
|
* @mode: current mode timings
|
|
|
|
* @hwmode: mode timings as programmed to hw regs
|
2008-11-08 06:05:41 +08:00
|
|
|
* @x: x position on screen
|
|
|
|
* @y: y position on screen
|
|
|
|
* @funcs: CRTC control functions
|
2011-11-08 04:03:14 +08:00
|
|
|
* @gamma_size: size of gamma ramp
|
|
|
|
* @gamma_store: gamma ramp values
|
|
|
|
* @helper_private: mid-layer private data
|
2012-05-16 05:09:05 +08:00
|
|
|
* @properties: property tracking for this CRTC
|
2008-11-08 06:05:41 +08:00
|
|
|
*
|
|
|
|
* Each CRTC may have one or more connectors associated with it. This structure
|
|
|
|
* allows the CRTC to be controlled.
|
|
|
|
*/
|
|
|
|
struct drm_crtc {
|
|
|
|
struct drm_device *dev;
|
2014-06-15 18:07:12 +08:00
|
|
|
struct device_node *port;
|
2008-11-08 06:05:41 +08:00
|
|
|
struct list_head head;
|
|
|
|
|
2015-12-09 00:41:53 +08:00
|
|
|
char *name;
|
|
|
|
|
2016-06-01 05:11:10 +08:00
|
|
|
/**
|
|
|
|
* @mutex:
|
drm: add per-crtc locks
*drumroll*
The basic idea is to protect per-crtc state which can change without
touching the output configuration with separate mutexes, i.e. all the
input side state to a crtc like framebuffers, cursor settings or plane
configuration. Holding such a crtc lock gives a read-lock on all the
other crtc state which can be changed by e.g. a modeset.
All non-crtc state is still protected by the mode_config mutex.
Callers that need to change modeset state of a crtc (e.g. dpms or
set_mode) need to grab both the mode_config lock and nested within any
crtc locks.
Note that since there can only ever be one holder of the mode_config
lock we can grab the subordinate crtc locks in any order (if we need
to grab more than one of them). Lockdep can handle such nesting with
the mutex_lock_nest_lock call correctly.
With this functions that only touch connectors/encoders but not crtcs
only need to take the mode_config lock. The biggest such case is the
output probing, which means that we can now pageflip and move cursors
while the output probe code is reading an edid.
Most cases neatly fall into the three buckets:
- Only touches connectors and similar output state and so only needs
the mode_config lock.
- Touches the global configuration and so needs all locks.
- Only touches the crtc input side and so only needs the crtc lock.
But a few cases that need special consideration:
- Load detection which requires a crtc. The mode_config lock already
prevents a modeset change, so we can use any unused crtc as we like
to do load detection. The only thing to consider is that such
temporary state changes don't leak out to userspace through ioctls
that only take the crtc look (like a pageflip). Hence the load
detect code needs to grab the crtc of any output pipes it touches
(but only if it touches state used by the pageflip or cursor
ioctls).
- Atomic pageflip when moving planes. The first case is sane hw, where
planes have a fixed association with crtcs - nothing needs to be
done there. More insane^Wflexible hw needs to have plane->crtc
mapping which is separately protect with a lock that nests within
the crtc lock. If the plane is unused we can just assign it to the
current crtc and continue. But if a plane is already in use by
another crtc we can't just reassign it.
Two solution present themselves: Either go back to a slow-path which
takes all modeset locks, potentially incure quite a hefty delay. Or
simply disallowing such changes in one atomic pageflip - in general
the vblanks of two crtcs are not synced, so there's no sane way to
atomically flip such plane changes accross more than one crtc. I'd
heavily favour the later approach, going as far as mandating it as
part of the ABI of such a new a nuclear pageflip.
And if we _really_ want such semantics, we can always get them by
introducing another pageflip mutex between the mode_config.mutex and
the individual crtc locks. Pageflips crossing more than one crtc
would then need to take that lock first, to lock out concurrent
multi-crtc pageflips.
- Optimized global modeset operations: We could just take the
mode_config lock and then lazily lock all crtc which are affected by
a modeset operation. This has the advantage that pageflip could
continue unhampered on unaffected crtc. But if e.g. global resources
like plls need to be reassigned and so affect unrelated crtcs we can
still do that - nested locking works in any order.
This patch just adds the locks and takes them in drm_modeset_lock_all,
no real locking changes yet.
v2: Need to initialize the new lock in crtc_init and lock it righ
away, for otherwise the modeset_unlock_all below will try to unlock a
not-locked mutex.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-02 09:18:25 +08:00
|
|
|
*
|
|
|
|
* This provides a read lock for the overall crtc state (mode, dpms
|
|
|
|
* state, ...) and a write lock for everything which can be update
|
2016-06-01 05:11:10 +08:00
|
|
|
* without a full modeset (fb, cursor data, crtc properties ...). Full
|
|
|
|
* modeset also need to grab dev->mode_config.connection_mutex.
|
drm: add per-crtc locks
*drumroll*
The basic idea is to protect per-crtc state which can change without
touching the output configuration with separate mutexes, i.e. all the
input side state to a crtc like framebuffers, cursor settings or plane
configuration. Holding such a crtc lock gives a read-lock on all the
other crtc state which can be changed by e.g. a modeset.
All non-crtc state is still protected by the mode_config mutex.
Callers that need to change modeset state of a crtc (e.g. dpms or
set_mode) need to grab both the mode_config lock and nested within any
crtc locks.
Note that since there can only ever be one holder of the mode_config
lock we can grab the subordinate crtc locks in any order (if we need
to grab more than one of them). Lockdep can handle such nesting with
the mutex_lock_nest_lock call correctly.
With this functions that only touch connectors/encoders but not crtcs
only need to take the mode_config lock. The biggest such case is the
output probing, which means that we can now pageflip and move cursors
while the output probe code is reading an edid.
Most cases neatly fall into the three buckets:
- Only touches connectors and similar output state and so only needs
the mode_config lock.
- Touches the global configuration and so needs all locks.
- Only touches the crtc input side and so only needs the crtc lock.
But a few cases that need special consideration:
- Load detection which requires a crtc. The mode_config lock already
prevents a modeset change, so we can use any unused crtc as we like
to do load detection. The only thing to consider is that such
temporary state changes don't leak out to userspace through ioctls
that only take the crtc look (like a pageflip). Hence the load
detect code needs to grab the crtc of any output pipes it touches
(but only if it touches state used by the pageflip or cursor
ioctls).
- Atomic pageflip when moving planes. The first case is sane hw, where
planes have a fixed association with crtcs - nothing needs to be
done there. More insane^Wflexible hw needs to have plane->crtc
mapping which is separately protect with a lock that nests within
the crtc lock. If the plane is unused we can just assign it to the
current crtc and continue. But if a plane is already in use by
another crtc we can't just reassign it.
Two solution present themselves: Either go back to a slow-path which
takes all modeset locks, potentially incure quite a hefty delay. Or
simply disallowing such changes in one atomic pageflip - in general
the vblanks of two crtcs are not synced, so there's no sane way to
atomically flip such plane changes accross more than one crtc. I'd
heavily favour the later approach, going as far as mandating it as
part of the ABI of such a new a nuclear pageflip.
And if we _really_ want such semantics, we can always get them by
introducing another pageflip mutex between the mode_config.mutex and
the individual crtc locks. Pageflips crossing more than one crtc
would then need to take that lock first, to lock out concurrent
multi-crtc pageflips.
- Optimized global modeset operations: We could just take the
mode_config lock and then lazily lock all crtc which are affected by
a modeset operation. This has the advantage that pageflip could
continue unhampered on unaffected crtc. But if e.g. global resources
like plls need to be reassigned and so affect unrelated crtcs we can
still do that - nested locking works in any order.
This patch just adds the locks and takes them in drm_modeset_lock_all,
no real locking changes yet.
v2: Need to initialize the new lock in crtc_init and lock it righ
away, for otherwise the modeset_unlock_all below will try to unlock a
not-locked mutex.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-02 09:18:25 +08:00
|
|
|
*/
|
2013-11-20 01:10:12 +08:00
|
|
|
struct drm_modeset_lock mutex;
|
drm: add per-crtc locks
*drumroll*
The basic idea is to protect per-crtc state which can change without
touching the output configuration with separate mutexes, i.e. all the
input side state to a crtc like framebuffers, cursor settings or plane
configuration. Holding such a crtc lock gives a read-lock on all the
other crtc state which can be changed by e.g. a modeset.
All non-crtc state is still protected by the mode_config mutex.
Callers that need to change modeset state of a crtc (e.g. dpms or
set_mode) need to grab both the mode_config lock and nested within any
crtc locks.
Note that since there can only ever be one holder of the mode_config
lock we can grab the subordinate crtc locks in any order (if we need
to grab more than one of them). Lockdep can handle such nesting with
the mutex_lock_nest_lock call correctly.
With this functions that only touch connectors/encoders but not crtcs
only need to take the mode_config lock. The biggest such case is the
output probing, which means that we can now pageflip and move cursors
while the output probe code is reading an edid.
Most cases neatly fall into the three buckets:
- Only touches connectors and similar output state and so only needs
the mode_config lock.
- Touches the global configuration and so needs all locks.
- Only touches the crtc input side and so only needs the crtc lock.
But a few cases that need special consideration:
- Load detection which requires a crtc. The mode_config lock already
prevents a modeset change, so we can use any unused crtc as we like
to do load detection. The only thing to consider is that such
temporary state changes don't leak out to userspace through ioctls
that only take the crtc look (like a pageflip). Hence the load
detect code needs to grab the crtc of any output pipes it touches
(but only if it touches state used by the pageflip or cursor
ioctls).
- Atomic pageflip when moving planes. The first case is sane hw, where
planes have a fixed association with crtcs - nothing needs to be
done there. More insane^Wflexible hw needs to have plane->crtc
mapping which is separately protect with a lock that nests within
the crtc lock. If the plane is unused we can just assign it to the
current crtc and continue. But if a plane is already in use by
another crtc we can't just reassign it.
Two solution present themselves: Either go back to a slow-path which
takes all modeset locks, potentially incure quite a hefty delay. Or
simply disallowing such changes in one atomic pageflip - in general
the vblanks of two crtcs are not synced, so there's no sane way to
atomically flip such plane changes accross more than one crtc. I'd
heavily favour the later approach, going as far as mandating it as
part of the ABI of such a new a nuclear pageflip.
And if we _really_ want such semantics, we can always get them by
introducing another pageflip mutex between the mode_config.mutex and
the individual crtc locks. Pageflips crossing more than one crtc
would then need to take that lock first, to lock out concurrent
multi-crtc pageflips.
- Optimized global modeset operations: We could just take the
mode_config lock and then lazily lock all crtc which are affected by
a modeset operation. This has the advantage that pageflip could
continue unhampered on unaffected crtc. But if e.g. global resources
like plls need to be reassigned and so affect unrelated crtcs we can
still do that - nested locking works in any order.
This patch just adds the locks and takes them in drm_modeset_lock_all,
no real locking changes yet.
v2: Need to initialize the new lock in crtc_init and lock it righ
away, for otherwise the modeset_unlock_all below will try to unlock a
not-locked mutex.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-02 09:18:25 +08:00
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
struct drm_mode_object base;
|
|
|
|
|
2014-04-02 06:22:38 +08:00
|
|
|
/* primary and cursor planes for CRTC */
|
|
|
|
struct drm_plane *primary;
|
|
|
|
struct drm_plane *cursor;
|
|
|
|
|
2016-07-16 03:47:59 +08:00
|
|
|
/**
|
|
|
|
* @index: Position inside the mode_config.list, can be used as an array
|
|
|
|
* index. It is invariant over the lifetime of the CRTC.
|
|
|
|
*/
|
2016-05-28 03:05:00 +08:00
|
|
|
unsigned index;
|
|
|
|
|
2014-06-10 23:28:10 +08:00
|
|
|
/* position of cursor plane on crtc */
|
|
|
|
int cursor_x;
|
|
|
|
int cursor_y;
|
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
bool enabled;
|
|
|
|
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 10:20:23 +08:00
|
|
|
/* Requested mode from modesetting. */
|
2008-11-08 06:05:41 +08:00
|
|
|
struct drm_display_mode mode;
|
|
|
|
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 10:20:23 +08:00
|
|
|
/* Programmed mode in hw, after adjustments for encoders,
|
|
|
|
* crtc, panel scaling etc. Needed for timestamping etc.
|
|
|
|
*/
|
|
|
|
struct drm_display_mode hwmode;
|
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
int x, y;
|
|
|
|
const struct drm_crtc_funcs *funcs;
|
|
|
|
|
2016-02-27 01:05:00 +08:00
|
|
|
/* Legacy FB CRTC gamma size for reporting to userspace */
|
2008-11-08 06:05:41 +08:00
|
|
|
uint32_t gamma_size;
|
|
|
|
uint16_t *gamma_store;
|
|
|
|
|
|
|
|
/* if you are using the helper */
|
2015-12-04 16:45:45 +08:00
|
|
|
const struct drm_crtc_helper_funcs *helper_private;
|
2012-05-16 05:09:05 +08:00
|
|
|
|
|
|
|
struct drm_object_properties properties;
|
2014-07-26 00:07:40 +08:00
|
|
|
|
2016-06-08 20:19:00 +08:00
|
|
|
/**
|
|
|
|
* @state:
|
|
|
|
*
|
|
|
|
* Current atomic state for this CRTC.
|
|
|
|
*/
|
2014-10-28 03:28:44 +08:00
|
|
|
struct drm_crtc_state *state;
|
|
|
|
|
2016-06-08 20:19:00 +08:00
|
|
|
/**
|
|
|
|
* @commit_list:
|
|
|
|
*
|
|
|
|
* List of &drm_crtc_commit structures tracking pending commits.
|
|
|
|
* Protected by @commit_lock. This list doesn't hold its own full
|
|
|
|
* reference, but burrows it from the ongoing commit. Commit entries
|
|
|
|
* must be removed from this list once the commit is fully completed,
|
|
|
|
* but before it's correspoding &drm_atomic_state gets destroyed.
|
|
|
|
*/
|
|
|
|
struct list_head commit_list;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @commit_lock:
|
|
|
|
*
|
|
|
|
* Spinlock to protect @commit_list.
|
|
|
|
*/
|
|
|
|
spinlock_t commit_lock;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @acquire_ctx:
|
|
|
|
*
|
|
|
|
* Per-CRTC implicit acquire context used by atomic drivers for legacy
|
|
|
|
* IOCTLs, so that atomic drivers can get at the locking acquire
|
|
|
|
* context.
|
2014-07-26 00:07:40 +08:00
|
|
|
*/
|
|
|
|
struct drm_modeset_acquire_ctx *acquire_ctx;
|
2016-10-06 23:21:06 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
/**
|
|
|
|
* @debugfs_entry:
|
|
|
|
*
|
|
|
|
* Debugfs directory for this CRTC.
|
|
|
|
*/
|
|
|
|
struct dentry *debugfs_entry;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @crc:
|
|
|
|
*
|
|
|
|
* Configuration settings of CRC capture.
|
|
|
|
*/
|
|
|
|
struct drm_crtc_crc crc;
|
|
|
|
#endif
|
2016-11-15 22:37:08 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @fence_context:
|
|
|
|
*
|
|
|
|
* timeline context used for fence operations.
|
|
|
|
*/
|
|
|
|
unsigned int fence_context;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @fence_lock:
|
|
|
|
*
|
|
|
|
* spinlock to protect the fences in the fence_context.
|
|
|
|
*/
|
|
|
|
|
|
|
|
spinlock_t fence_lock;
|
|
|
|
/**
|
|
|
|
* @fence_seqno:
|
|
|
|
*
|
|
|
|
* Seqno variable used as monotonic counter for the fences
|
|
|
|
* created on the CRTC's timeline.
|
|
|
|
*/
|
|
|
|
unsigned long fence_seqno;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @timeline_name:
|
|
|
|
*
|
|
|
|
* The name of the CRTC's fence timeline.
|
|
|
|
*/
|
|
|
|
char timeline_name[32];
|
2008-11-08 06:05:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2014-10-27 23:54:27 +08:00
|
|
|
* struct drm_mode_set - new values for a CRTC config change
|
2011-11-08 04:03:19 +08:00
|
|
|
* @fb: framebuffer to use for new config
|
|
|
|
* @crtc: CRTC whose configuration we're about to change
|
|
|
|
* @mode: mode timings to use
|
|
|
|
* @x: position of this CRTC relative to @fb
|
|
|
|
* @y: position of this CRTC relative to @fb
|
|
|
|
* @connectors: array of connectors to drive with this CRTC if possible
|
|
|
|
* @num_connectors: size of @connectors array
|
2008-11-08 06:05:41 +08:00
|
|
|
*
|
|
|
|
* Represents a single crtc the connectors that it drives with what mode
|
|
|
|
* and from which framebuffer it scans out from.
|
|
|
|
*
|
|
|
|
* This is used to set modes.
|
|
|
|
*/
|
|
|
|
struct drm_mode_set {
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
struct drm_display_mode *mode;
|
|
|
|
|
|
|
|
uint32_t x;
|
|
|
|
uint32_t y;
|
|
|
|
|
|
|
|
struct drm_connector **connectors;
|
|
|
|
size_t num_connectors;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
|
|
|
|
|
2016-11-14 19:58:25 +08:00
|
|
|
__printf(6, 7)
|
drm: Pass 'name' to drm_crtc_init_with_planes()
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ä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1449670771-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-09 22:19:31 +08:00
|
|
|
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, ...);
|
2016-11-14 19:58:25 +08:00
|
|
|
void drm_crtc_cleanup(struct drm_crtc *crtc);
|
2016-05-28 03:05:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* drm_crtc_index - find the index of a registered CRTC
|
|
|
|
* @crtc: CRTC to find index for
|
|
|
|
*
|
|
|
|
* Given a registered CRTC, return the index of that CRTC within a DRM
|
|
|
|
* device's list of CRTCs.
|
|
|
|
*/
|
2016-10-10 23:26:10 +08:00
|
|
|
static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc)
|
2016-05-28 03:05:00 +08:00
|
|
|
{
|
|
|
|
return crtc->index;
|
|
|
|
}
|
2014-01-03 05:27:33 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* drm_crtc_mask - find the mask of a registered CRTC
|
|
|
|
* @crtc: CRTC to find mask for
|
|
|
|
*
|
|
|
|
* Given a registered CRTC, return the mask bit of that CRTC for an
|
|
|
|
* encoder's possible_crtcs field.
|
|
|
|
*/
|
2016-10-13 16:38:11 +08:00
|
|
|
static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc)
|
2014-01-03 05:27:33 +08:00
|
|
|
{
|
|
|
|
return 1 << drm_crtc_index(crtc);
|
|
|
|
}
|
2008-11-08 06:05:41 +08:00
|
|
|
|
2016-11-14 19:58:25 +08:00
|
|
|
void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
|
|
|
|
int *hdisplay, int *vdisplay);
|
|
|
|
int drm_crtc_force_disable(struct drm_crtc *crtc);
|
|
|
|
int drm_crtc_force_disable_all(struct drm_device *dev);
|
2011-11-15 06:51:27 +08:00
|
|
|
|
2016-11-14 19:58:25 +08:00
|
|
|
int drm_mode_set_config_internal(struct drm_mode_set *set);
|
2016-06-21 16:54:13 +08:00
|
|
|
|
2012-08-15 20:59:49 +08:00
|
|
|
/* Helpers */
|
|
|
|
static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
|
|
|
|
uint32_t id)
|
|
|
|
{
|
|
|
|
struct drm_mode_object *mo;
|
|
|
|
mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CRTC);
|
|
|
|
return mo ? obj_to_crtc(mo) : NULL;
|
|
|
|
}
|
|
|
|
|
drm: Add modeset object iterators
And roll them out across drm_* files. The point here isn't code
prettification (it helps with that too) but that some of these lists
aren't static any more. And having macros will gives us a convenient
place to put locking checks into.
I didn't add an iterator for props since that's only used by a
list_for_each_entry_safe in the driver teardown code.
Search&replace was done with the below cocci spatch. Note that there's
a bunch more places that didn't match and which would need some manual
changes, but I've intentially left these out for this mostly automated
patch.
iterator name drm_for_each_crtc;
struct drm_crtc *crtc;
struct drm_device *dev;
expression head;
@@
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ drm_for_each_crtc (crtc, dev) {
...
}
@@
iterator name drm_for_each_encoder;
struct drm_encoder *encoder;
struct drm_device *dev;
expression head;
@@
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ drm_for_each_encoder (encoder, dev) {
...
}
@@
iterator name drm_for_each_fb;
struct drm_framebuffer *fb;
struct drm_device *dev;
expression head;
@@
- list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ drm_for_each_fb (fb, dev) {
...
}
@@
iterator name drm_for_each_connector;
struct drm_connector *connector;
struct drm_device *dev;
expression head;
@@
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_for_each_connector (connector, dev) {
...
}
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
2015-07-10 05:44:25 +08:00
|
|
|
#define drm_for_each_crtc(crtc, dev) \
|
|
|
|
list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
|
|
|
|
|
2015-07-10 05:44:28 +08:00
|
|
|
static inline void
|
|
|
|
assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config)
|
|
|
|
{
|
2015-07-10 05:44:33 +08:00
|
|
|
/*
|
|
|
|
* The connector hotadd/remove code currently grabs both locks when
|
|
|
|
* updating lists. Hence readers need only hold either of them to be
|
|
|
|
* safe and the check amounts to
|
|
|
|
*
|
|
|
|
* WARN_ON(not_holding(A) && not_holding(B)).
|
|
|
|
*/
|
|
|
|
WARN_ON(!mutex_is_locked(&mode_config->mutex) &&
|
|
|
|
!drm_modeset_is_locked(&mode_config->connection_mutex));
|
2015-07-10 05:44:28 +08:00
|
|
|
}
|
|
|
|
|
2008-11-08 06:05:41 +08:00
|
|
|
#endif /* __DRM_CRTC_H__ */
|