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

Icenowy Zheng zhengxingda at iscas.ac.cn
Wed Sep 30 00:35:28 PDT 2026


From: Dominique Belhachemi <domibel at debian.org>

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>
[Icenowy: add can_map_coherent check, rename vs_drm field to
 map_noncoherent, adapt for cursor planes]
Signed-off-by: Icenowy Zheng <zhengxingda at iscas.ac.cn>
---
 drivers/gpu/drm/verisilicon/vs_cursor_plane.c |  9 ++++++
 drivers/gpu/drm/verisilicon/vs_drm.c          | 32 ++++++++++++++++++-
 drivers/gpu/drm/verisilicon/vs_drm.h          |  7 ++++
 .../gpu/drm/verisilicon/vs_primary_plane.c    |  9 ++++++
 4 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/verisilicon/vs_cursor_plane.c b/drivers/gpu/drm/verisilicon/vs_cursor_plane.c
index 725921ac25d48..7216eaa6ef355 100644
--- a/drivers/gpu/drm/verisilicon/vs_cursor_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_cursor_plane.c
@@ -13,6 +13,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.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>
@@ -23,6 +24,7 @@
 #include "vs_crtc.h"
 #include "vs_plane.h"
 #include "vs_dc.h"
+#include "vs_drm.h"
 #include "vs_hwdb.h"
 #include "vs_cursor_plane_regs.h"
 
@@ -140,6 +142,8 @@ static void vs_cursor_plane_atomic_disable(struct drm_plane *plane,
 static void vs_cursor_plane_atomic_update(struct drm_plane *plane,
 					   struct drm_atomic_commit *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;
@@ -154,6 +158,8 @@ static void vs_cursor_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;
@@ -275,5 +281,8 @@ struct drm_plane *vs_cursor_plane_init(struct drm_device *drm_dev,
 	drm_plane_helper_add(plane, &vs_cursor_plane_helper_funcs);
 	drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_COVERAGE));
 
+	if (to_vs_drm_dev(drm_dev)->map_noncoherent)
+		drm_plane_enable_fb_damage_clips(plane);
+
 	return plane;
 }
diff --git a/drivers/gpu/drm/verisilicon/vs_drm.c b/drivers/gpu/drm/verisilicon/vs_drm.c
index fd259d53f49f1..6cde0ba7ef6a4 100644
--- a/drivers/gpu/drm/verisilicon/vs_drm.c
+++ b/drivers/gpu/drm/verisilicon/vs_drm.c
@@ -5,6 +5,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>
@@ -12,6 +13,7 @@
 
 #include <drm/clients/drm_client_setup.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_cache.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_dumb_buffers.h>
 #include <drm/drm_fbdev_dma.h>
@@ -49,6 +51,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)->map_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)->map_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 +85,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 +126,8 @@ int vs_drm_initialize(struct vs_dc *dc, struct platform_device *pdev)
 
 	drm = &vdrm->base;
 	vdrm->dc = dc;
+	vdrm->map_noncoherent = !of_dma_is_coherent(dev->of_node) &&
+				!drm_arch_can_map_coherent();
 	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 606338206a427..ee6a3317cc556 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 map_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 594d56bf32410..633e46638dc2b 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>
@@ -18,6 +19,7 @@
 #include "vs_crtc.h"
 #include "vs_plane.h"
 #include "vs_dc.h"
+#include "vs_drm.h"
 #include "vs_primary_plane_regs.h"
 
 static int vs_primary_plane_atomic_check(struct drm_plane *plane,
@@ -102,6 +104,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_commit *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 vs_plane_state *vs_state = to_vs_plane_state(state);
@@ -117,6 +121,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;
@@ -184,5 +190,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)->map_noncoherent)
+		drm_plane_enable_fb_damage_clips(plane);
+
 	return plane;
 }
-- 
2.55.0




More information about the linux-riscv mailing list