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

From: Icenowy Zheng

Date: Tue May 05 2026 - 05:29:18 EST


在 2026-05-05二的 17:05 +0800,Icenowy Zheng写道:
> 在 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?

Ah forgot to mention that drm/imagination driver requires uncached
mapping too, and this seems to be difficult to lower (currently
impossible because the userspace only does Vulkan coherent map now).

Thanks,
Icenowy

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