* [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
@ 2026-09-08 9:28 Joey Lu
2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: Joey Lu @ 2026-09-08 9:28 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.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v5:
- [dt-bindings] Renamed the patch from "generalize for single-output
variants" to "add support for nuvoton,ma35d1-dcu", since the binding
topology itself isn't being generalised, only a new compatible is
being added.
- [dt-bindings] Moved clocks/clock-names minItems to 4 and
resets/reset-names minItems to 1 at the top level (the lowest count
any variant needs), instead of overriding both minItems and maxItems
redundantly inside each allOf/if block.
- [dt-bindings] Kept the thead,th1520-dc8200 allOf/if block, tightening
it back up to minItems: 5 (clocks) / minItems: 3 (resets), since the
outer constraint is now looser than what that compatible requires.
- [dt-bindings] Dropped the nuvoton,ma35d1-dcu clock-names/reset-names
item overrides entirely: the devicetree will supply all four clocks
(core, axi, ahb, pix0) and the one core reset in the same order the
top-level schema already expects, so only maxItems: 4 / maxItems: 1
are needed to cap the count.
- [dt-bindings] Dropped the redundant "required: resets/reset-names"
sub-blocks, now that resets/reset-names are unconditionally required
at the top level (landed separately by Icenowy Zheng).
- [driver] Dropped "make axi and ahb clocks optional" entirely: since
the devicetree will always supply distinct axi/ahb clock properties
(sharing the core clock's phandle), vs_dc_probe() keeps treating them
as mandatory via devm_clk_get_enabled(), same as core and pix0.
- [driver] Added drm_WARN_ONCE() in both vs_dc8200_irq_ack() and
vs_dc8000_irq_ack() to flag any hardware IRQ bit that doesn't
translate to a known VSDC_IRQ_* definition.
Joey Lu (6):
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
.../bindings/display/verisilicon,dc.yaml | 44 +++++++
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, 375 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] 17+ messages in thread* [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 9:36 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu sashiko-bot ` (2 more replies) 2026-09-08 9:28 ` [PATCH v6 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu ` (4 subsequent siblings) 5 siblings, 3 replies; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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 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. Signed-off-by: Joey Lu <a0987203069@gmail.com> --- .../bindings/display/verisilicon,dc.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml index 919a900122012..773966677d0f4 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,45 @@ 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 + additionalProperties: false examples: -- 2.43.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu @ 2026-09-08 9:36 ` sashiko-bot 2026-09-08 17:55 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Conor Dooley 2026-09-09 5:44 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng 2 siblings, 0 replies; 17+ messages in thread From: sashiko-bot @ 2026-09-08 9:36 UTC (permalink / raw) To: Joey Lu; +Cc: robh, conor+dt, dri-devel, devicetree Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] The schema fails to restrict the `ports` property to prevent `port@1` for the `nuvoton,ma35d1-dcu` compatible, despite the hardware only having a single output port. -- commit aa050e9da3d62c01f3875ac6fea01c9b0fc78e94 Author: Joey Lu <a0987203069@gmail.com> dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu This commit adds support for the Nuvoton MA35D1 DCUltraLite in the verisilicon,dc binding. It adjusts the global minimum clocks and resets, and applies specific topology limits for supported variants via an allOf block. > diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > --- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > +++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml [ ... ] > @@ -79,6 +84,45 @@ required: [ ... ] > + - if: > + properties: > + compatible: > + contains: > + const: nuvoton,ma35d1-dcu > + then: > + properties: > + clocks: > + maxItems: 4 > + > + clock-names: > + maxItems: 4 > + > + resets: > + maxItems: 1 > + > + reset-names: > + maxItems: 1 [Severity: Low] Does this conditional block also need to restrict the ports property? The commit message notes that the DCUltraLite has a single output port, but the schema doesn't restrict port@1 from being used for the nuvoton,ma35d1-dcu compatible. Without disallowing the non-existent second output port here, an invalid device tree specifying port@1 would silently pass static schema validation. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908092840.225220-1-a0987203069@gmail.com?part=1 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton,ma35d1-dcu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu 2026-09-08 9:36 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu sashiko-bot @ 2026-09-08 17:55 ` Conor Dooley 2026-09-09 5:44 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng 2 siblings, 0 replies; 17+ messages in thread From: Conor Dooley @ 2026-09-08 17:55 UTC (permalink / raw) To: Joey Lu Cc: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied, simona, robh, krzk+dt, conor+dt, ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 75 bytes --] Acked-by: Conor Dooley <conor.dooley@microchip.com> pw-bot: not-applicable [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu 2026-09-08 9:36 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu sashiko-bot 2026-09-08 17:55 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Conor Dooley @ 2026-09-09 5:44 ` Icenowy Zheng 2026-09-10 1:52 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Joey Lu 2 siblings, 1 reply; 17+ messages in thread From: Icenowy Zheng @ 2026-09-09 5:44 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-08二的 17:28 +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. This is weird, but I must admit that we're limited by the Common Clock Framework here, so I cannot give a better solution either. Anyway let's settle with the current result. > > 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. > > Signed-off-by: Joey Lu <a0987203069@gmail.com> > --- > .../bindings/display/verisilicon,dc.yaml | 44 > +++++++++++++++++++ > 1 file changed, 44 insertions(+) > > diff --git > a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > index 919a900122012..773966677d0f4 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,45 @@ 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 Maybe it's reasonable to restrict max port count to 1 for MA35D1? Although I am not sure about how to do this... Thanks, Icenowy > + > additionalProperties: false > > examples: ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton,ma35d1-dcu 2026-09-09 5:44 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng @ 2026-09-10 1:52 ` Joey Lu 2026-09-10 7:08 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng 0 siblings, 1 reply; 17+ messages in thread From: Joey Lu @ 2026-09-10 1:52 UTC (permalink / raw) To: Icenowy Zheng, maarten.lankhorst, mripard, tzimmermann, airlied, simona, robh, krzk+dt, conor+dt Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel, linux-kernel Icenowy Zheng 於 2026/9/9 下午 01:44 寫道: > 在 2026-09-08二的 17:28 +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. > This is weird, but I must admit that we're limited by the Common Clock > Framework here, so I cannot give a better solution either. > > Anyway let's settle with the current result. > >> 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. >> >> Signed-off-by: Joey Lu <a0987203069@gmail.com> >> --- >> .../bindings/display/verisilicon,dc.yaml | 44 >> +++++++++++++++++++ >> 1 file changed, 44 insertions(+) >> >> diff --git >> a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml >> b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml >> index 919a900122012..773966677d0f4 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,45 @@ 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 > Maybe it's reasonable to restrict max port count to 1 for MA35D1? > Although I am not sure about how to do this... > > Thanks, > Icenowy I found the same kind of per-compatible port restriction already used upstream in renesas,du.yaml, e.g.: ports: properties: port@2: false port@3: false required: - port@0 - port@1 Applied to our binding, that would look like: ports: properties: port@1: false required: - port@0 in the existing nuvoton,ma35d1-dcu allOf/if/then block, so schema checks would reject a port@1 node on this compatible instead of silently accepting it. Happy to add it if you'd like the schema to enforce this, but wanted to check whether you consider it worth the extra lines given it doesn't reflect an actual bug in any DT today. Let me know which way you'd prefer and I'll fold it into the next version. Thanks. >> + >> additionalProperties: false >> >> examples: ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu 2026-09-10 1:52 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Joey Lu @ 2026-09-10 7:08 ` Icenowy Zheng 0 siblings, 0 replies; 17+ messages in thread From: Icenowy Zheng @ 2026-09-10 7:08 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-10四的 09:52 +0800,Joey Lu写道: > > Icenowy Zheng 於 2026/9/9 下午 01:44 寫道: > > 在 2026-09-08二的 17:28 +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. > > This is weird, but I must admit that we're limited by the Common > > Clock > > Framework here, so I cannot give a better solution either. > > > > Anyway let's settle with the current result. > > > > > 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. > > > > > > Signed-off-by: Joey Lu <a0987203069@gmail.com> > > > --- > > > .../bindings/display/verisilicon,dc.yaml | 44 > > > +++++++++++++++++++ > > > 1 file changed, 44 insertions(+) > > > > > > diff --git > > > a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > > > b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml > > > index 919a900122012..773966677d0f4 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,45 @@ 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 > > Maybe it's reasonable to restrict max port count to 1 for MA35D1? > > Although I am not sure about how to do this... > > > > Thanks, > > Icenowy > I found the same kind of per-compatible port restriction already > used > upstream in renesas,du.yaml, e.g.: > > ports: > properties: > port@2: false > port@3: false > required: > - port@0 > - port@1 > > Applied to our binding, that would look like: > > ports: > properties: > port@1: false > required: > - port@0 > > in the existing nuvoton,ma35d1-dcu allOf/if/then block, so schema > checks > would reject a port@1 node on this compatible instead of silently > accepting it. > > Happy to add it if you'd like the schema to enforce this, but wanted > to > check whether you consider it worth the extra lines given it doesn't > reflect an actual bug in any DT today. Let me know which way you'd > prefer and I'll fold it into the next version. Personally I think this is good, but maybe adding it as an additional patch after merging isn't a big problem, because this just plays as kind of a safety guard. Well this depends on how DT binding maintainers think, but as Conor has dropped his Ack, this shouldn't be a big issue. Thanks, Icenowy > > Thanks. > > > + > > > additionalProperties: false > > > > > > examples: ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v6 2/6] drm/verisilicon: add register-level macros for DC8000 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 9:28 ` [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu ` (3 subsequent siblings) 5 siblings, 0 replies; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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 related [flat|nested] 17+ messages in thread
* [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu 2026-09-08 9:28 ` [PATCH v6 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 9:51 ` sashiko-bot 2026-09-08 9:28 ` [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu ` (2 subsequent siblings) 5 siblings, 1 reply; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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..2d4bf6af1f56e 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..77752d0cb28b0 --- /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 2750016a7f2c3..85ba2068172db 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 related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table 2026-09-08 9:28 ` [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu @ 2026-09-08 9:51 ` sashiko-bot 0 siblings, 0 replies; 17+ messages in thread From: sashiko-bot @ 2026-09-08 9:51 UTC (permalink / raw) To: Joey Lu; +Cc: conor+dt, dri-devel, devicetree, robh Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: New issues: - [High] Variant-specific CRTC disable hook (`crtc_disable_ex`) is called after disabling the pixel clock, leading to hardware faults. - [High] The panel disable sequence in `vs_dc8200_panel_disable_ex` reverses the order of clearing CONFIG and START registers, violating the original sequence and hardware state machine. Pre-existing issues: - [High] Primary plane disable function incorrectly sets the plane enable bit instead of clearing it. - [High] IRQ handler is registered before DRM device initialization is complete, causing a potential NULL pointer dereference on early interrupts. - [High] Sleeping clock functions (`clk_prepare_enable`, `clk_disable_unprepare`) are called from CRTC atomic callbacks, violating DRM atomic context requirements. -- commit c35af4d919e849e303afa29d897c4d1581720138 Author: Joey Lu <a0987203069@gmail.com> drm/verisilicon: introduce per-variant hardware ops table This commit introduces a hardware ops table for the Verisilicon DC driver to handle variant-specific implementations. It extracts DC8200-specific ops into a new file and updates the shared code to dispatch hardware sequences through the new function pointers. The patch aims to avoid scattering variant checks across the core driver. > diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c > --- a/drivers/gpu/drm/verisilicon/vs_crtc.c > +++ b/drivers/gpu/drm/verisilicon/vs_crtc.c > @@ -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]); [Severity: High] This is a pre-existing issue, but calling clk_disable_unprepare() here sleeps in an atomic context, which is forbidden during non-blocking commits and can lead to system instability. > + > + if (dc->funcs->crtc_disable_ex) > + dc->funcs->crtc_disable_ex(dc, output); [Severity: High] Will this sequence cause hardware faults? The pixel clock is disabled via clk_disable_unprepare() right before calling the variant-specific crtc_disable_ex() callback. If follow-up implementations of crtc_disable_ex() attempt to access hardware registers within the now-disabled pixel clock domain, it could trigger an asynchronous external abort or bus error when userspace disables the display. Should the callback be invoked before disabling the clock? > } > > 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])); [Severity: High] This is a pre-existing issue, but does calling clk_prepare_enable() from vs_crtc_atomic_enable() violate the DRM atomic context requirements? The clock framework functions clk_prepare_enable() and clk_disable_unprepare() can sleep. Since CRTC atomic enable, disable, and update callbacks run in an atomic context during non-blocking commits, this can cause scheduling while atomic warnings and system instability during userspace modesets. > + if (dc->funcs->crtc_enable_ex) > + dc->funcs->crtc_enable_ex(dc, output); > + > drm_crtc_vblank_on(crtc); > } [ ... ] > diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c > --- /dev/null > +++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c > @@ -0,0 +1,121 @@ [ ... ] > +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)); [Severity: High] Does this reverse the original tear-down sequence? In the original vs_bridge_atomic_disable() code, VSDC_DISP_PANEL_START_RUNNING was cleared before clearing VSDC_DISP_PANEL_CONFIG_RUNNING. Here in vs_dc8200_panel_disable_ex(), VSDC_DISP_PANEL_CONFIG_RUNNING is cleared first. Modifying or clearing a pipeline's configuration while it is actively sending pixels could put the hardware into an invalid state and cause synchronization errors. > + > + regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output), > + VSDC_DISP_PANEL_CONFIG_EX_COMMIT); > +} [ ... ] > +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); [Severity: High] This is a pre-existing issue, but does this function actually enable the plane instead of disabling it? The code uses regmap_set_bits() to write a 1 to VSDC_FB_CONFIG_EX_FB_EN, which sets the enable bit. This could leave the primary plane active on the screen when userspace expects it to be hidden via vs_dc8200_primary_plane_disable_ex(). > + > + 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); [Severity: High] This is a pre-existing issue, but could this drm_WARN_ONCE() trigger a NULL pointer dereference during boot? In vs_dc_probe(), the IRQ handler is requested via devm_request_irq() before vs_drm_initialize() is called to allocate the DRM device. If a residual boot interrupt fires during this window, vs_dc_irq_handler() will run and call vs_dc8200_irq_ack() while dc->drm_dev is still NULL, causing the warning macro to dereference NULL. > + > + return unified; > +} -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908092840.225220-1-a0987203069@gmail.com?part=3 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu ` (2 preceding siblings ...) 2026-09-08 9:28 ` [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 10:04 ` sashiko-bot 2026-09-10 7:25 ` Icenowy Zheng 2026-09-08 9:28 ` [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu 2026-09-08 9:28 ` [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu 5 siblings, 2 replies; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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> --- 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 related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support 2026-09-08 9:28 ` [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu @ 2026-09-08 10:04 ` sashiko-bot 2026-09-10 7:25 ` Icenowy Zheng 1 sibling, 0 replies; 17+ messages in thread From: sashiko-bot @ 2026-09-08 10:04 UTC (permalink / raw) To: Joey Lu; +Cc: dri-devel, devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: New issues: - [High] The `vs_dc8000_panel_enable_ex` and `vs_dc8000_panel_disable_ex` functions incorrectly modify the `VSDC_FB_CONFIG` register using the `VSDC_FB_CONFIG_RESET` bit, instead of setting the `PANEL_CONFIG.RUNNING` bit. - [High] The `vs_dc8000_crtc_begin` and `vs_dc8000_crtc_flush` functions have inverted logic for the `VSDC_FB_CONFIG_VALID` bit. - [Medium] The `vs_dc8000_irq_ack` function reads `VSDC_DISP_IRQ_STA` but fails to perform any hardware write to clear the pending hardware interrupts. Pre-existing issues: - [High] Early interrupt registration in `vs_dc_probe` causes a NULL pointer dereference if an interrupt fires before DRM initialization is complete. -- commit 71018d22eb0156b0806e61d4495897f9c4f2d35b Author: Joey Lu <a0987203069@gmail.com> drm/verisilicon: add DC8000 (DCUltraLite) display controller support This commit adds support for the DC8000 (DCUltraLite) display controller generation to the Verisilicon DRM driver. It introduces a new vs_dc_funcs implementation that directly latches framebuffer updates through FB_CONFIG, handles panel output, and acknowledges VSYNC interrupts. > 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 @@ [ ... ] > +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); > +} [Severity: High] The commit message states that "panel output starts as soon as PANEL_CONFIG.RUNNING is set", but vs_dc8000_panel_enable_ex() and vs_dc8000_panel_disable_ex() modify VSDC_FB_CONFIG with the VSDC_FB_CONFIG_RESET bit instead of setting the PANEL_CONFIG.RUNNING bit. Will this cause the panel output to never start and inadvertently hold the framebuffer in 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); > +} [Severity: High] Does this invert the logic for the VSDC_FB_CONFIG_VALID bit? By asserting validity in vs_dc8000_crtc_begin() before plane register updates occur, and de-asserting it in vs_dc8000_crtc_flush() after the plane state is written, could this prevent the hardware from latching the correct configuration and lead to visual corruption? [ ... ] > +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); [Severity: Medium] The commit message implies the VSYNC interrupt is acknowledged through DISP_IRQ_STA/DISP_IRQ_EN, but vs_dc8000_irq_ack() only reads from VSDC_DISP_IRQ_STA without performing any hardware write to clear the pending interrupts. If the register does not auto-clear on read, could this missing clear mechanism cause an interrupt storm and hang the system? > + > + 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); [Severity: High] This is a pre-existing issue, but in vs_dc_probe() the interrupt line is registered and unmasked via devm_request_irq() before vs_drm_initialize() is called. If an interrupt fires early (e.g. left over from the bootloader), vs_dc8000_irq_ack() will be called while dc->drm_dev is still NULL, causing a NULL pointer dereference when accessing &dc->drm_dev->base here. Can the interrupt registration be deferred until DRM initialization is complete? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908092840.225220-1-a0987203069@gmail.com?part=4 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support 2026-09-08 9:28 ` [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu 2026-09-08 10:04 ` sashiko-bot @ 2026-09-10 7:25 ` Icenowy Zheng 1 sibling, 0 replies; 17+ messages in thread From: Icenowy Zheng @ 2026-09-10 7:25 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-08二的 17:28 +0800,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> Thanks, Icenowy > --- > 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, > +}; ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu ` (3 preceding siblings ...) 2026-09-08 9:28 ` [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 10:15 ` sashiko-bot 2026-09-08 9:28 ` [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu 5 siblings, 1 reply; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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 related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB 2026-09-08 9:28 ` [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu @ 2026-09-08 10:15 ` sashiko-bot 0 siblings, 0 replies; 17+ messages in thread From: sashiko-bot @ 2026-09-08 10:15 UTC (permalink / raw) To: Joey Lu; +Cc: robh, conor+dt, devicetree, dri-devel Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Negative cursor coordinates are programmed incorrectly because the offset values are not shifted before being passed to regmap_update_bits(). -- commit 71dc0bfa33a2021c1ba93da0095ed32939fb4009 Author: Joey Lu <a0987203069@gmail.com> drm/verisilicon: add DCUltraLite chip identity to HWDB 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. > 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, > + }, > }; [Severity: High] This isn't a bug introduced by this patch, but while reviewing the cursor handling code related to this new controller, I noticed an issue with how negative cursor coordinates are programmed. Looking at vs_cursor_plane_atomic_update() in drivers/gpu/drm/verisilicon/vs_cursor_plane.c, when handling negative X coordinates: } else { regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output), VSDC_CURSOR_CONFIG_X_OFF_MASK, -state->crtc_x); regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output), VSDC_CURSOR_LOCATION_X_MASK, 0); } Is the unshifted X offset (-state->crtc_x) completely masked out to 0 by regmap_update_bits() because it lacks the necessary shift macro (like VSDC_CURSOR_CONFIG_X_OFF)? Similarly, for the Y coordinate: } else { regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output), VSDC_CURSOR_CONFIG_Y_OFF_MASK, -state->crtc_y); regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output), VSDC_CURSOR_LOCATION_Y_MASK, 0); } Does this also cause the unshifted Y offset (-state->crtc_y) to be masked out to 0? When the cursor is moved off the left or top edge of the screen, the hardware offset is intended to clip the cursor. However, if the unshifted offset value is masked out by regmap_update_bits(), it results in an offset of 0. This would cause the cursor to stick at the edge of the screen fully visible, rather than sliding smoothly off-screen. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908092840.225220-1-a0987203069@gmail.com?part=5 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu ` (4 preceding siblings ...) 2026-09-08 9:28 ` [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu @ 2026-09-08 9:28 ` Joey Lu 2026-09-08 10:25 ` sashiko-bot 5 siblings, 1 reply; 17+ messages in thread From: Joey Lu @ 2026-09-08 9:28 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 related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms 2026-09-08 9:28 ` [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu @ 2026-09-08 10:25 ` sashiko-bot 0 siblings, 0 replies; 17+ messages in thread From: sashiko-bot @ 2026-09-08 10:25 UTC (permalink / raw) To: Joey Lu; +Cc: dri-devel, conor+dt, devicetree, robh Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The CRTC pixel clock is disabled before the hardware is instructed to disable the CRTC. -- commit c35af4d919e849e303afa29d897c4d1581720138 Author: Joey Lu <a0987203069@gmail.com> drm/verisilicon: introduce per-variant hardware ops table The DC8200 and DCUltraLite share a broadly similar register layout but differ in how the bridge, CRTC, primary plane and IRQ paths are driven. This commit introduces a vs_dc_funcs vtable so each variant can supply its own implementation without scattering conditionals across multiple files. > diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c > index 0b8a35d09cd2e..1c4aac7086694 100644 > --- a/drivers/gpu/drm/verisilicon/vs_crtc.c > +++ b/drivers/gpu/drm/verisilicon/vs_crtc.c > @@ -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); [Severity: High] Are hardware registers written after the pixel clock is disabled here? In vs_crtc_atomic_disable(), dc->funcs->crtc_disable_ex() executes out-of-order, writing to MMIO registers after the associated pixel clock has been disabled via clk_disable_unprepare(). Writing to hardware registers after disabling the pixel clock can cause bus hangs (asynchronous external aborts) resulting in kernel panics, or silently fail to latch the register value, leaving the hardware in an inconsistent state. This sequence can be triggered by local userspace through DRM atomic mode setting ioctls when the CRTC is disabled, such as when turning off the screen or performing a mode switch. Could the hardware disable callback be moved before the clock is disabled to correctly mirror the enable sequence? > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908092840.225220-1-a0987203069@gmail.com?part=6 ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-09-10 10:06 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-08 9:28 [PATCH v6 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support Joey Lu 2026-09-08 9:28 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: add support for nuvoton, ma35d1-dcu Joey Lu 2026-09-08 9:36 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: add support for nuvoton,ma35d1-dcu sashiko-bot 2026-09-08 17:55 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Conor Dooley 2026-09-09 5:44 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng 2026-09-10 1:52 ` [PATCH v6 1/6] dt-bindings: display: verisilicon, dc: " Joey Lu 2026-09-10 7:08 ` [PATCH v6 1/6] dt-bindings: display: verisilicon,dc: " Icenowy Zheng 2026-09-08 9:28 ` [PATCH v6 2/6] drm/verisilicon: add register-level macros for DC8000 Joey Lu 2026-09-08 9:28 ` [PATCH v6 3/6] drm/verisilicon: introduce per-variant hardware ops table Joey Lu 2026-09-08 9:51 ` sashiko-bot 2026-09-08 9:28 ` [PATCH v6 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support Joey Lu 2026-09-08 10:04 ` sashiko-bot 2026-09-10 7:25 ` Icenowy Zheng 2026-09-08 9:28 ` [PATCH v6 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB Joey Lu 2026-09-08 10:15 ` sashiko-bot 2026-09-08 9:28 ` [PATCH v6 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms Joey Lu 2026-09-08 10:25 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).