[PATCH] drm: verisilicon: support non-coherent DMA framebuffers
From: Dominique Belhachemi
Date: Tue May 05 2026 - 00:28:19 EST
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@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;
}
--
2.53.0