* [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
@ 2026-09-18 3:01 Joey Lu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
` (6 more replies)
0 siblings, 7 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
This series adds support for the Verisilicon DCUltraLite display
controller as integrated in the Nuvoton MA35D1 SoC.
The Verisilicon DC driver and its DT binding were originally written by
Icenowy Zheng <zhengxingda@iscas.ac.cn> for the T-Head TH1520 SoC, which
carries a DC8200 IP block. The present series builds on that foundation
with gratitude to Icenowy for the original work.
The DCUltraLite is a different variant in the DC IP family. While the two
IPs share a broadly similar register layout, a number of differences
prevent the existing driver from working on the MA35D1 without
modification:
- No CONFIG_EX commit path: the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX) are absent. The DCUltraLite uses enable (bit 0) and
reset (bit 4) bits in FB_CONFIG for direct framebuffer updates, and
requires a per-frame VALID bit toggle (FB_CONFIG bit 3) to latch
configuration changes.
- No PANEL_START register: panel output begins when
PANEL_CONFIG.RUNNING is set; the DC8200 multi-display sync start
register at 0x1CCC does not exist.
- Different IRQ registers: DISP_IRQ_STA at 0x147C / DISP_IRQ_EN at
0x1480, versus the DC8200's TOP_IRQ_ACK at 0x0010 / TOP_IRQ_EN at
0x0014.
- Simpler clock topology: the MA35D1 clock controller gates the core,
AXI and AHB clocks with a single bit, so the devicetree supplies the
same clock phandle for all three; only the pixel clock is distinct.
No second output port is present, so no pix1 clock is needed either.
- Single display output: no per-output indexing beyond index 0 is
needed.
- Hardware-discoverable identity: the DCUltraLite exposes chip identity
registers whose model field reads 0x0 (revision 0x5560,
customer_id 0x305), allowing the existing vs_fill_chip_identity()
path to identify the variant purely through register reads.
Patch 1 adds the nuvoton,ma35d1-dcu compatible to the verisilicon,dc DT
binding and relaxes the top-level clock/reset item counts so per-variant
allOf/if blocks can constrain each compatible's actual topology.
Patch 2 adds the register-level macros needed by the DC8000 ops.
Patches 3-4 introduce the driver changes in two logical steps: the
vs_dc_funcs hardware ops vtable with DC8200 ops extracted into
vs_dc8200.c, and the DC8000 ops in vs_dc8000.c. Patch 5 adds the
DCUltraLite HWDB entry that gates hardware recognition once all support
is in place.
Patch 6 adds the Kconfig dependency on ARCH_MA35, placed last because it
is only meaningful after the HWDB entry is added.
Patch 7 fixes a pre-existing DC8200 bug in the primary plane disable
path that Icenowy spotted while reviewing patch 3.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v6:
- [dt-bindings] Added a "port@1: false" / "required: port@0"
restriction to the nuvoton,ma35d1-dcu allOf/if block, since the
DCUltraLite only has a single output port.
- [driver] Fixed 3 "alignment should match open parenthesis"
checkpatch --strict issues introduced by patch 3:
vs_crtc_atomic_begin() and vs_crtc_atomic_flush() continuation
lines in vs_crtc.c, and vs_dc8200_primary_plane_update_ex()'s
continuation line in vs_dc8200.c.
- [driver] Added patch 7 to fix the pre-existing DC8200 FB_EN
regmap_set_bits()/regmap_clear_bits() bug in
vs_dc8200_primary_plane_disable_ex(), carried over unchanged since
commit dbf21777caa8 ("drm: verisilicon: add a driver for
Verisilicon display controllers").
Joey Lu (7):
dt-bindings: display: verisilicon,dc: add support for
nuvoton,ma35d1-dcu
drm/verisilicon: add register-level macros for DC8000
drm/verisilicon: introduce per-variant hardware ops table
drm/verisilicon: add DC8000 (DCUltraLite) display controller support
drm/verisilicon: add DCUltraLite chip identity to HWDB
drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN
.../bindings/display/verisilicon,dc.yaml | 51 ++++++++
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +--
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 +++++-
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc.c | 9 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 +++++
drivers/gpu/drm/verisilicon/vs_dc8000.c | 92 +++++++++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 121 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_drm.c | 5 +-
drivers/gpu/drm/verisilicon/vs_drm.h | 8 ++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 14 ++
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +----
.../drm/verisilicon/vs_primary_plane_regs.h | 3 +
16 files changed, 382 insertions(+), 55 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 5:57 ` Icenowy Zheng
2026-09-18 10:50 ` Icenowy Zheng
2026-09-18 3:01 ` [PATCH v7 2/7] drm/verisilicon: add register-level macros for DC8000 Joey Lu
` (5 subsequent siblings)
6 siblings, 2 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu, Conor Dooley
Add the Nuvoton MA35D1 DCUltraLite (nuvoton,ma35d1-dcu) to the binding.
The DCUltraLite uses only four clocks (core, axi, ahb, pix0) and one
reset (core), with a single output port.
The MA35D1 clock controller gates the core, AXI and AHB clocks with a
single bit, but each remains a distinct clock line feeding the IP with
its own rate constraints, so all four must still be listed individually
in the devicetree; core, axi and ahb happen to share the same clock
phandle.
Move the clocks/clock-names minItems to 4 and resets/reset-names
minItems to 1 at the top level, since that is the lowest count any
supported variant needs. Add an allOf/if block that tightens the
constraint back up to the fixed 5-clock/3-reset topology required by
the existing thead,th1520-dc8200 compatible, and another one that caps
the new nuvoton,ma35d1-dcu compatible at the 4-clock/1-reset count it
actually wires up.
Restrict the same nuvoton,ma35d1-dcu if block to a single port@0,
since the DCUltraLite only has one output port.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/display/verisilicon,dc.yaml | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 919a900122012..e1e6a3a953646 100644
--- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
+++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
@@ -17,6 +17,7 @@ properties:
items:
- enum:
- thead,th1520-dc8200
+ - nuvoton,ma35d1-dcu
- const: verisilicon,dc # DC IPs have discoverable ID/revision registers
reg:
@@ -26,6 +27,7 @@ properties:
maxItems: 1
clocks:
+ minItems: 4
items:
- description: DC Core clock
- description: DMA AXI bus clock
@@ -34,6 +36,7 @@ properties:
- description: Pixel clock of output 1
clock-names:
+ minItems: 4
items:
- const: core
- const: axi
@@ -42,12 +45,14 @@ properties:
- const: pix1
resets:
+ minItems: 1
items:
- description: DC Core reset
- description: DMA AXI bus reset
- description: Configuration AHB bus reset
reset-names:
+ minItems: 1
items:
- const: core
- const: axi
@@ -79,6 +84,52 @@ required:
- reset-names
- ports
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ minItems: 5
+
+ clock-names:
+ minItems: 5
+
+ resets:
+ minItems: 3
+
+ reset-names:
+ minItems: 3
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nuvoton,ma35d1-dcu
+ then:
+ properties:
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ maxItems: 4
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ maxItems: 1
+
+ ports:
+ properties:
+ port@1: false
+
+ required:
+ - port@0
+
additionalProperties: false
examples:
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 2/7] drm/verisilicon: add register-level macros for DC8000
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 3:01 ` [PATCH v7 3/7] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
` (4 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
Add register-level constants needed by the forthcoming DC8000 (DCUltraLite)
hardware ops:
VSDC_DISP_IRQ_VSYNC(n) in vs_crtc_regs.h: bit mask for per-output
VSYNC interrupt bits in DISP_IRQ_STA (0x147C) / DISP_IRQ_EN (0x1480),
which are the IRQ registers used by DCUltraLite in place of the DC8200
TOP_IRQ_ACK / TOP_IRQ_EN registers.
VSDC_FB_CONFIG_ENABLE (bit 0), VSDC_FB_CONFIG_VALID (bit 3) and
VSDC_FB_CONFIG_RESET (bit 4) in vs_primary_plane_regs.h: control bits
in the FB_CONFIG register used by DCUltraLite for framebuffer enable
and per-frame commit handshake.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
index c7930e817635c..d4da22b08cd5c 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
@@ -54,6 +54,7 @@
#define VSDC_DISP_GAMMA_DATA(n) (0x1460 + 0x4 * (n))
#define VSDC_DISP_IRQ_STA 0x147C
+#define VSDC_DISP_IRQ_VSYNC(n) BIT(n)
#define VSDC_DISP_IRQ_EN 0x1480
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
index cbb125c46b390..67d4b00f294e2 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
@@ -16,6 +16,9 @@
#define VSDC_FB_STRIDE(n) (0x1408 + 0x4 * (n))
#define VSDC_FB_CONFIG(n) (0x1518 + 0x4 * (n))
+#define VSDC_FB_CONFIG_ENABLE BIT(0)
+#define VSDC_FB_CONFIG_VALID BIT(3)
+#define VSDC_FB_CONFIG_RESET BIT(4)
#define VSDC_FB_CONFIG_CLEAR_EN BIT(8)
#define VSDC_FB_CONFIG_ROT_MASK GENMASK(13, 11)
#define VSDC_FB_CONFIG_ROT(v) ((v) << 11)
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 3/7] drm/verisilicon: introduce per-variant hardware ops table
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
2026-09-18 3:01 ` [PATCH v7 2/7] drm/verisilicon: add register-level macros for DC8000 Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 3:01 ` [PATCH v7 4/7] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
The DC8200 and DCUltraLite share a broadly similar register layout but
differ in how the bridge, CRTC, primary plane and IRQ paths are driven.
Introduce a vs_dc_funcs vtable so each variant can supply its own
implementation without scattering conditionals across multiple files.
Add a generation field to struct vs_chip_identity to distinguish variants.
Extract the DC8200-specific hardware ops into vs_dc8200.c and add unified
IRQ bit definitions so implementations can translate hardware-specific
bits to a common set. Update the shared code to dispatch through
dc->funcs.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +--
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 +++++-
drivers/gpu/drm/verisilicon/vs_dc.c | 6 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 32 +++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 121 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_drm.c | 5 +-
drivers/gpu/drm/verisilicon/vs_drm.h | 8 ++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +----
11 files changed, 220 insertions(+), 54 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 426f4bcaa834d..9d4cd16452fa1 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_bridge.c b/drivers/gpu/drm/verisilicon/vs_bridge.c
index dc7c85b07fe32..3fbc8d57f8a1e 100644
--- a/drivers/gpu/drm/verisilicon/vs_bridge.c
+++ b/drivers/gpu/drm/verisilicon/vs_bridge.c
@@ -162,15 +162,8 @@ static void vs_bridge_enable_common(struct vs_crtc *crtc,
VSDC_DISP_PANEL_CONFIG_DE_EN |
VSDC_DISP_PANEL_CONFIG_DAT_EN |
VSDC_DISP_PANEL_CONFIG_CLK_EN);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_RUNNING(output));
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+
+ dc->funcs->panel_enable_ex(dc, output);
}
static void vs_bridge_atomic_enable_dpi(struct drm_bridge *bridge,
@@ -228,14 +221,7 @@ static void vs_bridge_atomic_disable(struct drm_bridge *bridge,
struct vs_dc *dc = crtc->dc;
unsigned int output = crtc->id;
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
- VSDC_DISP_PANEL_START_RUNNING(output));
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+ dc->funcs->panel_disable_ex(dc, output);
}
static const struct drm_bridge_funcs vs_dpi_bridge_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
index c24c1588cbe69..6033662dd9221 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc.c
+++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
@@ -16,10 +16,33 @@
#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"
+static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_begin)
+ dc->funcs->crtc_begin(dc, output);
+}
+
+static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_flush)
+ dc->funcs->crtc_flush(dc, output);
+
+ drm_crtc_vblank_atomic_flush(crtc, state);
+}
+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
@@ -30,6 +53,9 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
clk_disable_unprepare(dc->pix_clk[output]);
+
+ if (dc->funcs->crtc_disable_ex)
+ dc->funcs->crtc_disable_ex(dc, output);
}
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -42,6 +68,9 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
drm_WARN_ON(&dc->drm_dev->base,
clk_prepare_enable(dc->pix_clk[output]));
+ if (dc->funcs->crtc_enable_ex)
+ dc->funcs->crtc_enable_ex(dc, output);
+
drm_crtc_vblank_on(crtc);
}
@@ -119,7 +148,8 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
- .atomic_flush = drm_crtc_vblank_atomic_flush,
+ .atomic_begin = vs_crtc_atomic_begin,
+ .atomic_flush = vs_crtc_atomic_flush,
.atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable,
.mode_set_nofb = vs_crtc_mode_set_nofb,
@@ -132,7 +162,7 @@ static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->enable_vblank(dc, vcrtc->id);
return 0;
}
@@ -142,7 +172,7 @@ static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->disable_vblank(dc, vcrtc->id);
}
static const struct drm_crtc_funcs vs_crtc_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index dad9967bc10b8..9729b693d360e 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -8,9 +8,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
-#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_hwdb.h"
@@ -33,7 +31,7 @@ static irqreturn_t vs_dc_irq_handler(int irq, void *private)
struct vs_dc *dc = private;
u32 irqs;
- regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ irqs = dc->funcs->irq_ack(dc);
vs_drm_handle_irq(dc, irqs);
@@ -136,6 +134,8 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
+ dc->funcs = &vs_dc8200_funcs;
+
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index ed1016f18758e..825f5dd6bf174 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -14,6 +14,7 @@
#include <linux/reset.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
#include "vs_hwdb.h"
@@ -22,6 +23,34 @@
struct vs_drm_dev;
struct vs_crtc;
+struct vs_dc;
+
+struct vs_dc_funcs {
+ /* Bridge: atomic_enable, atomic_disable */
+ void (*panel_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*panel_disable_ex)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_begin, atomic_flush */
+ void (*crtc_begin)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_flush)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_enable, atomic_disable */
+ void (*crtc_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable_ex)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: enable_vblank, disable_vblank */
+ void (*enable_vblank)(struct vs_dc *dc, unsigned int output);
+ void (*disable_vblank)(struct vs_dc *dc, unsigned int output);
+
+ /* Primary plane: atomic_enable, atomic_disable, atomic_update */
+ void (*primary_plane_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_disable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_update_ex)(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state);
+
+ /* IRQ acknowledge */
+ u32 (*irq_ack)(struct vs_dc *dc);
+};
struct vs_dc {
struct regmap *regs;
@@ -33,6 +62,9 @@ struct vs_dc {
struct vs_drm_dev *drm_dev;
struct vs_chip_identity identity;
+ const struct vs_dc_funcs *funcs;
};
+extern const struct vs_dc_funcs vs_dc8200_funcs;
+
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
new file mode 100644
index 0000000000000..f72da10295e1b
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include <drm/drm_print.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.h"
+#include "vs_drm.h"
+#include "vs_plane.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8200_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_plane_commit(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_primary_plane_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
+ VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_update_ex(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state)
+{
+ regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
+ regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
+ state->crtc_y + state->crtc_h));
+ regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
+ VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static u32 vs_dc8200_irq_ack(struct vs_dc *dc)
+{
+ u32 hw_irqs, unified = 0, known = 0;
+ unsigned int i;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &hw_irqs);
+
+ for (i = 0; i < VSDC_MAX_OUTPUTS; i++) {
+ known |= VSDC_TOP_IRQ_VSYNC(i);
+ if (hw_irqs & VSDC_TOP_IRQ_VSYNC(i))
+ unified |= VSDC_IRQ_VSYNC(i);
+ }
+
+ drm_WARN_ONCE(&dc->drm_dev->base, hw_irqs & ~known,
+ "Unknown hardware IRQ bits: %#x\n", hw_irqs & ~known);
+
+ return unified;
+}
+
+const struct vs_dc_funcs vs_dc8200_funcs = {
+ .panel_enable_ex = vs_dc8200_panel_enable_ex,
+ .panel_disable_ex = vs_dc8200_panel_disable_ex,
+ .enable_vblank = vs_dc8200_enable_vblank,
+ .disable_vblank = vs_dc8200_disable_vblank,
+ .primary_plane_enable_ex = vs_dc8200_primary_plane_enable_ex,
+ .primary_plane_disable_ex = vs_dc8200_primary_plane_disable_ex,
+ .primary_plane_update_ex = vs_dc8200_primary_plane_update_ex,
+ .irq_ack = vs_dc8200_irq_ack,
+};
diff --git a/drivers/gpu/drm/verisilicon/vs_drm.c b/drivers/gpu/drm/verisilicon/vs_drm.c
index fd259d53f49f1..24e9d0b008f31 100644
--- a/drivers/gpu/drm/verisilicon/vs_drm.c
+++ b/drivers/gpu/drm/verisilicon/vs_drm.c
@@ -25,7 +25,6 @@
#include "vs_bridge.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#define DRIVER_NAME "verisilicon"
@@ -168,8 +167,8 @@ void vs_drm_handle_irq(struct vs_dc *dc, u32 irqs)
unsigned int i;
for (i = 0; i < dc->identity.display_count; i++) {
- if (irqs & VSDC_TOP_IRQ_VSYNC(i)) {
- irqs &= ~VSDC_TOP_IRQ_VSYNC(i);
+ if (irqs & VSDC_IRQ_VSYNC(i)) {
+ irqs &= ~VSDC_IRQ_VSYNC(i);
if (dc->drm_dev->crtcs[i])
drm_crtc_handle_vblank(&dc->drm_dev->crtcs[i]->base);
}
diff --git a/drivers/gpu/drm/verisilicon/vs_drm.h b/drivers/gpu/drm/verisilicon/vs_drm.h
index 606338206a427..6a89c20879df7 100644
--- a/drivers/gpu/drm/verisilicon/vs_drm.h
+++ b/drivers/gpu/drm/verisilicon/vs_drm.h
@@ -6,6 +6,7 @@
#ifndef _VS_DRM_H_
#define _VS_DRM_H_
+#include <linux/bits.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -13,6 +14,13 @@
struct vs_dc;
+/*
+ * DC variants use different interrupt registers with diverging bit
+ * assignments; each irq_ack() implementation must translate its
+ * hardware-specific bits into these definitions.
+ */
+#define VSDC_IRQ_VSYNC(n) BIT(n)
+
struct vs_drm_dev {
struct drm_device base;
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 2a0f7c59afa3a..91524d16f7785 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -94,6 +94,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = ~0U,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -103,6 +104,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5721,
.customer_id = 0x30B,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -112,6 +114,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x310,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_with_yuv444,
@@ -121,6 +124,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x311,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.h b/drivers/gpu/drm/verisilicon/vs_hwdb.h
index 2065ecb730437..a15c8b5656044 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.h
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.h
@@ -9,6 +9,11 @@
#include <linux/regmap.h>
#include <linux/types.h>
+enum vs_dc_generation {
+ VSDC_GEN_DC8000,
+ VSDC_GEN_DC8200,
+};
+
struct vs_formats {
const u32 *array;
unsigned int num;
@@ -19,6 +24,7 @@ struct vs_chip_identity {
u32 revision;
u32 customer_id;
+ enum vs_dc_generation generation;
u32 display_count;
/*
* The hardware only supports square cursor planes, so this field
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
index 20a820f1ef302..0d7c6f424079b 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -54,12 +54,6 @@ static int vs_primary_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void vs_primary_plane_commit(struct vs_dc *dc, unsigned int output)
-{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_COMMIT);
-}
-
static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
struct drm_atomic_commit *atomic_state)
{
@@ -70,13 +64,8 @@ static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
- regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
- VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_enable_ex)
+ dc->funcs->primary_plane_enable_ex(dc, output);
}
static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -89,10 +78,8 @@ static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_disable_ex)
+ dc->funcs->primary_plane_disable_ex(dc, output);
}
static void vs_primary_plane_atomic_update(struct drm_plane *plane,
@@ -138,18 +125,11 @@ static void vs_primary_plane_atomic_update(struct drm_plane *plane,
regmap_write(dc->regs, VSDC_FB_STRIDE(output),
fb->pitches[0]);
- regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
- regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
- state->crtc_y + state->crtc_h));
regmap_write(dc->regs, VSDC_FB_SIZE(output),
VSDC_MAKE_PLANE_SIZE(state->crtc_w, state->crtc_h));
- regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
- VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_update_ex)
+ dc->funcs->primary_plane_update_ex(dc, output, state);
}
static const struct drm_plane_helper_funcs vs_primary_plane_helper_funcs = {
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 4/7] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (2 preceding siblings ...)
2026-09-18 3:01 ` [PATCH v7 3/7] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 3:01 ` [PATCH v7 5/7] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
The Verisilicon DC IP family also ships in a DCUltraLite (DC8000
generation) configuration that lacks the DC8200's CONFIG_EX staging
registers and PANEL_START sync register, and exposes its VSYNC
interrupt through a differently laid out status/enable register pair.
Add a vs_dc_funcs implementation for the DC8000 generation in
vs_dc8000.c: framebuffer updates are latched directly through
FB_CONFIG's enable/reset/valid bits instead of a staging commit, panel
output starts as soon as PANEL_CONFIG.RUNNING is set with no separate
sync register to arm, and the VSYNC interrupt is acknowledged through
DISP_IRQ_STA/DISP_IRQ_EN. Select this vtable in the probe path based
on the chip identity's generation field.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 5 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc8000.c | 92 +++++++++++++++++++++++++
4 files changed, 98 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 9d4cd16452fa1..d2fd8e4dff242 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_dc8000.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index 9729b693d360e..3e9e2c0264f5d 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -134,7 +134,10 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
- dc->funcs = &vs_dc8200_funcs;
+ if (dc->identity.generation == VSDC_GEN_DC8200)
+ dc->funcs = &vs_dc8200_funcs;
+ else
+ dc->funcs = &vs_dc8000_funcs;
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index 825f5dd6bf174..ac96ad7011994 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -66,5 +66,6 @@ struct vs_dc {
};
extern const struct vs_dc_funcs vs_dc8200_funcs;
+extern const struct vs_dc_funcs vs_dc8000_funcs;
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8000.c b/drivers/gpu/drm/verisilicon/vs_dc8000.c
new file mode 100644
index 0000000000000..df7bd5bdd7f2a
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8000.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include <drm/drm_print.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.h"
+#include "vs_drm.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8000_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_crtc_begin(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_flush(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_crtc_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8000_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static u32 vs_dc8000_irq_ack(struct vs_dc *dc)
+{
+ u32 hw_irqs, unified = 0, known = 0;
+ unsigned int i;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &hw_irqs);
+
+ for (i = 0; i < VSDC_MAX_OUTPUTS; i++) {
+ known |= VSDC_DISP_IRQ_VSYNC(i);
+ if (hw_irqs & VSDC_DISP_IRQ_VSYNC(i))
+ unified |= VSDC_IRQ_VSYNC(i);
+ }
+
+ drm_WARN_ONCE(&dc->drm_dev->base, hw_irqs & ~known,
+ "Unknown hardware IRQ bits: %#x\n", hw_irqs & ~known);
+
+ return unified;
+}
+
+const struct vs_dc_funcs vs_dc8000_funcs = {
+ .panel_enable_ex = vs_dc8000_panel_enable_ex,
+ .panel_disable_ex = vs_dc8000_panel_disable_ex,
+ .crtc_begin = vs_dc8000_crtc_begin,
+ .crtc_flush = vs_dc8000_crtc_flush,
+ .crtc_enable_ex = vs_dc8000_crtc_enable_ex,
+ .crtc_disable_ex = vs_dc8000_crtc_disable_ex,
+ .enable_vblank = vs_dc8000_enable_vblank,
+ .disable_vblank = vs_dc8000_disable_vblank,
+ .irq_ack = vs_dc8000_irq_ack,
+};
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 5/7] drm/verisilicon: add DCUltraLite chip identity to HWDB
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (3 preceding siblings ...)
2026-09-18 3:01 ` [PATCH v7 4/7] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 3:01 ` [PATCH v7 6/7] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
2026-09-18 3:01 ` [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN Joey Lu
6 siblings, 0 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
The Nuvoton MA35D1 chip contains a DCUltraLite display controller with
model number 0x0 (sic, the model name contains no number either),
revision 0x5560 and customer ID 0x305. It has a similar register map
with DC8000, only one display output and only 32x32 cursor supported.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/vs_hwdb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 91524d16f7785..7d630a667a3f0 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -129,6 +129,16 @@ static struct vs_chip_identity vs_chip_identities[] = {
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
},
+ {
+ .model = 0x0, /* DCUltraLite */
+ .revision = 0x5560,
+ .customer_id = 0x305,
+
+ .generation = VSDC_GEN_DC8000,
+ .display_count = 1,
+ .max_cursor_size = 32,
+ .formats = &vs_formats_no_yuv444,
+ },
};
int vs_fill_chip_identity(struct regmap *regs,
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 6/7] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (4 preceding siblings ...)
2026-09-18 3:01 ` [PATCH v7 5/7] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 3:01 ` [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN Joey Lu
6 siblings, 0 replies; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
Add ARCH_MA35 to the platform dependencies to allow the driver to be
built for Nuvoton MA35D1.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
index 7cce86ec8603c..295d246eb4b40 100644
--- a/drivers/gpu/drm/verisilicon/Kconfig
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -2,7 +2,7 @@
config DRM_VERISILICON_DC
tristate "DRM Support for Verisilicon DC-series display controllers"
depends on DRM && COMMON_CLK
- depends on RISCV || COMPILE_TEST
+ depends on RISCV || ARCH_MA35 || COMPILE_TEST
select DRM_BRIDGE_CONNECTOR
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (5 preceding siblings ...)
2026-09-18 3:01 ` [PATCH v7 6/7] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
@ 2026-09-18 3:01 ` Joey Lu
2026-09-18 5:52 ` Icenowy Zheng
6 siblings, 1 reply; 11+ messages in thread
From: Joey Lu @ 2026-09-18 3:01 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
vs_dc8200_primary_plane_disable_ex() calls regmap_set_bits() on
VSDC_FB_CONFIG_EX_FB_EN instead of regmap_clear_bits(), so disabling
the primary plane on DC8200-family hardware actually leaves the
framebuffer enable bit instead of clearing it.
This bug predates this series: it was carried over unchanged from
vs_primary_plane_atomic_disable() when patch "drm/verisilicon:
introduce per-variant hardware ops table" split the DC8200-specific
implementation out into vs_dc8200.c.
Fixes: dbf21777caa8 ("drm: verisilicon: add a driver for Verisilicon display controllers")
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_dc8200.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
index f72da10295e1b..25b5906a1c5fc 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc8200.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -70,8 +70,8 @@ static void vs_dc8200_primary_plane_enable_ex(struct vs_dc *dc, unsigned int out
static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc, unsigned int output)
{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
vs_dc8200_plane_commit(dc, output);
}
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN
2026-09-18 3:01 ` [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN Joey Lu
@ 2026-09-18 5:52 ` Icenowy Zheng
0 siblings, 0 replies; 11+ messages in thread
From: Icenowy Zheng @ 2026-09-18 5:52 UTC (permalink / raw)
To: Joey Lu, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel
在 2026-09-18五的 11:01 +0800,Joey Lu写道:
> vs_dc8200_primary_plane_disable_ex() calls regmap_set_bits() on
> VSDC_FB_CONFIG_EX_FB_EN instead of regmap_clear_bits(), so disabling
> the primary plane on DC8200-family hardware actually leaves the
> framebuffer enable bit instead of clearing it.
>
> This bug predates this series: it was carried over unchanged from
> vs_primary_plane_atomic_disable() when patch "drm/verisilicon:
> introduce per-variant hardware ops table" split the DC8200-specific
> implementation out into vs_dc8200.c.
>
> Fixes: dbf21777caa8 ("drm: verisilicon: add a driver for Verisilicon
> display controllers")
Maybe it'd be better to fix this before adding DC variant abstraction,
for easier backporting.
Thanks,
Icenowy
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> drivers/gpu/drm/verisilicon/vs_dc8200.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c
> b/drivers/gpu/drm/verisilicon/vs_dc8200.c
> index f72da10295e1b..25b5906a1c5fc 100644
> --- a/drivers/gpu/drm/verisilicon/vs_dc8200.c
> +++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
> @@ -70,8 +70,8 @@ static void
> vs_dc8200_primary_plane_enable_ex(struct vs_dc *dc, unsigned int out
>
> static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc,
> unsigned int output)
> {
> - regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
> - VSDC_FB_CONFIG_EX_FB_EN);
> + regmap_clear_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
> + VSDC_FB_CONFIG_EX_FB_EN);
>
> vs_dc8200_plane_commit(dc, output);
> }
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
@ 2026-09-18 5:57 ` Icenowy Zheng
2026-09-18 10:50 ` Icenowy Zheng
1 sibling, 0 replies; 11+ messages in thread
From: Icenowy Zheng @ 2026-09-18 5:57 UTC (permalink / raw)
To: Joey Lu, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Conor Dooley
在 2026-09-18五的 11:01 +0800,Joey Lu写道:
> Add the Nuvoton MA35D1 DCUltraLite (nuvoton,ma35d1-dcu) to the
> binding.
> The DCUltraLite uses only four clocks (core, axi, ahb, pix0) and one
> reset (core), with a single output port.
>
> The MA35D1 clock controller gates the core, AXI and AHB clocks with a
> single bit, but each remains a distinct clock line feeding the IP
> with
> its own rate constraints, so all four must still be listed
> individually
> in the devicetree; core, axi and ahb happen to share the same clock
> phandle.
>
> Move the clocks/clock-names minItems to 4 and resets/reset-names
> minItems to 1 at the top level, since that is the lowest count any
> supported variant needs. Add an allOf/if block that tightens the
> constraint back up to the fixed 5-clock/3-reset topology required by
> the existing thead,th1520-dc8200 compatible, and another one that
> caps
> the new nuvoton,ma35d1-dcu compatible at the 4-clock/1-reset count it
> actually wires up.
>
> Restrict the same nuvoton,ma35d1-dcu if block to a single port@0,
> since the DCUltraLite only has one output port.
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> ---
> .../bindings/display/verisilicon,dc.yaml | 51
> +++++++++++++++++++
> 1 file changed, 51 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> index 919a900122012..e1e6a3a953646 100644
> --- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> +++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> @@ -17,6 +17,7 @@ properties:
> items:
> - enum:
> - thead,th1520-dc8200
> + - nuvoton,ma35d1-dcu
> - const: verisilicon,dc # DC IPs have discoverable ID/revision
> registers
>
> reg:
> @@ -26,6 +27,7 @@ properties:
> maxItems: 1
>
> clocks:
> + minItems: 4
> items:
> - description: DC Core clock
> - description: DMA AXI bus clock
> @@ -34,6 +36,7 @@ properties:
> - description: Pixel clock of output 1
>
> clock-names:
> + minItems: 4
> items:
> - const: core
> - const: axi
> @@ -42,12 +45,14 @@ properties:
> - const: pix1
>
> resets:
> + minItems: 1
> items:
> - description: DC Core reset
> - description: DMA AXI bus reset
> - description: Configuration AHB bus reset
>
> reset-names:
> + minItems: 1
> items:
> - const: core
> - const: axi
> @@ -79,6 +84,52 @@ required:
> - reset-names
> - ports
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: thead,th1520-dc8200
Just a note: a new compatible string, `starfive,jh7110-dc8200`, is
floating in the mailing list; although I don't think it will be soon
enough for it to be applied before this patchset.
Thanks,
Icenowy
> + then:
> + properties:
> + clocks:
> + minItems: 5
> +
> + clock-names:
> + minItems: 5
> +
> + resets:
> + minItems: 3
> +
> + reset-names:
> + minItems: 3
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: nuvoton,ma35d1-dcu
> + then:
> + properties:
> + clocks:
> + maxItems: 4
> +
> + clock-names:
> + maxItems: 4
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + maxItems: 1
> +
> + ports:
> + properties:
> + port@1: false
> +
> + required:
> + - port@0
> +
> additionalProperties: false
>
> examples:
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
2026-09-18 5:57 ` Icenowy Zheng
@ 2026-09-18 10:50 ` Icenowy Zheng
1 sibling, 0 replies; 11+ messages in thread
From: Icenowy Zheng @ 2026-09-18 10:50 UTC (permalink / raw)
To: Joey Lu, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Conor Dooley
在 2026-09-18五的 11:01 +0800,Joey Lu写道:
> Add the Nuvoton MA35D1 DCUltraLite (nuvoton,ma35d1-dcu) to the
> binding.
> The DCUltraLite uses only four clocks (core, axi, ahb, pix0) and one
> reset (core), with a single output port.
>
> The MA35D1 clock controller gates the core, AXI and AHB clocks with a
> single bit, but each remains a distinct clock line feeding the IP
> with
> its own rate constraints, so all four must still be listed
> individually
> in the devicetree; core, axi and ahb happen to share the same clock
> phandle.
>
> Move the clocks/clock-names minItems to 4 and resets/reset-names
> minItems to 1 at the top level, since that is the lowest count any
> supported variant needs. Add an allOf/if block that tightens the
> constraint back up to the fixed 5-clock/3-reset topology required by
> the existing thead,th1520-dc8200 compatible, and another one that
> caps
> the new nuvoton,ma35d1-dcu compatible at the 4-clock/1-reset count it
> actually wires up.
>
> Restrict the same nuvoton,ma35d1-dcu if block to a single port@0,
> since the DCUltraLite only has one output port.
By the way, when will the MA35D1 device tree sources be updated? I saw
a lot of drivers being merged but w/o corresponding DT nodes: sdhci-of-
ma35d1, nuvoton-ma35d1-nand-controller, phy-ma35d1-usb2, rtc-ma35d1,
spi-ma35d1-qspi, ma35d1_wdt.
Thanks,
Icenowy
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> ---
> .../bindings/display/verisilicon,dc.yaml | 51
> +++++++++++++++++++
> 1 file changed, 51 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> index 919a900122012..e1e6a3a953646 100644
> --- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> +++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> @@ -17,6 +17,7 @@ properties:
> items:
> - enum:
> - thead,th1520-dc8200
> + - nuvoton,ma35d1-dcu
> - const: verisilicon,dc # DC IPs have discoverable ID/revision
> registers
>
> reg:
> @@ -26,6 +27,7 @@ properties:
> maxItems: 1
>
> clocks:
> + minItems: 4
> items:
> - description: DC Core clock
> - description: DMA AXI bus clock
> @@ -34,6 +36,7 @@ properties:
> - description: Pixel clock of output 1
>
> clock-names:
> + minItems: 4
> items:
> - const: core
> - const: axi
> @@ -42,12 +45,14 @@ properties:
> - const: pix1
>
> resets:
> + minItems: 1
> items:
> - description: DC Core reset
> - description: DMA AXI bus reset
> - description: Configuration AHB bus reset
>
> reset-names:
> + minItems: 1
> items:
> - const: core
> - const: axi
> @@ -79,6 +84,52 @@ required:
> - reset-names
> - ports
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: thead,th1520-dc8200
> + then:
> + properties:
> + clocks:
> + minItems: 5
> +
> + clock-names:
> + minItems: 5
> +
> + resets:
> + minItems: 3
> +
> + reset-names:
> + minItems: 3
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: nuvoton,ma35d1-dcu
> + then:
> + properties:
> + clocks:
> + maxItems: 4
> +
> + clock-names:
> + maxItems: 4
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + maxItems: 1
> +
> + ports:
> + properties:
> + port@1: false
> +
> + required:
> + - port@0
> +
> additionalProperties: false
>
> examples:
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-18 10:50 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18 3:01 [PATCH v7 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-09-18 3:01 ` [PATCH v7 1/7] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu Joey Lu
2026-09-18 5:57 ` Icenowy Zheng
2026-09-18 10:50 ` Icenowy Zheng
2026-09-18 3:01 ` [PATCH v7 2/7] drm/verisilicon: add register-level macros for DC8000 Joey Lu
2026-09-18 3:01 ` [PATCH v7 3/7] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
2026-09-18 3:01 ` [PATCH v7 4/7] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
2026-09-18 3:01 ` [PATCH v7 5/7] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
2026-09-18 3:01 ` [PATCH v7 6/7] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
2026-09-18 3:01 ` [PATCH v7 7/7] drm/verisilicon: fix DC8200 primary plane disable clearing FB_EN Joey Lu
2026-09-18 5:52 ` Icenowy Zheng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®