[PATCH v4 0/5] drm/ingenic: Add the X1600 display controller and the HiBy R1 panel
From: Olivier Louvignes
Date: Mon Nov 09 2026 - 12:48:29 EST
The display controller of the Ingenic X1600 is not the one ingenic-drm
drives: it fetches frames through descriptors and keeps its interface and
timings in register blocks of their own. It is the X2000's DPU without
the composer. This series adds a binding and a driver for it, then the
panel of the HiBy R1, an X1600 audio player: 480x800 parallel RGB, set up
over a 3-wire SPI bus.
The driver covers what the R1 uses and what could be tested: parallel RGB
panels on a 24-bit bus and one full-screen RGB565 plane. The composer,
smart panels and other pixel formats are left out.
Two things come from the vendor kernel rather than the manual. A flip
also writes SRD_CHAIN_START, which the manual doesn't describe for a
running controller; flips without it were not tried. The panel's set-up
sequence is the vendor's too: HiBy calls the panel LG35583, its maker and
controller are unknown, hence the hiby prefix.
Changes in v4:
- 3/5: the clock runs from probe to unbind (devm_clk_get_enabled()), as
in ingenic-drm, instead of being gated with the CRTC (Paul). The
controller only takes register writes while clocked, so the timings
and the output format can now be set in the encoder's
atomic_mode_set(), and the bus_flags and color_order fields go. The
burst length is set once in probe, and atomic_disable() no longer has
a failed clock start to handle.
- 3/5: probe brings the clock down to at most a 720p pixel clock right
after enabling it. After a reset it runs at its parent's rate, 1.4 GHz
on the R1, and kept that fast until the first modeset the controller
hung the R1 at every cold start.
- 3/5: atomic_enable() takes the mode from the new CRTC state, there is
no writel(readl()) nesting, and drm_mode_config_create_initial_state()
replaces drm_mode_config_reset() (Paul).
- 3/5: mode_valid() still checks the pixel count against 1280x720 rather
than 720 per side, which would refuse the R1's 480x800 panel (Paul
agreed).
- 3/5: the file is ingenic-dpu-x1600.c, and the module and driver are
ingenic-dpu-x1600 (Nikolaus).
- 5/5: unprepare() turns vcc off before vccio, the reverse of prepare()
(Sashiko).
- Rebased on drm-misc-next.
Changes in v3:
- The compatible is ingenic,x1600-dpu, and the binding and the driver say
"display controller" rather than "LCD controller" (Nikolaus). The X2000
and X2600 manuals call this block the DPU, and the X1600 manual does too
in its register and clock names. There is no generic ingenic,dpu
fallback, as writing-bindings.rst asks for SoC compatibles: an X2000
binding can fall back to the X1600's. The driver keeps its file name;
splitting it for the X2000's composer and interfaces belongs with
X2000 support.
- 2/5: no $nodename and no clock-names; the driver takes its one clock
unnamed (Krzysztof). The example's node is display-controller@.
- 2/5: there is no IPU in front of this controller (Krzysztof asked on v2,
Paul answered): it fetches its own frames, so the output port is its
only link.
- 4/5: reset-gpios, backlight and port dropped, panel-common has them
(Krzysztof). The example's endpoint points at the controller's new
label.
- Krzysztof's Acked-by on 1/5 and Reviewed-by on 4/5.
- Rebased on drm-misc-next after -rc1.
Changes in v2, all in 3/5 and all found by the Sashiko review of v1:
- Commits wait for flip_done instead of a vblank before the planes are
cleaned up. A flip's event waits until the controller reports reading
the new descriptor, which can be a frame after the vblank that v1's
default commit_tail waited for, so the old framebuffer could be freed
while still scanned out.
- A CRTC being enabled sends its event from atomic_enable(), once the
controller runs; v1 sent it from atomic_flush(), which runs first.
- A plane that is not visible is rejected: the controller always scans
out a whole frame, so v1 would have read past the end of a small
framebuffer placed off-screen.
- atomic_disable() returns early when atomic_enable() failed to start
the pixel clock, instead of touching an unclocked controller.
Tested on a HiBy R1: the fbdev console and a player drawing through
fbdev, blanking and unblanking, 60 page flips in 0.97 s at about 61 Hz,
and the colour order (RGB order swaps red and blue on this panel). For
v2 also: 120 fbdev pans in 1.95 s (one flip per frame, none timing out),
three blank/unblank cycles, and a 64x64 framebuffer set on the primary
plane just past the right edge through SETPLANE, which v1 accepted and
v2 refuses with -EINVAL, while a full-screen one is still accepted. v3
was run on the R1 with its node changed to match: the driver binds to
ingenic,x1600-dpu with its clock unnamed, and the player draws. For v4:
four blank/unblank cycles with the clock left running and the timing
registers kept, 60 pans in 0.98 s and 120 in 1.97 s with none failing,
an unbind and bind of the driver, which turns the clock off and then
writes the timings again from atomic_mode_set() on the first modeset,
and five cold starts with the kernel loaded into RAM through the boot
ROM's USB mode and started as the boot loader does.
The X1600 has no device tree upstream yet; its support is being posted
one subsystem at a time. The R1's backlight uses the X1600 PWM driver
posted separately, now at v3:
https://lore.kernel.org/r/20261102201325.29507-1-olivier@xxxxxxxxx
v3: https://lore.kernel.org/r/20261106112000.1612-1-olivier@xxxxxxxxx
v2: https://lore.kernel.org/r/20261025191640.13592-1-olivier@xxxxxxxxx
v1: https://lore.kernel.org/r/20261025085816.60405-1-olivier@xxxxxxxxx
Olivier Louvignes (5):
dt-bindings: vendor-prefixes: Add HiBy
dt-bindings: display: Add the Ingenic X1600 display controller
drm/ingenic: Add a driver for the X1600 display controller
dt-bindings: display: panel: Add the HiBy LG35583
drm/panel: Add the HiBy LG35583
.../bindings/display/ingenic,x1600-dpu.yaml | 61 ++
.../bindings/display/panel/hiby,lg35583.yaml | 67 ++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
MAINTAINERS | 12 +
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/ingenic/Kconfig | 22 +
drivers/gpu/drm/ingenic/Makefile | 1 +
drivers/gpu/drm/ingenic/ingenic-dpu-x1600.c | 739 ++++++++++++++++++
drivers/gpu/drm/panel/Kconfig | 10 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-hiby-lg35583.c | 342 ++++++++
11 files changed, 1258 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/ingenic,x1600-dpu.yaml
create mode 100644 Documentation/devicetree/bindings/display/panel/hiby,lg35583.yaml
create mode 100644 drivers/gpu/drm/ingenic/ingenic-dpu-x1600.c
create mode 100644 drivers/gpu/drm/panel/panel-hiby-lg35583.c
base-commit: 8deaade4a5a4ff635df91e246e42139ab2b33f6d
--
2.39.5