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

From: Icenowy Zheng

Date: Tue May 05 2026 - 05:12:02 EST


在 2026-05-05二的 04:26 +0000,Dominique Belhachemi写道:
> Wire up the standard non-coherent path matching the ingenic DRM
> driver.

Ah I forgot that my test platform is also noncoherent -- it uses
uncached memory map instead of cache maintenance.

Should some other facility to be wired in to check whether cache
maintenance or uncached mapping is available and use that
functionality?

Thanks,
Icenowy

>
> Tested on StarFive JH7110 (VisionFive 2 v1.3B).
>
> Signed-off-by: Dominique Belhachemi <domibel@xxxxxxxxxx>
> ---
>  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)
> + 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;
>  }