[PATCH] drm: verisilicon: support non-coherent DMA framebuffers

Icenowy Zheng zhengxingda at iscas.ac.cn
Fri Sep 11 08:33:27 PDT 2026


在 2026-05-05二的 04:26 +0000,Dominique Belhachemi写道:
> Wire up the standard non-coherent path matching the ingenic DRM
> driver.
> 
> Tested on StarFive JH7110 (VisionFive 2 v1.3B).
> 
> Signed-off-by: Dominique Belhachemi <domibel at debian.org>
> ---
>  drivers/gpu/drm/verisilicon/vs_drm.c          | 31
> +++++++++++++++++--
>  drivers/gpu/drm/verisilicon/vs_drm.h          |  7 +++++
>  .../gpu/drm/verisilicon/vs_primary_plane.c    | 11 ++++++-
>  3 files changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/verisilicon/vs_drm.c
> b/drivers/gpu/drm/verisilicon/vs_drm.c
> index fd259d53f49f..52d8749445df 100644
> --- a/drivers/gpu/drm/verisilicon/vs_drm.c
> +++ b/drivers/gpu/drm/verisilicon/vs_drm.c
> @@ -4,7 +4,7 @@
>   */
>  
>  #include <linux/aperture.h>
> -#include <linux/dma-mapping.h>
> +#include <linux/of_address.h>
>  #include <linux/platform_device.h>
>  #include <linux/module.h>
>  #include <linux/regmap.h>
> @@ -49,6 +49,31 @@ static int vs_gem_dumb_create(struct drm_file
> *file_priv,
>  
>  DEFINE_DRM_GEM_FOPS(vs_drm_driver_fops);
>  
> +static struct drm_gem_object *vs_gem_create_object(struct drm_device
> *drm,
> +						   size_t size)
> +{
> +	struct drm_gem_dma_object *obj;
> +
> +	obj = kzalloc_obj(*obj);
> +	if (!obj)
> +		return ERR_PTR(-ENOMEM);
> +
> +	obj->map_noncoherent = to_vs_drm_dev(drm)->noncoherent;
> +
> +	return &obj->base;
> +}
> +
> +static struct drm_framebuffer *
> +vs_gem_fb_create(struct drm_device *drm, struct drm_file *file,
> +		 const struct drm_format_info *info,
> +		 const struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +	if (to_vs_drm_dev(drm)->noncoherent)

(Added arch/riscv list/maintainers to To/Cc)

I am still thinking how to decide whether to use dirty-tracking-based
cache coherent maintenance or writecombine/uncached mapping.

Maybe a helper should be added, but where? Should it be in arch/riscv
(in this case architecture-specific code would be present in the
verisilicon driver) or in drivers/gpu/drm?

Nevertheless I think using dev->noncoherent is improper here because in
case of writecombine mapping it's also true.

Except for this I think I have no more opinion and okay with the
implementation of this patch now.

Thanks,
Icenowy

> +		return drm_gem_fb_create_with_dirty(drm, file, info,
> mode_cmd);
> +
> +	return drm_gem_fb_create(drm, file, info, mode_cmd);
> +}
> +
>  static const struct drm_driver vs_drm_driver = {
>  	.driver_features	= DRIVER_MODESET | DRIVER_GEM |
> DRIVER_ATOMIC,
>  	.fops			= &vs_drm_driver_fops,
> @@ -58,12 +83,13 @@ static const struct drm_driver vs_drm_driver = {
>  	.minor	= DRIVER_MINOR,
>  
>  	/* GEM Operations */
> +	.gem_create_object	= vs_gem_create_object,
>  	DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vs_gem_dumb_create),
>  	DRM_FBDEV_DMA_DRIVER_OPS,
>  };
>  
>  static const struct drm_mode_config_funcs vs_mode_config_funcs = {
> -	.fb_create		= drm_gem_fb_create,
> +	.fb_create		= vs_gem_fb_create,
>  	.atomic_check		= drm_atomic_helper_check,
>  	.atomic_commit		= drm_atomic_helper_commit,
>  };
> @@ -98,6 +124,7 @@ int vs_drm_initialize(struct vs_dc *dc, struct
> platform_device *pdev)
>  
>  	drm = &vdrm->base;
>  	vdrm->dc = dc;
> +	vdrm->noncoherent = !of_dma_is_coherent(dev->of_node);
>  	dc->drm_dev = vdrm;
>  
>  	ret = drmm_mode_config_init(drm);
> diff --git a/drivers/gpu/drm/verisilicon/vs_drm.h
> b/drivers/gpu/drm/verisilicon/vs_drm.h
> index 606338206a42..17704cd0df1d 100644
> --- a/drivers/gpu/drm/verisilicon/vs_drm.h
> +++ b/drivers/gpu/drm/verisilicon/vs_drm.h
> @@ -18,8 +18,15 @@ struct vs_drm_dev {
>  
>  	struct vs_dc *dc;
>  	struct vs_crtc *crtcs[VSDC_MAX_OUTPUTS];
> +
> +	bool noncoherent;
>  };
>  
> +static inline struct vs_drm_dev *to_vs_drm_dev(struct drm_device
> *drm)
> +{
> +	return container_of(drm, struct vs_drm_dev, base);
> +}
> +
>  int vs_drm_initialize(struct vs_dc *dc, struct platform_device
> *pdev);
>  void vs_drm_finalize(struct vs_dc *dc);
>  void vs_drm_shutdown_handler(struct vs_dc *dc);
> diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> index e8fcb5958615..0049737f492b 100644
> --- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> +++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> @@ -8,6 +8,7 @@
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_fb_dma_helper.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_gem_atomic_helper.h>
> @@ -16,8 +17,9 @@
>  #include <drm/drm_print.h>
>  
>  #include "vs_crtc.h"
> -#include "vs_plane.h"
>  #include "vs_dc.h"
> +#include "vs_drm.h"
> +#include "vs_plane.h"
>  #include "vs_primary_plane_regs.h"
>  
>  static int vs_primary_plane_atomic_check(struct drm_plane *plane,
> @@ -86,6 +88,8 @@ static void vs_primary_plane_atomic_disable(struct
> drm_plane *plane,
>  static void vs_primary_plane_atomic_update(struct drm_plane *plane,
>  					   struct drm_atomic_state
> *atomic_state)
>  {
> +	struct drm_plane_state *old_state =
> drm_atomic_get_old_plane_state(atomic_state,
> +								
> 	   plane);
>  	struct drm_plane_state *state =
> drm_atomic_get_new_plane_state(atomic_state,
>  								    
>    plane);
>  	struct drm_framebuffer *fb = state->fb;
> @@ -101,6 +105,8 @@ static void vs_primary_plane_atomic_update(struct
> drm_plane *plane,
>  		return;
>  	}
>  
> +	drm_fb_dma_sync_non_coherent(plane->dev, old_state, state);
> +
>  	vcrtc = drm_crtc_to_vs_crtc(crtc);
>  	output = vcrtc->id;
>  	dc = vcrtc->dc;
> @@ -169,5 +175,8 @@ struct drm_plane *vs_primary_plane_init(struct
> drm_device *drm_dev, struct vs_dc
>  
>  	drm_plane_helper_add(plane, &vs_primary_plane_helper_funcs);
>  
> +	if (to_vs_drm_dev(drm_dev)->noncoherent)
> +		drm_plane_enable_fb_damage_clips(plane);
> +
>  	return plane;
>  }




More information about the linux-riscv mailing list