Hi all,
Here's a pile of atomic helper cleanups. Big chunk is shredding the transitional helpers, I don't think they're useful anymore. armada is converted, vboxvideo is getting converted as we speak for 4.20, anything that's left is probably better to just move over to a simple display pipe driver.
Also some other related cleanups and driver patches mixed in, some (reworked) resends.
Comments very much welcome, as usual.
Thanks, Daniel
Daniel Vetter (17): drm/amdgpu: Remove default best_encoder hook from DC drm/atomic-helper: Unexport drm_atomic_helper_best_encoder drm: Extract drm_atomic_state_helper.[hc] drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property drm/vmwgfx: Don't look at state->allow_modeset drm/atomic: Improve docs for drm_atomic_state->allow_modeset drm/vmwgfx: Add FIXME comments for customer page_flip handlers drm/arcpgu: Drop transitional hooks drm/atmel: Drop transitional hooks drm/arcpgu: Use drm_atomic_helper_shutdown drm/msm: Use drm_atomic_helper_shutdown drm/sti: Use drm_atomic_helper_shutdown drm/vc4: Use drm_atomic_helper_shutdown drm/zte: Use drm_atomic_helper_shutdown drm: Remove transitional helpers drm: Unexport drm_plane_helper_check_update drm: Unexport primary plane helpers
Thomas Hellstrom (1): drm/vmwgfx: Fix vmw_du_cursor_plane_atomic_check
Documentation/gpu/drm-kms-helpers.rst | 19 +- drivers/gpu/drm/Makefile | 3 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +- drivers/gpu/drm/arc/arcpgu_crtc.c | 3 - drivers/gpu/drm/arc/arcpgu_drv.c | 1 + .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 2 - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 590 +---------------- drivers/gpu/drm/drm_atomic_state_helper.c | 601 ++++++++++++++++++ drivers/gpu/drm/drm_crtc_helper.c | 115 ---- drivers/gpu/drm/drm_plane_helper.c | 331 +--------- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 - drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 1 - drivers/gpu/drm/msm/msm_drv.c | 1 + drivers/gpu/drm/sti/sti_cursor.c | 1 - drivers/gpu/drm/sti/sti_drv.c | 6 +- drivers/gpu/drm/sti/sti_gdp.c | 1 - drivers/gpu/drm/sti/sti_hqvdp.c | 1 - drivers/gpu/drm/vc4/vc4_drv.c | 3 + drivers/gpu/drm/vc4/vc4_plane.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 38 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 +- drivers/gpu/drm/zte/zx_drm_drv.c | 1 + drivers/gpu/drm/zte/zx_plane.c | 1 - include/drm/drm_atomic.h | 10 +- include/drm/drm_atomic_helper.h | 46 +- include/drm/drm_atomic_state_helper.h | 80 +++ include/drm/drm_crtc_helper.h | 6 - include/drm/drm_plane_helper.h | 35 - 32 files changed, 767 insertions(+), 1154 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic_state_helper.c create mode 100644 include/drm/drm_atomic_state_helper.h
For atomic driver this is the default, no need to reimplement it. We still need to keep the copypasta for not-atomic drivers though, since no one polished the legacy crtc helpers as much as the atomic ones.
v2: amdgpu uses ->best_encoder internally, give it a local copy. It might be a good idea to merge the connector and encoder into one amdgpu_dm_sink structure, that might match DC internals better. At least for non-DPMST outputs. Kudos to Ville for spotting this.
v3: Rebase onto a487411a6481 ("drm/amd/display: Use DRM helper for best_encoder").
Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Alex Deucher alexander.deucher@amd.com Cc: Harry Wentland harry.wentland@amd.com Cc: Andrey Grodzovsky andrey.grodzovsky@amd.com Cc: Tony Cheng Tony.Cheng@amd.com Cc: "Leo (Sunpeng) Li" sunpeng.li@amd.com Cc: Shirish S shirish.s@amd.com --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6a2342d72742..107e70658238 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3189,7 +3189,6 @@ amdgpu_dm_connector_helper_funcs = { */ .get_modes = get_modes, .mode_valid = amdgpu_dm_connector_mode_valid, - .best_encoder = drm_atomic_helper_best_encoder };
static void dm_crtc_helper_disable(struct drm_crtc *crtc) @@ -3592,14 +3591,17 @@ static int to_drm_connector_type(enum signal_type st) } }
+static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector) +{ + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); +} + static void amdgpu_dm_get_native_mode(struct drm_connector *connector) { - const struct drm_connector_helper_funcs *helper = - connector->helper_private; struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder;
- encoder = helper->best_encoder(connector); + encoder = amdgpu_dm_connector_to_encoder(connector);
if (encoder == NULL) return; @@ -3726,14 +3728,12 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) { - const struct drm_connector_helper_funcs *helper = - connector->helper_private; struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); struct drm_encoder *encoder; struct edid *edid = amdgpu_dm_connector->edid;
- encoder = helper->best_encoder(connector); + encoder = amdgpu_dm_connector_to_encoder(connector);
if (!edid || !drm_edid_is_valid(edid)) { amdgpu_dm_connector->num_modes =
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1957,7 +1957,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { .get_modes = dw_hdmi_connector_get_modes, - .best_encoder = drm_atomic_helper_best_encoder, };
static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } }
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{ + WARN_ON(connector->encoder_ids[1]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); +} + static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/** - * drm_atomic_helper_best_encoder - Helper for - * &drm_connector_helper_funcs.best_encoder callback - * @connector: Connector control structure - * - * This is a &drm_connector_helper_funcs.best_encoder callback helper for - * connectors that support exactly 1 encoder, statically determined at driver - * init time. - */ -struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{ - WARN_ON(connector->encoder_ids[1]); - return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); -} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder); - /** * DOC: atomic state reset and initialization * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 723578117191..4b5378495eea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -274,7 +274,6 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = { - .best_encoder = drm_atomic_helper_best_encoder, };
/* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index ad0de7f0cd60..4c68ad6f3605 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -389,7 +389,6 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_sou_connector_helper_funcs = { - .best_encoder = drm_atomic_helper_best_encoder, };
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index f30e839f7bfd..e28bb08114a5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1037,7 +1037,6 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { - .best_encoder = drm_atomic_helper_best_encoder, };
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 657af7b39379..e60c4f0f8827 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -144,8 +144,6 @@ int drm_atomic_helper_page_flip_target( uint32_t flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector);
/* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
Hi Daniel,
Thank you for the patch.
On Tuesday, 2 October 2018 16:35:10 EEST Daniel Vetter wrote:
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
[snip]
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } }
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{
- WARN_ON(connector->encoder_ids[1]);
As you're removing the documentation, I would add a comment here to explain the WARN_ON. Something along the lines of "For connectors that support multiple encoders, the .atomic_best_encoder() or .atomic_encoder() operation must be implemented".
You could also rename the function to make it more explicit that it's a default for the single encoder case.
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+}
static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- drm_atomic_helper_best_encoder - Helper for
- &drm_connector_helper_funcs.best_encoder callback
- @connector: Connector control structure
- This is a &drm_connector_helper_funcs.best_encoder callback helper for
- connectors that support exactly 1 encoder, statically determined at
driver - * init time.
- */
-struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
/**
- DOC: atomic state reset and initialization
[snip]
On Tue, Oct 02, 2018 at 04:53:12PM +0300, Laurent Pinchart wrote:
Hi Daniel,
Thank you for the patch.
On Tuesday, 2 October 2018 16:35:10 EEST Daniel Vetter wrote:
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
[snip]
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } }
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{
- WARN_ON(connector->encoder_ids[1]);
As you're removing the documentation, I would add a comment here to explain the WARN_ON. Something along the lines of "For connectors that support multiple encoders, the .atomic_best_encoder() or .atomic_encoder() operation must be implemented".
You could also rename the function to make it more explicit that it's a default for the single encoder case.
So pick_single_encoder_for_connector()? I think that would avoid the need for a comment. r-b: you with that fixed up?
Thanks, Daniel
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+}
static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- drm_atomic_helper_best_encoder - Helper for
- &drm_connector_helper_funcs.best_encoder callback
- @connector: Connector control structure
- This is a &drm_connector_helper_funcs.best_encoder callback helper for
- connectors that support exactly 1 encoder, statically determined at
driver - * init time.
- */
-struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
/**
- DOC: atomic state reset and initialization
[snip]
-- Regards,
Laurent Pinchart
Hi Daniel,
On Wednesday, 3 October 2018 12:08:38 EEST Daniel Vetter wrote:
On Tue, Oct 02, 2018 at 04:53:12PM +0300, Laurent Pinchart wrote:
On Tuesday, 2 October 2018 16:35:10 EEST Daniel Vetter wrote:
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
[snip]
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, }
}
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{
- WARN_ON(connector->encoder_ids[1]);
As you're removing the documentation, I would add a comment here to explain the WARN_ON. Something along the lines of "For connectors that support multiple encoders, the .atomic_best_encoder() or .atomic_encoder() operation must be implemented".
You could also rename the function to make it more explicit that it's a default for the single encoder case.
So pick_single_encoder_for_connector()?
Works for me.
I think that would avoid the need for a comment.
I'd still keep the comment, it won't hurt, and you have it already :-)
r-b: you with that fixed up?
With the comment and function renamed,
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
- return drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[0]); +}
static int handle_conflicting_encoders(struct drm_atomic_state *state,
bool disable_conflicting_encoders)
{
@@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, }
EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- drm_atomic_helper_best_encoder - Helper for
- &drm_connector_helper_funcs.best_encoder callback
- @connector: Connector control structure
- This is a &drm_connector_helper_funcs.best_encoder callback helper
for
- connectors that support exactly 1 encoder, statically determined at
driver - * init time.
- */
-struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[0]); -} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
/**
- DOC: atomic state reset and initialization
[snip]
On Tue, Oct 02, 2018 at 03:35:10PM +0200, Daniel Vetter wrote:
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1957,7 +1957,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { .get_modes = dw_hdmi_connector_get_modes,
- .best_encoder = drm_atomic_helper_best_encoder,
};
static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } }
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+}
static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- drm_atomic_helper_best_encoder - Helper for
- &drm_connector_helper_funcs.best_encoder callback
- @connector: Connector control structure
- This is a &drm_connector_helper_funcs.best_encoder callback helper for
- connectors that support exactly 1 encoder, statically determined at driver
- init time.
- */
-struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
/**
- DOC: atomic state reset and initialization
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 723578117191..4b5378495eea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -274,7 +274,6 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
Seems like you can remove this entirely, as well as the helper funcs registration call? Same goes for a few other drivers.
Sean
/* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index ad0de7f0cd60..4c68ad6f3605 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -389,7 +389,6 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index f30e839f7bfd..e28bb08114a5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1037,7 +1037,6 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 657af7b39379..e60c4f0f8827 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -144,8 +144,6 @@ int drm_atomic_helper_page_flip_target( uint32_t flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector);
/* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Thu, Oct 04, 2018 at 02:33:24PM -0400, Sean Paul wrote:
On Tue, Oct 02, 2018 at 03:35:10PM +0200, Daniel Vetter wrote:
It's the default. The exported version was kinda a transition state, before we made this the default.
To stop new atomic drivers from using it (instead of just relying on the default) let's unexport it.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: Gustavo Padovan gustavo@padovan.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sean Paul seanpaul@chromium.org Cc: David Airlie airlied@linux.ie Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com Cc: Archit Taneja architt@codeaurora.org Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: Hans Verkuil hverkuil@xs4all.nl Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: Jani Nikula jani.nikula@intel.com Cc: Pierre-Hugues Husson phh@phh.me Cc: Fabio Estevam fabio.estevam@nxp.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 - drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++---------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 - include/drm/drm_atomic_helper.h | 2 -- 6 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ac37c50d6c4b..5ac979d3450b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1957,7 +1957,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { .get_modes = dw_hdmi_connector_get_modes,
- .best_encoder = drm_atomic_helper_best_encoder,
};
static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f92b7cf4cbd7..8c93f33fe92f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } }
+static struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+}
static int handle_conflicting_encoders(struct drm_atomic_state *state, bool disable_conflicting_encoders) { @@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- drm_atomic_helper_best_encoder - Helper for
- &drm_connector_helper_funcs.best_encoder callback
- @connector: Connector control structure
- This is a &drm_connector_helper_funcs.best_encoder callback helper for
- connectors that support exactly 1 encoder, statically determined at driver
- init time.
- */
-struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector) -{
- WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-} -EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
/**
- DOC: atomic state reset and initialization
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 723578117191..4b5378495eea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -274,7 +274,6 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
Seems like you can remove this entirely, as well as the helper funcs registration call? Same goes for a few other drivers.
Needs a huge audit, at least in the past we've had cases where everything started oopsing because helpers didn't check carefully whether the vtable pointer was NULL or not.
Heck even this patch here blew up on amdgpu at first.
So good idea, but maybe not in this patch here :-) -Daniel
/* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index ad0de7f0cd60..4c68ad6f3605 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -389,7 +389,6 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index f30e839f7bfd..e28bb08114a5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1037,7 +1037,6 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
- .best_encoder = drm_atomic_helper_best_encoder,
};
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 657af7b39379..e60c4f0f8827 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -144,8 +144,6 @@ int drm_atomic_helper_page_flip_target( uint32_t flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -struct drm_encoder * -drm_atomic_helper_best_encoder(struct drm_connector *connector);
/* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
-- Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
We already have a separate overview doc for this, makes sense to untangle it from the overall atomic helpers.
v2: Rebase
v3: Rebase more.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- Documentation/gpu/drm-kms-helpers.rst | 19 +- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_atomic_helper.c | 566 -------------------- drivers/gpu/drm/drm_atomic_state_helper.c | 601 ++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 44 +- include/drm/drm_atomic_state_helper.h | 80 +++ 6 files changed, 698 insertions(+), 615 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic_state_helper.c create mode 100644 include/drm/drm_atomic_state_helper.h
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index f9cfcdcdf024..4b4dc236ef6f 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -59,19 +59,28 @@ Implementing Asynchronous Atomic Commit .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c :doc: implementing nonblocking commit
+Helper Functions Reference +-------------------------- + +.. kernel-doc:: include/drm/drm_atomic_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c + :export: + Atomic State Reset and Initialization -------------------------------------
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :doc: atomic state reset and initialization
-Helper Functions Reference --------------------------- +Atomic State Helper Reference +-----------------------------
-.. kernel-doc:: include/drm/drm_atomic_helper.h +.. kernel-doc:: include/drm/drm_atomic_state_helper.h :internal:
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :export:
Simple KMS Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index bc6a16a3c36e..576ba985e138 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -36,7 +36,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_simple_kms_helper.o drm_modeset_helper.o \ - drm_scdc_helper.o drm_gem_framebuffer_helper.o + drm_scdc_helper.o drm_gem_framebuffer_helper.o \ + drm_atomic_state_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8c93f33fe92f..a5edc8757056 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3382,569 +3382,3 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, return ret; } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); - -/** - * DOC: atomic state reset and initialization - * - * Both the drm core and the atomic helpers assume that there is always the full - * and correct atomic software state for all connectors, CRTCs and planes - * available. Which is a bit a problem on driver load and also after system - * suspend. One way to solve this is to have a hardware state read-out - * infrastructure which reconstructs the full software state (e.g. the i915 - * driver). - * - * The simpler solution is to just reset the software state to everything off, - * which is easiest to do by calling drm_mode_config_reset(). To facilitate this - * the atomic helpers provide default reset implementations for all hooks. - * - * On the upside the precise state tracking of atomic simplifies system suspend - * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe - * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume(). - * For other drivers the building blocks are split out, see the documentation - * for these functions. - */ - -/** - * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs - * @crtc: drm CRTC - * - * Resets the atomic state for @crtc by freeing the state pointer (which might - * be NULL, e.g. at driver load time) and allocating a new empty state object. - */ -void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) -{ - if (crtc->state) - __drm_atomic_helper_crtc_destroy_state(crtc->state); - - kfree(crtc->state); - crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); - - if (crtc->state) - crtc->state->crtc = crtc; -} -EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); - -/** - * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state - * @crtc: CRTC object - * @state: atomic CRTC state - * - * Copies atomic state from a CRTC's current state and resets inferred values. - * This is useful for drivers that subclass the CRTC state. - */ -void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - memcpy(state, crtc->state, sizeof(*state)); - - if (state->mode_blob) - drm_property_blob_get(state->mode_blob); - if (state->degamma_lut) - drm_property_blob_get(state->degamma_lut); - if (state->ctm) - drm_property_blob_get(state->ctm); - if (state->gamma_lut) - drm_property_blob_get(state->gamma_lut); - state->mode_changed = false; - state->active_changed = false; - state->planes_changed = false; - state->connectors_changed = false; - state->color_mgmt_changed = false; - state->zpos_changed = false; - state->commit = NULL; - state->event = NULL; - state->pageflip_flags = 0; -} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); - -/** - * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook - * @crtc: drm CRTC - * - * Default CRTC state duplicate hook for drivers which don't have their own - * subclassed CRTC state structure. - */ -struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) -{ - struct drm_crtc_state *state; - - if (WARN_ON(!crtc->state)) - return NULL; - - state = kmalloc(sizeof(*state), GFP_KERNEL); - if (state) - __drm_atomic_helper_crtc_duplicate_state(crtc, state); - - return state; -} -EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); - -/** - * __drm_atomic_helper_crtc_destroy_state - release CRTC state - * @state: CRTC state object to release - * - * Releases all resources stored in the CRTC state without actually freeing - * the memory of the CRTC state. This is useful for drivers that subclass the - * CRTC state. - */ -void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) -{ - if (state->commit) { - /* - * In the event that a non-blocking commit returns - * -ERESTARTSYS before the commit_tail work is queued, we will - * have an extra reference to the commit object. Release it, if - * the event has not been consumed by the worker. - * - * state->event may be freed, so we can't directly look at - * state->event->base.completion. - */ - if (state->event && state->commit->abort_completion) - drm_crtc_commit_put(state->commit); - - kfree(state->commit->event); - state->commit->event = NULL; - - drm_crtc_commit_put(state->commit); - } - - drm_property_blob_put(state->mode_blob); - drm_property_blob_put(state->degamma_lut); - drm_property_blob_put(state->ctm); - drm_property_blob_put(state->gamma_lut); -} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); - -/** - * drm_atomic_helper_crtc_destroy_state - default state destroy hook - * @crtc: drm CRTC - * @state: CRTC state object to release - * - * Default CRTC state destroy hook for drivers which don't have their own - * subclassed CRTC state structure. - */ -void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - __drm_atomic_helper_crtc_destroy_state(state); - kfree(state); -} -EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); - -/** - * __drm_atomic_helper_plane_reset - resets planes state to default values - * @plane: plane object, must not be NULL - * @state: atomic plane state, must not be NULL - * - * Initializes plane state to default. This is useful for drivers that subclass - * the plane state. - */ -void __drm_atomic_helper_plane_reset(struct drm_plane *plane, - struct drm_plane_state *state) -{ - state->plane = plane; - state->rotation = DRM_MODE_ROTATE_0; - - state->alpha = DRM_BLEND_ALPHA_OPAQUE; - state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; - - plane->state = state; -} -EXPORT_SYMBOL(__drm_atomic_helper_plane_reset); - -/** - * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes - * @plane: drm plane - * - * Resets the atomic state for @plane by freeing the state pointer (which might - * be NULL, e.g. at driver load time) and allocating a new empty state object. - */ -void drm_atomic_helper_plane_reset(struct drm_plane *plane) -{ - if (plane->state) - __drm_atomic_helper_plane_destroy_state(plane->state); - - kfree(plane->state); - plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); - if (plane->state) - __drm_atomic_helper_plane_reset(plane, plane->state); -} -EXPORT_SYMBOL(drm_atomic_helper_plane_reset); - -/** - * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state - * @plane: plane object - * @state: atomic plane state - * - * Copies atomic state from a plane's current state. This is useful for - * drivers that subclass the plane state. - */ -void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, - struct drm_plane_state *state) -{ - memcpy(state, plane->state, sizeof(*state)); - - if (state->fb) - drm_framebuffer_get(state->fb); - - state->fence = NULL; - state->commit = NULL; -} -EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); - -/** - * drm_atomic_helper_plane_duplicate_state - default state duplicate hook - * @plane: drm plane - * - * Default plane state duplicate hook for drivers which don't have their own - * subclassed plane state structure. - */ -struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) -{ - struct drm_plane_state *state; - - if (WARN_ON(!plane->state)) - return NULL; - - state = kmalloc(sizeof(*state), GFP_KERNEL); - if (state) - __drm_atomic_helper_plane_duplicate_state(plane, state); - - return state; -} -EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); - -/** - * __drm_atomic_helper_plane_destroy_state - release plane state - * @state: plane state object to release - * - * Releases all resources stored in the plane state without actually freeing - * the memory of the plane state. This is useful for drivers that subclass the - * plane state. - */ -void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) -{ - if (state->fb) - drm_framebuffer_put(state->fb); - - if (state->fence) - dma_fence_put(state->fence); - - if (state->commit) - drm_crtc_commit_put(state->commit); -} -EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); - -/** - * drm_atomic_helper_plane_destroy_state - default state destroy hook - * @plane: drm plane - * @state: plane state object to release - * - * Default plane state destroy hook for drivers which don't have their own - * subclassed plane state structure. - */ -void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) -{ - __drm_atomic_helper_plane_destroy_state(state); - kfree(state); -} -EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); - -/** - * __drm_atomic_helper_connector_reset - reset state on connector - * @connector: drm connector - * @conn_state: connector state to assign - * - * Initializes the newly allocated @conn_state and assigns it to - * the &drm_conector->state pointer of @connector, usually required when - * initializing the drivers or when called from the &drm_connector_funcs.reset - * hook. - * - * This is useful for drivers that subclass the connector state. - */ -void -__drm_atomic_helper_connector_reset(struct drm_connector *connector, - struct drm_connector_state *conn_state) -{ - if (conn_state) - conn_state->connector = connector; - - connector->state = conn_state; -} -EXPORT_SYMBOL(__drm_atomic_helper_connector_reset); - -/** - * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors - * @connector: drm connector - * - * Resets the atomic state for @connector by freeing the state pointer (which - * might be NULL, e.g. at driver load time) and allocating a new empty state - * object. - */ -void drm_atomic_helper_connector_reset(struct drm_connector *connector) -{ - struct drm_connector_state *conn_state = - kzalloc(sizeof(*conn_state), GFP_KERNEL); - - if (connector->state) - __drm_atomic_helper_connector_destroy_state(connector->state); - - kfree(connector->state); - __drm_atomic_helper_connector_reset(connector, conn_state); -} -EXPORT_SYMBOL(drm_atomic_helper_connector_reset); - -/** - * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state - * @connector: connector object - * @state: atomic connector state - * - * Copies atomic state from a connector's current state. This is useful for - * drivers that subclass the connector state. - */ -void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, - struct drm_connector_state *state) -{ - memcpy(state, connector->state, sizeof(*state)); - if (state->crtc) - drm_connector_get(connector); - state->commit = NULL; - - /* Don't copy over a writeback job, they are used only once */ - state->writeback_job = NULL; -} -EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); - -/** - * drm_atomic_helper_connector_duplicate_state - default state duplicate hook - * @connector: drm connector - * - * Default connector state duplicate hook for drivers which don't have their own - * subclassed connector state structure. - */ -struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) -{ - struct drm_connector_state *state; - - if (WARN_ON(!connector->state)) - return NULL; - - state = kmalloc(sizeof(*state), GFP_KERNEL); - if (state) - __drm_atomic_helper_connector_duplicate_state(connector, state); - - return state; -} -EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); - -/** - * drm_atomic_helper_duplicate_state - duplicate an atomic state object - * @dev: DRM device - * @ctx: lock acquisition context - * - * Makes a copy of the current atomic state by looping over all objects and - * duplicating their respective states. This is used for example by suspend/ - * resume support code to save the state prior to suspend such that it can - * be restored upon resume. - * - * Note that this treats atomic state as persistent between save and restore. - * Drivers must make sure that this is possible and won't result in confusion - * or erroneous behaviour. - * - * Note that if callers haven't already acquired all modeset locks this might - * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). - * - * Returns: - * A pointer to the copy of the atomic state object on success or an - * ERR_PTR()-encoded error code on failure. - * - * See also: - * drm_atomic_helper_suspend(), drm_atomic_helper_resume() - */ -struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_atomic_state *state; - struct drm_connector *conn; - struct drm_connector_list_iter conn_iter; - struct drm_plane *plane; - struct drm_crtc *crtc; - int err = 0; - - state = drm_atomic_state_alloc(dev); - if (!state) - return ERR_PTR(-ENOMEM); - - state->acquire_ctx = ctx; - - drm_for_each_crtc(crtc, dev) { - struct drm_crtc_state *crtc_state; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - err = PTR_ERR(crtc_state); - goto free; - } - } - - drm_for_each_plane(plane, dev) { - struct drm_plane_state *plane_state; - - plane_state = drm_atomic_get_plane_state(state, plane); - if (IS_ERR(plane_state)) { - err = PTR_ERR(plane_state); - goto free; - } - } - - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(conn, &conn_iter) { - struct drm_connector_state *conn_state; - - conn_state = drm_atomic_get_connector_state(state, conn); - if (IS_ERR(conn_state)) { - err = PTR_ERR(conn_state); - drm_connector_list_iter_end(&conn_iter); - goto free; - } - } - drm_connector_list_iter_end(&conn_iter); - - /* clear the acquire context so that it isn't accidentally reused */ - state->acquire_ctx = NULL; - -free: - if (err < 0) { - drm_atomic_state_put(state); - state = ERR_PTR(err); - } - - return state; -} -EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); - -/** - * __drm_atomic_helper_connector_destroy_state - release connector state - * @state: connector state object to release - * - * Releases all resources stored in the connector state without actually - * freeing the memory of the connector state. This is useful for drivers that - * subclass the connector state. - */ -void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) -{ - if (state->crtc) - drm_connector_put(state->connector); - - if (state->commit) - drm_crtc_commit_put(state->commit); -} -EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); - -/** - * drm_atomic_helper_connector_destroy_state - default state destroy hook - * @connector: drm connector - * @state: connector state object to release - * - * Default connector state destroy hook for drivers which don't have their own - * subclassed connector state structure. - */ -void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, - struct drm_connector_state *state) -{ - __drm_atomic_helper_connector_destroy_state(state); - kfree(state); -} -EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); - -/** - * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table - * @crtc: CRTC object - * @red: red correction table - * @green: green correction table - * @blue: green correction table - * @size: size of the tables - * @ctx: lock acquire context - * - * Implements support for legacy gamma correction table for drivers - * that support color management through the DEGAMMA_LUT/GAMMA_LUT - * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for - * how the atomic color management and gamma tables work. - */ -int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, - u16 *red, u16 *green, u16 *blue, - uint32_t size, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_device *dev = crtc->dev; - struct drm_atomic_state *state; - struct drm_crtc_state *crtc_state; - struct drm_property_blob *blob = NULL; - struct drm_color_lut *blob_data; - int i, ret = 0; - bool replaced; - - state = drm_atomic_state_alloc(crtc->dev); - if (!state) - return -ENOMEM; - - blob = drm_property_create_blob(dev, - sizeof(struct drm_color_lut) * size, - NULL); - if (IS_ERR(blob)) { - ret = PTR_ERR(blob); - blob = NULL; - goto fail; - } - - /* Prepare GAMMA_LUT with the legacy values. */ - blob_data = blob->data; - for (i = 0; i < size; i++) { - blob_data[i].red = red[i]; - blob_data[i].green = green[i]; - blob_data[i].blue = blue[i]; - } - - state->acquire_ctx = ctx; - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - goto fail; - } - - /* Reset DEGAMMA_LUT and CTM properties. */ - replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL); - replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); - replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); - crtc_state->color_mgmt_changed |= replaced; - - ret = drm_atomic_commit(state); - -fail: - drm_atomic_state_put(state); - drm_property_blob_put(blob); - return ret; -} -EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); - -/** - * __drm_atomic_helper_private_duplicate_state - copy atomic private state - * @obj: CRTC object - * @state: new private object state - * - * Copies atomic state from a private objects's current state and resets inferred values. - * This is useful for drivers that subclass the private state. - */ -void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, - struct drm_private_state *state) -{ - memcpy(state, obj->state, sizeof(*state)); -} -EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c new file mode 100644 index 000000000000..3ba996069d69 --- /dev/null +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2018 Intel Corp. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Rob Clark robdclark@gmail.com + * Daniel Vetter daniel.vetter@ffwll.ch + */ + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_plane.h> +#include <drm/drm_connector.h> +#include <drm/drm_atomic.h> +#include <drm/drm_device.h> + +#include <linux/slab.h> +#include <linux/dma-fence.h> + +/** + * DOC: atomic state reset and initialization + * + * Both the drm core and the atomic helpers assume that there is always the full + * and correct atomic software state for all connectors, CRTCs and planes + * available. Which is a bit a problem on driver load and also after system + * suspend. One way to solve this is to have a hardware state read-out + * infrastructure which reconstructs the full software state (e.g. the i915 + * driver). + * + * The simpler solution is to just reset the software state to everything off, + * which is easiest to do by calling drm_mode_config_reset(). To facilitate this + * the atomic helpers provide default reset implementations for all hooks. + * + * On the upside the precise state tracking of atomic simplifies system suspend + * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe + * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume(). + * For other drivers the building blocks are split out, see the documentation + * for these functions. + */ + +/** + * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs + * @crtc: drm CRTC + * + * Resets the atomic state for @crtc by freeing the state pointer (which might + * be NULL, e.g. at driver load time) and allocating a new empty state object. + */ +void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) +{ + if (crtc->state) + __drm_atomic_helper_crtc_destroy_state(crtc->state); + + kfree(crtc->state); + crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); + + if (crtc->state) + crtc->state->crtc = crtc; +} +EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); + +/** + * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state + * @crtc: CRTC object + * @state: atomic CRTC state + * + * Copies atomic state from a CRTC's current state and resets inferred values. + * This is useful for drivers that subclass the CRTC state. + */ +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + memcpy(state, crtc->state, sizeof(*state)); + + if (state->mode_blob) + drm_property_blob_get(state->mode_blob); + if (state->degamma_lut) + drm_property_blob_get(state->degamma_lut); + if (state->ctm) + drm_property_blob_get(state->ctm); + if (state->gamma_lut) + drm_property_blob_get(state->gamma_lut); + state->mode_changed = false; + state->active_changed = false; + state->planes_changed = false; + state->connectors_changed = false; + state->color_mgmt_changed = false; + state->zpos_changed = false; + state->commit = NULL; + state->event = NULL; + state->pageflip_flags = 0; +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); + +/** + * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook + * @crtc: drm CRTC + * + * Default CRTC state duplicate hook for drivers which don't have their own + * subclassed CRTC state structure. + */ +struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct drm_crtc_state *state; + + if (WARN_ON(!crtc->state)) + return NULL; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_crtc_duplicate_state(crtc, state); + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); + +/** + * __drm_atomic_helper_crtc_destroy_state - release CRTC state + * @state: CRTC state object to release + * + * Releases all resources stored in the CRTC state without actually freeing + * the memory of the CRTC state. This is useful for drivers that subclass the + * CRTC state. + */ +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) +{ + if (state->commit) { + /* + * In the event that a non-blocking commit returns + * -ERESTARTSYS before the commit_tail work is queued, we will + * have an extra reference to the commit object. Release it, if + * the event has not been consumed by the worker. + * + * state->event may be freed, so we can't directly look at + * state->event->base.completion. + */ + if (state->event && state->commit->abort_completion) + drm_crtc_commit_put(state->commit); + + kfree(state->commit->event); + state->commit->event = NULL; + + drm_crtc_commit_put(state->commit); + } + + drm_property_blob_put(state->mode_blob); + drm_property_blob_put(state->degamma_lut); + drm_property_blob_put(state->ctm); + drm_property_blob_put(state->gamma_lut); +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); + +/** + * drm_atomic_helper_crtc_destroy_state - default state destroy hook + * @crtc: drm CRTC + * @state: CRTC state object to release + * + * Default CRTC state destroy hook for drivers which don't have their own + * subclassed CRTC state structure. + */ +void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + __drm_atomic_helper_crtc_destroy_state(state); + kfree(state); +} +EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); + +/** + * __drm_atomic_helper_plane_reset - resets planes state to default values + * @plane: plane object, must not be NULL + * @state: atomic plane state, must not be NULL + * + * Initializes plane state to default. This is useful for drivers that subclass + * the plane state. + */ +void __drm_atomic_helper_plane_reset(struct drm_plane *plane, + struct drm_plane_state *state) +{ + state->plane = plane; + state->rotation = DRM_MODE_ROTATE_0; + + state->alpha = DRM_BLEND_ALPHA_OPAQUE; + state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; + + plane->state = state; +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_reset); + +/** + * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes + * @plane: drm plane + * + * Resets the atomic state for @plane by freeing the state pointer (which might + * be NULL, e.g. at driver load time) and allocating a new empty state object. + */ +void drm_atomic_helper_plane_reset(struct drm_plane *plane) +{ + if (plane->state) + __drm_atomic_helper_plane_destroy_state(plane->state); + + kfree(plane->state); + plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); + if (plane->state) + __drm_atomic_helper_plane_reset(plane, plane->state); +} +EXPORT_SYMBOL(drm_atomic_helper_plane_reset); + +/** + * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state + * @plane: plane object + * @state: atomic plane state + * + * Copies atomic state from a plane's current state. This is useful for + * drivers that subclass the plane state. + */ +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + memcpy(state, plane->state, sizeof(*state)); + + if (state->fb) + drm_framebuffer_get(state->fb); + + state->fence = NULL; + state->commit = NULL; +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); + +/** + * drm_atomic_helper_plane_duplicate_state - default state duplicate hook + * @plane: drm plane + * + * Default plane state duplicate hook for drivers which don't have their own + * subclassed plane state structure. + */ +struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) +{ + struct drm_plane_state *state; + + if (WARN_ON(!plane->state)) + return NULL; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_plane_duplicate_state(plane, state); + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); + +/** + * __drm_atomic_helper_plane_destroy_state - release plane state + * @state: plane state object to release + * + * Releases all resources stored in the plane state without actually freeing + * the memory of the plane state. This is useful for drivers that subclass the + * plane state. + */ +void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) +{ + if (state->fb) + drm_framebuffer_put(state->fb); + + if (state->fence) + dma_fence_put(state->fence); + + if (state->commit) + drm_crtc_commit_put(state->commit); +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); + +/** + * drm_atomic_helper_plane_destroy_state - default state destroy hook + * @plane: drm plane + * @state: plane state object to release + * + * Default plane state destroy hook for drivers which don't have their own + * subclassed plane state structure. + */ +void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + __drm_atomic_helper_plane_destroy_state(state); + kfree(state); +} +EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); + +/** + * __drm_atomic_helper_connector_reset - reset state on connector + * @connector: drm connector + * @conn_state: connector state to assign + * + * Initializes the newly allocated @conn_state and assigns it to + * the &drm_conector->state pointer of @connector, usually required when + * initializing the drivers or when called from the &drm_connector_funcs.reset + * hook. + * + * This is useful for drivers that subclass the connector state. + */ +void +__drm_atomic_helper_connector_reset(struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + if (conn_state) + conn_state->connector = connector; + + connector->state = conn_state; +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_reset); + +/** + * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors + * @connector: drm connector + * + * Resets the atomic state for @connector by freeing the state pointer (which + * might be NULL, e.g. at driver load time) and allocating a new empty state + * object. + */ +void drm_atomic_helper_connector_reset(struct drm_connector *connector) +{ + struct drm_connector_state *conn_state = + kzalloc(sizeof(*conn_state), GFP_KERNEL); + + if (connector->state) + __drm_atomic_helper_connector_destroy_state(connector->state); + + kfree(connector->state); + __drm_atomic_helper_connector_reset(connector, conn_state); +} +EXPORT_SYMBOL(drm_atomic_helper_connector_reset); + +/** + * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state + * @connector: connector object + * @state: atomic connector state + * + * Copies atomic state from a connector's current state. This is useful for + * drivers that subclass the connector state. + */ +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + memcpy(state, connector->state, sizeof(*state)); + if (state->crtc) + drm_connector_get(connector); + state->commit = NULL; + + /* Don't copy over a writeback job, they are used only once */ + state->writeback_job = NULL; +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); + +/** + * drm_atomic_helper_connector_duplicate_state - default state duplicate hook + * @connector: drm connector + * + * Default connector state duplicate hook for drivers which don't have their own + * subclassed connector state structure. + */ +struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) +{ + struct drm_connector_state *state; + + if (WARN_ON(!connector->state)) + return NULL; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_connector_duplicate_state(connector, state); + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); + +/** + * drm_atomic_helper_duplicate_state - duplicate an atomic state object + * @dev: DRM device + * @ctx: lock acquisition context + * + * Makes a copy of the current atomic state by looping over all objects and + * duplicating their respective states. This is used for example by suspend/ + * resume support code to save the state prior to suspend such that it can + * be restored upon resume. + * + * Note that this treats atomic state as persistent between save and restore. + * Drivers must make sure that this is possible and won't result in confusion + * or erroneous behaviour. + * + * Note that if callers haven't already acquired all modeset locks this might + * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). + * + * Returns: + * A pointer to the copy of the atomic state object on success or an + * ERR_PTR()-encoded error code on failure. + * + * See also: + * drm_atomic_helper_suspend(), drm_atomic_helper_resume() + */ +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_connector_list_iter conn_iter; + struct drm_plane *plane; + struct drm_crtc *crtc; + int err = 0; + + state = drm_atomic_state_alloc(dev); + if (!state) + return ERR_PTR(-ENOMEM); + + state->acquire_ctx = ctx; + + drm_for_each_crtc(crtc, dev) { + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + err = PTR_ERR(crtc_state); + goto free; + } + } + + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + err = PTR_ERR(plane_state); + goto free; + } + } + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { + struct drm_connector_state *conn_state; + + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + err = PTR_ERR(conn_state); + drm_connector_list_iter_end(&conn_iter); + goto free; + } + } + drm_connector_list_iter_end(&conn_iter); + + /* clear the acquire context so that it isn't accidentally reused */ + state->acquire_ctx = NULL; + +free: + if (err < 0) { + drm_atomic_state_put(state); + state = ERR_PTR(err); + } + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); + +/** + * __drm_atomic_helper_connector_destroy_state - release connector state + * @state: connector state object to release + * + * Releases all resources stored in the connector state without actually + * freeing the memory of the connector state. This is useful for drivers that + * subclass the connector state. + */ +void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) +{ + if (state->crtc) + drm_connector_put(state->connector); + + if (state->commit) + drm_crtc_commit_put(state->commit); +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); + +/** + * drm_atomic_helper_connector_destroy_state - default state destroy hook + * @connector: drm connector + * @state: connector state object to release + * + * Default connector state destroy hook for drivers which don't have their own + * subclassed connector state structure. + */ +void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + __drm_atomic_helper_connector_destroy_state(state); + kfree(state); +} +EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); + +/** + * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table + * @crtc: CRTC object + * @red: red correction table + * @green: green correction table + * @blue: green correction table + * @size: size of the tables + * @ctx: lock acquire context + * + * Implements support for legacy gamma correction table for drivers + * that support color management through the DEGAMMA_LUT/GAMMA_LUT + * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for + * how the atomic color management and gamma tables work. + */ +int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, + u16 *red, u16 *green, u16 *blue, + uint32_t size, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_device *dev = crtc->dev; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_property_blob *blob = NULL; + struct drm_color_lut *blob_data; + int i, ret = 0; + bool replaced; + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) + return -ENOMEM; + + blob = drm_property_create_blob(dev, + sizeof(struct drm_color_lut) * size, + NULL); + if (IS_ERR(blob)) { + ret = PTR_ERR(blob); + blob = NULL; + goto fail; + } + + /* Prepare GAMMA_LUT with the legacy values. */ + blob_data = blob->data; + for (i = 0; i < size; i++) { + blob_data[i].red = red[i]; + blob_data[i].green = green[i]; + blob_data[i].blue = blue[i]; + } + + state->acquire_ctx = ctx; + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto fail; + } + + /* Reset DEGAMMA_LUT and CTM properties. */ + replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL); + replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); + replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); + crtc_state->color_mgmt_changed |= replaced; + + ret = drm_atomic_commit(state); + +fail: + drm_atomic_state_put(state); + drm_property_blob_put(blob); + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); + +/** + * __drm_atomic_helper_private_duplicate_state - copy atomic private state + * @obj: CRTC object + * @state: new private object state + * + * Copies atomic state from a private objects's current state and resets inferred values. + * This is useful for drivers that subclass the private state. + */ +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + memcpy(state, obj->state, sizeof(*state)); +} +EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index e60c4f0f8827..25ca0097563e 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -31,6 +31,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_modeset_helper.h> +#include <drm/drm_atomic_state_helper.h> #include <drm/drm_util.h>
struct drm_atomic_state; @@ -145,49 +146,6 @@ int drm_atomic_helper_page_flip_target( uint32_t target, struct drm_modeset_acquire_ctx *ctx);
-/* default implementations for state handling */ -void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, - struct drm_crtc_state *state); -struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); -void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state); - -void __drm_atomic_helper_plane_reset(struct drm_plane *plane, - struct drm_plane_state *state); -void drm_atomic_helper_plane_reset(struct drm_plane *plane); -void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, - struct drm_plane_state *state); -struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); -void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); -void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state); - -void __drm_atomic_helper_connector_reset(struct drm_connector *connector, - struct drm_connector_state *conn_state); -void drm_atomic_helper_connector_reset(struct drm_connector *connector); -void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, - struct drm_connector_state *state); -struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); -struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev, - struct drm_modeset_acquire_ctx *ctx); -void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); -void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, - struct drm_connector_state *state); -int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, - u16 *red, u16 *green, u16 *blue, - uint32_t size, - struct drm_modeset_acquire_ctx *ctx); -void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, - struct drm_private_state *state); - /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC * @plane: the loop cursor diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h new file mode 100644 index 000000000000..5b82ccfdb502 --- /dev/null +++ b/include/drm/drm_atomic_state_helper.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018 Intel Corp. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Rob Clark robdclark@gmail.com + * Daniel Vetter daniel.vetter@ffwll.ch + */ + +#include <linux/types.h> + +struct drm_crtc; +struct drm_crtc_state; +struct drm_plane; +struct drm_plane_state; +struct drm_connector; +struct drm_connector_state; +struct drm_private_obj; +struct drm_private_state; +struct drm_modeset_acquire_ctx; +struct drm_device; + +void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); +struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); +void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); + +void __drm_atomic_helper_plane_reset(struct drm_plane *plane, + struct drm_plane_state *state); +void drm_atomic_helper_plane_reset(struct drm_plane *plane); +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, + struct drm_plane_state *state); +struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); +void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); +void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); + +void __drm_atomic_helper_connector_reset(struct drm_connector *connector, + struct drm_connector_state *conn_state); +void drm_atomic_helper_connector_reset(struct drm_connector *connector); +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, + struct drm_connector_state *state); +struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx); +void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); +void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state); +int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, + u16 *red, u16 *green, u16 *blue, + uint32_t size, + struct drm_modeset_acquire_ctx *ctx); +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state);
On Tue, Oct 02, 2018 at 03:35:11PM +0200, Daniel Vetter wrote:
We already have a separate overview doc for this, makes sense to untangle it from the overall atomic helpers.
v2: Rebase
v3: Rebase more.
Hopefully the rebases didn't leave any code changes behind...
Too lazy to read in full detail so Acked-by: Ville Syrjälä ville.syrjala@linux.intel.com
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
Documentation/gpu/drm-kms-helpers.rst | 19 +- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_atomic_helper.c | 566 -------------------- drivers/gpu/drm/drm_atomic_state_helper.c | 601 ++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 44 +- include/drm/drm_atomic_state_helper.h | 80 +++ 6 files changed, 698 insertions(+), 615 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic_state_helper.c create mode 100644 include/drm/drm_atomic_state_helper.h
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index f9cfcdcdf024..4b4dc236ef6f 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -59,19 +59,28 @@ Implementing Asynchronous Atomic Commit .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c :doc: implementing nonblocking commit
+Helper Functions Reference +--------------------------
+.. kernel-doc:: include/drm/drm_atomic_helper.h
- :internal:
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
- :export:
Atomic State Reset and Initialization
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :doc: atomic state reset and initialization
-Helper Functions Reference
+Atomic State Helper Reference +-----------------------------
-.. kernel-doc:: include/drm/drm_atomic_helper.h +.. kernel-doc:: include/drm/drm_atomic_state_helper.h :internal:
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :export:
Simple KMS Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index bc6a16a3c36e..576ba985e138 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -36,7 +36,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_simple_kms_helper.o drm_modeset_helper.o \
drm_scdc_helper.o drm_gem_framebuffer_helper.o
drm_scdc_helper.o drm_gem_framebuffer_helper.o \
drm_atomic_state_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8c93f33fe92f..a5edc8757056 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3382,569 +3382,3 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, return ret; } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- DOC: atomic state reset and initialization
- Both the drm core and the atomic helpers assume that there is always the full
- and correct atomic software state for all connectors, CRTCs and planes
- available. Which is a bit a problem on driver load and also after system
- suspend. One way to solve this is to have a hardware state read-out
- infrastructure which reconstructs the full software state (e.g. the i915
- driver).
- The simpler solution is to just reset the software state to everything off,
- which is easiest to do by calling drm_mode_config_reset(). To facilitate this
- the atomic helpers provide default reset implementations for all hooks.
- On the upside the precise state tracking of atomic simplifies system suspend
- and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
- is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
- For other drivers the building blocks are split out, see the documentation
- for these functions.
- */
-/**
- drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
- @crtc: drm CRTC
- Resets the atomic state for @crtc by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) -{
- if (crtc->state)
__drm_atomic_helper_crtc_destroy_state(crtc->state);
- kfree(crtc->state);
- crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state)
crtc->state->crtc = crtc;
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
-/**
- __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
- @crtc: CRTC object
- @state: atomic CRTC state
- Copies atomic state from a CRTC's current state and resets inferred values.
- This is useful for drivers that subclass the CRTC state.
- */
-void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
-{
- memcpy(state, crtc->state, sizeof(*state));
- if (state->mode_blob)
drm_property_blob_get(state->mode_blob);
- if (state->degamma_lut)
drm_property_blob_get(state->degamma_lut);
- if (state->ctm)
drm_property_blob_get(state->ctm);
- if (state->gamma_lut)
drm_property_blob_get(state->gamma_lut);
- state->mode_changed = false;
- state->active_changed = false;
- state->planes_changed = false;
- state->connectors_changed = false;
- state->color_mgmt_changed = false;
- state->zpos_changed = false;
- state->commit = NULL;
- state->event = NULL;
- state->pageflip_flags = 0;
-} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
-/**
- drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
- @crtc: drm CRTC
- Default CRTC state duplicate hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
-struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) -{
- struct drm_crtc_state *state;
- if (WARN_ON(!crtc->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
-/**
- __drm_atomic_helper_crtc_destroy_state - release CRTC state
- @state: CRTC state object to release
- Releases all resources stored in the CRTC state without actually freeing
- the memory of the CRTC state. This is useful for drivers that subclass the
- CRTC state.
- */
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) -{
- if (state->commit) {
/*
* In the event that a non-blocking commit returns
* -ERESTARTSYS before the commit_tail work is queued, we will
* have an extra reference to the commit object. Release it, if
* the event has not been consumed by the worker.
*
* state->event may be freed, so we can't directly look at
* state->event->base.completion.
*/
if (state->event && state->commit->abort_completion)
drm_crtc_commit_put(state->commit);
kfree(state->commit->event);
state->commit->event = NULL;
drm_crtc_commit_put(state->commit);
- }
- drm_property_blob_put(state->mode_blob);
- drm_property_blob_put(state->degamma_lut);
- drm_property_blob_put(state->ctm);
- drm_property_blob_put(state->gamma_lut);
-} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
-/**
- drm_atomic_helper_crtc_destroy_state - default state destroy hook
- @crtc: drm CRTC
- @state: CRTC state object to release
- Default CRTC state destroy hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
-void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
-{
- __drm_atomic_helper_crtc_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
-/**
- __drm_atomic_helper_plane_reset - resets planes state to default values
- @plane: plane object, must not be NULL
- @state: atomic plane state, must not be NULL
- Initializes plane state to default. This is useful for drivers that subclass
- the plane state.
- */
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- state->plane = plane;
- state->rotation = DRM_MODE_ROTATE_0;
- state->alpha = DRM_BLEND_ALPHA_OPAQUE;
- state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
- plane->state = state;
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
-/**
- drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
- @plane: drm plane
- Resets the atomic state for @plane by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_plane_reset(struct drm_plane *plane) -{
- if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
- kfree(plane->state);
- plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
- if (plane->state)
__drm_atomic_helper_plane_reset(plane, plane->state);
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
-/**
- __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
- @plane: plane object
- @state: atomic plane state
- Copies atomic state from a plane's current state. This is useful for
- drivers that subclass the plane state.
- */
-void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- memcpy(state, plane->state, sizeof(*state));
- if (state->fb)
drm_framebuffer_get(state->fb);
- state->fence = NULL;
- state->commit = NULL;
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
-/**
- drm_atomic_helper_plane_duplicate_state - default state duplicate hook
- @plane: drm plane
- Default plane state duplicate hook for drivers which don't have their own
- subclassed plane state structure.
- */
-struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) -{
- struct drm_plane_state *state;
- if (WARN_ON(!plane->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_plane_duplicate_state(plane, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
-/**
- __drm_atomic_helper_plane_destroy_state - release plane state
- @state: plane state object to release
- Releases all resources stored in the plane state without actually freeing
- the memory of the plane state. This is useful for drivers that subclass the
- plane state.
- */
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) -{
- if (state->fb)
drm_framebuffer_put(state->fb);
- if (state->fence)
dma_fence_put(state->fence);
- if (state->commit)
drm_crtc_commit_put(state->commit);
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
-/**
- drm_atomic_helper_plane_destroy_state - default state destroy hook
- @plane: drm plane
- @state: plane state object to release
- Default plane state destroy hook for drivers which don't have their own
- subclassed plane state structure.
- */
-void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- __drm_atomic_helper_plane_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
-/**
- __drm_atomic_helper_connector_reset - reset state on connector
- @connector: drm connector
- @conn_state: connector state to assign
- Initializes the newly allocated @conn_state and assigns it to
- the &drm_conector->state pointer of @connector, usually required when
- initializing the drivers or when called from the &drm_connector_funcs.reset
- hook.
- This is useful for drivers that subclass the connector state.
- */
-void -__drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state)
-{
- if (conn_state)
conn_state->connector = connector;
- connector->state = conn_state;
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
-/**
- drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
- @connector: drm connector
- Resets the atomic state for @connector by freeing the state pointer (which
- might be NULL, e.g. at driver load time) and allocating a new empty state
- object.
- */
-void drm_atomic_helper_connector_reset(struct drm_connector *connector) -{
- struct drm_connector_state *conn_state =
kzalloc(sizeof(*conn_state), GFP_KERNEL);
- if (connector->state)
__drm_atomic_helper_connector_destroy_state(connector->state);
- kfree(connector->state);
- __drm_atomic_helper_connector_reset(connector, conn_state);
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
-/**
- __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
- @connector: connector object
- @state: atomic connector state
- Copies atomic state from a connector's current state. This is useful for
- drivers that subclass the connector state.
- */
-void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state)
-{
- memcpy(state, connector->state, sizeof(*state));
- if (state->crtc)
drm_connector_get(connector);
- state->commit = NULL;
- /* Don't copy over a writeback job, they are used only once */
- state->writeback_job = NULL;
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
-/**
- drm_atomic_helper_connector_duplicate_state - default state duplicate hook
- @connector: drm connector
- Default connector state duplicate hook for drivers which don't have their own
- subclassed connector state structure.
- */
-struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) -{
- struct drm_connector_state *state;
- if (WARN_ON(!connector->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_connector_duplicate_state(connector, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
-/**
- drm_atomic_helper_duplicate_state - duplicate an atomic state object
- @dev: DRM device
- @ctx: lock acquisition context
- Makes a copy of the current atomic state by looping over all objects and
- duplicating their respective states. This is used for example by suspend/
- resume support code to save the state prior to suspend such that it can
- be restored upon resume.
- Note that this treats atomic state as persistent between save and restore.
- Drivers must make sure that this is possible and won't result in confusion
- or erroneous behaviour.
- Note that if callers haven't already acquired all modeset locks this might
- return -EDEADLK, which must be handled by calling drm_modeset_backoff().
- Returns:
- A pointer to the copy of the atomic state object on success or an
- ERR_PTR()-encoded error code on failure.
- See also:
- drm_atomic_helper_suspend(), drm_atomic_helper_resume()
- */
-struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_atomic_state *state;
- struct drm_connector *conn;
- struct drm_connector_list_iter conn_iter;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- int err = 0;
- state = drm_atomic_state_alloc(dev);
- if (!state)
return ERR_PTR(-ENOMEM);
- state->acquire_ctx = ctx;
- drm_for_each_crtc(crtc, dev) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
err = PTR_ERR(crtc_state);
goto free;
}
- }
- drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
err = PTR_ERR(plane_state);
goto free;
}
- }
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
conn_state = drm_atomic_get_connector_state(state, conn);
if (IS_ERR(conn_state)) {
err = PTR_ERR(conn_state);
drm_connector_list_iter_end(&conn_iter);
goto free;
}
- }
- drm_connector_list_iter_end(&conn_iter);
- /* clear the acquire context so that it isn't accidentally reused */
- state->acquire_ctx = NULL;
-free:
- if (err < 0) {
drm_atomic_state_put(state);
state = ERR_PTR(err);
- }
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
-/**
- __drm_atomic_helper_connector_destroy_state - release connector state
- @state: connector state object to release
- Releases all resources stored in the connector state without actually
- freeing the memory of the connector state. This is useful for drivers that
- subclass the connector state.
- */
-void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) -{
- if (state->crtc)
drm_connector_put(state->connector);
- if (state->commit)
drm_crtc_commit_put(state->commit);
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
-/**
- drm_atomic_helper_connector_destroy_state - default state destroy hook
- @connector: drm connector
- @state: connector state object to release
- Default connector state destroy hook for drivers which don't have their own
- subclassed connector state structure.
- */
-void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
-{
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
-/**
- drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
- @crtc: CRTC object
- @red: red correction table
- @green: green correction table
- @blue: green correction table
- @size: size of the tables
- @ctx: lock acquire context
- Implements support for legacy gamma correction table for drivers
- that support color management through the DEGAMMA_LUT/GAMMA_LUT
- properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
- how the atomic color management and gamma tables work.
- */
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_atomic_state *state;
- struct drm_crtc_state *crtc_state;
- struct drm_property_blob *blob = NULL;
- struct drm_color_lut *blob_data;
- int i, ret = 0;
- bool replaced;
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state)
return -ENOMEM;
- blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
- if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
- }
- /* Prepare GAMMA_LUT with the legacy values. */
- blob_data = blob->data;
- for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
- }
- state->acquire_ctx = ctx;
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
- }
- /* Reset DEGAMMA_LUT and CTM properties. */
- replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
- crtc_state->color_mgmt_changed |= replaced;
- ret = drm_atomic_commit(state);
-fail:
- drm_atomic_state_put(state);
- drm_property_blob_put(blob);
- return ret;
-} -EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
-/**
- __drm_atomic_helper_private_duplicate_state - copy atomic private state
- @obj: CRTC object
- @state: new private object state
- Copies atomic state from a private objects's current state and resets inferred values.
- This is useful for drivers that subclass the private state.
- */
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state)
-{
- memcpy(state, obj->state, sizeof(*state));
-} -EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c new file mode 100644 index 000000000000..3ba996069d69 --- /dev/null +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -0,0 +1,601 @@ +/*
- Copyright (C) 2018 Intel Corp.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- Authors:
- Rob Clark robdclark@gmail.com
- Daniel Vetter daniel.vetter@ffwll.ch
- */
+#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_plane.h> +#include <drm/drm_connector.h> +#include <drm/drm_atomic.h> +#include <drm/drm_device.h>
+#include <linux/slab.h> +#include <linux/dma-fence.h>
+/**
- DOC: atomic state reset and initialization
- Both the drm core and the atomic helpers assume that there is always the full
- and correct atomic software state for all connectors, CRTCs and planes
- available. Which is a bit a problem on driver load and also after system
- suspend. One way to solve this is to have a hardware state read-out
- infrastructure which reconstructs the full software state (e.g. the i915
- driver).
- The simpler solution is to just reset the software state to everything off,
- which is easiest to do by calling drm_mode_config_reset(). To facilitate this
- the atomic helpers provide default reset implementations for all hooks.
- On the upside the precise state tracking of atomic simplifies system suspend
- and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
- is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
- For other drivers the building blocks are split out, see the documentation
- for these functions.
- */
+/**
- drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
- @crtc: drm CRTC
- Resets the atomic state for @crtc by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) +{
- if (crtc->state)
__drm_atomic_helper_crtc_destroy_state(crtc->state);
- kfree(crtc->state);
- crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state)
crtc->state->crtc = crtc;
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
+/**
- __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
- @crtc: CRTC object
- @state: atomic CRTC state
- Copies atomic state from a CRTC's current state and resets inferred values.
- This is useful for drivers that subclass the CRTC state.
- */
+void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
+{
- memcpy(state, crtc->state, sizeof(*state));
- if (state->mode_blob)
drm_property_blob_get(state->mode_blob);
- if (state->degamma_lut)
drm_property_blob_get(state->degamma_lut);
- if (state->ctm)
drm_property_blob_get(state->ctm);
- if (state->gamma_lut)
drm_property_blob_get(state->gamma_lut);
- state->mode_changed = false;
- state->active_changed = false;
- state->planes_changed = false;
- state->connectors_changed = false;
- state->color_mgmt_changed = false;
- state->zpos_changed = false;
- state->commit = NULL;
- state->event = NULL;
- state->pageflip_flags = 0;
+} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
+/**
- drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
- @crtc: drm CRTC
- Default CRTC state duplicate hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
+struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) +{
- struct drm_crtc_state *state;
- if (WARN_ON(!crtc->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
+/**
- __drm_atomic_helper_crtc_destroy_state - release CRTC state
- @state: CRTC state object to release
- Releases all resources stored in the CRTC state without actually freeing
- the memory of the CRTC state. This is useful for drivers that subclass the
- CRTC state.
- */
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) +{
- if (state->commit) {
/*
* In the event that a non-blocking commit returns
* -ERESTARTSYS before the commit_tail work is queued, we will
* have an extra reference to the commit object. Release it, if
* the event has not been consumed by the worker.
*
* state->event may be freed, so we can't directly look at
* state->event->base.completion.
*/
if (state->event && state->commit->abort_completion)
drm_crtc_commit_put(state->commit);
kfree(state->commit->event);
state->commit->event = NULL;
drm_crtc_commit_put(state->commit);
- }
- drm_property_blob_put(state->mode_blob);
- drm_property_blob_put(state->degamma_lut);
- drm_property_blob_put(state->ctm);
- drm_property_blob_put(state->gamma_lut);
+} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
+/**
- drm_atomic_helper_crtc_destroy_state - default state destroy hook
- @crtc: drm CRTC
- @state: CRTC state object to release
- Default CRTC state destroy hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
+void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
+{
- __drm_atomic_helper_crtc_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
+/**
- __drm_atomic_helper_plane_reset - resets planes state to default values
- @plane: plane object, must not be NULL
- @state: atomic plane state, must not be NULL
- Initializes plane state to default. This is useful for drivers that subclass
- the plane state.
- */
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- state->plane = plane;
- state->rotation = DRM_MODE_ROTATE_0;
- state->alpha = DRM_BLEND_ALPHA_OPAQUE;
- state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
- plane->state = state;
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
+/**
- drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
- @plane: drm plane
- Resets the atomic state for @plane by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
+void drm_atomic_helper_plane_reset(struct drm_plane *plane) +{
- if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
- kfree(plane->state);
- plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
- if (plane->state)
__drm_atomic_helper_plane_reset(plane, plane->state);
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
+/**
- __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
- @plane: plane object
- @state: atomic plane state
- Copies atomic state from a plane's current state. This is useful for
- drivers that subclass the plane state.
- */
+void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- memcpy(state, plane->state, sizeof(*state));
- if (state->fb)
drm_framebuffer_get(state->fb);
- state->fence = NULL;
- state->commit = NULL;
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
+/**
- drm_atomic_helper_plane_duplicate_state - default state duplicate hook
- @plane: drm plane
- Default plane state duplicate hook for drivers which don't have their own
- subclassed plane state structure.
- */
+struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) +{
- struct drm_plane_state *state;
- if (WARN_ON(!plane->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_plane_duplicate_state(plane, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
+/**
- __drm_atomic_helper_plane_destroy_state - release plane state
- @state: plane state object to release
- Releases all resources stored in the plane state without actually freeing
- the memory of the plane state. This is useful for drivers that subclass the
- plane state.
- */
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) +{
- if (state->fb)
drm_framebuffer_put(state->fb);
- if (state->fence)
dma_fence_put(state->fence);
- if (state->commit)
drm_crtc_commit_put(state->commit);
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
+/**
- drm_atomic_helper_plane_destroy_state - default state destroy hook
- @plane: drm plane
- @state: plane state object to release
- Default plane state destroy hook for drivers which don't have their own
- subclassed plane state structure.
- */
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- __drm_atomic_helper_plane_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
+/**
- __drm_atomic_helper_connector_reset - reset state on connector
- @connector: drm connector
- @conn_state: connector state to assign
- Initializes the newly allocated @conn_state and assigns it to
- the &drm_conector->state pointer of @connector, usually required when
- initializing the drivers or when called from the &drm_connector_funcs.reset
- hook.
- This is useful for drivers that subclass the connector state.
- */
+void +__drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state)
+{
- if (conn_state)
conn_state->connector = connector;
- connector->state = conn_state;
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
+/**
- drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
- @connector: drm connector
- Resets the atomic state for @connector by freeing the state pointer (which
- might be NULL, e.g. at driver load time) and allocating a new empty state
- object.
- */
+void drm_atomic_helper_connector_reset(struct drm_connector *connector) +{
- struct drm_connector_state *conn_state =
kzalloc(sizeof(*conn_state), GFP_KERNEL);
- if (connector->state)
__drm_atomic_helper_connector_destroy_state(connector->state);
- kfree(connector->state);
- __drm_atomic_helper_connector_reset(connector, conn_state);
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
+/**
- __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
- @connector: connector object
- @state: atomic connector state
- Copies atomic state from a connector's current state. This is useful for
- drivers that subclass the connector state.
- */
+void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state)
+{
- memcpy(state, connector->state, sizeof(*state));
- if (state->crtc)
drm_connector_get(connector);
- state->commit = NULL;
- /* Don't copy over a writeback job, they are used only once */
- state->writeback_job = NULL;
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
+/**
- drm_atomic_helper_connector_duplicate_state - default state duplicate hook
- @connector: drm connector
- Default connector state duplicate hook for drivers which don't have their own
- subclassed connector state structure.
- */
+struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) +{
- struct drm_connector_state *state;
- if (WARN_ON(!connector->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_connector_duplicate_state(connector, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
+/**
- drm_atomic_helper_duplicate_state - duplicate an atomic state object
- @dev: DRM device
- @ctx: lock acquisition context
- Makes a copy of the current atomic state by looping over all objects and
- duplicating their respective states. This is used for example by suspend/
- resume support code to save the state prior to suspend such that it can
- be restored upon resume.
- Note that this treats atomic state as persistent between save and restore.
- Drivers must make sure that this is possible and won't result in confusion
- or erroneous behaviour.
- Note that if callers haven't already acquired all modeset locks this might
- return -EDEADLK, which must be handled by calling drm_modeset_backoff().
- Returns:
- A pointer to the copy of the atomic state object on success or an
- ERR_PTR()-encoded error code on failure.
- See also:
- drm_atomic_helper_suspend(), drm_atomic_helper_resume()
- */
+struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
+{
- struct drm_atomic_state *state;
- struct drm_connector *conn;
- struct drm_connector_list_iter conn_iter;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- int err = 0;
- state = drm_atomic_state_alloc(dev);
- if (!state)
return ERR_PTR(-ENOMEM);
- state->acquire_ctx = ctx;
- drm_for_each_crtc(crtc, dev) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
err = PTR_ERR(crtc_state);
goto free;
}
- }
- drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
err = PTR_ERR(plane_state);
goto free;
}
- }
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
conn_state = drm_atomic_get_connector_state(state, conn);
if (IS_ERR(conn_state)) {
err = PTR_ERR(conn_state);
drm_connector_list_iter_end(&conn_iter);
goto free;
}
- }
- drm_connector_list_iter_end(&conn_iter);
- /* clear the acquire context so that it isn't accidentally reused */
- state->acquire_ctx = NULL;
+free:
- if (err < 0) {
drm_atomic_state_put(state);
state = ERR_PTR(err);
- }
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
+/**
- __drm_atomic_helper_connector_destroy_state - release connector state
- @state: connector state object to release
- Releases all resources stored in the connector state without actually
- freeing the memory of the connector state. This is useful for drivers that
- subclass the connector state.
- */
+void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) +{
- if (state->crtc)
drm_connector_put(state->connector);
- if (state->commit)
drm_crtc_commit_put(state->commit);
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
+/**
- drm_atomic_helper_connector_destroy_state - default state destroy hook
- @connector: drm connector
- @state: connector state object to release
- Default connector state destroy hook for drivers which don't have their own
- subclassed connector state structure.
- */
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
+{
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
+/**
- drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
- @crtc: CRTC object
- @red: red correction table
- @green: green correction table
- @blue: green correction table
- @size: size of the tables
- @ctx: lock acquire context
- Implements support for legacy gamma correction table for drivers
- that support color management through the DEGAMMA_LUT/GAMMA_LUT
- properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
- how the atomic color management and gamma tables work.
- */
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
+{
- struct drm_device *dev = crtc->dev;
- struct drm_atomic_state *state;
- struct drm_crtc_state *crtc_state;
- struct drm_property_blob *blob = NULL;
- struct drm_color_lut *blob_data;
- int i, ret = 0;
- bool replaced;
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state)
return -ENOMEM;
- blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
- if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
- }
- /* Prepare GAMMA_LUT with the legacy values. */
- blob_data = blob->data;
- for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
- }
- state->acquire_ctx = ctx;
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
- }
- /* Reset DEGAMMA_LUT and CTM properties. */
- replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
- crtc_state->color_mgmt_changed |= replaced;
- ret = drm_atomic_commit(state);
+fail:
- drm_atomic_state_put(state);
- drm_property_blob_put(blob);
- return ret;
+} +EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+/**
- __drm_atomic_helper_private_duplicate_state - copy atomic private state
- @obj: CRTC object
- @state: new private object state
- Copies atomic state from a private objects's current state and resets inferred values.
- This is useful for drivers that subclass the private state.
- */
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state)
+{
- memcpy(state, obj->state, sizeof(*state));
+} +EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index e60c4f0f8827..25ca0097563e 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -31,6 +31,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_modeset_helper.h> +#include <drm/drm_atomic_state_helper.h> #include <drm/drm_util.h>
struct drm_atomic_state; @@ -145,49 +146,6 @@ int drm_atomic_helper_page_flip_target( uint32_t target, struct drm_modeset_acquire_ctx *ctx);
-/* default implementations for state handling */ -void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
-struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); -void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state);
-void drm_atomic_helper_plane_reset(struct drm_plane *plane); -void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state);
-struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); -void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); -void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
-void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state);
-void drm_atomic_helper_connector_reset(struct drm_connector *connector); -void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state);
-struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); -struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
-void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); -void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state);
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state);
/**
- drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
- @plane: the loop cursor
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h new file mode 100644 index 000000000000..5b82ccfdb502 --- /dev/null +++ b/include/drm/drm_atomic_state_helper.h @@ -0,0 +1,80 @@ +/*
- Copyright (C) 2018 Intel Corp.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- Authors:
- Rob Clark robdclark@gmail.com
- Daniel Vetter daniel.vetter@ffwll.ch
- */
+#include <linux/types.h>
+struct drm_crtc; +struct drm_crtc_state; +struct drm_plane; +struct drm_plane_state; +struct drm_connector; +struct drm_connector_state; +struct drm_private_obj; +struct drm_private_state; +struct drm_modeset_acquire_ctx; +struct drm_device;
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
+struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); +void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state);
+void drm_atomic_helper_plane_reset(struct drm_plane *plane); +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state);
+struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); +void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); +void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
+void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state);
+void drm_atomic_helper_connector_reset(struct drm_connector *connector); +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state);
+struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
+void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); +void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state);
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state);
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Tue, Oct 02, 2018 at 06:40:52PM +0300, Ville Syrjälä wrote:
On Tue, Oct 02, 2018 at 03:35:11PM +0200, Daniel Vetter wrote:
We already have a separate overview doc for this, makes sense to untangle it from the overall atomic helpers.
v2: Rebase
v3: Rebase more.
Hopefully the rebases didn't leave any code changes behind...
I've redone the move on every rebase :-/
Too lazy to read in full detail so Acked-by: Ville Syrjälä ville.syrjala@linux.intel.com
Thanks, I'll pick this one right up (just need to double-check CI). -Daniel
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
Documentation/gpu/drm-kms-helpers.rst | 19 +- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_atomic_helper.c | 566 -------------------- drivers/gpu/drm/drm_atomic_state_helper.c | 601 ++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 44 +- include/drm/drm_atomic_state_helper.h | 80 +++ 6 files changed, 698 insertions(+), 615 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic_state_helper.c create mode 100644 include/drm/drm_atomic_state_helper.h
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index f9cfcdcdf024..4b4dc236ef6f 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -59,19 +59,28 @@ Implementing Asynchronous Atomic Commit .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c :doc: implementing nonblocking commit
+Helper Functions Reference +--------------------------
+.. kernel-doc:: include/drm/drm_atomic_helper.h
- :internal:
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
- :export:
Atomic State Reset and Initialization
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :doc: atomic state reset and initialization
-Helper Functions Reference
+Atomic State Helper Reference +-----------------------------
-.. kernel-doc:: include/drm/drm_atomic_helper.h +.. kernel-doc:: include/drm/drm_atomic_state_helper.h :internal:
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c :export:
Simple KMS Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index bc6a16a3c36e..576ba985e138 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -36,7 +36,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_simple_kms_helper.o drm_modeset_helper.o \
drm_scdc_helper.o drm_gem_framebuffer_helper.o
drm_scdc_helper.o drm_gem_framebuffer_helper.o \
drm_atomic_state_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8c93f33fe92f..a5edc8757056 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3382,569 +3382,3 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, return ret; } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-/**
- DOC: atomic state reset and initialization
- Both the drm core and the atomic helpers assume that there is always the full
- and correct atomic software state for all connectors, CRTCs and planes
- available. Which is a bit a problem on driver load and also after system
- suspend. One way to solve this is to have a hardware state read-out
- infrastructure which reconstructs the full software state (e.g. the i915
- driver).
- The simpler solution is to just reset the software state to everything off,
- which is easiest to do by calling drm_mode_config_reset(). To facilitate this
- the atomic helpers provide default reset implementations for all hooks.
- On the upside the precise state tracking of atomic simplifies system suspend
- and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
- is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
- For other drivers the building blocks are split out, see the documentation
- for these functions.
- */
-/**
- drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
- @crtc: drm CRTC
- Resets the atomic state for @crtc by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) -{
- if (crtc->state)
__drm_atomic_helper_crtc_destroy_state(crtc->state);
- kfree(crtc->state);
- crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state)
crtc->state->crtc = crtc;
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
-/**
- __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
- @crtc: CRTC object
- @state: atomic CRTC state
- Copies atomic state from a CRTC's current state and resets inferred values.
- This is useful for drivers that subclass the CRTC state.
- */
-void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
-{
- memcpy(state, crtc->state, sizeof(*state));
- if (state->mode_blob)
drm_property_blob_get(state->mode_blob);
- if (state->degamma_lut)
drm_property_blob_get(state->degamma_lut);
- if (state->ctm)
drm_property_blob_get(state->ctm);
- if (state->gamma_lut)
drm_property_blob_get(state->gamma_lut);
- state->mode_changed = false;
- state->active_changed = false;
- state->planes_changed = false;
- state->connectors_changed = false;
- state->color_mgmt_changed = false;
- state->zpos_changed = false;
- state->commit = NULL;
- state->event = NULL;
- state->pageflip_flags = 0;
-} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
-/**
- drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
- @crtc: drm CRTC
- Default CRTC state duplicate hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
-struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) -{
- struct drm_crtc_state *state;
- if (WARN_ON(!crtc->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
-/**
- __drm_atomic_helper_crtc_destroy_state - release CRTC state
- @state: CRTC state object to release
- Releases all resources stored in the CRTC state without actually freeing
- the memory of the CRTC state. This is useful for drivers that subclass the
- CRTC state.
- */
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) -{
- if (state->commit) {
/*
* In the event that a non-blocking commit returns
* -ERESTARTSYS before the commit_tail work is queued, we will
* have an extra reference to the commit object. Release it, if
* the event has not been consumed by the worker.
*
* state->event may be freed, so we can't directly look at
* state->event->base.completion.
*/
if (state->event && state->commit->abort_completion)
drm_crtc_commit_put(state->commit);
kfree(state->commit->event);
state->commit->event = NULL;
drm_crtc_commit_put(state->commit);
- }
- drm_property_blob_put(state->mode_blob);
- drm_property_blob_put(state->degamma_lut);
- drm_property_blob_put(state->ctm);
- drm_property_blob_put(state->gamma_lut);
-} -EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
-/**
- drm_atomic_helper_crtc_destroy_state - default state destroy hook
- @crtc: drm CRTC
- @state: CRTC state object to release
- Default CRTC state destroy hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
-void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
-{
- __drm_atomic_helper_crtc_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
-/**
- __drm_atomic_helper_plane_reset - resets planes state to default values
- @plane: plane object, must not be NULL
- @state: atomic plane state, must not be NULL
- Initializes plane state to default. This is useful for drivers that subclass
- the plane state.
- */
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- state->plane = plane;
- state->rotation = DRM_MODE_ROTATE_0;
- state->alpha = DRM_BLEND_ALPHA_OPAQUE;
- state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
- plane->state = state;
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
-/**
- drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
- @plane: drm plane
- Resets the atomic state for @plane by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_plane_reset(struct drm_plane *plane) -{
- if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
- kfree(plane->state);
- plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
- if (plane->state)
__drm_atomic_helper_plane_reset(plane, plane->state);
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
-/**
- __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
- @plane: plane object
- @state: atomic plane state
- Copies atomic state from a plane's current state. This is useful for
- drivers that subclass the plane state.
- */
-void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- memcpy(state, plane->state, sizeof(*state));
- if (state->fb)
drm_framebuffer_get(state->fb);
- state->fence = NULL;
- state->commit = NULL;
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
-/**
- drm_atomic_helper_plane_duplicate_state - default state duplicate hook
- @plane: drm plane
- Default plane state duplicate hook for drivers which don't have their own
- subclassed plane state structure.
- */
-struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) -{
- struct drm_plane_state *state;
- if (WARN_ON(!plane->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_plane_duplicate_state(plane, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
-/**
- __drm_atomic_helper_plane_destroy_state - release plane state
- @state: plane state object to release
- Releases all resources stored in the plane state without actually freeing
- the memory of the plane state. This is useful for drivers that subclass the
- plane state.
- */
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) -{
- if (state->fb)
drm_framebuffer_put(state->fb);
- if (state->fence)
dma_fence_put(state->fence);
- if (state->commit)
drm_crtc_commit_put(state->commit);
-} -EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
-/**
- drm_atomic_helper_plane_destroy_state - default state destroy hook
- @plane: drm plane
- @state: plane state object to release
- Default plane state destroy hook for drivers which don't have their own
- subclassed plane state structure.
- */
-void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
-{
- __drm_atomic_helper_plane_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
-/**
- __drm_atomic_helper_connector_reset - reset state on connector
- @connector: drm connector
- @conn_state: connector state to assign
- Initializes the newly allocated @conn_state and assigns it to
- the &drm_conector->state pointer of @connector, usually required when
- initializing the drivers or when called from the &drm_connector_funcs.reset
- hook.
- This is useful for drivers that subclass the connector state.
- */
-void -__drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state)
-{
- if (conn_state)
conn_state->connector = connector;
- connector->state = conn_state;
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
-/**
- drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
- @connector: drm connector
- Resets the atomic state for @connector by freeing the state pointer (which
- might be NULL, e.g. at driver load time) and allocating a new empty state
- object.
- */
-void drm_atomic_helper_connector_reset(struct drm_connector *connector) -{
- struct drm_connector_state *conn_state =
kzalloc(sizeof(*conn_state), GFP_KERNEL);
- if (connector->state)
__drm_atomic_helper_connector_destroy_state(connector->state);
- kfree(connector->state);
- __drm_atomic_helper_connector_reset(connector, conn_state);
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
-/**
- __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
- @connector: connector object
- @state: atomic connector state
- Copies atomic state from a connector's current state. This is useful for
- drivers that subclass the connector state.
- */
-void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state)
-{
- memcpy(state, connector->state, sizeof(*state));
- if (state->crtc)
drm_connector_get(connector);
- state->commit = NULL;
- /* Don't copy over a writeback job, they are used only once */
- state->writeback_job = NULL;
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
-/**
- drm_atomic_helper_connector_duplicate_state - default state duplicate hook
- @connector: drm connector
- Default connector state duplicate hook for drivers which don't have their own
- subclassed connector state structure.
- */
-struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) -{
- struct drm_connector_state *state;
- if (WARN_ON(!connector->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_connector_duplicate_state(connector, state);
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
-/**
- drm_atomic_helper_duplicate_state - duplicate an atomic state object
- @dev: DRM device
- @ctx: lock acquisition context
- Makes a copy of the current atomic state by looping over all objects and
- duplicating their respective states. This is used for example by suspend/
- resume support code to save the state prior to suspend such that it can
- be restored upon resume.
- Note that this treats atomic state as persistent between save and restore.
- Drivers must make sure that this is possible and won't result in confusion
- or erroneous behaviour.
- Note that if callers haven't already acquired all modeset locks this might
- return -EDEADLK, which must be handled by calling drm_modeset_backoff().
- Returns:
- A pointer to the copy of the atomic state object on success or an
- ERR_PTR()-encoded error code on failure.
- See also:
- drm_atomic_helper_suspend(), drm_atomic_helper_resume()
- */
-struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_atomic_state *state;
- struct drm_connector *conn;
- struct drm_connector_list_iter conn_iter;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- int err = 0;
- state = drm_atomic_state_alloc(dev);
- if (!state)
return ERR_PTR(-ENOMEM);
- state->acquire_ctx = ctx;
- drm_for_each_crtc(crtc, dev) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
err = PTR_ERR(crtc_state);
goto free;
}
- }
- drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
err = PTR_ERR(plane_state);
goto free;
}
- }
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
conn_state = drm_atomic_get_connector_state(state, conn);
if (IS_ERR(conn_state)) {
err = PTR_ERR(conn_state);
drm_connector_list_iter_end(&conn_iter);
goto free;
}
- }
- drm_connector_list_iter_end(&conn_iter);
- /* clear the acquire context so that it isn't accidentally reused */
- state->acquire_ctx = NULL;
-free:
- if (err < 0) {
drm_atomic_state_put(state);
state = ERR_PTR(err);
- }
- return state;
-} -EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
-/**
- __drm_atomic_helper_connector_destroy_state - release connector state
- @state: connector state object to release
- Releases all resources stored in the connector state without actually
- freeing the memory of the connector state. This is useful for drivers that
- subclass the connector state.
- */
-void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) -{
- if (state->crtc)
drm_connector_put(state->connector);
- if (state->commit)
drm_crtc_commit_put(state->commit);
-} -EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
-/**
- drm_atomic_helper_connector_destroy_state - default state destroy hook
- @connector: drm connector
- @state: connector state object to release
- Default connector state destroy hook for drivers which don't have their own
- subclassed connector state structure.
- */
-void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
-{
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(state);
-} -EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
-/**
- drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
- @crtc: CRTC object
- @red: red correction table
- @green: green correction table
- @blue: green correction table
- @size: size of the tables
- @ctx: lock acquire context
- Implements support for legacy gamma correction table for drivers
- that support color management through the DEGAMMA_LUT/GAMMA_LUT
- properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
- how the atomic color management and gamma tables work.
- */
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_atomic_state *state;
- struct drm_crtc_state *crtc_state;
- struct drm_property_blob *blob = NULL;
- struct drm_color_lut *blob_data;
- int i, ret = 0;
- bool replaced;
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state)
return -ENOMEM;
- blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
- if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
- }
- /* Prepare GAMMA_LUT with the legacy values. */
- blob_data = blob->data;
- for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
- }
- state->acquire_ctx = ctx;
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
- }
- /* Reset DEGAMMA_LUT and CTM properties. */
- replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
- crtc_state->color_mgmt_changed |= replaced;
- ret = drm_atomic_commit(state);
-fail:
- drm_atomic_state_put(state);
- drm_property_blob_put(blob);
- return ret;
-} -EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
-/**
- __drm_atomic_helper_private_duplicate_state - copy atomic private state
- @obj: CRTC object
- @state: new private object state
- Copies atomic state from a private objects's current state and resets inferred values.
- This is useful for drivers that subclass the private state.
- */
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state)
-{
- memcpy(state, obj->state, sizeof(*state));
-} -EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c new file mode 100644 index 000000000000..3ba996069d69 --- /dev/null +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -0,0 +1,601 @@ +/*
- Copyright (C) 2018 Intel Corp.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- Authors:
- Rob Clark robdclark@gmail.com
- Daniel Vetter daniel.vetter@ffwll.ch
- */
+#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_plane.h> +#include <drm/drm_connector.h> +#include <drm/drm_atomic.h> +#include <drm/drm_device.h>
+#include <linux/slab.h> +#include <linux/dma-fence.h>
+/**
- DOC: atomic state reset and initialization
- Both the drm core and the atomic helpers assume that there is always the full
- and correct atomic software state for all connectors, CRTCs and planes
- available. Which is a bit a problem on driver load and also after system
- suspend. One way to solve this is to have a hardware state read-out
- infrastructure which reconstructs the full software state (e.g. the i915
- driver).
- The simpler solution is to just reset the software state to everything off,
- which is easiest to do by calling drm_mode_config_reset(). To facilitate this
- the atomic helpers provide default reset implementations for all hooks.
- On the upside the precise state tracking of atomic simplifies system suspend
- and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
- is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
- For other drivers the building blocks are split out, see the documentation
- for these functions.
- */
+/**
- drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
- @crtc: drm CRTC
- Resets the atomic state for @crtc by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) +{
- if (crtc->state)
__drm_atomic_helper_crtc_destroy_state(crtc->state);
- kfree(crtc->state);
- crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
- if (crtc->state)
crtc->state->crtc = crtc;
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
+/**
- __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
- @crtc: CRTC object
- @state: atomic CRTC state
- Copies atomic state from a CRTC's current state and resets inferred values.
- This is useful for drivers that subclass the CRTC state.
- */
+void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
+{
- memcpy(state, crtc->state, sizeof(*state));
- if (state->mode_blob)
drm_property_blob_get(state->mode_blob);
- if (state->degamma_lut)
drm_property_blob_get(state->degamma_lut);
- if (state->ctm)
drm_property_blob_get(state->ctm);
- if (state->gamma_lut)
drm_property_blob_get(state->gamma_lut);
- state->mode_changed = false;
- state->active_changed = false;
- state->planes_changed = false;
- state->connectors_changed = false;
- state->color_mgmt_changed = false;
- state->zpos_changed = false;
- state->commit = NULL;
- state->event = NULL;
- state->pageflip_flags = 0;
+} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
+/**
- drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
- @crtc: drm CRTC
- Default CRTC state duplicate hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
+struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) +{
- struct drm_crtc_state *state;
- if (WARN_ON(!crtc->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
+/**
- __drm_atomic_helper_crtc_destroy_state - release CRTC state
- @state: CRTC state object to release
- Releases all resources stored in the CRTC state without actually freeing
- the memory of the CRTC state. This is useful for drivers that subclass the
- CRTC state.
- */
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) +{
- if (state->commit) {
/*
* In the event that a non-blocking commit returns
* -ERESTARTSYS before the commit_tail work is queued, we will
* have an extra reference to the commit object. Release it, if
* the event has not been consumed by the worker.
*
* state->event may be freed, so we can't directly look at
* state->event->base.completion.
*/
if (state->event && state->commit->abort_completion)
drm_crtc_commit_put(state->commit);
kfree(state->commit->event);
state->commit->event = NULL;
drm_crtc_commit_put(state->commit);
- }
- drm_property_blob_put(state->mode_blob);
- drm_property_blob_put(state->degamma_lut);
- drm_property_blob_put(state->ctm);
- drm_property_blob_put(state->gamma_lut);
+} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
+/**
- drm_atomic_helper_crtc_destroy_state - default state destroy hook
- @crtc: drm CRTC
- @state: CRTC state object to release
- Default CRTC state destroy hook for drivers which don't have their own
- subclassed CRTC state structure.
- */
+void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
+{
- __drm_atomic_helper_crtc_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
+/**
- __drm_atomic_helper_plane_reset - resets planes state to default values
- @plane: plane object, must not be NULL
- @state: atomic plane state, must not be NULL
- Initializes plane state to default. This is useful for drivers that subclass
- the plane state.
- */
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- state->plane = plane;
- state->rotation = DRM_MODE_ROTATE_0;
- state->alpha = DRM_BLEND_ALPHA_OPAQUE;
- state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
- plane->state = state;
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
+/**
- drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
- @plane: drm plane
- Resets the atomic state for @plane by freeing the state pointer (which might
- be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
+void drm_atomic_helper_plane_reset(struct drm_plane *plane) +{
- if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
- kfree(plane->state);
- plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
- if (plane->state)
__drm_atomic_helper_plane_reset(plane, plane->state);
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
+/**
- __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
- @plane: plane object
- @state: atomic plane state
- Copies atomic state from a plane's current state. This is useful for
- drivers that subclass the plane state.
- */
+void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- memcpy(state, plane->state, sizeof(*state));
- if (state->fb)
drm_framebuffer_get(state->fb);
- state->fence = NULL;
- state->commit = NULL;
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
+/**
- drm_atomic_helper_plane_duplicate_state - default state duplicate hook
- @plane: drm plane
- Default plane state duplicate hook for drivers which don't have their own
- subclassed plane state structure.
- */
+struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) +{
- struct drm_plane_state *state;
- if (WARN_ON(!plane->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_plane_duplicate_state(plane, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
+/**
- __drm_atomic_helper_plane_destroy_state - release plane state
- @state: plane state object to release
- Releases all resources stored in the plane state without actually freeing
- the memory of the plane state. This is useful for drivers that subclass the
- plane state.
- */
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) +{
- if (state->fb)
drm_framebuffer_put(state->fb);
- if (state->fence)
dma_fence_put(state->fence);
- if (state->commit)
drm_crtc_commit_put(state->commit);
+} +EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
+/**
- drm_atomic_helper_plane_destroy_state - default state destroy hook
- @plane: drm plane
- @state: plane state object to release
- Default plane state destroy hook for drivers which don't have their own
- subclassed plane state structure.
- */
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- __drm_atomic_helper_plane_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
+/**
- __drm_atomic_helper_connector_reset - reset state on connector
- @connector: drm connector
- @conn_state: connector state to assign
- Initializes the newly allocated @conn_state and assigns it to
- the &drm_conector->state pointer of @connector, usually required when
- initializing the drivers or when called from the &drm_connector_funcs.reset
- hook.
- This is useful for drivers that subclass the connector state.
- */
+void +__drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state)
+{
- if (conn_state)
conn_state->connector = connector;
- connector->state = conn_state;
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
+/**
- drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
- @connector: drm connector
- Resets the atomic state for @connector by freeing the state pointer (which
- might be NULL, e.g. at driver load time) and allocating a new empty state
- object.
- */
+void drm_atomic_helper_connector_reset(struct drm_connector *connector) +{
- struct drm_connector_state *conn_state =
kzalloc(sizeof(*conn_state), GFP_KERNEL);
- if (connector->state)
__drm_atomic_helper_connector_destroy_state(connector->state);
- kfree(connector->state);
- __drm_atomic_helper_connector_reset(connector, conn_state);
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
+/**
- __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
- @connector: connector object
- @state: atomic connector state
- Copies atomic state from a connector's current state. This is useful for
- drivers that subclass the connector state.
- */
+void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state)
+{
- memcpy(state, connector->state, sizeof(*state));
- if (state->crtc)
drm_connector_get(connector);
- state->commit = NULL;
- /* Don't copy over a writeback job, they are used only once */
- state->writeback_job = NULL;
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
+/**
- drm_atomic_helper_connector_duplicate_state - default state duplicate hook
- @connector: drm connector
- Default connector state duplicate hook for drivers which don't have their own
- subclassed connector state structure.
- */
+struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) +{
- struct drm_connector_state *state;
- if (WARN_ON(!connector->state))
return NULL;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state)
__drm_atomic_helper_connector_duplicate_state(connector, state);
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
+/**
- drm_atomic_helper_duplicate_state - duplicate an atomic state object
- @dev: DRM device
- @ctx: lock acquisition context
- Makes a copy of the current atomic state by looping over all objects and
- duplicating their respective states. This is used for example by suspend/
- resume support code to save the state prior to suspend such that it can
- be restored upon resume.
- Note that this treats atomic state as persistent between save and restore.
- Drivers must make sure that this is possible and won't result in confusion
- or erroneous behaviour.
- Note that if callers haven't already acquired all modeset locks this might
- return -EDEADLK, which must be handled by calling drm_modeset_backoff().
- Returns:
- A pointer to the copy of the atomic state object on success or an
- ERR_PTR()-encoded error code on failure.
- See also:
- drm_atomic_helper_suspend(), drm_atomic_helper_resume()
- */
+struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
+{
- struct drm_atomic_state *state;
- struct drm_connector *conn;
- struct drm_connector_list_iter conn_iter;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- int err = 0;
- state = drm_atomic_state_alloc(dev);
- if (!state)
return ERR_PTR(-ENOMEM);
- state->acquire_ctx = ctx;
- drm_for_each_crtc(crtc, dev) {
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
err = PTR_ERR(crtc_state);
goto free;
}
- }
- drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
err = PTR_ERR(plane_state);
goto free;
}
- }
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
conn_state = drm_atomic_get_connector_state(state, conn);
if (IS_ERR(conn_state)) {
err = PTR_ERR(conn_state);
drm_connector_list_iter_end(&conn_iter);
goto free;
}
- }
- drm_connector_list_iter_end(&conn_iter);
- /* clear the acquire context so that it isn't accidentally reused */
- state->acquire_ctx = NULL;
+free:
- if (err < 0) {
drm_atomic_state_put(state);
state = ERR_PTR(err);
- }
- return state;
+} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
+/**
- __drm_atomic_helper_connector_destroy_state - release connector state
- @state: connector state object to release
- Releases all resources stored in the connector state without actually
- freeing the memory of the connector state. This is useful for drivers that
- subclass the connector state.
- */
+void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) +{
- if (state->crtc)
drm_connector_put(state->connector);
- if (state->commit)
drm_crtc_commit_put(state->commit);
+} +EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
+/**
- drm_atomic_helper_connector_destroy_state - default state destroy hook
- @connector: drm connector
- @state: connector state object to release
- Default connector state destroy hook for drivers which don't have their own
- subclassed connector state structure.
- */
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
+{
- __drm_atomic_helper_connector_destroy_state(state);
- kfree(state);
+} +EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
+/**
- drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
- @crtc: CRTC object
- @red: red correction table
- @green: green correction table
- @blue: green correction table
- @size: size of the tables
- @ctx: lock acquire context
- Implements support for legacy gamma correction table for drivers
- that support color management through the DEGAMMA_LUT/GAMMA_LUT
- properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
- how the atomic color management and gamma tables work.
- */
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
+{
- struct drm_device *dev = crtc->dev;
- struct drm_atomic_state *state;
- struct drm_crtc_state *crtc_state;
- struct drm_property_blob *blob = NULL;
- struct drm_color_lut *blob_data;
- int i, ret = 0;
- bool replaced;
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state)
return -ENOMEM;
- blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
- if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
- }
- /* Prepare GAMMA_LUT with the legacy values. */
- blob_data = blob->data;
- for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
- }
- state->acquire_ctx = ctx;
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
- }
- /* Reset DEGAMMA_LUT and CTM properties. */
- replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
- replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
- crtc_state->color_mgmt_changed |= replaced;
- ret = drm_atomic_commit(state);
+fail:
- drm_atomic_state_put(state);
- drm_property_blob_put(blob);
- return ret;
+} +EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+/**
- __drm_atomic_helper_private_duplicate_state - copy atomic private state
- @obj: CRTC object
- @state: new private object state
- Copies atomic state from a private objects's current state and resets inferred values.
- This is useful for drivers that subclass the private state.
- */
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state)
+{
- memcpy(state, obj->state, sizeof(*state));
+} +EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index e60c4f0f8827..25ca0097563e 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -31,6 +31,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_modeset_helper.h> +#include <drm/drm_atomic_state_helper.h> #include <drm/drm_util.h>
struct drm_atomic_state; @@ -145,49 +146,6 @@ int drm_atomic_helper_page_flip_target( uint32_t target, struct drm_modeset_acquire_ctx *ctx);
-/* default implementations for state handling */ -void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
-struct drm_crtc_state * -drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); -void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state);
-void drm_atomic_helper_plane_reset(struct drm_plane *plane); -void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state);
-struct drm_plane_state * -drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); -void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); -void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
-void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state);
-void drm_atomic_helper_connector_reset(struct drm_connector *connector); -void -__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state);
-struct drm_connector_state * -drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); -struct drm_atomic_state * -drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
-void -__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); -void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state);
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state);
/**
- drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
- @plane: the loop cursor
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h new file mode 100644 index 000000000000..5b82ccfdb502 --- /dev/null +++ b/include/drm/drm_atomic_state_helper.h @@ -0,0 +1,80 @@ +/*
- Copyright (C) 2018 Intel Corp.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- Authors:
- Rob Clark robdclark@gmail.com
- Daniel Vetter daniel.vetter@ffwll.ch
- */
+#include <linux/types.h>
+struct drm_crtc; +struct drm_crtc_state; +struct drm_plane; +struct drm_plane_state; +struct drm_connector; +struct drm_connector_state; +struct drm_private_obj; +struct drm_private_state; +struct drm_modeset_acquire_ctx; +struct drm_device;
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
+struct drm_crtc_state * +drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); +void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
struct drm_plane_state *state);
+void drm_atomic_helper_plane_reset(struct drm_plane *plane); +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
struct drm_plane_state *state);
+struct drm_plane_state * +drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); +void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); +void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
+void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
struct drm_connector_state *conn_state);
+void drm_atomic_helper_connector_reset(struct drm_connector *connector); +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
struct drm_connector_state *state);
+struct drm_connector_state * +drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
+void +__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state); +void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state);
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state);
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
-- Ville Syrjälä Intel
The core _does_ the call to drm_atomic_commit for you. That's pretty much the entire point of having the fancy new atomic_set/get_prop callbacks.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 292e48feba83..049bd50eea87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2311,12 +2311,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
if (property == dev_priv->implicit_placement_property) { vcs->is_implicit = val; - - /* - * We should really be doing a drm_atomic_commit() to - * commit the new state, but since this doesn't cause - * an immedate state change, this is probably ok - */ du->is_implicit = vcs->is_implicit; } else { return -EINVAL;
On Tue, Oct 02, 2018 at 03:35:12PM +0200, Daniel Vetter wrote:
The core _does_ the call to drm_atomic_commit for you. That's pretty much the entire point of having the fancy new atomic_set/get_prop callbacks.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 292e48feba83..049bd50eea87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2311,12 +2311,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
if (property == dev_priv->implicit_placement_property) { vcs->is_implicit = val;
/*
* We should really be doing a drm_atomic_commit() to
* commit the new state, but since this doesn't cause
* an immedate state change, this is probably ok
du->is_implicit = vcs->is_implicit;*/
Maybe the comment is referring to delaying the du->is_implicit assignment to commit time? Otherwise a TEST_ONLY/failed commit will clobber this.
Hmm. There's both .set_property() and .atomic_set_property() in there. I wonder what that's about.
} else { return -EINVAL; -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
On 10/02/2018 05:15 PM, Ville Syrjälä wrote:
On Tue, Oct 02, 2018 at 03:35:12PM +0200, Daniel Vetter wrote:
The core _does_ the call to drm_atomic_commit for you. That's pretty much the entire point of having the fancy new atomic_set/get_prop callbacks.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 292e48feba83..049bd50eea87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2311,12 +2311,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
if (property == dev_priv->implicit_placement_property) { vcs->is_implicit = val;
/*
* We should really be doing a drm_atomic_commit() to
* commit the new state, but since this doesn't cause
* an immedate state change, this is probably ok
du->is_implicit = vcs->is_implicit;*/
Maybe the comment is referring to delaying the du->is_implicit assignment to commit time? Otherwise a TEST_ONLY/failed commit will clobber this.
The is_implicit property is made read-only in a vmwgfx recent commit. Not sure exactly where it ended up, though. (-fixes, -next or -limbo). Need to take a look.
Hmm. There's both .set_property() and .atomic_set_property() in there. I wonder what that's about.
Probably a leftover. I take it .set_property() is not needed when we have .atomic_set_property()?
/Thomas
} else { return -EINVAL; -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freed...
On Tue, Oct 02, 2018 at 04:36:31PM +0000, Thomas Hellstrom wrote:
On 10/02/2018 05:15 PM, Ville Syrjälä wrote:
On Tue, Oct 02, 2018 at 03:35:12PM +0200, Daniel Vetter wrote:
The core _does_ the call to drm_atomic_commit for you. That's pretty much the entire point of having the fancy new atomic_set/get_prop callbacks.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 292e48feba83..049bd50eea87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2311,12 +2311,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
if (property == dev_priv->implicit_placement_property) { vcs->is_implicit = val;
/*
* We should really be doing a drm_atomic_commit() to
* commit the new state, but since this doesn't cause
* an immedate state change, this is probably ok
du->is_implicit = vcs->is_implicit;*/
Maybe the comment is referring to delaying the du->is_implicit assignment to commit time? Otherwise a TEST_ONLY/failed commit will clobber this.
The is_implicit property is made read-only in a vmwgfx recent commit. Not sure exactly where it ended up, though. (-fixes, -next or -limbo). Need to take a look.
Hmm. There's both .set_property() and .atomic_set_property() in there. I wonder what that's about.
Probably a leftover. I take it .set_property() is not needed when we have .atomic_set_property()?
Yeah, the legacy one is dead weight at this point.
On Tue, Oct 02, 2018 at 04:36:31PM +0000, Thomas Hellstrom wrote:
On 10/02/2018 05:15 PM, Ville Syrjälä wrote:
On Tue, Oct 02, 2018 at 03:35:12PM +0200, Daniel Vetter wrote:
The core _does_ the call to drm_atomic_commit for you. That's pretty much the entire point of having the fancy new atomic_set/get_prop callbacks.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 292e48feba83..049bd50eea87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2311,12 +2311,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
if (property == dev_priv->implicit_placement_property) { vcs->is_implicit = val;
/*
* We should really be doing a drm_atomic_commit() to
* commit the new state, but since this doesn't cause
* an immedate state change, this is probably ok
du->is_implicit = vcs->is_implicit;*/
Maybe the comment is referring to delaying the du->is_implicit assignment to commit time? Otherwise a TEST_ONLY/failed commit will clobber this.
The is_implicit property is made read-only in a vmwgfx recent commit. Not sure exactly where it ended up, though. (-fixes, -next or -limbo). Need to take a look.
I guess -limbo, since my tree contains both drm-fixes and drm-next. Or at least they didn't make it to Dave yet. -Daniel
Hmm. There's both .set_property() and .atomic_set_property() in there. I wonder what that's about.
Probably a leftover. I take it .set_property() is not needed when we have .atomic_set_property()?
/Thomas
} else { return -EINVAL; -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freed...
That's purely for the uapi layer to implement the ALLOW_MODESET flag.
Drivers should instead look at the state, e.g. through drm_atomic_crtc_needs_modeset(), which vmwgfx already does. Also remove the confusing comment, since checking allow_modeset is at best a micro optimization.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 -------- 1 file changed, 8 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 049bd50eea87..1b2a406b7742 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1681,14 +1681,6 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev, if (ret) return ret;
- if (!state->allow_modeset) - return ret; - - /* - * Legacy path do not set allow_modeset properly like - * @drm_atomic_helper_update_plane, This will result in unnecessary call - * to vmw_kms_check_topology. So extra set of check. - */ for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (drm_atomic_crtc_needs_modeset(crtc_state)) need_modeset = true;
Motivated by vmwgfx digging around in core uapi bits it shouldn't dig around in.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- include/drm/drm_atomic.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index d6adebcd6ea4..c09ecaf43825 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -254,7 +254,6 @@ struct __drm_private_objs_state { * struct drm_atomic_state - the global state object for atomic updates * @ref: count of all references to this state (will not be freed until zero) * @dev: parent DRM device - * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics * @async_update: hint for asynchronous plane update * @planes: pointer to array of structures with per-plane data @@ -273,6 +272,15 @@ struct drm_atomic_state { struct kref ref;
struct drm_device *dev; + + /** + * @allow_modeset: + * + * Allow full modeset. This is used by the ATOMIC IOCTL handler to + * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should + * never consult this flag, instead looking at the output of + * drm_atomic_crtc_needs_modeset(). + */ bool allow_modeset : 1; bool legacy_cursor_update : 1; bool async_update : 1;
On Tue, Oct 02, 2018 at 03:35:14PM +0200, Daniel Vetter wrote:
Motivated by vmwgfx digging around in core uapi bits it shouldn't dig around in.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
include/drm/drm_atomic.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index d6adebcd6ea4..c09ecaf43825 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -254,7 +254,6 @@ struct __drm_private_objs_state {
- struct drm_atomic_state - the global state object for atomic updates
- @ref: count of all references to this state (will not be freed until zero)
- @dev: parent DRM device
- @allow_modeset: allow full modeset
- @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
- @async_update: hint for asynchronous plane update
- @planes: pointer to array of structures with per-plane data
@@ -273,6 +272,15 @@ struct drm_atomic_state { struct kref ref;
struct drm_device *dev;
- /**
* @allow_modeset:
*
* Allow full modeset. This is used by the ATOMIC IOCTL handler to
* implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should
* never consult this flag, instead looking at the output of
* drm_atomic_crtc_needs_modeset().
bool allow_modeset : 1; bool legacy_cursor_update : 1; bool async_update : 1;*/
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
The idea behind allowing drivers to override legacy ioctls (instead of using the generic implementations unconditionally) is to handle bugs in old driver-specific userspace. Like e.g. vmw_kms_set_config does, to work around some vmwgfx userspace not clearing its ioctl structs properly.
But you can't use it to augment semantics and put in additional checks, since from a correctly working userspace's pov there should not be any difference in behaviour between the legacy and the atomic paths.
vmwgfx seems to be doing some strange things in its page_flip handlers. Since I'm not an expert of this codebase just wrap some FIXME comments around the potentially problematic code.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 + 2 files changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 4c68ad6f3605..8e692334c3b9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -326,6 +326,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, struct vmw_private *dev_priv = vmw_priv(crtc->dev); int ret;
+ /* FIMXE: This check needs to be moved into ->atomic_check code. */ if (!vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL;
@@ -335,6 +336,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, return ret; }
+ /* FIMXE: This code needs to be moved into ->atomic_commit callbacks. */ if (vmw_crtc_to_du(crtc)->is_implicit) vmw_kms_update_implicit_fb(dev_priv, crtc);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index e28bb08114a5..199927f20e0a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -501,6 +501,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); int ret;
+ /* FIMXE: This check needs to be moved into ->atomic_check code. */ if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL;
Hi, Daniel,
On 10/02/2018 03:35 PM, Daniel Vetter wrote:
The idea behind allowing drivers to override legacy ioctls (instead of using the generic implementations unconditionally) is to handle bugs in old driver-specific userspace. Like e.g. vmw_kms_set_config does, to work around some vmwgfx userspace not clearing its ioctl structs properly.
But you can't use it to augment semantics and put in additional checks, since from a correctly working userspace's pov there should not be any difference in behaviour between the legacy and the atomic paths.
vmwgfx seems to be doing some strange things in its page_flip handlers. Since I'm not an expert of this codebase just wrap some FIXME comments around the potentially problematic code.
We've got proper patches for these. Apparently they got lost in my -next pull request, though.
/Thomas
On Tue, Oct 02, 2018 at 04:49:30PM +0000, Thomas Hellstrom wrote:
Hi, Daniel,
On 10/02/2018 03:35 PM, Daniel Vetter wrote:
The idea behind allowing drivers to override legacy ioctls (instead of using the generic implementations unconditionally) is to handle bugs in old driver-specific userspace. Like e.g. vmw_kms_set_config does, to work around some vmwgfx userspace not clearing its ioctl structs properly.
But you can't use it to augment semantics and put in additional checks, since from a correctly working userspace's pov there should not be any difference in behaviour between the legacy and the atomic paths.
vmwgfx seems to be doing some strange things in its page_flip handlers. Since I'm not an expert of this codebase just wrap some FIXME comments around the potentially problematic code.
We've got proper patches for these. Apparently they got lost in my -next pull request, though.
Yeah I wondered why this one here didn't conflict yet, I can carry it around a bit longer as a memo. -Daniel
These do absolutely nothing for atomic drivers.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 965cda48dc13..26cb2800f3ad 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -158,8 +158,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_valid = arc_pgu_crtc_mode_valid, - .mode_set = drm_helper_crtc_mode_set, - .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, .atomic_begin = arc_pgu_crtc_atomic_begin, .atomic_enable = arc_pgu_crtc_atomic_enable,
On Tue, Oct 02, 2018 at 03:35:16PM +0200, Daniel Vetter wrote:
These do absolutely nothing for atomic drivers.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com
drivers/gpu/drm/arc/arcpgu_crtc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 965cda48dc13..26cb2800f3ad 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -158,8 +158,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_valid = arc_pgu_crtc_mode_valid,
- .mode_set = drm_helper_crtc_mode_set,
- .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, .atomic_begin = arc_pgu_crtc_atomic_begin, .atomic_enable = arc_pgu_crtc_atomic_enable,
It's easy to get confused with all the hooks and helpers. But after staring at the code a bit this looks correct to me: Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Tue, Oct 02, 2018 at 06:34:39PM +0300, Ville Syrjälä wrote:
On Tue, Oct 02, 2018 at 03:35:16PM +0200, Daniel Vetter wrote:
These do absolutely nothing for atomic drivers.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com
drivers/gpu/drm/arc/arcpgu_crtc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 965cda48dc13..26cb2800f3ad 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -158,8 +158,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_valid = arc_pgu_crtc_mode_valid,
- .mode_set = drm_helper_crtc_mode_set,
- .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, .atomic_begin = arc_pgu_crtc_atomic_begin, .atomic_enable = arc_pgu_crtc_atomic_enable,
It's easy to get confused with all the hooks and helpers. But after staring at the code a bit this looks correct to me:
Hm, I guess I could write a patch that liberally sprinkles WARN_ON on all the deprecated hooks if you're an atomic driver. But that's kinda for another time.
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
-- Ville Syrjälä Intel
These do absolutely nothing for atomic drivers.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Boris Brezillon boris.brezillon@bootlin.com Cc: Nicolas Ferre nicolas.ferre@microchip.com Cc: Alexandre Belloni alexandre.belloni@bootlin.com Cc: linux-arm-kernel@lists.infradead.org --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 9e34bce089d0..96f4082671fe 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -364,9 +364,7 @@ static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { .mode_valid = atmel_hlcdc_crtc_mode_valid, - .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, - .mode_set_base = drm_helper_crtc_mode_set_base, .atomic_check = atmel_hlcdc_crtc_atomic_check, .atomic_begin = atmel_hlcdc_crtc_atomic_begin, .atomic_flush = atmel_hlcdc_crtc_atomic_flush,
On Tue, Oct 02, 2018 at 03:35:17PM +0200, Daniel Vetter wrote:
These do absolutely nothing for atomic drivers.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Boris Brezillon boris.brezillon@bootlin.com Cc: Nicolas Ferre nicolas.ferre@microchip.com Cc: Alexandre Belloni alexandre.belloni@bootlin.com Cc: linux-arm-kernel@lists.infradead.org
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 9e34bce089d0..96f4082671fe 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -364,9 +364,7 @@ static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { .mode_valid = atmel_hlcdc_crtc_mode_valid,
- .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb,
- .mode_set_base = drm_helper_crtc_mode_set_base, .atomic_check = atmel_hlcdc_crtc_atomic_check, .atomic_begin = atmel_hlcdc_crtc_atomic_begin, .atomic_flush = atmel_hlcdc_crtc_atomic_flush,
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 1 - drivers/gpu/drm/arc/arcpgu_drv.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 26cb2800f3ad..62f51f70606d 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -184,7 +184,6 @@ static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
static void arc_pgu_plane_destroy(struct drm_plane *plane) { - drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane); }
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index f067de4e1e82..e85e3a349f24 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -134,6 +134,7 @@ static int arcpgu_unload(struct drm_device *drm) arcpgu->fbdev = NULL; } drm_kms_helper_poll_fini(drm); + drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm);
return 0;
On Tue, Oct 02, 2018 at 03:35:18PM +0200, Daniel Vetter wrote:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Alexey Brodkin abrodkin@synopsys.com
Matches earlier changes made to other drivers. I wonder if there are any more left?
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/arc/arcpgu_crtc.c | 1 - drivers/gpu/drm/arc/arcpgu_drv.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 26cb2800f3ad..62f51f70606d 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -184,7 +184,6 @@ static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
static void arc_pgu_plane_destroy(struct drm_plane *plane) {
- drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
}
Could eliminate this (now pointless) wrapper as well.
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index f067de4e1e82..e85e3a349f24 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -134,6 +134,7 @@ static int arcpgu_unload(struct drm_device *drm) arcpgu->fbdev = NULL; } drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm);
return 0;
-- 2.19.0.rc2
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Rob Clark robdclark@gmail.com Cc: Rajesh Yadav ryadav@codeaurora.org Cc: Chandan Uddaraju chandanu@codeaurora.org Cc: Archit Taneja architt@codeaurora.org Cc: Jeykumar Sankaran jsanka@codeaurora.org Cc: Sean Paul seanpaul@chromium.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sinclair Yeh syeh@vmware.com Cc: "Ville Syrjälä" ville.syrjala@linux.intel.com Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Gustavo Padovan gustavo.padovan@collabora.com Cc: Arnd Bergmann arnd@arndb.de Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 -- drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 1 - drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 015341e2dd4c..ec959f847d5f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1482,8 +1482,6 @@ static void dpu_plane_destroy(struct drm_plane *plane)
mutex_destroy(&pdpu->lock);
- drm_plane_helper_disable(plane, NULL); - /* this will destroy the states as well */ drm_plane_cleanup(plane);
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index 79ff653d8081..7a499731ce93 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -68,7 +68,6 @@ static void mdp4_plane_destroy(struct drm_plane *plane) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
- drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
kfree(mdp4_plane); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index 7d306c5acd09..d5e4f0de321a 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -46,7 +46,6 @@ static void mdp5_plane_destroy(struct drm_plane *plane) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
- drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
kfree(mdp5_plane); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c1abad8a8612..69dbdba183fe 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -312,6 +312,7 @@ static int msm_drm_uninit(struct device *dev) if (fbdev && priv->fbdev) msm_fbdev_free(ddev); #endif + drm_atomic_helper_shutdown(ddev); drm_mode_config_cleanup(ddev);
pm_runtime_get_sync(dev);
On Wed, Oct 03, 2018 at 11:16:44AM +0200, Daniel Vetter wrote:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
lgtm Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Rob Clark robdclark@gmail.com Cc: Rajesh Yadav ryadav@codeaurora.org Cc: Chandan Uddaraju chandanu@codeaurora.org Cc: Archit Taneja architt@codeaurora.org Cc: Jeykumar Sankaran jsanka@codeaurora.org Cc: Sean Paul seanpaul@chromium.org Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com Cc: Sinclair Yeh syeh@vmware.com Cc: "Ville Syrjälä" ville.syrjala@linux.intel.com Cc: Russell King rmk+kernel@armlinux.org.uk Cc: Gustavo Padovan gustavo.padovan@collabora.com Cc: Arnd Bergmann arnd@arndb.de Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 -- drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 1 - drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 015341e2dd4c..ec959f847d5f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1482,8 +1482,6 @@ static void dpu_plane_destroy(struct drm_plane *plane)
mutex_destroy(&pdpu->lock);
drm_plane_helper_disable(plane, NULL);
- /* this will destroy the states as well */ drm_plane_cleanup(plane);
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index 79ff653d8081..7a499731ce93 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -68,7 +68,6 @@ static void mdp4_plane_destroy(struct drm_plane *plane) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
kfree(mdp4_plane);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index 7d306c5acd09..d5e4f0de321a 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -46,7 +46,6 @@ static void mdp5_plane_destroy(struct drm_plane *plane) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
kfree(mdp5_plane);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c1abad8a8612..69dbdba183fe 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -312,6 +312,7 @@ static int msm_drm_uninit(struct device *dev) if (fbdev && priv->fbdev) msm_fbdev_free(ddev); #endif
drm_atomic_helper_shutdown(ddev); drm_mode_config_cleanup(ddev);
pm_runtime_get_sync(dev);
-- 2.19.0.rc2
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
The sti cleanup code seems supremely confused: - In the load error path it calls drm_mode_config_cleanup before it stops various kms services like poll worker or fbdev emulation. That's going to oops. - The actual unload code doesn't even bother with the cleanup and just leaks.
Try to fix this while at it.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Benjamin Gaignard benjamin.gaignard@linaro.org Cc: Vincent Abriou vincent.abriou@st.com --- drivers/gpu/drm/sti/sti_cursor.c | 1 - drivers/gpu/drm/sti/sti_drv.c | 6 +++--- drivers/gpu/drm/sti/sti_gdp.c | 1 - drivers/gpu/drm/sti/sti_hqvdp.c | 1 - 4 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 57b870e1e696..bc908453ffb3 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -332,7 +332,6 @@ static void sti_cursor_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane); }
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 6dced8abcf16..ac54e0f9caea 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -206,6 +206,8 @@ static void sti_cleanup(struct drm_device *ddev) struct sti_private *private = ddev->dev_private;
drm_kms_helper_poll_fini(ddev); + drm_atomic_helper_shutdown(ddev); + drm_mode_config_cleanup(ddev); component_unbind_all(ddev->dev, ddev); kfree(private); ddev->dev_private = NULL; @@ -230,7 +232,7 @@ static int sti_bind(struct device *dev)
ret = drm_dev_register(ddev, 0); if (ret) - goto err_register; + goto err_cleanup;
drm_mode_config_reset(ddev);
@@ -238,8 +240,6 @@ static int sti_bind(struct device *dev)
return 0;
-err_register: - drm_mode_config_cleanup(ddev); err_cleanup: sti_cleanup(ddev); err_drm_dev_put: diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index c32de6cbf061..3c19614d3f75 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -883,7 +883,6 @@ static void sti_gdp_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane); }
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 03ac3b4a4469..23565f52dd71 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1260,7 +1260,6 @@ static void sti_hqvdp_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane); }
On Wed, Oct 03, 2018 at 11:17:26AM +0200, Daniel Vetter wrote:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
The sti cleanup code seems supremely confused:
- In the load error path it calls drm_mode_config_cleanup before it stops various kms services like poll worker or fbdev emulation. That's going to oops.
- The actual unload code doesn't even bother with the cleanup and just leaks.
Try to fix this while at it.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Benjamin Gaignard benjamin.gaignard@linaro.org Cc: Vincent Abriou vincent.abriou@st.com
drivers/gpu/drm/sti/sti_cursor.c | 1 - drivers/gpu/drm/sti/sti_drv.c | 6 +++--- drivers/gpu/drm/sti/sti_gdp.c | 1 - drivers/gpu/drm/sti/sti_hqvdp.c | 1 - 4 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 57b870e1e696..bc908453ffb3 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -332,7 +332,6 @@ static void sti_cursor_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane);
}
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 6dced8abcf16..ac54e0f9caea 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -206,6 +206,8 @@ static void sti_cleanup(struct drm_device *ddev) struct sti_private *private = ddev->dev_private;
drm_kms_helper_poll_fini(ddev);
- drm_atomic_helper_shutdown(ddev);
- drm_mode_config_cleanup(ddev);
Looks like a more sane ordering. Not really sure how these component based drivers work so probably not the best person to judge this, but based on my weak understanding Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
component_unbind_all(ddev->dev, ddev); kfree(private); ddev->dev_private = NULL; @@ -230,7 +232,7 @@ static int sti_bind(struct device *dev)
ret = drm_dev_register(ddev, 0); if (ret)
goto err_register;
goto err_cleanup;
drm_mode_config_reset(ddev);
@@ -238,8 +240,6 @@ static int sti_bind(struct device *dev)
return 0;
-err_register:
- drm_mode_config_cleanup(ddev);
err_cleanup: sti_cleanup(ddev); err_drm_dev_put: diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index c32de6cbf061..3c19614d3f75 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -883,7 +883,6 @@ static void sti_gdp_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane);
}
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 03ac3b4a4469..23565f52dd71 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1260,7 +1260,6 @@ static void sti_hqvdp_destroy(struct drm_plane *drm_plane) { DRM_DEBUG_DRIVER("\n");
- drm_plane_helper_disable(drm_plane, NULL); drm_plane_cleanup(drm_plane);
}
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
v2: Rebase.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Eric Anholt eric@anholt.net --- drivers/gpu/drm/vc4/vc4_drv.c | 3 +++ drivers/gpu/drm/vc4/vc4_plane.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 1f1780ccdbdf..f6f5cd80c04d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -33,6 +33,7 @@ #include <linux/pm_runtime.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic_helper.h>
#include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" @@ -308,6 +309,8 @@ static void vc4_drm_unbind(struct device *dev)
drm_dev_unregister(drm);
+ drm_atomic_helper_shutdown(drm); + drm_mode_config_cleanup(drm);
drm_atomic_private_obj_fini(&vc4->ctm_manager); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 9dc3fcbd290b..d04b3c3246ba 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -903,7 +903,6 @@ static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
static void vc4_plane_destroy(struct drm_plane *plane) { - drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane); }
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Shawn Guo shawnguo@kernel.org --- drivers/gpu/drm/zte/zx_drm_drv.c | 1 + drivers/gpu/drm/zte/zx_plane.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index 5b6f1eda52e0..f5ea32ae8600 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -124,6 +124,7 @@ static void zx_drm_unbind(struct device *dev)
drm_dev_unregister(drm); drm_kms_helper_poll_fini(drm); + drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm); component_unbind_all(dev, drm); dev_set_drvdata(dev, NULL); diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index ae8c53b4b261..83d236fd893c 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -446,7 +446,6 @@ static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
static void zx_plane_destroy(struct drm_plane *plane) { - drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane); }
On Wed, Oct 03, 2018 at 11:18:23AM +0200, Daniel Vetter wrote:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Shawn Guo shawnguo@kernel.org
drivers/gpu/drm/zte/zx_drm_drv.c | 1 + drivers/gpu/drm/zte/zx_plane.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index 5b6f1eda52e0..f5ea32ae8600 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -124,6 +124,7 @@ static void zx_drm_unbind(struct device *dev)
drm_dev_unregister(drm); drm_kms_helper_poll_fini(drm);
- drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm);
Familiar pattern by now, so
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
component_unbind_all(dev, drm); dev_set_drvdata(dev, NULL); diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index ae8c53b4b261..83d236fd893c 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -446,7 +446,6 @@ static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
static void zx_plane_destroy(struct drm_plane *plane) {
- drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
}
-- 2.19.0.rc2
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
With armada the last bigger driver that realistically needed these to convert from legacy kms to atomic is converted. These helpers have been broken more often than not the past 2 years, and as this little patch series shows, tricked a bunch of people into using the wrong helpers for their functions.
Aside: I think a lot more drivers should be using the device-level drm_atomic_helper_shutdown/suspend/resume helpers and related functions. In almost all the cases they get things exactly right.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/drm_crtc_helper.c | 115 ----------------- drivers/gpu/drm/drm_plane_helper.c | 197 ----------------------------- include/drm/drm_crtc_helper.h | 6 - include/drm/drm_plane_helper.h | 14 -- 4 files changed, 332 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ce75e9506e85..a3c81850e755 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -984,118 +984,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev) drm_modeset_unlock_all(dev); } EXPORT_SYMBOL(drm_helper_resume_force_mode); - -/** - * drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers - * @crtc: DRM CRTC - * @mode: DRM display mode which userspace requested - * @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks - * @x: x offset of the CRTC scanout area on the underlying framebuffer - * @y: y offset of the CRTC scanout area on the underlying framebuffer - * @old_fb: previous framebuffer - * - * This function implements a callback useable as the ->mode_set callback - * required by the CRTC helpers. Besides the atomic plane helper functions for - * the primary plane the driver must also provide the ->mode_set_nofb callback - * to set up the CRTC. - * - * This is a transitional helper useful for converting drivers to the atomic - * interfaces. - */ -int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_crtc_state *crtc_state; - const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - int ret; - - if (crtc->funcs->atomic_duplicate_state) - crtc_state = crtc->funcs->atomic_duplicate_state(crtc); - else { - if (!crtc->state) - drm_atomic_helper_crtc_reset(crtc); - - crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc); - } - - if (!crtc_state) - return -ENOMEM; - - crtc_state->planes_changed = true; - crtc_state->mode_changed = true; - ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); - if (ret) - goto out; - drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode); - - if (crtc_funcs->atomic_check) { - ret = crtc_funcs->atomic_check(crtc, crtc_state); - if (ret) - goto out; - } - - swap(crtc->state, crtc_state); - - crtc_funcs->mode_set_nofb(crtc); - - ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); - -out: - if (crtc_state) { - if (crtc->funcs->atomic_destroy_state) - crtc->funcs->atomic_destroy_state(crtc, crtc_state); - else - drm_atomic_helper_crtc_destroy_state(crtc, crtc_state); - } - - return ret; -} -EXPORT_SYMBOL(drm_helper_crtc_mode_set); - -/** - * drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers - * @crtc: DRM CRTC - * @x: x offset of the CRTC scanout area on the underlying framebuffer - * @y: y offset of the CRTC scanout area on the underlying framebuffer - * @old_fb: previous framebuffer - * - * This function implements a callback useable as the ->mode_set_base used - * required by the CRTC helpers. The driver must provide the atomic plane helper - * functions for the primary plane. - * - * This is a transitional helper useful for converting drivers to the atomic - * interfaces. - */ -int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_plane_state *plane_state; - struct drm_plane *plane = crtc->primary; - - if (plane->funcs->atomic_duplicate_state) - plane_state = plane->funcs->atomic_duplicate_state(plane); - else { - if (!plane->state) - drm_atomic_helper_plane_reset(plane); - - plane_state = drm_atomic_helper_plane_duplicate_state(plane); - } - if (!plane_state) - return -ENOMEM; - plane_state->plane = plane; - - plane_state->crtc = crtc; - drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); - plane_state->crtc_x = 0; - plane_state->crtc_y = 0; - plane_state->crtc_h = crtc->mode.vdisplay; - plane_state->crtc_w = crtc->mode.hdisplay; - plane_state->src_x = x << 16; - plane_state->src_y = y << 16; - plane_state->src_h = crtc->mode.vdisplay << 16; - plane_state->src_w = crtc->mode.hdisplay << 16; - - return drm_plane_helper_commit(plane, plane_state, old_fb); -} -EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index a393756b664e..965286231600 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -336,200 +336,3 @@ const struct drm_plane_funcs drm_primary_helper_funcs = { .destroy = drm_primary_helper_destroy, }; EXPORT_SYMBOL(drm_primary_helper_funcs); - -int drm_plane_helper_commit(struct drm_plane *plane, - struct drm_plane_state *plane_state, - struct drm_framebuffer *old_fb) -{ - const struct drm_plane_helper_funcs *plane_funcs; - struct drm_crtc *crtc[2]; - const struct drm_crtc_helper_funcs *crtc_funcs[2]; - int i, ret = 0; - - plane_funcs = plane->helper_private; - - /* Since this is a transitional helper we can't assume that plane->state - * is always valid. Hence we need to use plane->crtc instead of - * plane->state->crtc as the old crtc. */ - crtc[0] = plane->crtc; - crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL; - - for (i = 0; i < 2; i++) - crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL; - - if (plane_funcs->atomic_check) { - ret = plane_funcs->atomic_check(plane, plane_state); - if (ret) - goto out; - } - - if (plane_funcs->prepare_fb && plane_state->fb != old_fb) { - ret = plane_funcs->prepare_fb(plane, - plane_state); - if (ret) - goto out; - } - - /* Point of no return, commit sw state. */ - swap(plane->state, plane_state); - - for (i = 0; i < 2; i++) { - if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin) - crtc_funcs[i]->atomic_begin(crtc[i], crtc[i]->state); - } - - /* - * Drivers may optionally implement the ->atomic_disable callback, so - * special-case that here. - */ - if (drm_atomic_plane_disabling(plane_state, plane->state) && - plane_funcs->atomic_disable) - plane_funcs->atomic_disable(plane, plane_state); - else - plane_funcs->atomic_update(plane, plane_state); - - for (i = 0; i < 2; i++) { - if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) - crtc_funcs[i]->atomic_flush(crtc[i], crtc[i]->state); - } - - /* - * If we only moved the plane and didn't change fb's, there's no need to - * wait for vblank. - */ - if (plane->state->fb == old_fb) - goto out; - - for (i = 0; i < 2; i++) { - if (!crtc[i]) - continue; - - if (crtc[i]->cursor == plane) - continue; - - /* There's no other way to figure out whether the crtc is running. */ - ret = drm_crtc_vblank_get(crtc[i]); - if (ret == 0) { - drm_crtc_wait_one_vblank(crtc[i]); - drm_crtc_vblank_put(crtc[i]); - } - - ret = 0; - } - - if (plane_funcs->cleanup_fb) - plane_funcs->cleanup_fb(plane, plane_state); -out: - if (plane->funcs->atomic_destroy_state) - plane->funcs->atomic_destroy_state(plane, plane_state); - else - drm_atomic_helper_plane_destroy_state(plane, plane_state); - - return ret; -} - -/** - * drm_plane_helper_update() - Transitional helper for plane update - * @plane: plane object to update - * @crtc: owning CRTC of owning plane - * @fb: framebuffer to flip onto plane - * @crtc_x: x offset of primary plane on crtc - * @crtc_y: y offset of primary plane on crtc - * @crtc_w: width of primary plane rectangle on crtc - * @crtc_h: height of primary plane rectangle on crtc - * @src_x: x offset of @fb for panning - * @src_y: y offset of @fb for panning - * @src_w: width of source rectangle in @fb - * @src_h: height of source rectangle in @fb - * @ctx: lock acquire context, not used here - * - * Provides a default plane update handler using the atomic plane update - * functions. It is fully left to the driver to check plane constraints and - * handle corner-cases like a fully occluded or otherwise invisible plane. - * - * This is useful for piecewise transitioning of a driver to the atomic helpers. - * - * RETURNS: - * Zero on success, error code on failure - */ -int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_plane_state *plane_state; - - if (plane->funcs->atomic_duplicate_state) - plane_state = plane->funcs->atomic_duplicate_state(plane); - else { - if (!plane->state) - drm_atomic_helper_plane_reset(plane); - - plane_state = drm_atomic_helper_plane_duplicate_state(plane); - } - if (!plane_state) - return -ENOMEM; - plane_state->plane = plane; - - plane_state->crtc = crtc; - drm_atomic_set_fb_for_plane(plane_state, fb); - plane_state->crtc_x = crtc_x; - plane_state->crtc_y = crtc_y; - plane_state->crtc_h = crtc_h; - plane_state->crtc_w = crtc_w; - plane_state->src_x = src_x; - plane_state->src_y = src_y; - plane_state->src_h = src_h; - plane_state->src_w = src_w; - - return drm_plane_helper_commit(plane, plane_state, plane->fb); -} -EXPORT_SYMBOL(drm_plane_helper_update); - -/** - * drm_plane_helper_disable() - Transitional helper for plane disable - * @plane: plane to disable - * @ctx: lock acquire context, not used here - * - * Provides a default plane disable handler using the atomic plane update - * functions. It is fully left to the driver to check plane constraints and - * handle corner-cases like a fully occluded or otherwise invisible plane. - * - * This is useful for piecewise transitioning of a driver to the atomic helpers. - * - * RETURNS: - * Zero on success, error code on failure - */ -int drm_plane_helper_disable(struct drm_plane *plane, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_plane_state *plane_state; - struct drm_framebuffer *old_fb; - - /* crtc helpers love to call disable functions for already disabled hw - * functions. So cope with that. */ - if (!plane->crtc) - return 0; - - if (plane->funcs->atomic_duplicate_state) - plane_state = plane->funcs->atomic_duplicate_state(plane); - else { - if (!plane->state) - drm_atomic_helper_plane_reset(plane); - - plane_state = drm_atomic_helper_plane_duplicate_state(plane); - } - if (!plane_state) - return -ENOMEM; - plane_state->plane = plane; - - plane_state->crtc = NULL; - old_fb = plane_state->fb; - drm_atomic_set_fb_for_plane(plane_state, NULL); - - return drm_plane_helper_commit(plane, plane_state, old_fb); -} -EXPORT_SYMBOL(drm_plane_helper_disable); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 6914633037a5..d65f034843ce 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -57,12 +57,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
void drm_helper_resume_force_mode(struct drm_device *dev);
-int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb); -int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb); - /* drm_probe_helper.c */ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 26cee2934781..1999781781c7 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -62,18 +62,4 @@ int drm_primary_helper_disable(struct drm_plane *plane, void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs;
-int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx); -int drm_plane_helper_disable(struct drm_plane *plane, - struct drm_modeset_acquire_ctx *ctx); - -/* For use by drm_crtc_helper.c */ -int drm_plane_helper_commit(struct drm_plane *plane, - struct drm_plane_state *plane_state, - struct drm_framebuffer *old_fb); #endif
On Wed, Oct 03, 2018 at 11:18:24AM +0200, Daniel Vetter wrote:
With armada the last bigger driver that realistically needed these to convert from legacy kms to atomic is converted. These helpers have been broken more often than not the past 2 years, and as this little patch series shows, tricked a bunch of people into using the wrong helpers for their functions.
Aside: I think a lot more drivers should be using the device-level drm_atomic_helper_shutdown/suspend/resume helpers and related functions. In almost all the cases they get things exactly right.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
drivers/gpu/drm/drm_crtc_helper.c | 115 ----------------- drivers/gpu/drm/drm_plane_helper.c | 197 ----------------------------- include/drm/drm_crtc_helper.h | 6 - include/drm/drm_plane_helper.h | 14 -- 4 files changed, 332 deletions(-)
Pretty nice diffstat.
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ce75e9506e85..a3c81850e755 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -984,118 +984,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev) drm_modeset_unlock_all(dev); } EXPORT_SYMBOL(drm_helper_resume_force_mode);
-/**
- drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers
- @crtc: DRM CRTC
- @mode: DRM display mode which userspace requested
- @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks
- @x: x offset of the CRTC scanout area on the underlying framebuffer
- @y: y offset of the CRTC scanout area on the underlying framebuffer
- @old_fb: previous framebuffer
- This function implements a callback useable as the ->mode_set callback
- required by the CRTC helpers. Besides the atomic plane helper functions for
- the primary plane the driver must also provide the ->mode_set_nofb callback
- to set up the CRTC.
- This is a transitional helper useful for converting drivers to the atomic
- interfaces.
- */
-int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb)
-{
- struct drm_crtc_state *crtc_state;
- const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- int ret;
- if (crtc->funcs->atomic_duplicate_state)
crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
- else {
if (!crtc->state)
drm_atomic_helper_crtc_reset(crtc);
crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc);
- }
- if (!crtc_state)
return -ENOMEM;
- crtc_state->planes_changed = true;
- crtc_state->mode_changed = true;
- ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
- if (ret)
goto out;
- drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
- if (crtc_funcs->atomic_check) {
ret = crtc_funcs->atomic_check(crtc, crtc_state);
if (ret)
goto out;
- }
- swap(crtc->state, crtc_state);
- crtc_funcs->mode_set_nofb(crtc);
- ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb);
-out:
- if (crtc_state) {
if (crtc->funcs->atomic_destroy_state)
crtc->funcs->atomic_destroy_state(crtc, crtc_state);
else
drm_atomic_helper_crtc_destroy_state(crtc, crtc_state);
- }
- return ret;
-} -EXPORT_SYMBOL(drm_helper_crtc_mode_set);
-/**
- drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers
- @crtc: DRM CRTC
- @x: x offset of the CRTC scanout area on the underlying framebuffer
- @y: y offset of the CRTC scanout area on the underlying framebuffer
- @old_fb: previous framebuffer
- This function implements a callback useable as the ->mode_set_base used
- required by the CRTC helpers. The driver must provide the atomic plane helper
- functions for the primary plane.
- This is a transitional helper useful for converting drivers to the atomic
- interfaces.
- */
-int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
-{
- struct drm_plane_state *plane_state;
- struct drm_plane *plane = crtc->primary;
- if (plane->funcs->atomic_duplicate_state)
plane_state = plane->funcs->atomic_duplicate_state(plane);
- else {
if (!plane->state)
drm_atomic_helper_plane_reset(plane);
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
- }
- if (!plane_state)
return -ENOMEM;
- plane_state->plane = plane;
- plane_state->crtc = crtc;
- drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb);
- plane_state->crtc_x = 0;
- plane_state->crtc_y = 0;
- plane_state->crtc_h = crtc->mode.vdisplay;
- plane_state->crtc_w = crtc->mode.hdisplay;
- plane_state->src_x = x << 16;
- plane_state->src_y = y << 16;
- plane_state->src_h = crtc->mode.vdisplay << 16;
- plane_state->src_w = crtc->mode.hdisplay << 16;
- return drm_plane_helper_commit(plane, plane_state, old_fb);
-} -EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index a393756b664e..965286231600 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -336,200 +336,3 @@ const struct drm_plane_funcs drm_primary_helper_funcs = { .destroy = drm_primary_helper_destroy, }; EXPORT_SYMBOL(drm_primary_helper_funcs);
-int drm_plane_helper_commit(struct drm_plane *plane,
struct drm_plane_state *plane_state,
struct drm_framebuffer *old_fb)
-{
- const struct drm_plane_helper_funcs *plane_funcs;
- struct drm_crtc *crtc[2];
- const struct drm_crtc_helper_funcs *crtc_funcs[2];
- int i, ret = 0;
- plane_funcs = plane->helper_private;
- /* Since this is a transitional helper we can't assume that plane->state
* is always valid. Hence we need to use plane->crtc instead of
* plane->state->crtc as the old crtc. */
- crtc[0] = plane->crtc;
- crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL;
- for (i = 0; i < 2; i++)
crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL;
- if (plane_funcs->atomic_check) {
ret = plane_funcs->atomic_check(plane, plane_state);
if (ret)
goto out;
- }
- if (plane_funcs->prepare_fb && plane_state->fb != old_fb) {
ret = plane_funcs->prepare_fb(plane,
plane_state);
if (ret)
goto out;
- }
- /* Point of no return, commit sw state. */
- swap(plane->state, plane_state);
- for (i = 0; i < 2; i++) {
if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin)
crtc_funcs[i]->atomic_begin(crtc[i], crtc[i]->state);
- }
- /*
* Drivers may optionally implement the ->atomic_disable callback, so
* special-case that here.
*/
- if (drm_atomic_plane_disabling(plane_state, plane->state) &&
plane_funcs->atomic_disable)
plane_funcs->atomic_disable(plane, plane_state);
- else
plane_funcs->atomic_update(plane, plane_state);
- for (i = 0; i < 2; i++) {
if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
crtc_funcs[i]->atomic_flush(crtc[i], crtc[i]->state);
- }
- /*
* If we only moved the plane and didn't change fb's, there's no need to
* wait for vblank.
*/
- if (plane->state->fb == old_fb)
goto out;
- for (i = 0; i < 2; i++) {
if (!crtc[i])
continue;
if (crtc[i]->cursor == plane)
continue;
/* There's no other way to figure out whether the crtc is running. */
ret = drm_crtc_vblank_get(crtc[i]);
if (ret == 0) {
drm_crtc_wait_one_vblank(crtc[i]);
drm_crtc_vblank_put(crtc[i]);
}
ret = 0;
- }
- if (plane_funcs->cleanup_fb)
plane_funcs->cleanup_fb(plane, plane_state);
-out:
- if (plane->funcs->atomic_destroy_state)
plane->funcs->atomic_destroy_state(plane, plane_state);
- else
drm_atomic_helper_plane_destroy_state(plane, plane_state);
- return ret;
-}
-/**
- drm_plane_helper_update() - Transitional helper for plane update
- @plane: plane object to update
- @crtc: owning CRTC of owning plane
- @fb: framebuffer to flip onto plane
- @crtc_x: x offset of primary plane on crtc
- @crtc_y: y offset of primary plane on crtc
- @crtc_w: width of primary plane rectangle on crtc
- @crtc_h: height of primary plane rectangle on crtc
- @src_x: x offset of @fb for panning
- @src_y: y offset of @fb for panning
- @src_w: width of source rectangle in @fb
- @src_h: height of source rectangle in @fb
- @ctx: lock acquire context, not used here
- Provides a default plane update handler using the atomic plane update
- functions. It is fully left to the driver to check plane constraints and
- handle corner-cases like a fully occluded or otherwise invisible plane.
- This is useful for piecewise transitioning of a driver to the atomic helpers.
- RETURNS:
- Zero on success, error code on failure
- */
-int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_plane_state *plane_state;
- if (plane->funcs->atomic_duplicate_state)
plane_state = plane->funcs->atomic_duplicate_state(plane);
- else {
if (!plane->state)
drm_atomic_helper_plane_reset(plane);
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
- }
- if (!plane_state)
return -ENOMEM;
- plane_state->plane = plane;
- plane_state->crtc = crtc;
- drm_atomic_set_fb_for_plane(plane_state, fb);
- plane_state->crtc_x = crtc_x;
- plane_state->crtc_y = crtc_y;
- plane_state->crtc_h = crtc_h;
- plane_state->crtc_w = crtc_w;
- plane_state->src_x = src_x;
- plane_state->src_y = src_y;
- plane_state->src_h = src_h;
- plane_state->src_w = src_w;
- return drm_plane_helper_commit(plane, plane_state, plane->fb);
-} -EXPORT_SYMBOL(drm_plane_helper_update);
-/**
- drm_plane_helper_disable() - Transitional helper for plane disable
- @plane: plane to disable
- @ctx: lock acquire context, not used here
- Provides a default plane disable handler using the atomic plane update
- functions. It is fully left to the driver to check plane constraints and
- handle corner-cases like a fully occluded or otherwise invisible plane.
- This is useful for piecewise transitioning of a driver to the atomic helpers.
- RETURNS:
- Zero on success, error code on failure
- */
-int drm_plane_helper_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_plane_state *plane_state;
- struct drm_framebuffer *old_fb;
- /* crtc helpers love to call disable functions for already disabled hw
* functions. So cope with that. */
- if (!plane->crtc)
return 0;
- if (plane->funcs->atomic_duplicate_state)
plane_state = plane->funcs->atomic_duplicate_state(plane);
- else {
if (!plane->state)
drm_atomic_helper_plane_reset(plane);
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
- }
- if (!plane_state)
return -ENOMEM;
- plane_state->plane = plane;
- plane_state->crtc = NULL;
- old_fb = plane_state->fb;
- drm_atomic_set_fb_for_plane(plane_state, NULL);
- return drm_plane_helper_commit(plane, plane_state, old_fb);
-} -EXPORT_SYMBOL(drm_plane_helper_disable); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 6914633037a5..d65f034843ce 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -57,12 +57,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
void drm_helper_resume_force_mode(struct drm_device *dev);
-int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb);
-int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb);
/* drm_probe_helper.c */ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 26cee2934781..1999781781c7 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -62,18 +62,4 @@ int drm_primary_helper_disable(struct drm_plane *plane, void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs;
-int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx);
-int drm_plane_helper_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx);
-/* For use by drm_crtc_helper.c */ -int drm_plane_helper_commit(struct drm_plane *plane,
struct drm_plane_state *plane_state,
struct drm_framebuffer *old_fb);
#endif
2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
From: Thomas Hellstrom thellstrom@vmware.com
Use the correct helper and also return early on helper success rather than on helper failure.
Also explicitly return 0 in the case of no fb.
v2: Check for !fb after updating state->visible (Ville).
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com (v1) Reported-by: Dan Carpenter dan.carpenter@oracle.com Reported-by: Daniel Vetter daniel@ffwll.ch Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 1b2a406b7742..8e3e262b6ef4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -493,24 +493,24 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *new_state) { int ret = 0; + struct drm_crtc_state *crtc_state = NULL; struct vmw_surface *surface = NULL; struct drm_framebuffer *fb = new_state->fb;
- struct drm_rect src = drm_plane_state_src(new_state); - struct drm_rect dest = drm_plane_state_dest(new_state); + if (new_state->crtc) + crtc_state = drm_atomic_get_new_crtc_state(new_state->state, + new_state->crtc);
- /* Turning off */ - if (!fb) + ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) return ret;
- ret = drm_plane_helper_check_update(plane, new_state->crtc, fb, - &src, &dest, - DRM_MODE_ROTATE_0, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true, &new_state->visible); - if (!ret) - return ret; + /* Turning off */ + if (!fb) + return 0;
/* A lot of the code assumes this */ if (new_state->crtc_w != 64 || new_state->crtc_h != 64) {
On Wed, Oct 03, 2018 at 11:18:25AM +0200, Daniel Vetter wrote:
From: Thomas Hellstrom thellstrom@vmware.com
Use the correct helper and also return early on helper success rather than on helper failure.
Also explicitly return 0 in the case of no fb.
v2: Check for !fb after updating state->visible (Ville).
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com (v1) Reported-by: Dan Carpenter dan.carpenter@oracle.com Reported-by: Daniel Vetter daniel@ffwll.ch Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 1b2a406b7742..8e3e262b6ef4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -493,24 +493,24 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *new_state) { int ret = 0;
- struct drm_crtc_state *crtc_state = NULL; struct vmw_surface *surface = NULL; struct drm_framebuffer *fb = new_state->fb;
- struct drm_rect src = drm_plane_state_src(new_state);
- struct drm_rect dest = drm_plane_state_dest(new_state);
- if (new_state->crtc)
crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
new_state->crtc);
- /* Turning off */
- if (!fb)
- ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
true, true);
- if (ret) return ret;
- ret = drm_plane_helper_check_update(plane, new_state->crtc, fb,
&src, &dest,
DRM_MODE_ROTATE_0,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
true, true, &new_state->visible);
- if (!ret)
return ret;
- /* Turning off */
- if (!fb)
return 0;
Yep, now ->visible should be up to date. Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
/* A lot of the code assumes this */ if (new_state->crtc_w != 64 || new_state->crtc_h != 64) { -- 2.19.0.rc2
It's for legacy drivers only (atomic ones should use drm_atomic_helper_check_plane_state() instead), and there's no users left except the one in the primary plane helpers.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/drm_plane_helper.c | 49 +++++++----------------------- include/drm/drm_plane_helper.h | 11 ------- 2 files changed, 11 insertions(+), 49 deletions(-)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 965286231600..33b3e6892787 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -100,43 +100,17 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, return count; }
-/** - * drm_plane_helper_check_update() - Check plane update for validity - * @plane: plane object to update - * @crtc: owning CRTC of owning plane - * @fb: framebuffer to flip onto plane - * @src: source coordinates in 16.16 fixed point - * @dst: integer destination coordinates - * @rotation: plane rotation - * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point - * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point - * @can_position: is it legal to position the plane such that it - * doesn't cover the entire crtc? This will generally - * only be false for primary planes. - * @can_update_disabled: can the plane be updated while the crtc - * is disabled? - * @visible: output parameter indicating whether plane is still visible after - * clipping - * - * Checks that a desired plane update is valid. Drivers that provide - * their own plane handling rather than helper-provided implementations may - * still wish to call this function to avoid duplication of error checking - * code. - * - * RETURNS: - * Zero if update appears valid, error code on failure - */ -int drm_plane_helper_check_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_rect *src, - struct drm_rect *dst, - unsigned int rotation, - int min_scale, - int max_scale, - bool can_position, - bool can_update_disabled, - bool *visible) +static int drm_plane_helper_check_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_rect *src, + struct drm_rect *dst, + unsigned int rotation, + int min_scale, + int max_scale, + bool can_position, + bool can_update_disabled, + bool *visible) { struct drm_plane_state plane_state = { .plane = plane, @@ -173,7 +147,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
return 0; } -EXPORT_SYMBOL(drm_plane_helper_check_update);
/** * drm_primary_helper_update() - Helper for primary plane update diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 1999781781c7..7bff930b8b10 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -38,17 +38,6 @@ */ #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-int drm_plane_helper_check_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_rect *src, - struct drm_rect *dest, - unsigned int rotation, - int min_scale, - int max_scale, - bool can_position, - bool can_update_disabled, - bool *visible); int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb,
On Wed, Oct 03, 2018 at 11:18:26AM +0200, Daniel Vetter wrote:
It's for legacy drivers only (atomic ones should use drm_atomic_helper_check_plane_state() instead), and there's no users left except the one in the primary plane helpers.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/drm_plane_helper.c | 49 +++++++----------------------- include/drm/drm_plane_helper.h | 11 ------- 2 files changed, 11 insertions(+), 49 deletions(-)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 965286231600..33b3e6892787 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -100,43 +100,17 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, return count; }
-/**
- drm_plane_helper_check_update() - Check plane update for validity
- @plane: plane object to update
- @crtc: owning CRTC of owning plane
- @fb: framebuffer to flip onto plane
- @src: source coordinates in 16.16 fixed point
- @dst: integer destination coordinates
- @rotation: plane rotation
- @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
- @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
- @can_position: is it legal to position the plane such that it
doesn't cover the entire crtc? This will generally
only be false for primary planes.
- @can_update_disabled: can the plane be updated while the crtc
is disabled?
- @visible: output parameter indicating whether plane is still visible after
clipping
- Checks that a desired plane update is valid. Drivers that provide
- their own plane handling rather than helper-provided implementations may
- still wish to call this function to avoid duplication of error checking
- code.
- RETURNS:
- Zero if update appears valid, error code on failure
- */
-int drm_plane_helper_check_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_rect *src,
struct drm_rect *dst,
unsigned int rotation,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled,
bool *visible)
+static int drm_plane_helper_check_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_rect *src,
struct drm_rect *dst,
unsigned int rotation,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled,
bool *visible)
{ struct drm_plane_state plane_state = { .plane = plane, @@ -173,7 +147,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
return 0; } -EXPORT_SYMBOL(drm_plane_helper_check_update);
/**
- drm_primary_helper_update() - Helper for primary plane update
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 1999781781c7..7bff930b8b10 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -38,17 +38,6 @@ */ #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-int drm_plane_helper_check_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_rect *src,
struct drm_rect *dest,
unsigned int rotation,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled,
bool *visible);
int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, -- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Well except the destroy helper, which isn't really a primary helper but generally useful, if mislabelled.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com --- drivers/gpu/drm/drm_plane_helper.c | 85 ++++-------------------------- include/drm/drm_plane_helper.h | 10 ---- 2 files changed, 11 insertions(+), 84 deletions(-)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 33b3e6892787..0fff72dcd06d 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -42,11 +42,8 @@ * primary plane support on top of the normal CRTC configuration interface. * Since the legacy &drm_mode_config_funcs.set_config interface ties the primary * plane together with the CRTC state this does not allow userspace to disable - * the primary plane itself. To avoid too much duplicated code use - * drm_plane_helper_check_update() which can be used to enforce the same - * restrictions as primary planes had thus. The default primary plane only - * expose XRBG8888 and ARGB8888 as valid pixel formats for the attached - * framebuffer. + * the primary plane itself. The default primary plane only expose XRBG8888 and + * ARGB8888 as valid pixel formats for the attached framebuffer. * * Drivers are highly recommended to implement proper support for primary * planes, and newly merged drivers must not rely upon these transitional @@ -148,50 +145,13 @@ static int drm_plane_helper_check_update(struct drm_plane *plane, return 0; }
-/** - * drm_primary_helper_update() - Helper for primary plane update - * @plane: plane object to update - * @crtc: owning CRTC of owning plane - * @fb: framebuffer to flip onto plane - * @crtc_x: x offset of primary plane on crtc - * @crtc_y: y offset of primary plane on crtc - * @crtc_w: width of primary plane rectangle on crtc - * @crtc_h: height of primary plane rectangle on crtc - * @src_x: x offset of @fb for panning - * @src_y: y offset of @fb for panning - * @src_w: width of source rectangle in @fb - * @src_h: height of source rectangle in @fb - * @ctx: lock acquire context, not used here - * - * Provides a default plane update handler for primary planes. This is handler - * is called in response to a userspace SetPlane operation on the plane with a - * non-NULL framebuffer. We call the driver's modeset handler to update the - * framebuffer. - * - * SetPlane() on a primary plane of a disabled CRTC is not supported, and will - * return an error. - * - * Note that we make some assumptions about hardware limitations that may not be - * true for all hardware -- - * - * 1. Primary plane cannot be repositioned. - * 2. Primary plane cannot be scaled. - * 3. Primary plane must cover the entire CRTC. - * 4. Subpixel positioning is not supported. - * - * Drivers for hardware that don't have these restrictions can provide their - * own implementation rather than using this helper. - * - * RETURNS: - * Zero on success, error code on failure - */ -int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx) +static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h, + struct drm_modeset_acquire_ctx *ctx) { struct drm_mode_set set = { .crtc = crtc, @@ -258,35 +218,12 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, kfree(connector_list); return ret; } -EXPORT_SYMBOL(drm_primary_helper_update);
-/** - * drm_primary_helper_disable() - Helper for primary plane disable - * @plane: plane to disable - * @ctx: lock acquire context, not used here - * - * Provides a default plane disable handler for primary planes. This is handler - * is called in response to a userspace SetPlane operation on the plane with a - * NULL framebuffer parameter. It unconditionally fails the disable call with - * -EINVAL the only way to disable the primary plane without driver support is - * to disable the entire CRTC. Which does not match the plane - * &drm_plane_funcs.disable_plane hook. - * - * Note that some hardware may be able to disable the primary plane without - * disabling the whole CRTC. Drivers for such hardware should provide their - * own disable handler that disables just the primary plane (and they'll likely - * need to provide their own update handler as well to properly re-enable a - * disabled primary plane). - * - * RETURNS: - * Unconditionally returns -EINVAL. - */ -int drm_primary_helper_disable(struct drm_plane *plane, - struct drm_modeset_acquire_ctx *ctx) +static int drm_primary_helper_disable(struct drm_plane *plane, + struct drm_modeset_acquire_ctx *ctx) { return -EINVAL; } -EXPORT_SYMBOL(drm_primary_helper_disable);
/** * drm_primary_helper_destroy() - Helper for primary plane destruction diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 7bff930b8b10..331ebd60b3a3 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -38,16 +38,6 @@ */ #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-int drm_primary_helper_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx); -int drm_primary_helper_disable(struct drm_plane *plane, - struct drm_modeset_acquire_ctx *ctx); void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs;
On Wed, Oct 03, 2018 at 11:18:27AM +0200, Daniel Vetter wrote:
Well except the destroy helper, which isn't really a primary helper but generally useful, if mislabelled.
Signed-off-by: Daniel Vetter daniel.vetter@intel.com
drivers/gpu/drm/drm_plane_helper.c | 85 ++++-------------------------- include/drm/drm_plane_helper.h | 10 ---- 2 files changed, 11 insertions(+), 84 deletions(-)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 33b3e6892787..0fff72dcd06d 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -42,11 +42,8 @@
- primary plane support on top of the normal CRTC configuration interface.
- Since the legacy &drm_mode_config_funcs.set_config interface ties the primary
- plane together with the CRTC state this does not allow userspace to disable
- the primary plane itself. To avoid too much duplicated code use
- drm_plane_helper_check_update() which can be used to enforce the same
- restrictions as primary planes had thus. The default primary plane only
- expose XRBG8888 and ARGB8888 as valid pixel formats for the attached
- framebuffer.
- the primary plane itself. The default primary plane only expose XRBG8888 and
- ARGB8888 as valid pixel formats for the attached framebuffer.
- Drivers are highly recommended to implement proper support for primary
- planes, and newly merged drivers must not rely upon these transitional
@@ -148,50 +145,13 @@ static int drm_plane_helper_check_update(struct drm_plane *plane, return 0; }
-/**
- drm_primary_helper_update() - Helper for primary plane update
- @plane: plane object to update
- @crtc: owning CRTC of owning plane
- @fb: framebuffer to flip onto plane
- @crtc_x: x offset of primary plane on crtc
- @crtc_y: y offset of primary plane on crtc
- @crtc_w: width of primary plane rectangle on crtc
- @crtc_h: height of primary plane rectangle on crtc
- @src_x: x offset of @fb for panning
- @src_y: y offset of @fb for panning
- @src_w: width of source rectangle in @fb
- @src_h: height of source rectangle in @fb
- @ctx: lock acquire context, not used here
- Provides a default plane update handler for primary planes. This is handler
- is called in response to a userspace SetPlane operation on the plane with a
- non-NULL framebuffer. We call the driver's modeset handler to update the
- framebuffer.
- SetPlane() on a primary plane of a disabled CRTC is not supported, and will
- return an error.
- Note that we make some assumptions about hardware limitations that may not be
- true for all hardware --
- Primary plane cannot be repositioned.
- Primary plane cannot be scaled.
- Primary plane must cover the entire CRTC.
- Subpixel positioning is not supported.
- Drivers for hardware that don't have these restrictions can provide their
- own implementation rather than using this helper.
- RETURNS:
- Zero on success, error code on failure
- */
-int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx)
+static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx)
{ struct drm_mode_set set = { .crtc = crtc, @@ -258,35 +218,12 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, kfree(connector_list); return ret; } -EXPORT_SYMBOL(drm_primary_helper_update);
-/**
- drm_primary_helper_disable() - Helper for primary plane disable
- @plane: plane to disable
- @ctx: lock acquire context, not used here
- Provides a default plane disable handler for primary planes. This is handler
- is called in response to a userspace SetPlane operation on the plane with a
- NULL framebuffer parameter. It unconditionally fails the disable call with
- -EINVAL the only way to disable the primary plane without driver support is
- to disable the entire CRTC. Which does not match the plane
- &drm_plane_funcs.disable_plane hook.
- Note that some hardware may be able to disable the primary plane without
- disabling the whole CRTC. Drivers for such hardware should provide their
- own disable handler that disables just the primary plane (and they'll likely
- need to provide their own update handler as well to properly re-enable a
- disabled primary plane).
- RETURNS:
- Unconditionally returns -EINVAL.
- */
-int drm_primary_helper_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx)
+static int drm_primary_helper_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx)
{ return -EINVAL; } -EXPORT_SYMBOL(drm_primary_helper_disable);
/**
- drm_primary_helper_destroy() - Helper for primary plane destruction
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 7bff930b8b10..331ebd60b3a3 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -38,16 +38,6 @@ */ #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-int drm_primary_helper_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx);
-int drm_primary_helper_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx);
Cool. Less things to snare people by accident.
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs;
-- 2.19.0.rc2
Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Wed, Oct 03, 2018 at 11:18:22AM +0200, Daniel Vetter wrote:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
v2: Rebase.
Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: Eric Anholt eric@anholt.net
Looks correct to me.
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
drivers/gpu/drm/vc4/vc4_drv.c | 3 +++ drivers/gpu/drm/vc4/vc4_plane.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 1f1780ccdbdf..f6f5cd80c04d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -33,6 +33,7 @@ #include <linux/pm_runtime.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic_helper.h>
#include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" @@ -308,6 +309,8 @@ static void vc4_drm_unbind(struct device *dev)
drm_dev_unregister(drm);
drm_atomic_helper_shutdown(drm);
drm_mode_config_cleanup(drm);
drm_atomic_private_obj_fini(&vc4->ctm_manager);
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 9dc3fcbd290b..d04b3c3246ba 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -903,7 +903,6 @@ static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
static void vc4_plane_destroy(struct drm_plane *plane) {
- drm_plane_helper_disable(plane, NULL); drm_plane_cleanup(plane);
}
-- 2.19.0.rc2
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Daniel Vetter daniel.vetter@ffwll.ch writes:
drm_plane_helper_disable is a non-atomic drivers only function, and will blow up (since no one passes the locking context it needs).
Atomic drivers which want to quiescent their hw on unload should use drm_atomic_helper_shutdown() instead.
v2: Rebase.
I've definitely never tested unload.
Looks like we could drop vc4_plane_destroy() entirely? Regardless, acked-by.
dri-devel@lists.freedesktop.org