All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Liu Ying <victor.liu@nxp.com>
Cc: marex@denx.de, stefan@agner.ch, airlied@gmail.com,
	daniel@ffwll.ch, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, shawnguo@kernel.org,
	s.hauer@pengutronix.de, kernel@pengutronix.de,
	festevam@gmail.com, linux-imx@nxp.com,
	krzysztof.kozlowski@linaro.org, LW@karo-electronics.de
Subject: Re: [PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()
Date: Tue, 14 Feb 2023 15:12:55 +0100	[thread overview]
Message-ID: <1755644.VLH7GnMWUR@steina-w> (raw)
In-Reply-To: <20230213085612.1026538-4-victor.liu@nxp.com>

Hi Liu,

thanks for the update.

Am Montag, 13. Februar 2023, 09:56:09 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@nxp.com>
> ---
> 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 | 138 ++++++++++++++++++++++--------
>  1 file changed, 100 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> b/drivers/gpu/drm/mxsfb/lcdif_kms.c index e54200a9fcb9..294cecdf5439 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 */

Is it strictly necessary that base is the first member? to_lcdif_crtc_state() 
should be able to handle any position within the struct. I mean it's sensible 
to put it in first place. But the comment somehow bugs me.

> +	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,35 +494,21 @@ 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_plane_state *new_pstate = 
drm_atomic_get_new_plane_state(state,
> -								
	    crtc->primary);
> +	struct drm_crtc_state *new_crtc_state =
> drm_atomic_get_new_crtc_state(state, crtc); +	struct drm_plane_state
> *new_plane_state = drm_atomic_get_new_plane_state(state, +			
							
> crtc->primary);

While the rename to 'new_plane_state' makes sense, this is an unrelated 
change.

>  	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_crtc_state, new_plane_state);
> 
>  	/* Write cur_buf as well to avoid an initial corrupt frame */
> -	paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
> +	paddr = drm_fb_dma_get_gem_addr(new_plane_state->fb, 
new_plane_state, 0);
>  	if (paddr) {
>  		writel(lower_32_bits(paddr),
>  		       lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4);
> @@ -520,6 +542,46 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc
> *crtc, pm_runtime_put_sync(drm->dev);
>  }
> 
> +static void lcdif_crtc_reset(struct drm_crtc *crtc)
> +{
> +	struct lcdif_crtc_state *state;
> +
> +	if (crtc->state)
> +		__drm_atomic_helper_crtc_destroy_state(crtc->state);
> +
> +	kfree(to_lcdif_crtc_state(crtc->state));

Shouldn't this be just
if (crtc->state)
	crtc->funcs->atomic_destroy_state(crtc, crtc->state);

similar to what drm_atomic_helper_crtc_reset is doing? This will eventually 
call lcdif_crtc_atomic_destroy_state().

> +	crtc->state = NULL;
> +
> +	state = kzalloc(sizeof(*state), GFP_KERNEL);
> +	if (state)
> +		__drm_atomic_helper_crtc_reset(crtc, &state->base);

Is there a specific reason to not call this helper when 'state==NULL'? 
drm_atomic_helper_crtc_reset() does call this even when passing NULL for 
crtc_state.

> +}
> +
> +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;
> +

drm_atomic_helper_crtc_duplicate_state() has a check for
if (WARN_ON(!crtc->state))
	return NULL;

Maybe it should be added here as well. But then the call to 
to_lcdif_crtc_state() has to be moved down.

Best regards,
Alexander

> +	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 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 int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
>  {
>  	struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
> @@ -548,12 +610,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/



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Liu Ying <victor.liu@nxp.com>
Cc: marex@denx.de, stefan@agner.ch, airlied@gmail.com,
	daniel@ffwll.ch, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, shawnguo@kernel.org,
	s.hauer@pengutronix.de, kernel@pengutronix.de,
	festevam@gmail.com, linux-imx@nxp.com,
	krzysztof.kozlowski@linaro.org, LW@karo-electronics.de
Subject: Re: [PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()
Date: Tue, 14 Feb 2023 15:12:55 +0100	[thread overview]
Message-ID: <1755644.VLH7GnMWUR@steina-w> (raw)
In-Reply-To: <20230213085612.1026538-4-victor.liu@nxp.com>

Hi Liu,

thanks for the update.

Am Montag, 13. Februar 2023, 09:56:09 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@nxp.com>
> ---
> 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 | 138 ++++++++++++++++++++++--------
>  1 file changed, 100 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> b/drivers/gpu/drm/mxsfb/lcdif_kms.c index e54200a9fcb9..294cecdf5439 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 */

Is it strictly necessary that base is the first member? to_lcdif_crtc_state() 
should be able to handle any position within the struct. I mean it's sensible 
to put it in first place. But the comment somehow bugs me.

> +	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,35 +494,21 @@ 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_plane_state *new_pstate = 
drm_atomic_get_new_plane_state(state,
> -								
	    crtc->primary);
> +	struct drm_crtc_state *new_crtc_state =
> drm_atomic_get_new_crtc_state(state, crtc); +	struct drm_plane_state
> *new_plane_state = drm_atomic_get_new_plane_state(state, +			
							
> crtc->primary);

While the rename to 'new_plane_state' makes sense, this is an unrelated 
change.

>  	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_crtc_state, new_plane_state);
> 
>  	/* Write cur_buf as well to avoid an initial corrupt frame */
> -	paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
> +	paddr = drm_fb_dma_get_gem_addr(new_plane_state->fb, 
new_plane_state, 0);
>  	if (paddr) {
>  		writel(lower_32_bits(paddr),
>  		       lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4);
> @@ -520,6 +542,46 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc
> *crtc, pm_runtime_put_sync(drm->dev);
>  }
> 
> +static void lcdif_crtc_reset(struct drm_crtc *crtc)
> +{
> +	struct lcdif_crtc_state *state;
> +
> +	if (crtc->state)
> +		__drm_atomic_helper_crtc_destroy_state(crtc->state);
> +
> +	kfree(to_lcdif_crtc_state(crtc->state));

Shouldn't this be just
if (crtc->state)
	crtc->funcs->atomic_destroy_state(crtc, crtc->state);

similar to what drm_atomic_helper_crtc_reset is doing? This will eventually 
call lcdif_crtc_atomic_destroy_state().

> +	crtc->state = NULL;
> +
> +	state = kzalloc(sizeof(*state), GFP_KERNEL);
> +	if (state)
> +		__drm_atomic_helper_crtc_reset(crtc, &state->base);

Is there a specific reason to not call this helper when 'state==NULL'? 
drm_atomic_helper_crtc_reset() does call this even when passing NULL for 
crtc_state.

> +}
> +
> +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;
> +

drm_atomic_helper_crtc_duplicate_state() has a check for
if (WARN_ON(!crtc->state))
	return NULL;

Maybe it should be added here as well. But then the call to 
to_lcdif_crtc_state() has to be moved down.

Best regards,
Alexander

> +	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 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 int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
>  {
>  	struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
> @@ -548,12 +610,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/



WARNING: multiple messages have this Message-ID (diff)
From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Liu Ying <victor.liu@nxp.com>
Cc: marex@denx.de, shawnguo@kernel.org, s.hauer@pengutronix.de,
	krzysztof.kozlowski@linaro.org, robh+dt@kernel.org,
	linux-imx@nxp.com, krzysztof.kozlowski+dt@linaro.org,
	kernel@pengutronix.de, LW@karo-electronics.de
Subject: Re: [PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()
Date: Tue, 14 Feb 2023 15:12:55 +0100	[thread overview]
Message-ID: <1755644.VLH7GnMWUR@steina-w> (raw)
In-Reply-To: <20230213085612.1026538-4-victor.liu@nxp.com>

Hi Liu,

thanks for the update.

Am Montag, 13. Februar 2023, 09:56:09 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@nxp.com>
> ---
> 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 | 138 ++++++++++++++++++++++--------
>  1 file changed, 100 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> b/drivers/gpu/drm/mxsfb/lcdif_kms.c index e54200a9fcb9..294cecdf5439 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 */

Is it strictly necessary that base is the first member? to_lcdif_crtc_state() 
should be able to handle any position within the struct. I mean it's sensible 
to put it in first place. But the comment somehow bugs me.

> +	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,35 +494,21 @@ 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_plane_state *new_pstate = 
drm_atomic_get_new_plane_state(state,
> -								
	    crtc->primary);
> +	struct drm_crtc_state *new_crtc_state =
> drm_atomic_get_new_crtc_state(state, crtc); +	struct drm_plane_state
> *new_plane_state = drm_atomic_get_new_plane_state(state, +			
							
> crtc->primary);

While the rename to 'new_plane_state' makes sense, this is an unrelated 
change.

>  	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_crtc_state, new_plane_state);
> 
>  	/* Write cur_buf as well to avoid an initial corrupt frame */
> -	paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
> +	paddr = drm_fb_dma_get_gem_addr(new_plane_state->fb, 
new_plane_state, 0);
>  	if (paddr) {
>  		writel(lower_32_bits(paddr),
>  		       lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4);
> @@ -520,6 +542,46 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc
> *crtc, pm_runtime_put_sync(drm->dev);
>  }
> 
> +static void lcdif_crtc_reset(struct drm_crtc *crtc)
> +{
> +	struct lcdif_crtc_state *state;
> +
> +	if (crtc->state)
> +		__drm_atomic_helper_crtc_destroy_state(crtc->state);
> +
> +	kfree(to_lcdif_crtc_state(crtc->state));

Shouldn't this be just
if (crtc->state)
	crtc->funcs->atomic_destroy_state(crtc, crtc->state);

similar to what drm_atomic_helper_crtc_reset is doing? This will eventually 
call lcdif_crtc_atomic_destroy_state().

> +	crtc->state = NULL;
> +
> +	state = kzalloc(sizeof(*state), GFP_KERNEL);
> +	if (state)
> +		__drm_atomic_helper_crtc_reset(crtc, &state->base);

Is there a specific reason to not call this helper when 'state==NULL'? 
drm_atomic_helper_crtc_reset() does call this even when passing NULL for 
crtc_state.

> +}
> +
> +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;
> +

drm_atomic_helper_crtc_duplicate_state() has a check for
if (WARN_ON(!crtc->state))
	return NULL;

Maybe it should be added here as well. But then the call to 
to_lcdif_crtc_state() has to be moved down.

Best regards,
Alexander

> +	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 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 int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
>  {
>  	struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
> @@ -548,12 +610,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/



  reply	other threads:[~2023-02-14 14:58 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-13  8:56 [PATCH v3 0/6] drm: lcdif: Add i.MX93 LCDIF support Liu Ying
2023-02-13  8:56 ` Liu Ying
2023-02-13  8:56 ` Liu Ying
2023-02-13  8:56 ` [PATCH v3 1/6] dt-bindings: " Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-15  7:26   ` Alexander Stein
2023-02-15  7:26     ` Alexander Stein
2023-02-15  7:26     ` Alexander Stein
2023-02-15  7:49     ` Liu Ying
2023-02-15  7:49       ` Liu Ying
2023-02-15  7:49       ` Liu Ying
2023-02-15  8:44       ` Alexander Stein
2023-02-15  8:44         ` Alexander Stein
2023-02-15  8:44         ` Alexander Stein
2023-02-13  8:56 ` [PATCH v3 2/6] drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-14 13:42   ` Alexander Stein
2023-02-14 13:42     ` Alexander Stein
2023-02-14 13:42     ` Alexander Stein
2023-02-13  8:56 ` [PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check() Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-14 14:12   ` Alexander Stein [this message]
2023-02-14 14:12     ` Alexander Stein
2023-02-14 14:12     ` Alexander Stein
2023-02-14 14:16     ` Ville Syrjälä
2023-02-14 14:16       ` Ville Syrjälä
2023-02-14 14:16       ` Ville Syrjälä
2023-02-15  3:44     ` Liu Ying
2023-02-15  3:44       ` Liu Ying
2023-02-15  3:44       ` Liu Ying
2023-02-15  8:27       ` Alexander Stein
2023-02-15  8:27         ` Alexander Stein
2023-02-15  8:27         ` Alexander Stein
2023-02-13  8:56 ` [PATCH v3 4/6] drm: lcdif: Check consistent bus format and flags across first bridges Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-15  7:55   ` Alexander Stein
2023-02-15  7:55     ` Alexander Stein
2023-02-15  7:55     ` Alexander Stein
2023-02-15  8:40     ` Liu Ying
2023-02-15  8:40       ` Liu Ying
2023-02-15  8:40       ` Liu Ying
2023-02-13  8:56 ` [PATCH v3 5/6] drm: lcdif: Add multiple encoders and first bridges support Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-15  7:54   ` Alexander Stein
2023-02-15  7:54     ` Alexander Stein
2023-02-15  7:54     ` Alexander Stein
2023-02-15  8:52     ` Liu Ying
2023-02-15  8:52       ` Liu Ying
2023-02-15  8:52       ` Liu Ying
2023-02-13  8:56 ` [PATCH v3 6/6] drm: lcdif: Add i.MX93 LCDIF compatible string Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-13  8:56   ` Liu Ying
2023-02-15  7:55   ` Alexander Stein
2023-02-15  7:55     ` Alexander Stein
2023-02-15  7:55     ` Alexander Stein

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=1755644.VLH7GnMWUR@steina-w \
    --to=alexander.stein@ew.tq-group.com \
    --cc=LW@karo-electronics.de \
    --cc=airlied@gmail.com \
    --cc=daniel@ffwll.ch \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=krzysztof.kozlowski@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marex@denx.de \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=shawnguo@kernel.org \
    --cc=stefan@agner.ch \
    --cc=victor.liu@nxp.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: link
Be 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.