Re: [PATCH v4 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

From: Alexander Stein
Date: Fri Feb 17 2023 - 03:09:23 EST


Hi Liu,

thanks for the update.

Am Freitag, 17. Februar 2023, 07:54:04 CET schrieb Liu Ying:
> Instead of determining LCDIF output bus format and bus flags in
> ->atomic_enable(), do that in ->atomic_check(). This is a
> preparation for the upcoming patch to check consistent bus format
> and bus flags across all first downstream bridges in ->atomic_check().
> New lcdif_crtc_state structure is introduced to cache bus format
> and bus flags states in ->atomic_check() so that they can be read
> in ->atomic_enable().
>
> Signed-off-by: Liu Ying <victor.liu@xxxxxxx>

Look good to me.
Reviewed-by: Alexander Stein <alexander.stein@xxxxxxxxxxxxxxx>

> ---
> v3->v4:
> * Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state'. (Alexander)
> * Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state().
> (Alexander)
> * Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state().
> (Alexander)
>
> v2->v3:
> * No change.
>
> v1->v2:
> * Split from patch 2/2 in v1. (Marek, Alexander)
> * Add comment on the 'base' member of lcdif_crtc_state structure to
> note it should always be the first member. (Lothar)
>
> drivers/gpu/drm/mxsfb/lcdif_kms.c | 134 ++++++++++++++++++++++--------
> 1 file changed, 99 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> b/drivers/gpu/drm/mxsfb/lcdif_kms.c index e54200a9fcb9..d46de433cd8e 100644
> --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> @@ -30,6 +30,18 @@
> #include "lcdif_drv.h"
> #include "lcdif_regs.h"
>
> +struct lcdif_crtc_state {
> + struct drm_crtc_state base; /* always be the first
member */
> + u32 bus_format;
> + u32 bus_flags;
> +};
> +
> +static inline struct lcdif_crtc_state *
> +to_lcdif_crtc_state(struct drm_crtc_state *s)
> +{
> + return container_of(s, struct lcdif_crtc_state, base);
> +}
> +
> /*
> ---------------------------------------------------------------------------
> -- * CRTC
> */
> @@ -385,48 +397,72 @@ static void lcdif_reset_block(struct lcdif_drm_private
> *lcdif) readl(lcdif->base + LCDC_V8_CTRL);
> }
>
> -static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
> - struct drm_plane_state
*plane_state,
> - struct drm_bridge_state
*bridge_state,
> - const u32 bus_format)
> +static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
> + struct drm_plane_state
*plane_state)
> {
> - struct drm_device *drm = lcdif->crtc.dev;
> - struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
> - u32 bus_flags = 0;
> -
> - if (lcdif->bridge->timings)
> - bus_flags = lcdif->bridge->timings->input_bus_flags;
> - else if (bridge_state)
> - bus_flags = bridge_state->input_bus_cfg.flags;
> + struct lcdif_crtc_state *lcdif_crtc_state =
> to_lcdif_crtc_state(crtc_state); + struct drm_device *drm =
> crtc_state->crtc->dev;
> + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
> + struct drm_display_mode *m = &crtc_state->adjusted_mode;
>
> DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)
\n",
> m->crtc_clock,
> (int)(clk_get_rate(lcdif->clk) / 1000));
> DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
> - bus_flags);
> + lcdif_crtc_state->bus_flags);
> DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
>
> /* Mandatory eLCDIF reset as per the Reference Manual */
> lcdif_reset_block(lcdif);
>
> - lcdif_set_formats(lcdif, plane_state, bus_format);
> + lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
>
> - lcdif_set_mode(lcdif, bus_flags);
> + lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
> }
>
> static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
> struct drm_atomic_state *state)
> {
> + struct drm_device *drm = crtc->dev;
> + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
> struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state,
>
crtc);
> + struct lcdif_crtc_state *lcdif_crtc_state =
> to_lcdif_crtc_state(crtc_state); bool has_primary = crtc_state->plane_mask
> &
> drm_plane_mask(crtc->primary);
> + struct drm_bridge_state *bridge_state;
> + struct drm_bridge *bridge = lcdif->bridge;
> + int ret;
>
> /* The primary plane has to be enabled when the CRTC is active. */
> if (crtc_state->active && !has_primary)
> return -EINVAL;
>
> - return drm_atomic_add_affected_planes(state, crtc);
> + ret = drm_atomic_add_affected_planes(state, crtc);
> + if (ret)
> + return ret;
> +
> + bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> + if (!bridge_state)
> + lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
> + else
> + lcdif_crtc_state->bus_format = bridge_state-
>input_bus_cfg.format;
> +
> + if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
> + dev_warn_once(drm->dev,
> + "Bridge does not provide bus format,
assuming
> MEDIA_BUS_FMT_RGB888_1X24.\n" + "Please fix
bridge driver by
> handling atomic_get_input_bus_fmts.\n"); + lcdif_crtc_state-
>bus_format =
> MEDIA_BUS_FMT_RGB888_1X24;
> + }
> +
> + if (bridge->timings)
> + lcdif_crtc_state->bus_flags = bridge->timings-
>input_bus_flags;
> + else if (bridge_state)
> + lcdif_crtc_state->bus_flags = bridge_state-
>input_bus_cfg.flags;
> + else
> + lcdif_crtc_state->bus_flags = 0;
> +
> + return 0;
> }
>
> static void lcdif_crtc_atomic_flush(struct drm_crtc *crtc,
> @@ -458,32 +494,18 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc
> *crtc, struct drm_atomic_state *state)
> {
> struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
> + struct drm_crtc_state *new_cstate =
drm_atomic_get_new_crtc_state(state,
> crtc); struct drm_plane_state *new_pstate =
> drm_atomic_get_new_plane_state(state, crtc->primary);
> struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
> - struct drm_bridge_state *bridge_state = NULL;
> struct drm_device *drm = lcdif->drm;
> - u32 bus_format;
> dma_addr_t paddr;
>
> - bridge_state = drm_atomic_get_new_bridge_state(state, lcdif-
>bridge);
> - if (!bridge_state)
> - bus_format = MEDIA_BUS_FMT_FIXED;
> - else
> - bus_format = bridge_state->input_bus_cfg.format;
> -
> - if (bus_format == MEDIA_BUS_FMT_FIXED) {
> - dev_warn_once(drm->dev,
> - "Bridge does not provide bus format,
assuming
> MEDIA_BUS_FMT_RGB888_1X24.\n" - "Please fix
bridge driver by
> handling atomic_get_input_bus_fmts.\n"); - bus_format =
> MEDIA_BUS_FMT_RGB888_1X24;
> - }
> -
> clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
>
> pm_runtime_get_sync(drm->dev);
>
> - lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state,
bus_format);
> + lcdif_crtc_mode_set_nofb(new_cstate, new_pstate);
>
> /* Write cur_buf as well to avoid an initial corrupt frame */
> paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
> @@ -520,6 +542,48 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc
> *crtc, pm_runtime_put_sync(drm->dev);
> }
>
> +static void lcdif_crtc_atomic_destroy_state(struct drm_crtc *crtc,
> + struct drm_crtc_state
*state)
> +{
> + __drm_atomic_helper_crtc_destroy_state(state);
> + kfree(to_lcdif_crtc_state(state));
> +}
> +
> +static void lcdif_crtc_reset(struct drm_crtc *crtc)
> +{
> + struct lcdif_crtc_state *state;
> +
> + if (crtc->state)
> + lcdif_crtc_atomic_destroy_state(crtc, crtc->state);
> +
> + crtc->state = NULL;
> +
> + state = kzalloc(sizeof(*state), GFP_KERNEL);
> + if (state)
> + __drm_atomic_helper_crtc_reset(crtc, &state->base);
> +}
> +
> +static struct drm_crtc_state *
> +lcdif_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
> +{
> + struct lcdif_crtc_state *old = to_lcdif_crtc_state(crtc->state);
> + struct lcdif_crtc_state *new;
> +
> + if (WARN_ON(!crtc->state))
> + return NULL;
> +
> + new = kzalloc(sizeof(*new), GFP_KERNEL);
> + if (!new)
> + return NULL;
> +
> + __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
> +
> + new->bus_format = old->bus_format;
> + new->bus_flags = old->bus_flags;
> +
> + return &new->base;
> +}
> +
> static int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
> {
> struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
> @@ -548,12 +612,12 @@ static const struct drm_crtc_helper_funcs
> lcdif_crtc_helper_funcs = { };
>
> static const struct drm_crtc_funcs lcdif_crtc_funcs = {
> - .reset = drm_atomic_helper_crtc_reset,
> + .reset = lcdif_crtc_reset,
> .destroy = drm_crtc_cleanup,
> .set_config = drm_atomic_helper_set_config,
> .page_flip = drm_atomic_helper_page_flip,
> - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> + .atomic_duplicate_state = lcdif_crtc_atomic_duplicate_state,
> + .atomic_destroy_state = lcdif_crtc_atomic_destroy_state,
> .enable_vblank = lcdif_crtc_enable_vblank,
> .disable_vblank = lcdif_crtc_disable_vblank,
> };


--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/