From: Neil Armstrong <narmstrong@baylibre.com> To: dri-devel@lists.freedesktop.org Cc: Boris Brezillon <boris.brezillon@collabora.com>, Mark Rutland <mark.rutland@arm.com>, Neil Armstrong <narmstrong@baylibre.com>, Thierry Reding <thierry.reding@gmail.com>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, kernel@collabora.com, Sam Ravnborg <sam@ravnborg.org>, Nikita Yushchenko <nikita.yoush@cogentembedded.com>, Andrey Smirnov <andrew.smirnov@gmail.com>, Kyungmin Park <kyungmin.park@samsung.com>, Chris Healy <cphealy@gmail.com>, devicetree@vger.kernel.org, Jonas Karlman <jonas@kwiboo.se>, Rob Herring <robh+dt@kernel.org>, Jernej Skrabec <jernej.skrabec@siol.net>, Seung-Woo Kim <sw0312.kim@samsung.com> Subject: [PATCH v5 3/4] drm/bridge: Add an ->atomic_check() hook Date: Thu, 19 Dec 2019 11:11:50 +0100 [thread overview] Message-ID: <20191219101151.28039-4-narmstrong@baylibre.com> (raw) In-Reply-To: <20191219101151.28039-1-narmstrong@baylibre.com> From: Boris Brezillon <boris.brezillon@collabora.com> So that bridge drivers have a way to check/reject an atomic operation. The drm_atomic_bridge_chain_check() (which is just a wrapper around the ->atomic_check() hook) is called in place of drm_bridge_chain_mode_fixup() (when ->atomic_check() is not implemented, the core falls back on ->mode_fixup(), so the behavior should stay the same for existing bridge drivers). Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- Changes in v5: * None Changes in v4: * Add R-bs Changes in v3: * None Changes in v2: * Clarify the fact that ->atomic_check() is replacing ->mode_fixup() --- drivers/gpu/drm/drm_atomic_helper.c | 12 +++--- drivers/gpu/drm/drm_bridge.c | 62 +++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 29 +++++++++++++- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index b3e1aedd9d7a..44536b421d65 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -437,12 +437,12 @@ mode_fixup(struct drm_atomic_state *state) funcs = encoder->helper_private; bridge = drm_bridge_chain_get_first_bridge(encoder); - ret = drm_bridge_chain_mode_fixup(bridge, - &new_crtc_state->mode, - &new_crtc_state->adjusted_mode); - if (!ret) { - DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); - return -EINVAL; + ret = drm_atomic_bridge_chain_check(bridge, + new_crtc_state, + new_conn_state); + if (ret) { + DRM_DEBUG_ATOMIC("Bridge atomic check failed\n"); + return ret; } if (funcs && funcs->atomic_check) { diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 6bdc4ab789c9..442804598f60 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -609,6 +609,68 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); +static int drm_atomic_bridge_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + if (bridge->funcs->atomic_check) { + struct drm_bridge_state *bridge_state; + int ret; + + bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, + bridge); + if (WARN_ON(!bridge_state)) + return -EINVAL; + + ret = bridge->funcs->atomic_check(bridge, bridge_state, + crtc_state, conn_state); + if (ret) + return ret; + } else if (bridge->funcs->mode_fixup) { + if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode, + &crtc_state->adjusted_mode)) + return -EINVAL; + } + + return 0; +} + +/** + * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain + * @bridge: bridge control structure + * @crtc_state: new CRTC state + * @conn_state: new connector state + * + * Calls &drm_bridge_funcs.atomic_check() (falls back on + * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, + * starting from the last bridge to the first. These are called before calling + * &drm_encoder_helper_funcs.atomic_check() + * + * RETURNS: + * 0 on success, a negative error code on failure + */ +int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_encoder *encoder = bridge->encoder; + struct drm_bridge *iter; + + list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { + int ret; + + ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); + if (ret) + return ret; + + if (iter == bridge) + break; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_bridge_chain_check); + /** * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper * @bridge: the bridge this state refers to diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 0331e330635b..269f0d1da339 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -128,7 +128,9 @@ struct drm_bridge_funcs { * this function passes all other callbacks must succeed for this * configuration. * - * The @mode_fixup callback is optional. + * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup() + * is not called when &drm_bridge_funcs.atomic_check() is implemented, + * so only one of them should be provided. * * NOTE: * @@ -385,6 +387,28 @@ struct drm_bridge_funcs { void (*atomic_destroy_state)(struct drm_bridge *bridge, struct drm_bridge_state *state); + /** + * @atomic_check: + * + * This method is responsible for checking bridge state correctness. + * It can also check the state of the surrounding components in chain + * to make sure the whole pipeline can work properly. + * + * &drm_bridge_funcs.atomic_check() hooks are called in reverse + * order (from the last to the first bridge). + * + * This method is optional. &drm_bridge_funcs.mode_fixup() is not + * called when &drm_bridge_funcs.atomic_check() is implemented, so only + * one of them should be provided. + * + * RETURNS: + * zero if the check passed, a negative error code otherwise. + */ + int (*atomic_check)(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); + /** * @atomic_reset: * @@ -552,6 +576,9 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge, void drm_bridge_chain_pre_enable(struct drm_bridge *bridge); void drm_bridge_chain_enable(struct drm_bridge *bridge); +int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, struct drm_atomic_state *state); void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, -- 2.22.0
WARNING: multiple messages have this Message-ID (diff)
From: Neil Armstrong <narmstrong@baylibre.com> To: dri-devel@lists.freedesktop.org Cc: Mark Rutland <mark.rutland@arm.com>, Nikita Yushchenko <nikita.yoush@cogentembedded.com>, devicetree@vger.kernel.org, Neil Armstrong <narmstrong@baylibre.com>, Andrey Smirnov <andrew.smirnov@gmail.com>, Jonas Karlman <jonas@kwiboo.se>, Seung-Woo Kim <sw0312.kim@samsung.com>, Jernej Skrabec <jernej.skrabec@siol.net>, Rob Herring <robh+dt@kernel.org>, Kyungmin Park <kyungmin.park@samsung.com>, Boris Brezillon <boris.brezillon@collabora.com>, Thierry Reding <thierry.reding@gmail.com>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, kernel@collabora.com, Sam Ravnborg <sam@ravnborg.org>, Chris Healy <cphealy@gmail.com> Subject: [PATCH v5 3/4] drm/bridge: Add an ->atomic_check() hook Date: Thu, 19 Dec 2019 11:11:50 +0100 [thread overview] Message-ID: <20191219101151.28039-4-narmstrong@baylibre.com> (raw) In-Reply-To: <20191219101151.28039-1-narmstrong@baylibre.com> From: Boris Brezillon <boris.brezillon@collabora.com> So that bridge drivers have a way to check/reject an atomic operation. The drm_atomic_bridge_chain_check() (which is just a wrapper around the ->atomic_check() hook) is called in place of drm_bridge_chain_mode_fixup() (when ->atomic_check() is not implemented, the core falls back on ->mode_fixup(), so the behavior should stay the same for existing bridge drivers). Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> --- Changes in v5: * None Changes in v4: * Add R-bs Changes in v3: * None Changes in v2: * Clarify the fact that ->atomic_check() is replacing ->mode_fixup() --- drivers/gpu/drm/drm_atomic_helper.c | 12 +++--- drivers/gpu/drm/drm_bridge.c | 62 +++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 29 +++++++++++++- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index b3e1aedd9d7a..44536b421d65 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -437,12 +437,12 @@ mode_fixup(struct drm_atomic_state *state) funcs = encoder->helper_private; bridge = drm_bridge_chain_get_first_bridge(encoder); - ret = drm_bridge_chain_mode_fixup(bridge, - &new_crtc_state->mode, - &new_crtc_state->adjusted_mode); - if (!ret) { - DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); - return -EINVAL; + ret = drm_atomic_bridge_chain_check(bridge, + new_crtc_state, + new_conn_state); + if (ret) { + DRM_DEBUG_ATOMIC("Bridge atomic check failed\n"); + return ret; } if (funcs && funcs->atomic_check) { diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 6bdc4ab789c9..442804598f60 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -609,6 +609,68 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); +static int drm_atomic_bridge_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + if (bridge->funcs->atomic_check) { + struct drm_bridge_state *bridge_state; + int ret; + + bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, + bridge); + if (WARN_ON(!bridge_state)) + return -EINVAL; + + ret = bridge->funcs->atomic_check(bridge, bridge_state, + crtc_state, conn_state); + if (ret) + return ret; + } else if (bridge->funcs->mode_fixup) { + if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode, + &crtc_state->adjusted_mode)) + return -EINVAL; + } + + return 0; +} + +/** + * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain + * @bridge: bridge control structure + * @crtc_state: new CRTC state + * @conn_state: new connector state + * + * Calls &drm_bridge_funcs.atomic_check() (falls back on + * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, + * starting from the last bridge to the first. These are called before calling + * &drm_encoder_helper_funcs.atomic_check() + * + * RETURNS: + * 0 on success, a negative error code on failure + */ +int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_encoder *encoder = bridge->encoder; + struct drm_bridge *iter; + + list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { + int ret; + + ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); + if (ret) + return ret; + + if (iter == bridge) + break; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_bridge_chain_check); + /** * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper * @bridge: the bridge this state refers to diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 0331e330635b..269f0d1da339 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -128,7 +128,9 @@ struct drm_bridge_funcs { * this function passes all other callbacks must succeed for this * configuration. * - * The @mode_fixup callback is optional. + * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup() + * is not called when &drm_bridge_funcs.atomic_check() is implemented, + * so only one of them should be provided. * * NOTE: * @@ -385,6 +387,28 @@ struct drm_bridge_funcs { void (*atomic_destroy_state)(struct drm_bridge *bridge, struct drm_bridge_state *state); + /** + * @atomic_check: + * + * This method is responsible for checking bridge state correctness. + * It can also check the state of the surrounding components in chain + * to make sure the whole pipeline can work properly. + * + * &drm_bridge_funcs.atomic_check() hooks are called in reverse + * order (from the last to the first bridge). + * + * This method is optional. &drm_bridge_funcs.mode_fixup() is not + * called when &drm_bridge_funcs.atomic_check() is implemented, so only + * one of them should be provided. + * + * RETURNS: + * zero if the check passed, a negative error code otherwise. + */ + int (*atomic_check)(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); + /** * @atomic_reset: * @@ -552,6 +576,9 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge, void drm_bridge_chain_pre_enable(struct drm_bridge *bridge); void drm_bridge_chain_enable(struct drm_bridge *bridge); +int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, struct drm_atomic_state *state); void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, -- 2.22.0 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2019-12-19 10:12 UTC|newest] Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-12-19 10:11 [PATCH v5 0/4] drm: Add support for bus-format negotiation Neil Armstrong 2019-12-19 10:11 ` Neil Armstrong 2019-12-19 10:11 ` [PATCH v5 1/4] drm/bridge: Add a drm_bridge_state object Neil Armstrong 2019-12-19 10:11 ` Neil Armstrong 2019-12-19 21:52 ` Jernej Škrabec 2019-12-19 21:52 ` Jernej Škrabec 2020-01-06 10:03 ` Boris Brezillon 2020-01-06 10:03 ` Boris Brezillon 2020-01-06 10:41 ` Neil Armstrong 2020-01-06 10:41 ` Neil Armstrong 2020-01-06 11:52 ` Laurent Pinchart 2020-01-06 11:52 ` Laurent Pinchart 2019-12-19 10:11 ` [PATCH v5 2/4] drm/bridge: Patch atomic hooks to take a drm_bridge_state Neil Armstrong 2019-12-19 10:11 ` Neil Armstrong 2019-12-19 21:53 ` Jernej Škrabec 2019-12-19 21:53 ` Jernej Škrabec 2019-12-19 10:11 ` Neil Armstrong [this message] 2019-12-19 10:11 ` [PATCH v5 3/4] drm/bridge: Add an ->atomic_check() hook Neil Armstrong 2019-12-19 21:53 ` Jernej Škrabec 2019-12-19 21:53 ` Jernej Škrabec 2019-12-19 10:11 ` [PATCH v5 4/4] drm/bridge: Add the necessary bits to support bus format negotiation Neil Armstrong 2019-12-19 10:11 ` Neil Armstrong 2019-12-19 21:56 ` Jernej Škrabec 2019-12-19 21:56 ` Jernej Škrabec
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20191219101151.28039-4-narmstrong@baylibre.com \ --to=narmstrong@baylibre.com \ --cc=andrew.smirnov@gmail.com \ --cc=boris.brezillon@collabora.com \ --cc=cphealy@gmail.com \ --cc=devicetree@vger.kernel.org \ --cc=dri-devel@lists.freedesktop.org \ --cc=jernej.skrabec@siol.net \ --cc=jonas@kwiboo.se \ --cc=kernel@collabora.com \ --cc=kyungmin.park@samsung.com \ --cc=laurent.pinchart@ideasonboard.com \ --cc=mark.rutland@arm.com \ --cc=nikita.yoush@cogentembedded.com \ --cc=robh+dt@kernel.org \ --cc=sam@ravnborg.org \ --cc=sw0312.kim@samsung.com \ --cc=thierry.reding@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.