* [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
@ 2026-06-15 6:49 Joey Lu
2026-06-15 6:49 ` [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants Joey Lu
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:49 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: two clocks ("core" bus gate and "pix0" pixel
divider); no axi or ahb clocks required.
- 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 generalises the verisilicon,dc DT binding to accommodate the
Nuvoton MA35D1 SoC-specific compatible and the variant's two-clock,
one-reset, single-port topology.
Patch 2 adds the register-level macros needed by the DC8000 ops.
Patches 3-5 introduce the driver changes in three logical steps: the
vs_dc_funcs hardware ops vtable with DC8200 ops extracted into
vs_dc8200.c; the DC8000 ops in vs_dc8000.c with the necessary
clock-optionality changes; and finally 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.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v3:
- [dt-bindings] Reverted extra space before inline '#' comment.
- [dt-bindings] Moved clock/reset items descriptions from the top-level
clocks:/resets: into the per-variant allOf/if blocks; kept only
minItems/maxItems at the top level.
- [dt-bindings] Restored full items lists for clock-names and reset-names
at the top level with minItems so names are still validated.
- [dt-bindings] Added minItems: 1 to resets: in the nuvoton block.
- [dt-bindings] Added required: [resets, reset-names] inside the then:
block for both thead,th1520-dc8200 and nuvoton,ma35d1-dcu.
- [dt-bindings] Added minItems: 3 to reset-names in the thead block.
- [dt-bindings] Added maxItems: 1 to reset-names in the nuvoton block.
- [dt-bindings] Reverted unevaluatedProperties: false back to
additionalProperties: false.
- [dt-bindings] Removed the second DT example for nuvoton,ma35d1-dcu
since a difference in clocks/resets does not need a new example.
- [ops] Renamed bridge_enable/bridge_disable to panel_enable_ex/
panel_disable_ex.
- [ops] Renamed irq_handler to irq_ack.
- [ops] Renamed plane_enable_ex/disable_ex/update_ex to
primary_plane_enable_ex/disable_ex/update_ex.
- [ops] Renamed vs_dcu_lite.c to vs_dc8000.c, all internal functions
from vs_dcu_lite_* to vs_dc8000_*, exported symbol from
vs_dcu_lite_funcs to vs_dc8000_funcs; updated Makefile.
- [kconfig] Moved ARCH_MA35 Kconfig change to a separate final commit,
placed after the HWDB entry.
Joey Lu (6):
dt-bindings: display: verisilicon,dc: generalize for single-output
variants
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
.../bindings/display/verisilicon,dc.yaml | 80 +++++++++++--
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 | 13 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 ++++++
drivers/gpu/drm/verisilicon/vs_dc8000.c | 78 +++++++++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
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 +
14 files changed, 368 insertions(+), 61 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] 13+ messages in thread
* [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
@ 2026-06-15 6:49 ` Joey Lu
2026-06-15 8:19 ` [PATCH v4 1/6] dt-bindings: display: verisilicon, dc: " Icenowy Zheng
2026-06-15 6:49 ` [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:49 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 existing schema hard-codes the five-clock/three-reset/dual-port
topology of the DC8200 IP block, preventing reuse for single-output
variants such as the Verisilicon DCUltraLite used in the Nuvoton MA35D1
SoC.
Rework the schema so that variant-specific constraints are expressed via
allOf/if blocks:
- Add nuvoton,ma35d1-dcu to the SoC-specific compatible enum. The
generic verisilicon,dc fallback remains the driver-binding string.
- Move clock and reset items descriptions into the per-variant allOf/if
blocks; keep only minItems/maxItems at the top level so the base schema
accepts all variants.
- Restore full items lists for clock-names and reset-names at the top
level with minItems so the names are validated against the descriptions.
- Keep ports in the global required list and keep additionalProperties: false.
- Add an allOf/if block for thead,th1520-dc8200: five-clock (core, axi,
ahb, pix0, pix1), three-reset (core, axi, ahb), required resets.
- Add an allOf/if block for nuvoton,ma35d1-dcu: two-clock (core, pix0),
one-reset (core), required resets.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../bindings/display/verisilicon,dc.yaml | 80 +++++++++++++++++--
1 file changed, 73 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 9dc35ab973f2..0c41286b8223 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,14 +27,12 @@ properties:
maxItems: 1
clocks:
- items:
- - description: DC Core clock
- - description: DMA AXI bus clock
- - description: Configuration AHB bus clock
- - description: Pixel clock of output 0
- - description: Pixel clock of output 1
+ minItems: 2
+ maxItems: 5
clock-names:
+ minItems: 2
+ maxItems: 5
items:
- const: core
- const: axi
@@ -42,12 +41,16 @@ properties:
- const: pix1
resets:
+ minItems: 1
+ maxItems: 3
items:
- description: DC Core reset
- description: DMA AXI bus reset
- description: Configuration AHB bus reset
reset-names:
+ minItems: 1
+ maxItems: 3
items:
- const: core
- const: axi
@@ -59,7 +62,7 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description: The first output channel , endpoint 0 should be
+ description: The first output channel, endpoint 0 should be
used for DPI format output and endpoint 1 should be used
for DP format output.
@@ -77,6 +80,69 @@ required:
- clock-names
- ports
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ minItems: 5
+ maxItems: 5
+ items:
+ - description: DC Core clock
+ - description: DMA AXI bus clock
+ - description: Configuration AHB bus clock
+ - description: Pixel clock of output 0
+ - description: Pixel clock of output 1
+
+ clock-names:
+ minItems: 5
+ maxItems: 5
+
+ resets:
+ minItems: 3
+ maxItems: 3
+
+ reset-names:
+ minItems: 3
+ maxItems: 3
+
+ required:
+ - resets
+ - reset-names
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nuvoton,ma35d1-dcu
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+ items:
+ - description: DC Core clock
+ - description: Pixel clock of output 0
+
+ clock-names:
+ minItems: 2
+ maxItems: 2
+
+ resets:
+ minItems: 1
+ maxItems: 1
+
+ reset-names:
+ maxItems: 1
+
+ required:
+ - resets
+ - reset-names
+
additionalProperties: false
examples:
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-06-15 6:49 ` [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants Joey Lu
@ 2026-06-15 6:49 ` Joey Lu
2026-06-15 8:24 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:49 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>
---
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 c7930e817635..d4da22b08cd5 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 cbb125c46b39..67d4b00f294e 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 related [flat|nested] 13+ messages in thread
* [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-06-15 6:49 ` [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants Joey Lu
2026-06-15 6:49 ` [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu
@ 2026-06-15 6:50 ` Joey Lu
2026-06-15 8:37 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:50 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 enum vs_dc_generation (VSDC_GEN_DC8000 / VSDC_GEN_DC8200) to
vs_hwdb.h and a generation field to struct vs_chip_identity. Annotate
all four existing DC8200 HWDB entries with VSDC_GEN_DC8200.
Extract the DC8200-specific hardware ops into a new vs_dc8200.c:
panel_enable_ex / panel_disable_ex - PANEL_CONFIG/START + CONFIG_EX commit
enable_vblank / disable_vblank - TOP_IRQ_EN VSYNC bit
primary_plane_enable_ex / disable_ex / update_ex - FB_CONFIG_EX path
irq_ack - reads TOP_IRQ_ACK
Update vs_bridge.c, vs_crtc.c, vs_primary_plane.c and vs_dc.c to
dispatch through dc->funcs instead of directly touching registers.
vs_crtc.c gains atomic_begin and atomic_flush hooks to allow variants
to gate per-frame commit cycles.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
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 | 107 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
9 files changed, 196 insertions(+), 51 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 426f4bcaa834..9d4cd16452fa 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 7a93049368db..6ff2ac745b15 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 0b8a35d09cd2..679d6541ba1b 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)
+ dc->funcs->crtc_disable(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)
+ dc->funcs->crtc_enable(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 dad9967bc10b..9729b693d360 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 ed1016f18758..544e1a37065b 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)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable)(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 000000000000..800df9279e9b
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.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 irqs;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ return irqs;
+}
+
+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_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 2a0f7c59afa3..91524d16f778 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 2065ecb73043..a15c8b565604 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 1f2be41ae496..f992cb277f61 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -53,12 +53,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)
{
@@ -69,13 +63,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,
@@ -88,10 +77,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,
@@ -133,18 +120,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 related [flat|nested] 13+ messages in thread
* [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (2 preceding siblings ...)
2026-06-15 6:50 ` [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
@ 2026-06-15 6:50 ` Joey Lu
2026-06-15 8:51 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
2026-06-15 6:50 ` [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:50 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 SoC integrates a Verisilicon DCUltraLite display
controller whose register layout differs from the DC8200 in several
important ways:
1. No CONFIG_EX commit path: framebuffer updates use the enable (bit 0)
and reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging
registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
FB_BLEND_CONFIG, PANEL_CONFIG_EX).
2. No PANEL_START register: panel output starts when
PANEL_CONFIG.RUNNING is set; there is no multi-display sync start
register.
3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA (0x147C) /
DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
TOP_IRQ_EN (0x0014).
4. Per-frame commit cycle: DCUltraLite requires the VALID bit in
FB_CONFIG to be set at the start of each atomic commit (crtc_begin)
and cleared after (crtc_flush).
5. Simpler clock topology: only 'core' (bus gate) and 'pix0' (pixel
divider) clocks; no axi or ahb clocks required. Make axi_clk and
ahb_clk optional (devm_clk_get_optional_enabled) so DC8000 nodes
without those clocks are handled gracefully.
Add vs_dc8000.c implementing the vs_dc_funcs vtable for the above
differences. The probe now selects vs_dc8000_funcs when the identified
generation is VSDC_GEN_DC8000 (DCUltraLite reads model 0x0,
revision 0x5560, customer_id 0x305).
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc8000.c | 78 +++++++++++++++++++++++++
4 files changed, 86 insertions(+), 4 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 9d4cd16452fa..d2fd8e4dff24 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 9729b693d360..9499fffbca58 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->core_clk);
}
- dc->axi_clk = devm_clk_get_enabled(dev, "axi");
+ dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
if (IS_ERR(dc->axi_clk)) {
dev_err(dev, "can't get axi clock\n");
return PTR_ERR(dc->axi_clk);
}
- dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
+ dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
if (IS_ERR(dc->ahb_clk)) {
dev_err(dev, "can't get ahb clock\n");
return PTR_ERR(dc->ahb_clk);
@@ -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 544e1a37065b..5218e8cf63e2 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 000000000000..be0c0d7baf52
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8000.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.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(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(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 irqs;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &irqs);
+ return irqs;
+}
+
+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 = vs_dc8000_crtc_enable,
+ .crtc_disable = vs_dc8000_crtc_disable,
+ .enable_vblank = vs_dc8000_enable_vblank,
+ .disable_vblank = vs_dc8000_disable_vblank,
+ .irq_ack = vs_dc8000_irq_ack,
+};
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (3 preceding siblings ...)
2026-06-15 6:50 ` [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
@ 2026-06-15 6:50 ` Joey Lu
2026-06-15 8:57 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:50 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
Register the Nuvoton MA35D1 DCUltraLite chip identity in
vs_chip_identities[]:
model = 0x0 (DCUltraLite; Verisilicon uses 0 for this IP)
revision = 0x5560
customer_id = 0x305
generation = VSDC_GEN_DC8000
display_count = 1
max_cursor_size = 32
Placing this entry last makes it the gate that enables MA35D1 hardware
recognition only after all the supporting ops and DT binding changes are
in place.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
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 91524d16f778..7d630a667a3f 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 related [flat|nested] 13+ messages in thread
* [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
` (4 preceding siblings ...)
2026-06-15 6:50 ` [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
@ 2026-06-15 6:50 ` Joey Lu
2026-06-15 8:58 ` Icenowy Zheng
5 siblings, 1 reply; 13+ messages in thread
From: Joey Lu @ 2026-06-15 6:50 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 DCUltraLite hardware ops and HWDB entry added in the preceding commits
enable the driver to work on Nuvoton MA35D1 hardware. Allow the driver
to be built when ARCH_MA35 is selected; this dependency is meaningful only
now that all supporting code is in place.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
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 7cce86ec8603..295d246eb4b4 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 related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/6] dt-bindings: display: verisilicon, dc: generalize for single-output variants
2026-06-15 6:49 ` [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants Joey Lu
@ 2026-06-15 8:19 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8:19 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-06-15一的 14:49 +0800,Joey Lu写道:
> The existing schema hard-codes the five-clock/three-reset/dual-port
> topology of the DC8200 IP block, preventing reuse for single-output
> variants such as the Verisilicon DCUltraLite used in the Nuvoton
> MA35D1
> SoC.
>
> Rework the schema so that variant-specific constraints are expressed
> via
> allOf/if blocks:
>
> - Add nuvoton,ma35d1-dcu to the SoC-specific compatible enum. The
> generic verisilicon,dc fallback remains the driver-binding string.
> - Move clock and reset items descriptions into the per-variant
> allOf/if
> blocks; keep only minItems/maxItems at the top level so the base
> schema
> accepts all variants.
> - Restore full items lists for clock-names and reset-names at the top
> level with minItems so the names are validated against the
> descriptions.
> - Keep ports in the global required list and keep
> additionalProperties: false.
> - Add an allOf/if block for thead,th1520-dc8200: five-clock (core,
> axi,
> ahb, pix0, pix1), three-reset (core, axi, ahb), required resets.
> - Add an allOf/if block for nuvoton,ma35d1-dcu: two-clock (core,
> pix0),
> one-reset (core), required resets.
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> .../bindings/display/verisilicon,dc.yaml | 80
> +++++++++++++++++--
> 1 file changed, 73 insertions(+), 7 deletions(-)
>
> diff --git
> a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> index 9dc35ab973f2..0c41286b8223 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,14 +27,12 @@ properties:
> maxItems: 1
>
> clocks:
> - items:
> - - description: DC Core clock
> - - description: DMA AXI bus clock
> - - description: Configuration AHB bus clock
> - - description: Pixel clock of output 0
> - - description: Pixel clock of output 1
Clock descriptions should still be in the global part instead of the
per-compatible part.
In the per-compatible part, clock-names should be constraint for SoCs.
> + minItems: 2
> + maxItems: 5
>
> clock-names:
> + minItems: 2
> + maxItems: 5
> items:
> - const: core
> - const: axi
> @@ -42,12 +41,16 @@ properties:
> - const: pix1
>
> resets:
> + minItems: 1
> + maxItems: 3
> items:
> - description: DC Core reset
> - description: DMA AXI bus reset
> - description: Configuration AHB bus reset
>
> reset-names:
> + minItems: 1
> + maxItems: 3
> items:
> - const: core
> - const: axi
> @@ -59,7 +62,7 @@ properties:
> properties:
> port@0:
> $ref: /schemas/graph.yaml#/properties/port
> - description: The first output channel , endpoint 0 should be
> + description: The first output channel, endpoint 0 should be
If you really want to fix this, please make it a separated patch
instead of doing it here, for commit atomicity.
Thanks,
Icenowy
> used for DPI format output and endpoint 1 should be used
> for DP format output.
>
> @@ -77,6 +80,69 @@ required:
> - clock-names
> - ports
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: thead,th1520-dc8200
> + then:
> + properties:
> + clocks:
> + minItems: 5
> + maxItems: 5
> + items:
> + - description: DC Core clock
> + - description: DMA AXI bus clock
> + - description: Configuration AHB bus clock
> + - description: Pixel clock of output 0
> + - description: Pixel clock of output 1
> +
> + clock-names:
> + minItems: 5
> + maxItems: 5
> +
> + resets:
> + minItems: 3
> + maxItems: 3
> +
> + reset-names:
> + minItems: 3
> + maxItems: 3
> +
> + required:
> + - resets
> + - reset-names
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: nuvoton,ma35d1-dcu
> + then:
> + properties:
> + clocks:
> + minItems: 2
> + maxItems: 2
> + items:
> + - description: DC Core clock
> + - description: Pixel clock of output 0
> +
> + clock-names:
> + minItems: 2
> + maxItems: 2
> +
> + resets:
> + minItems: 1
> + maxItems: 1
> +
> + reset-names:
> + maxItems: 1
> +
> + required:
> + - resets
> + - reset-names
> +
> additionalProperties: false
>
> examples:
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000
2026-06-15 6:49 ` [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu
@ 2026-06-15 8:24 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8:24 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-06-15一的 14:49 +0800,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.
Validated against DC8000 register list.
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
>
> No behaviour change for existing DC8200 platforms.
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> 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 c7930e817635..d4da22b08cd5 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 cbb125c46b39..67d4b00f294e 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)
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table
2026-06-15 6:50 ` [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
@ 2026-06-15 8:37 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8:37 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-06-15一的 14:50 +0800,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 enum vs_dc_generation (VSDC_GEN_DC8000 / VSDC_GEN_DC8200) to
> vs_hwdb.h and a generation field to struct vs_chip_identity.
> Annotate
> all four existing DC8200 HWDB entries with VSDC_GEN_DC8200.
>
> Extract the DC8200-specific hardware ops into a new vs_dc8200.c:
> panel_enable_ex / panel_disable_ex - PANEL_CONFIG/START + CONFIG_EX
> commit
> enable_vblank / disable_vblank - TOP_IRQ_EN VSYNC bit
> primary_plane_enable_ex / disable_ex / update_ex - FB_CONFIG_EX
> path
> irq_ack - reads TOP_IRQ_ACK
>
> Update vs_bridge.c, vs_crtc.c, vs_primary_plane.c and vs_dc.c to
> dispatch through dc->funcs instead of directly touching registers.
> vs_crtc.c gains atomic_begin and atomic_flush hooks to allow variants
> to gate per-frame commit cycles.
>
> No behaviour change for existing DC8200 platforms.
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> 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 | 107
> ++++++++++++++++++
> drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
> drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
> .../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
> 9 files changed, 196 insertions(+), 51 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 426f4bcaa834..9d4cd16452fa 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 7a93049368db..6ff2ac745b15 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 0b8a35d09cd2..679d6541ba1b 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)
> + dc->funcs->crtc_disable(dc, output);
Should this be `crtc_disable_ex` ? Because the clock-related operation
is shared.
> }
>
> 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)
> + dc->funcs->crtc_enable(dc, output);
Ditto for appending `_ex` .
> +
> 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 dad9967bc10b..9729b693d360 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);
The definition of bits in 0x0010 seems to be different to ones in
0x147C, although the first 2 bits are the same. (e.g. `BIT(2)` is
"cursor interrupt" in DC8000 0x147C but "secure reset done" in DC8200
0x0010).
Should some kind of translation be done in `irq_ack` ? (and add a
unified interrupt definition that aims to be the translation target).
Thanks,
Icenowy
>
> 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 ed1016f18758..544e1a37065b 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)(struct vs_dc *dc, unsigned int output);
> + void (*crtc_disable)(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 000000000000..800df9279e9b
> --- /dev/null
> +++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
> + */
> +
> +#include <linux/regmap.h>
> +
> +#include "vs_bridge_regs.h"
> +#include "vs_dc.h"
> +#include "vs_dc_top_regs.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 irqs;
> +
> + regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
> + return irqs;
> +}
> +
> +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_hwdb.c
> b/drivers/gpu/drm/verisilicon/vs_hwdb.c
> index 2a0f7c59afa3..91524d16f778 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 2065ecb73043..a15c8b565604 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 1f2be41ae496..f992cb277f61 100644
> --- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> +++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
> @@ -53,12 +53,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)
> {
> @@ -69,13 +63,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,
> @@ -88,10 +77,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,
> @@ -133,18 +120,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 = {
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
2026-06-15 6:50 ` [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
@ 2026-06-15 8:51 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8:51 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-06-15一的 14:50 +0800,Joey Lu写道:
> The Nuvoton MA35D1 SoC integrates a Verisilicon DCUltraLite display
> controller whose register layout differs from the DC8200 in several
> important ways:
>
> 1. No CONFIG_EX commit path: framebuffer updates use the enable (bit
> 0)
> and reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging
> registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
> FB_BLEND_CONFIG, PANEL_CONFIG_EX).
>
> 2. No PANEL_START register: panel output starts when
> PANEL_CONFIG.RUNNING is set; there is no multi-display sync start
> register.
>
> 3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA (0x147C) /
> DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
> TOP_IRQ_EN (0x0014).
>
> 4. Per-frame commit cycle: DCUltraLite requires the VALID bit in
> FB_CONFIG to be set at the start of each atomic commit
> (crtc_begin)
> and cleared after (crtc_flush).
>
> 5. Simpler clock topology: only 'core' (bus gate) and 'pix0' (pixel
> divider) clocks; no axi or ahb clocks required. Make axi_clk and
> ahb_clk optional (devm_clk_get_optional_enabled) so DC8000 nodes
> without those clocks are handled gracefully.
>
> Add vs_dc8000.c implementing the vs_dc_funcs vtable for the above
> differences. The probe now selects vs_dc8000_funcs when the
> identified
> generation is VSDC_GEN_DC8000 (DCUltraLite reads model 0x0,
> revision 0x5560, customer_id 0x305).
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> drivers/gpu/drm/verisilicon/Makefile | 2 +-
> drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
> drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
> drivers/gpu/drm/verisilicon/vs_dc8000.c | 78
> +++++++++++++++++++++++++
> 4 files changed, 86 insertions(+), 4 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 9d4cd16452fa..d2fd8e4dff24 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 9729b693d360..9499fffbca58 100644
> --- a/drivers/gpu/drm/verisilicon/vs_dc.c
> +++ b/drivers/gpu/drm/verisilicon/vs_dc.c
> @@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device
> *pdev)
> return PTR_ERR(dc->core_clk);
> }
>
> - dc->axi_clk = devm_clk_get_enabled(dev, "axi");
> + dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
> if (IS_ERR(dc->axi_clk)) {
> dev_err(dev, "can't get axi clock\n");
> return PTR_ERR(dc->axi_clk);
> }
>
> - dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
> + dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
Please make the clock change a separated patch for atomicity.
BTW the MA35D1 manual's clock tree shows that DCUltra appears on AXI2
ACLK, AHB_HCLK2, behind a mux of SYS-PLL/EPLL-DIV2 (which seems to be
the core clock), and behind a divider (which seems to be the pixel
clock).
However it's weird that only one DCUltra Clock Enable Bit exists
despite both bus clocks have "ICG" (I think it means "Integrated Clock
Gating"). In addition the linux clk-ma35d1 driver assigns "dcu_gate" as
a downstream of "dcu_mux", although the Figure 6.5-2 in the TRM shows
no ICG after the "Display core CLK" mux.
Is the two bus clocks controlled by a single gate bit, and is the bit
also gating DC core clock?
Thanks,
Icenowy
> if (IS_ERR(dc->ahb_clk)) {
> dev_err(dev, "can't get ahb clock\n");
> return PTR_ERR(dc->ahb_clk);
> @@ -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 544e1a37065b..5218e8cf63e2 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 000000000000..be0c0d7baf52
> --- /dev/null
> +++ b/drivers/gpu/drm/verisilicon/vs_dc8000.c
> @@ -0,0 +1,78 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
> + */
> +
> +#include <linux/regmap.h>
> +
> +#include "vs_crtc_regs.h"
> +#include "vs_dc.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(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(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 irqs;
> +
> + regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &irqs);
> + return irqs;
> +}
> +
> +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 = vs_dc8000_crtc_enable,
> + .crtc_disable = vs_dc8000_crtc_disable,
> + .enable_vblank = vs_dc8000_enable_vblank,
> + .disable_vblank = vs_dc8000_disable_vblank,
> + .irq_ack = vs_dc8000_irq_ack,
> +};
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB
2026-06-15 6:50 ` [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
@ 2026-06-15 8:57 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8: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
在 2026-06-15一的 14:50 +0800,Joey Lu写道:
> Register the Nuvoton MA35D1 DCUltraLite chip identity in
> vs_chip_identities[]:
> model = 0x0 (DCUltraLite; Verisilicon uses 0 for this IP)
> revision = 0x5560
> customer_id = 0x305
> generation = VSDC_GEN_DC8000
> display_count = 1
> max_cursor_size = 32
I suggest make this more human-readable instead of replicating the
machine-readable data of HWDB.
My proposal here:
```
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.
```
>
> Placing this entry last makes it the gate that enables MA35D1
> hardware
> recognition only after all the supporting ops and DT binding changes
> are
> in place.
It's a little ambiguous that "last" here means whether the last in the
patchset or the last in the HWDB array, although I think it's not so
needed to explain the reason of the place in the patchset.
I propose just say `Adding it to the HWDB to enable it to be usable
with the verisilicon driver.` .
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> 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 91524d16f778..7d630a667a3f 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,
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
2026-06-15 6:50 ` [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
@ 2026-06-15 8:58 ` Icenowy Zheng
0 siblings, 0 replies; 13+ messages in thread
From: Icenowy Zheng @ 2026-06-15 8:58 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-06-15一的 14:50 +0800,Joey Lu写道:
> The DCUltraLite hardware ops and HWDB entry added in the preceding
> commits
> enable the driver to work on Nuvoton MA35D1 hardware. Allow the
> driver
> to be built when ARCH_MA35 is selected; this dependency is meaningful
> only
> now that all supporting code is in place.
The explaination of patch sequence is not needed, but anyway,
`Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>`
Thanks,
Icenowy
>
> Signed-off-by: Joey Lu <a0987203069@gmail.com>
> ---
> 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 7cce86ec8603..295d246eb4b4 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
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-06-15 8:59 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-15 6:49 [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu
2026-06-15 6:49 ` [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants Joey Lu
2026-06-15 8:19 ` [PATCH v4 1/6] dt-bindings: display: verisilicon, dc: " Icenowy Zheng
2026-06-15 6:49 ` [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu
2026-06-15 8:24 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu
2026-06-15 8:37 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu
2026-06-15 8:51 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu
2026-06-15 8:57 ` Icenowy Zheng
2026-06-15 6:50 ` [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu
2026-06-15 8:58 ` Icenowy Zheng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox